Only shift BoundVars that come from outside TyLoweringContext

This commit is contained in:
Ryo Yoshida 2022-12-08 20:41:42 +09:00
parent 46e1486a90
commit 19e3085481
No known key found for this signature in database
GPG key ID: E25698A930586171
2 changed files with 39 additions and 17 deletions

View file

@ -603,9 +603,8 @@ impl<'a> TyLoweringContext<'a> {
}
fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
let (def, res) = match (self.resolver.generic_def(), res) {
(Some(def), Some(res)) => (def, res),
_ => return TyKind::Error.intern(Interner),
let Some((def, res)) = self.resolver.generic_def().zip(res) else {
return TyKind::Error.intern(Interner);
};
let ty = named_associated_type_shorthand_candidates(
self.db,
@ -617,6 +616,21 @@ impl<'a> TyLoweringContext<'a> {
return None;
}
let parent_subst = t.substitution.clone();
let parent_subst = match self.type_param_mode {
ParamLoweringMode::Placeholder => {
// if we're lowering to placeholders, we have to put them in now.
let generics = generics(self.db.upcast(), def);
let s = generics.placeholder_subst(self.db);
s.apply(parent_subst, Interner)
}
ParamLoweringMode::Variable => {
// We need to shift in the bound vars, since
// `named_associated_type_shorthand_candidates` does not do that.
parent_subst.shifted_in_from(Interner, self.in_binders)
}
};
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
// generic params. It's inefficient to splice the `Substitution`s, so we may want
// that method to optionally take parent `Substitution` as we already know them at
@ -632,22 +646,9 @@ impl<'a> TyLoweringContext<'a> {
let substs = Substitution::from_iter(
Interner,
substs.iter(Interner).take(len_self).chain(t.substitution.iter(Interner)),
substs.iter(Interner).take(len_self).chain(parent_subst.iter(Interner)),
);
let substs = match self.type_param_mode {
ParamLoweringMode::Placeholder => {
// if we're lowering to placeholders, we have to put
// them in now
let generics = generics(self.db.upcast(), def);
let s = generics.placeholder_subst(self.db);
s.apply(substs, Interner)
}
ParamLoweringMode::Variable => substs,
};
// We need to shift in the bound vars, since
// associated_type_shorthand_candidates does not do that
let substs = substs.shifted_in_from(Interner, self.in_binders);
Some(
TyKind::Alias(AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(associated_ty),

View file

@ -1723,3 +1723,24 @@ fn bar() -> ControlFlow<(), ()> {
"#,
);
}
#[test]
fn assoc_type_shorthand_with_gats_in_binders() {
// c.f. test `issue_4885()`
check_no_mismatches(
r#"
trait Gats {
type Assoc<T>;
}
trait Foo<T> {}
struct Bar<'a, B: Gats, A> {
field: &'a dyn Foo<B::Assoc<A>>,
}
fn foo(b: Bar) {
let _ = b.field;
}
"#,
);
}