]> git.lizzy.rs Git - rust.git/commitdiff
Handle `Self::Type` in trait definitions when referring to own associated type
authorFlorian Diebold <flodiebold@gmail.com>
Sun, 12 Apr 2020 10:29:03 +0000 (12:29 +0200)
committerFlorian Diebold <flodiebold@gmail.com>
Mon, 13 Apr 2020 14:32:23 +0000 (16:32 +0200)
It was implemented for other generic parameters for the trait, but not for `Self`.

crates/ra_hir_ty/src/lower.rs
crates/ra_hir_ty/src/tests/regression.rs
crates/ra_hir_ty/src/tests/traits.rs

index 6c7bbc448981ff244c5c7876819025a9e963bec9..7b5990a47cfed1478c9063774b551355de7e38b7 100644 (file)
@@ -360,13 +360,23 @@ fn select_associated_type(
             },
             Some(TypeNs::GenericParam(param_id)) => {
                 let predicates = ctx.db.generic_predicates_for_param(param_id);
-                predicates
+                let mut traits_: Vec<_> = predicates
                     .iter()
                     .filter_map(|pred| match &pred.value {
                         GenericPredicate::Implemented(tr) => Some(tr.trait_),
                         _ => None,
                     })
-                    .collect()
+                    .collect();
+                // Handle `Self::Type` referring to own associated type in trait definitions
+                if let GenericDefId::TraitId(trait_id) = param_id.parent {
+                    let generics = generics(ctx.db.upcast(), trait_id.into());
+                    if generics.params.types[param_id.local_id].provenance
+                        == TypeParamProvenance::TraitSelf
+                    {
+                        traits_.push(trait_id);
+                    }
+                }
+                traits_
             }
             _ => return Ty::Unknown,
         };
index 3402e0cb5aa49a4ae2e814d46e60e06a3f42f605..d69115a2f527bd32e81e2bf046799a8d6aeb4923 100644 (file)
@@ -451,8 +451,7 @@ fn next(&mut self) -> Option<char> {}
 "#,
     );
 
-    // should be Option<char>, but currently not because of Chalk ambiguity problem
-    assert_eq!("(Option<{unknown}>, Option<{unknown}>)", super::type_at_pos(&db, pos));
+    assert_eq!("(Option<char>, Option<char>)", super::type_at_pos(&db, pos));
 }
 
 #[test]
index 22ae6ca90922eb5c7cfc4a2ce0c6b9f29e382a06..d088bf3096e4c2d30a622ea7cf5c741d19dd23b9 100644 (file)
@@ -1803,7 +1803,7 @@ fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
 }
 
 #[test]
-fn unselected_projection_on_trait_self() {
+fn unselected_projection_on_impl_self() {
     assert_snapshot!(infer(
         r#"
 //- /main.rs
@@ -1843,6 +1843,30 @@ impl Trait for S2 {
     "###);
 }
 
+#[test]
+fn unselected_projection_on_trait_self() {
+    let t = type_at(
+        r#"
+//- /main.rs
+trait Trait {
+    type Item;
+
+    fn f(&self) -> Self::Item { loop {} }
+}
+
+struct S;
+impl Trait for S {
+    type Item = u32;
+}
+
+fn test() {
+    S.f()<|>;
+}
+"#,
+    );
+    assert_eq!(t, "u32");
+}
+
 #[test]
 fn trait_impl_self_ty() {
     let t = type_at(