diff options
| author | Lukas Wirth <lukastw97@gmail.com> | 2021-05-25 16:08:18 +0200 |
|---|---|---|
| committer | Lukas Wirth <lukastw97@gmail.com> | 2021-05-25 16:16:29 +0200 |
| commit | 28ca37175572403edeb92324d251fbceb4c2487f (patch) | |
| tree | 047556acaa4ff4044d2900902810a3555c6eb2c1 | |
| parent | 35db5e99f6f982f4257e88d13cbecca250b05efe (diff) | |
| download | rust-28ca37175572403edeb92324d251fbceb4c2487f.tar.gz rust-28ca37175572403edeb92324d251fbceb4c2487f.zip | |
Consider trait to be in scope for trait-impl
| -rw-r--r-- | crates/hir_def/src/resolver.rs | 38 | ||||
| -rw-r--r-- | crates/hir_ty/src/infer.rs | 2 | ||||
| -rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 30 |
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 + "#]], + ); +} |
