Skip to content

Commit 518e39b

Browse files
committed
Auto merge of rust-lang#13742 - lowr:fix/assoc-type-shorthand-with-gats, r=flodiebold
fix: only shift `BoundVar`s that come from outside lowering context Fixes rust-lang#13734 There are some free functions `TyLoweringContext` methods call, which do not know anything about current binders in scope. We need to shift in the `BoundVar`s in substitutions that we get from them (rust-lang#4952), but not those we get from `TyLoweringContext` methods.
2 parents 1449204 + 19e3085 commit 518e39b

File tree

4 files changed

+46
-21
lines changed

4 files changed

+46
-21
lines changed

crates/hir-ty/src/lower.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,8 @@ impl<'a> TyLoweringContext<'a> {
603603
}
604604

605605
fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
606-
let (def, res) = match (self.resolver.generic_def(), res) {
607-
(Some(def), Some(res)) => (def, res),
608-
_ => return TyKind::Error.intern(Interner),
606+
let Some((def, res)) = self.resolver.generic_def().zip(res) else {
607+
return TyKind::Error.intern(Interner);
609608
};
610609
let ty = named_associated_type_shorthand_candidates(
611610
self.db,
@@ -617,6 +616,21 @@ impl<'a> TyLoweringContext<'a> {
617616
return None;
618617
}
619618

619+
let parent_subst = t.substitution.clone();
620+
let parent_subst = match self.type_param_mode {
621+
ParamLoweringMode::Placeholder => {
622+
// if we're lowering to placeholders, we have to put them in now.
623+
let generics = generics(self.db.upcast(), def);
624+
let s = generics.placeholder_subst(self.db);
625+
s.apply(parent_subst, Interner)
626+
}
627+
ParamLoweringMode::Variable => {
628+
// We need to shift in the bound vars, since
629+
// `named_associated_type_shorthand_candidates` does not do that.
630+
parent_subst.shifted_in_from(Interner, self.in_binders)
631+
}
632+
};
633+
620634
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
621635
// generic params. It's inefficient to splice the `Substitution`s, so we may want
622636
// that method to optionally take parent `Substitution` as we already know them at
@@ -632,22 +646,9 @@ impl<'a> TyLoweringContext<'a> {
632646

633647
let substs = Substitution::from_iter(
634648
Interner,
635-
substs.iter(Interner).take(len_self).chain(t.substitution.iter(Interner)),
649+
substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)),
636650
);
637651

638-
let substs = match self.type_param_mode {
639-
ParamLoweringMode::Placeholder => {
640-
// if we're lowering to placeholders, we have to put
641-
// them in now
642-
let generics = generics(self.db.upcast(), def);
643-
let s = generics.placeholder_subst(self.db);
644-
s.apply(substs, Interner)
645-
}
646-
ParamLoweringMode::Variable => substs,
647-
};
648-
// We need to shift in the bound vars, since
649-
// associated_type_shorthand_candidates does not do that
650-
let substs = substs.shifted_in_from(Interner, self.in_binders);
651652
Some(
652653
TyKind::Alias(AliasTy::Projection(ProjectionTy {
653654
associated_ty_id: to_assoc_type_id(associated_ty),
@@ -1190,9 +1191,9 @@ pub fn associated_type_shorthand_candidates<R>(
11901191
db: &dyn HirDatabase,
11911192
def: GenericDefId,
11921193
res: TypeNs,
1193-
cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
1194+
mut cb: impl FnMut(&Name, TypeAliasId) -> Option<R>,
11941195
) -> Option<R> {
1195-
named_associated_type_shorthand_candidates(db, def, res, None, cb)
1196+
named_associated_type_shorthand_candidates(db, def, res, None, |name, _, id| cb(name, id))
11961197
}
11971198

11981199
fn named_associated_type_shorthand_candidates<R>(
@@ -1202,6 +1203,9 @@ fn named_associated_type_shorthand_candidates<R>(
12021203
def: GenericDefId,
12031204
res: TypeNs,
12041205
assoc_name: Option<Name>,
1206+
// Do NOT let `cb` touch `TraitRef` outside of `TyLoweringContext`. Its substitution contains
1207+
// free `BoundVar`s that need to be shifted and only `TyLoweringContext` knows how to do that
1208+
// properly (see `TyLoweringContext::select_associated_type()`).
12051209
mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
12061210
) -> Option<R> {
12071211
let mut search = |t| {

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

+21
Original file line numberDiff line numberDiff line change
@@ -1723,3 +1723,24 @@ fn bar() -> ControlFlow<(), ()> {
17231723
"#,
17241724
);
17251725
}
1726+
1727+
#[test]
1728+
fn assoc_type_shorthand_with_gats_in_binders() {
1729+
// c.f. test `issue_4885()`
1730+
check_no_mismatches(
1731+
r#"
1732+
trait Gats {
1733+
type Assoc<T>;
1734+
}
1735+
trait Foo<T> {}
1736+
1737+
struct Bar<'a, B: Gats, A> {
1738+
field: &'a dyn Foo<B::Assoc<A>>,
1739+
}
1740+
1741+
fn foo(b: Bar) {
1742+
let _ = b.field;
1743+
}
1744+
"#,
1745+
);
1746+
}

crates/hir/src/semantics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,7 @@ impl<'a> SemanticsScope<'a> {
16001600
self.db,
16011601
def,
16021602
resolution.in_type_ns()?,
1603-
|name, _, id| cb(name, id.into()),
1603+
|name, id| cb(name, id.into()),
16041604
)
16051605
}
16061606
}

crates/hir/src/source_analyzer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ fn resolve_hir_path_(
967967
db,
968968
def,
969969
res.in_type_ns()?,
970-
|name, _, id| (name == unresolved.name).then(|| id),
970+
|name, id| (name == unresolved.name).then(|| id),
971971
)
972972
})
973973
.map(TypeAlias::from)

0 commit comments

Comments
 (0)