about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2021-05-25 16:08:18 +0200
committerLukas Wirth <lukastw97@gmail.com>2021-05-25 16:16:29 +0200
commit28ca37175572403edeb92324d251fbceb4c2487f (patch)
tree047556acaa4ff4044d2900902810a3555c6eb2c1
parent35db5e99f6f982f4257e88d13cbecca250b05efe (diff)
downloadrust-28ca37175572403edeb92324d251fbceb4c2487f.tar.gz
rust-28ca37175572403edeb92324d251fbceb4c2487f.zip
Consider trait to be in scope for trait-impl
-rw-r--r--crates/hir_def/src/resolver.rs38
-rw-r--r--crates/hir_ty/src/infer.rs2
-rw-r--r--crates/hir_ty/src/tests/traits.rs30
3 files changed, 57 insertions, 13 deletions
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 0391cc49b64..fb8a6f26063 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -337,22 +337,34 @@ impl Resolver {
     pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> {
         let mut traits = FxHashSet::default();
         for scope in &self.scopes {
-            if let Scope::ModuleScope(m) = scope {
-                if let Some(prelude) = m.def_map.prelude() {
-                    let prelude_def_map = prelude.def_map(db);
-                    traits.extend(prelude_def_map[prelude.local_id].scope.traits());
-                }
-                traits.extend(m.def_map[m.module_id].scope.traits());
-
-                // Add all traits that are in scope because of the containing DefMaps
-                m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| {
-                    if let Some(prelude) = def_map.prelude() {
+            match scope {
+                Scope::ModuleScope(m) => {
+                    if let Some(prelude) = m.def_map.prelude() {
                         let prelude_def_map = prelude.def_map(db);
                         traits.extend(prelude_def_map[prelude.local_id].scope.traits());
                     }
-                    traits.extend(def_map[module].scope.traits());
-                    None::<()>
-                });
+                    traits.extend(m.def_map[m.module_id].scope.traits());
+
+                    // Add all traits that are in scope because of the containing DefMaps
+                    m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| {
+                        if let Some(prelude) = def_map.prelude() {
+                            let prelude_def_map = prelude.def_map(db);
+                            traits.extend(prelude_def_map[prelude.local_id].scope.traits());
+                        }
+                        traits.extend(def_map[module].scope.traits());
+                        None::<()>
+                    });
+                }
+                &Scope::ImplDefScope(impl_) => {
+                    if let Some(target_trait) = &db.impl_data(impl_).target_trait {
+                        if let Some(TypeNs::TraitId(trait_)) =
+                            self.resolve_path_in_type_ns_fully(db, target_trait.path.mod_path())
+                        {
+                            traits.insert(trait_);
+                        }
+                    }
+                }
+                _ => (),
             }
         }
         traits
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index edb65622f19..164e8505044 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -578,10 +578,12 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
+        // FIXME resolve via lang_item once try v2 is stable
         let path = path![core::ops::Try];
         let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
         let trait_data = self.db.trait_data(trait_);
         trait_data
+            // FIXME remove once try v2 is stable
             .associated_type_by_name(&name![Ok])
             .or_else(|| trait_data.associated_type_by_name(&name![Output]))
     }
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 6cd8786eae1..6ad96bfe383 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3630,3 +3630,33 @@ fn test<F: FnOnce()>(f: F) {
         "#]],
     );
 }
+
+#[test]
+fn trait_in_scope_of_trait_impl() {
+    check_infer(
+        r#"
+mod foo {
+    pub trait Foo {
+        fn foo(self);
+        fn bar(self) -> usize { 0 }
+    }
+}
+impl foo::Foo for u32 {
+    fn foo(self) {
+        let _x = self.bar();
+    }
+}
+    "#,
+        expect![[r#"
+            45..49 'self': Self
+            67..71 'self': Self
+            82..87 '{ 0 }': usize
+            84..85 '0': usize
+            131..135 'self': u32
+            137..173 '{     ...     }': ()
+            151..153 '_x': usize
+            156..160 'self': u32
+            156..166 'self.bar()': usize
+        "#]],
+    );
+}