diff options
| -rw-r--r-- | crates/ra_hir/src/resolve.rs | 25 | ||||
| -rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 2 | ||||
| -rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 29 |
3 files changed, 42 insertions, 14 deletions
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 707556ef8..2fb219908 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
| @@ -3,7 +3,7 @@ use std::sync::Arc; | |||
| 3 | 3 | ||
| 4 | use ra_syntax::ast; | 4 | use ra_syntax::ast; |
| 5 | 5 | ||
| 6 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::{FxHashMap, FxHashSet}; |
| 7 | 7 | ||
| 8 | use crate::{ | 8 | use crate::{ |
| 9 | ModuleDef, Trait, | 9 | ModuleDef, Trait, |
| @@ -193,19 +193,18 @@ impl Resolver { | |||
| 193 | names | 193 | names |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | pub(crate) fn traits_in_scope<'a>(&'a self) -> impl Iterator<Item = Trait> + 'a { | 196 | pub(crate) fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<Trait> { |
| 197 | // FIXME prelude | 197 | let mut traits = FxHashSet::default(); |
| 198 | self.scopes | 198 | for scope in &self.scopes { |
| 199 | .iter() | 199 | if let Scope::ModuleScope(m) = scope { |
| 200 | .rev() | 200 | if let Some(prelude) = m.crate_def_map.prelude() { |
| 201 | .flat_map(|scope| { | 201 | let prelude_def_map = db.crate_def_map(prelude.krate); |
| 202 | match scope { | 202 | traits.extend(prelude_def_map[prelude.module_id].scope.traits()); |
| 203 | Scope::ModuleScope(m) => Some(m.crate_def_map[m.module_id].scope.traits()), | ||
| 204 | _ => None, | ||
| 205 | } | 203 | } |
| 206 | .into_iter() | 204 | traits.extend(m.crate_def_map[m.module_id].scope.traits()); |
| 207 | }) | 205 | } |
| 208 | .flatten() | 206 | } |
| 207 | traits | ||
| 209 | } | 208 | } |
| 210 | 209 | ||
| 211 | fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { | 210 | fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index e8cfa0b85..34817a5ec 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
| @@ -185,7 +185,7 @@ fn iterate_trait_method_candidates<T>( | |||
| 185 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 185 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
| 186 | ) -> Option<T> { | 186 | ) -> Option<T> { |
| 187 | let krate = resolver.krate()?; | 187 | let krate = resolver.krate()?; |
| 188 | 'traits: for t in resolver.traits_in_scope() { | 188 | 'traits: for t in resolver.traits_in_scope(db) { |
| 189 | let data = t.trait_data(db); | 189 | let data = t.trait_data(db); |
| 190 | // we'll be lazy about checking whether the type implements the | 190 | // we'll be lazy about checking whether the type implements the |
| 191 | // trait, but if we find out it doesn't, we'll skip the rest of the | 191 | // trait, but if we find out it doesn't, we'll skip the rest of the |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 510fa5333..978cc2587 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
| @@ -2502,6 +2502,35 @@ fn test() { (&S).foo()<|>; } | |||
| 2502 | } | 2502 | } |
| 2503 | 2503 | ||
| 2504 | #[test] | 2504 | #[test] |
| 2505 | fn method_resolution_trait_from_prelude() { | ||
| 2506 | let (mut db, pos) = MockDatabase::with_position( | ||
| 2507 | r#" | ||
| 2508 | //- /main.rs | ||
| 2509 | struct S; | ||
| 2510 | impl Clone for S {} | ||
| 2511 | |||
| 2512 | fn test() { | ||
| 2513 | S.clone()<|>; | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | //- /lib.rs | ||
| 2517 | #[prelude_import] use foo::*; | ||
| 2518 | |||
| 2519 | mod foo { | ||
| 2520 | trait Clone { | ||
| 2521 | fn clone(&self) -> Self; | ||
| 2522 | } | ||
| 2523 | } | ||
| 2524 | "#, | ||
| 2525 | ); | ||
| 2526 | db.set_crate_graph_from_fixture(crate_graph! { | ||
| 2527 | "main": ("/main.rs", ["other_crate"]), | ||
| 2528 | "other_crate": ("/lib.rs", []), | ||
| 2529 | }); | ||
| 2530 | assert_eq!("S", type_at_pos(&db, pos)); | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | #[test] | ||
| 2505 | fn method_resolution_where_clause_for_unknown_trait() { | 2534 | fn method_resolution_where_clause_for_unknown_trait() { |
| 2506 | // The blanket impl shouldn't apply because we can't even resolve UnknownTrait | 2535 | // The blanket impl shouldn't apply because we can't even resolve UnknownTrait |
| 2507 | let t = type_at( | 2536 | let t = type_at( |
