aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/resolve.rs25
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs2
-rw-r--r--crates/ra_hir/src/ty/tests.rs29
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
4use ra_syntax::ast; 4use ra_syntax::ast;
5 5
6use rustc_hash::FxHashMap; 6use rustc_hash::{FxHashMap, FxHashSet};
7 7
8use crate::{ 8use 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]
2505fn method_resolution_trait_from_prelude() {
2506 let (mut db, pos) = MockDatabase::with_position(
2507 r#"
2508//- /main.rs
2509struct S;
2510impl Clone for S {}
2511
2512fn test() {
2513 S.clone()<|>;
2514}
2515
2516//- /lib.rs
2517#[prelude_import] use foo::*;
2518
2519mod 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]
2505fn method_resolution_where_clause_for_unknown_trait() { 2534fn 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(