diff options
| author | Ryo Yoshida <low.ryoshida@gmail.com> | 2022-12-08 20:41:42 +0900 |
|---|---|---|
| committer | Ryo Yoshida <low.ryoshida@gmail.com> | 2022-12-08 21:17:13 +0900 |
| commit | 19e3085481351cf9e0d1ef954a1b03c55c534f27 (patch) | |
| tree | 1e7bcaf6734c2b2ab2af65468abea4826dcaa600 | |
| parent | 46e1486a90d76c6ff15a7a2baed7b15f54a2e42c (diff) | |
| download | rust-19e3085481351cf9e0d1ef954a1b03c55c534f27.tar.gz rust-19e3085481351cf9e0d1ef954a1b03c55c534f27.zip | |
Only shift `BoundVar`s that come from outside `TyLoweringContext`
| -rw-r--r-- | crates/hir-ty/src/lower.rs | 35 | ||||
| -rw-r--r-- | crates/hir-ty/src/tests/regression.rs | 21 |
2 files changed, 39 insertions, 17 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs index 5b0c1a63752..e8466a7eda5 100644 --- a/crates/hir-ty/src/lower.rs +++ b/crates/hir-ty/src/lower.rs @@ -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), diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 4e46397459d..de6ae7fff8f 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -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; +} +"#, + ); +} |
