Skip to content

Commit ae57b69

Browse files
committed
Auto merge of #13049 - lowr:fix/bare-dyn-assoc-type, r=Veykril
fix: resolve associated types of bare dyn types Fixes #13031 We've been dropping the associated type bindings of trait object types that were written without the `dyn` keyword. This patch reuses the lowering logic for `TypeRef::DynTrait` so the associated type bindings are properly lowered.
2 parents 82ff740 + 12abaf8 commit ae57b69

File tree

2 files changed

+54
-35
lines changed

2 files changed

+54
-35
lines changed

crates/hir-ty/src/lower.rs

+26-35
Original file line numberDiff line numberDiff line change
@@ -238,18 +238,7 @@ impl<'a> TyLoweringContext<'a> {
238238
})
239239
.intern(Interner)
240240
}
241-
TypeRef::DynTrait(bounds) => {
242-
let self_ty =
243-
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
244-
let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
245-
QuantifiedWhereClauses::from_iter(
246-
Interner,
247-
bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
248-
)
249-
});
250-
let bounds = crate::make_single_type_binders(bounds);
251-
TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
252-
}
241+
TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
253242
TypeRef::ImplTrait(bounds) => {
254243
match self.impl_trait_mode {
255244
ImplTraitLoweringMode::Opaque => {
@@ -468,29 +457,10 @@ impl<'a> TyLoweringContext<'a> {
468457
}
469458
}
470459
0 => {
471-
let self_ty = Some(
472-
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
473-
.intern(Interner),
474-
);
475-
let trait_ref = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
476-
ctx.lower_trait_ref_from_resolved_path(
477-
trait_,
478-
resolved_segment,
479-
self_ty,
480-
)
481-
});
482-
let dyn_ty = DynTy {
483-
bounds: crate::make_single_type_binders(
484-
QuantifiedWhereClauses::from_iter(
485-
Interner,
486-
Some(crate::wrap_empty_binders(WhereClause::Implemented(
487-
trait_ref,
488-
))),
489-
),
490-
),
491-
lifetime: static_lifetime(),
492-
};
493-
TyKind::Dyn(dyn_ty).intern(Interner)
460+
// Trait object type without dyn; this should be handled in upstream. See
461+
// `lower_path()`.
462+
stdx::never!("unexpected fully resolved trait path");
463+
TyKind::Error.intern(Interner)
494464
}
495465
_ => {
496466
// FIXME report error (ambiguous associated type)
@@ -555,11 +525,20 @@ impl<'a> TyLoweringContext<'a> {
555525
let (ty, res) = self.lower_ty_ext(type_ref);
556526
return self.lower_ty_relative_path(ty, res, path.segments());
557527
}
528+
558529
let (resolution, remaining_index) =
559530
match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
560531
Some(it) => it,
561532
None => return (TyKind::Error.intern(Interner), None),
562533
};
534+
535+
if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
536+
// trait object type without dyn
537+
let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None);
538+
let ty = self.lower_dyn_trait(&[Interned::new(bound)]);
539+
return (ty, None);
540+
}
541+
563542
let (resolved_segment, remaining_segments) = match remaining_index {
564543
None => (
565544
path.segments().last().expect("resolved path has at least one element"),
@@ -987,6 +966,18 @@ impl<'a> TyLoweringContext<'a> {
987966
})
988967
}
989968

969+
fn lower_dyn_trait(&self, bounds: &[Interned<TypeBound>]) -> Ty {
970+
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
971+
let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
972+
QuantifiedWhereClauses::from_iter(
973+
Interner,
974+
bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
975+
)
976+
});
977+
let bounds = crate::make_single_type_binders(bounds);
978+
TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
979+
}
980+
990981
fn lower_impl_trait(
991982
&self,
992983
bounds: &[Interned<TypeBound>],

crates/hir-ty/src/tests/traits.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1476,6 +1476,34 @@ fn test(x: Trait, y: &Trait) -> u64 {
14761476
165..172 'z.foo()': u64
14771477
"#]],
14781478
);
1479+
1480+
check_infer_with_mismatches(
1481+
r#"
1482+
//- minicore: fn, coerce_unsized
1483+
struct S;
1484+
impl S {
1485+
fn foo(&self) {}
1486+
}
1487+
fn f(_: &Fn(S)) {}
1488+
fn main() {
1489+
f(&|number| number.foo());
1490+
}
1491+
"#,
1492+
expect![[r#"
1493+
31..35 'self': &S
1494+
37..39 '{}': ()
1495+
47..48 '_': &dyn Fn(S)
1496+
58..60 '{}': ()
1497+
71..105 '{ ...()); }': ()
1498+
77..78 'f': fn f(&dyn Fn(S))
1499+
77..102 'f(&|nu...foo())': ()
1500+
79..101 '&|numb....foo()': &|S| -> ()
1501+
80..101 '|numbe....foo()': |S| -> ()
1502+
81..87 'number': S
1503+
89..95 'number': S
1504+
89..101 'number.foo()': ()
1505+
"#]],
1506+
)
14791507
}
14801508

14811509
#[test]

0 commit comments

Comments
 (0)