about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRyo Yoshida <low.ryoshida@gmail.com>2022-12-08 20:41:42 +0900
committerRyo Yoshida <low.ryoshida@gmail.com>2022-12-08 21:17:13 +0900
commit19e3085481351cf9e0d1ef954a1b03c55c534f27 (patch)
tree1e7bcaf6734c2b2ab2af65468abea4826dcaa600
parent46e1486a90d76c6ff15a7a2baed7b15f54a2e42c (diff)
downloadrust-19e3085481351cf9e0d1ef954a1b03c55c534f27.tar.gz
rust-19e3085481351cf9e0d1ef954a1b03c55c534f27.zip
Only shift `BoundVar`s that come from outside `TyLoweringContext`
-rw-r--r--crates/hir-ty/src/lower.rs35
-rw-r--r--crates/hir-ty/src/tests/regression.rs21
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;
+}
+"#,
+    );
+}