aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model.rs74
-rw-r--r--crates/ra_hir/src/source_analyzer.rs56
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs19
-rw-r--r--crates/ra_hir_ty/src/infer/path.rs9
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs103
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs17
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs26
7 files changed, 192 insertions, 112 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 346118350..3b479356f 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -21,8 +21,8 @@ use hir_expand::{
21 MacroDefId, 21 MacroDefId,
22}; 22};
23use hir_ty::{ 23use hir_ty::{
24 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution::implements_trait, 24 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
25 ApplicationTy, Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, 25 Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
26}; 26};
27use ra_db::{CrateId, Edition, FileId}; 27use ra_db::{CrateId, Edition, FileId};
28use ra_prof::profile; 28use ra_prof::profile;
@@ -120,7 +120,8 @@ impl_froms!(
120 BuiltinType 120 BuiltinType
121); 121);
122 122
123pub use hir_def::{attr::Attrs, visibility::Visibility}; 123pub use hir_def::{attr::Attrs, visibility::Visibility, AssocItemId};
124use rustc_hash::FxHashSet;
124 125
125impl Module { 126impl Module {
126 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { 127 pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module {
@@ -891,7 +892,13 @@ impl Type {
891 }; 892 };
892 893
893 let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 }; 894 let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 };
894 implements_trait(&canonical_ty, db, self.ty.environment.clone(), krate, std_future_trait) 895 method_resolution::implements_trait(
896 &canonical_ty,
897 db,
898 self.ty.environment.clone(),
899 krate,
900 std_future_trait,
901 )
895 } 902 }
896 903
897 // FIXME: this method is broken, as it doesn't take closures into account. 904 // FIXME: this method is broken, as it doesn't take closures into account.
@@ -1002,6 +1009,65 @@ impl Type {
1002 None 1009 None
1003 } 1010 }
1004 1011
1012 pub fn iterate_method_candidates<T>(
1013 &self,
1014 db: &impl HirDatabase,
1015 krate: Crate,
1016 traits_in_scope: &FxHashSet<TraitId>,
1017 name: Option<&Name>,
1018 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
1019 ) -> Option<T> {
1020 // There should be no inference vars in types passed here
1021 // FIXME check that?
1022 // FIXME replace Unknown by bound vars here
1023 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
1024
1025 let env = self.ty.environment.clone();
1026 let krate = krate.id;
1027
1028 method_resolution::iterate_method_candidates(
1029 &canonical,
1030 db,
1031 env,
1032 krate,
1033 traits_in_scope,
1034 name,
1035 method_resolution::LookupMode::MethodCall,
1036 |ty, it| match it {
1037 AssocItemId::FunctionId(f) => callback(ty, f.into()),
1038 _ => None,
1039 },
1040 )
1041 }
1042
1043 pub fn iterate_path_candidates<T>(
1044 &self,
1045 db: &impl HirDatabase,
1046 krate: Crate,
1047 traits_in_scope: &FxHashSet<TraitId>,
1048 name: Option<&Name>,
1049 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
1050 ) -> Option<T> {
1051 // There should be no inference vars in types passed here
1052 // FIXME check that?
1053 // FIXME replace Unknown by bound vars here
1054 let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 };
1055
1056 let env = self.ty.environment.clone();
1057 let krate = krate.id;
1058
1059 method_resolution::iterate_method_candidates(
1060 &canonical,
1061 db,
1062 env,
1063 krate,
1064 traits_in_scope,
1065 name,
1066 method_resolution::LookupMode::Path,
1067 |ty, it| callback(ty, it.into()),
1068 )
1069 }
1070
1005 pub fn as_adt(&self) -> Option<Adt> { 1071 pub fn as_adt(&self) -> Option<Adt> {
1006 let (adt, _subst) = self.ty.value.as_adt()?; 1072 let (adt, _subst) = self.ty.value.as_adt()?;
1007 Some(adt.into()) 1073 Some(adt.into())
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 3df48842d..76e0bff34 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -16,12 +16,12 @@ use hir_def::{
16 expr::{ExprId, PatId}, 16 expr::{ExprId, PatId},
17 nameres::ModuleSource, 17 nameres::ModuleSource,
18 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 18 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
19 AssocItemId, DefWithBodyId, 19 DefWithBodyId, TraitId,
20}; 20};
21use hir_expand::{ 21use hir_expand::{
22 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, 22 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind,
23}; 23};
24use hir_ty::{method_resolution, Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty}; 24use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment};
25use ra_prof::profile; 25use ra_prof::profile;
26use ra_syntax::{ 26use ra_syntax::{
27 ast::{self, AstNode}, 27 ast::{self, AstNode},
@@ -29,11 +29,11 @@ use ra_syntax::{
29 SyntaxKind::*, 29 SyntaxKind::*,
30 SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit, 30 SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextUnit,
31}; 31};
32use rustc_hash::FxHashSet;
32 33
33use crate::{ 34use crate::{
34 db::HirDatabase, Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, 35 db::HirDatabase, Adt, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, ImplBlock,
35 ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, 36 Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam,
36 TypeParam,
37}; 37};
38 38
39/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 39/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
@@ -347,49 +347,9 @@ impl SourceAnalyzer {
347 .collect() 347 .collect()
348 } 348 }
349 349
350 pub fn iterate_method_candidates<T>( 350 /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
351 &self, 351 pub fn traits_in_scope(&self, db: &impl HirDatabase) -> FxHashSet<TraitId> {
352 db: &impl HirDatabase, 352 self.resolver.traits_in_scope(db)
353 ty: &Type,
354 name: Option<&Name>,
355 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
356 ) -> Option<T> {
357 // There should be no inference vars in types passed here
358 // FIXME check that?
359 // FIXME replace Unknown by bound vars here
360 let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
361 method_resolution::iterate_method_candidates(
362 &canonical,
363 db,
364 &self.resolver,
365 name,
366 method_resolution::LookupMode::MethodCall,
367 |ty, it| match it {
368 AssocItemId::FunctionId(f) => callback(ty, f.into()),
369 _ => None,
370 },
371 )
372 }
373
374 pub fn iterate_path_candidates<T>(
375 &self,
376 db: &impl HirDatabase,
377 ty: &Type,
378 name: Option<&Name>,
379 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
380 ) -> Option<T> {
381 // There should be no inference vars in types passed here
382 // FIXME check that?
383 // FIXME replace Unknown by bound vars here
384 let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
385 method_resolution::iterate_method_candidates(
386 &canonical,
387 db,
388 &self.resolver,
389 name,
390 method_resolution::LookupMode::Path,
391 |ty, it| callback(ty, it.into()),
392 )
393 } 353 }
394 354
395 pub fn expand( 355 pub fn expand(
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 3af05394c..d6a17e469 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -569,12 +569,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
569 ) -> Ty { 569 ) -> Ty {
570 let receiver_ty = self.infer_expr(receiver, &Expectation::none()); 570 let receiver_ty = self.infer_expr(receiver, &Expectation::none());
571 let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone()); 571 let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone());
572 let resolved = method_resolution::lookup_method( 572
573 &canonicalized_receiver.value, 573 let traits_in_scope = self.resolver.traits_in_scope(self.db);
574 self.db, 574
575 method_name, 575 let resolved = self.resolver.krate().and_then(|krate| {
576 &self.resolver, 576 method_resolution::lookup_method(
577 ); 577 &canonicalized_receiver.value,
578 self.db,
579 self.trait_env.clone(),
580 krate,
581 &traits_in_scope,
582 method_name,
583 )
584 });
578 let (derefed_receiver_ty, method_ty, def_generics) = match resolved { 585 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
579 Some((ty, func)) => { 586 Some((ty, func)) => {
580 let ty = canonicalized_receiver.decanonicalize_ty(ty); 587 let ty = canonicalized_receiver.decanonicalize_ty(ty);
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs
index ffd358367..2c1d4831d 100644
--- a/crates/ra_hir_ty/src/infer/path.rs
+++ b/crates/ra_hir_ty/src/infer/path.rs
@@ -11,7 +11,7 @@ use hir_expand::name::Name;
11 11
12use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId}; 12use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId};
13 13
14use super::{ExprOrPatId, InferenceContext, TraitRef}; 14use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef};
15 15
16impl<'a, D: HirDatabase> InferenceContext<'a, D> { 16impl<'a, D: HirDatabase> InferenceContext<'a, D> {
17 pub(super) fn infer_path( 17 pub(super) fn infer_path(
@@ -193,11 +193,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
193 } 193 }
194 194
195 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone()); 195 let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
196 let env = TraitEnvironment::lower(self.db, &self.resolver);
197 let krate = self.resolver.krate()?;
198 let traits_in_scope = self.resolver.traits_in_scope(self.db);
196 199
197 method_resolution::iterate_method_candidates( 200 method_resolution::iterate_method_candidates(
198 &canonical_ty.value, 201 &canonical_ty.value,
199 self.db, 202 self.db,
200 &self.resolver.clone(), 203 env,
204 krate,
205 &traits_in_scope,
201 Some(name), 206 Some(name),
202 method_resolution::LookupMode::Path, 207 method_resolution::LookupMode::Path,
203 move |_ty, item| { 208 move |_ty, item| {
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 55435e6ea..5bacbbd7c 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -6,13 +6,13 @@ use std::sync::Arc;
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId, 9 lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId,
10 AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, 10 HasModule, ImplId, Lookup, TraitId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use ra_db::CrateId; 13use ra_db::CrateId;
14use ra_prof::profile; 14use ra_prof::profile;
15use rustc_hash::FxHashMap; 15use rustc_hash::{FxHashMap, FxHashSet};
16 16
17use super::Substs; 17use super::Substs;
18use crate::{ 18use crate::{
@@ -144,14 +144,24 @@ impl Ty {
144pub(crate) fn lookup_method( 144pub(crate) fn lookup_method(
145 ty: &Canonical<Ty>, 145 ty: &Canonical<Ty>,
146 db: &impl HirDatabase, 146 db: &impl HirDatabase,
147 env: Arc<TraitEnvironment>,
148 krate: CrateId,
149 traits_in_scope: &FxHashSet<TraitId>,
147 name: &Name, 150 name: &Name,
148 resolver: &Resolver,
149) -> Option<(Ty, FunctionId)> { 151) -> Option<(Ty, FunctionId)> {
150 iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f 152 iterate_method_candidates(
151 { 153 ty,
152 AssocItemId::FunctionId(f) => Some((ty.clone(), f)), 154 db,
153 _ => None, 155 env,
154 }) 156 krate,
157 &traits_in_scope,
158 Some(name),
159 LookupMode::MethodCall,
160 |ty, f| match f {
161 AssocItemId::FunctionId(f) => Some((ty.clone(), f)),
162 _ => None,
163 },
164 )
155} 165}
156 166
157/// Whether we're looking up a dotted method call (like `v.len()`) or a path 167/// Whether we're looking up a dotted method call (like `v.len()`) or a path
@@ -172,7 +182,9 @@ pub enum LookupMode {
172pub fn iterate_method_candidates<T>( 182pub fn iterate_method_candidates<T>(
173 ty: &Canonical<Ty>, 183 ty: &Canonical<Ty>,
174 db: &impl HirDatabase, 184 db: &impl HirDatabase,
175 resolver: &Resolver, 185 env: Arc<TraitEnvironment>,
186 krate: CrateId,
187 traits_in_scope: &FxHashSet<TraitId>,
176 name: Option<&Name>, 188 name: Option<&Name>,
177 mode: LookupMode, 189 mode: LookupMode,
178 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 190 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
@@ -187,9 +199,7 @@ pub fn iterate_method_candidates<T>(
187 // Also note that when we've got a receiver like &S, even if the method we 199 // Also note that when we've got a receiver like &S, even if the method we
188 // find in the end takes &self, we still do the autoderef step (just as 200 // find in the end takes &self, we still do the autoderef step (just as
189 // rustc does an autoderef and then autoref again). 201 // rustc does an autoderef and then autoref again).
190 let environment = TraitEnvironment::lower(db, resolver); 202 let ty = InEnvironment { value: ty.clone(), environment: env.clone() };
191 let ty = InEnvironment { value: ty.clone(), environment };
192 let krate = resolver.krate()?;
193 203
194 // We have to be careful about the order we're looking at candidates 204 // We have to be careful about the order we're looking at candidates
195 // in here. Consider the case where we're resolving `x.clone()` 205 // in here. Consider the case where we're resolving `x.clone()`
@@ -209,7 +219,9 @@ pub fn iterate_method_candidates<T>(
209 if let Some(result) = iterate_method_candidates_with_autoref( 219 if let Some(result) = iterate_method_candidates_with_autoref(
210 &deref_chain[i..], 220 &deref_chain[i..],
211 db, 221 db,
212 resolver, 222 env.clone(),
223 krate,
224 traits_in_scope,
213 name, 225 name,
214 &mut callback, 226 &mut callback,
215 ) { 227 ) {
@@ -220,7 +232,15 @@ pub fn iterate_method_candidates<T>(
220 } 232 }
221 LookupMode::Path => { 233 LookupMode::Path => {
222 // No autoderef for path lookups 234 // No autoderef for path lookups
223 iterate_method_candidates_for_self_ty(&ty, db, resolver, name, &mut callback) 235 iterate_method_candidates_for_self_ty(
236 &ty,
237 db,
238 env,
239 krate,
240 traits_in_scope,
241 name,
242 &mut callback,
243 )
224 } 244 }
225 } 245 }
226} 246}
@@ -228,7 +248,9 @@ pub fn iterate_method_candidates<T>(
228fn iterate_method_candidates_with_autoref<T>( 248fn iterate_method_candidates_with_autoref<T>(
229 deref_chain: &[Canonical<Ty>], 249 deref_chain: &[Canonical<Ty>],
230 db: &impl HirDatabase, 250 db: &impl HirDatabase,
231 resolver: &Resolver, 251 env: Arc<TraitEnvironment>,
252 krate: CrateId,
253 traits_in_scope: &FxHashSet<TraitId>,
232 name: Option<&Name>, 254 name: Option<&Name>,
233 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 255 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
234) -> Option<T> { 256) -> Option<T> {
@@ -236,7 +258,9 @@ fn iterate_method_candidates_with_autoref<T>(
236 &deref_chain[0], 258 &deref_chain[0],
237 &deref_chain[1..], 259 &deref_chain[1..],
238 db, 260 db,
239 resolver, 261 env.clone(),
262 krate,
263 &traits_in_scope,
240 name, 264 name,
241 &mut callback, 265 &mut callback,
242 ) { 266 ) {
@@ -250,7 +274,9 @@ fn iterate_method_candidates_with_autoref<T>(
250 &refed, 274 &refed,
251 deref_chain, 275 deref_chain,
252 db, 276 db,
253 resolver, 277 env.clone(),
278 krate,
279 &traits_in_scope,
254 name, 280 name,
255 &mut callback, 281 &mut callback,
256 ) { 282 ) {
@@ -264,7 +290,9 @@ fn iterate_method_candidates_with_autoref<T>(
264 &ref_muted, 290 &ref_muted,
265 deref_chain, 291 deref_chain,
266 db, 292 db,
267 resolver, 293 env.clone(),
294 krate,
295 &traits_in_scope,
268 name, 296 name,
269 &mut callback, 297 &mut callback,
270 ) { 298 ) {
@@ -277,14 +305,15 @@ fn iterate_method_candidates_by_receiver<T>(
277 receiver_ty: &Canonical<Ty>, 305 receiver_ty: &Canonical<Ty>,
278 rest_of_deref_chain: &[Canonical<Ty>], 306 rest_of_deref_chain: &[Canonical<Ty>],
279 db: &impl HirDatabase, 307 db: &impl HirDatabase,
280 resolver: &Resolver, 308 env: Arc<TraitEnvironment>,
309 krate: CrateId,
310 traits_in_scope: &FxHashSet<TraitId>,
281 name: Option<&Name>, 311 name: Option<&Name>,
282 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 312 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
283) -> Option<T> { 313) -> Option<T> {
284 // We're looking for methods with *receiver* type receiver_ty. These could 314 // We're looking for methods with *receiver* type receiver_ty. These could
285 // be found in any of the derefs of receiver_ty, so we have to go through 315 // be found in any of the derefs of receiver_ty, so we have to go through
286 // that. 316 // that.
287 let krate = resolver.krate()?;
288 for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { 317 for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
289 if let Some(result) = 318 if let Some(result) =
290 iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) 319 iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback)
@@ -296,7 +325,9 @@ fn iterate_method_candidates_by_receiver<T>(
296 if let Some(result) = iterate_trait_method_candidates( 325 if let Some(result) = iterate_trait_method_candidates(
297 self_ty, 326 self_ty,
298 db, 327 db,
299 resolver, 328 env.clone(),
329 krate,
330 &traits_in_scope,
300 name, 331 name,
301 Some(receiver_ty), 332 Some(receiver_ty),
302 &mut callback, 333 &mut callback,
@@ -310,17 +341,25 @@ fn iterate_method_candidates_by_receiver<T>(
310fn iterate_method_candidates_for_self_ty<T>( 341fn iterate_method_candidates_for_self_ty<T>(
311 self_ty: &Canonical<Ty>, 342 self_ty: &Canonical<Ty>,
312 db: &impl HirDatabase, 343 db: &impl HirDatabase,
313 resolver: &Resolver, 344 env: Arc<TraitEnvironment>,
345 krate: CrateId,
346 traits_in_scope: &FxHashSet<TraitId>,
314 name: Option<&Name>, 347 name: Option<&Name>,
315 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 348 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
316) -> Option<T> { 349) -> Option<T> {
317 let krate = resolver.krate()?;
318 if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { 350 if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) {
319 return Some(result); 351 return Some(result);
320 } 352 }
321 if let Some(result) = 353 if let Some(result) = iterate_trait_method_candidates(
322 iterate_trait_method_candidates(self_ty, db, resolver, name, None, &mut callback) 354 self_ty,
323 { 355 db,
356 env,
357 krate,
358 traits_in_scope,
359 name,
360 None,
361 &mut callback,
362 ) {
324 return Some(result); 363 return Some(result);
325 } 364 }
326 None 365 None
@@ -329,14 +368,13 @@ fn iterate_method_candidates_for_self_ty<T>(
329fn iterate_trait_method_candidates<T>( 368fn iterate_trait_method_candidates<T>(
330 self_ty: &Canonical<Ty>, 369 self_ty: &Canonical<Ty>,
331 db: &impl HirDatabase, 370 db: &impl HirDatabase,
332 resolver: &Resolver, 371 env: Arc<TraitEnvironment>,
372 krate: CrateId,
373 traits_in_scope: &FxHashSet<TraitId>,
333 name: Option<&Name>, 374 name: Option<&Name>,
334 receiver_ty: Option<&Canonical<Ty>>, 375 receiver_ty: Option<&Canonical<Ty>>,
335 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 376 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
336) -> Option<T> { 377) -> Option<T> {
337 let krate = resolver.krate()?;
338 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
339 let env = TraitEnvironment::lower(db, resolver);
340 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope 378 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
341 let inherent_trait = self_ty.value.inherent_trait().into_iter(); 379 let inherent_trait = self_ty.value.inherent_trait().into_iter();
342 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 380 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
@@ -344,8 +382,7 @@ fn iterate_trait_method_candidates<T>(
344 .trait_predicates_for_self_ty(&self_ty.value) 382 .trait_predicates_for_self_ty(&self_ty.value)
345 .map(|tr| tr.trait_) 383 .map(|tr| tr.trait_)
346 .flat_map(|t| all_super_traits(db, t)); 384 .flat_map(|t| all_super_traits(db, t));
347 let traits = 385 let traits = inherent_trait.chain(traits_from_env).chain(traits_in_scope.iter().copied());
348 inherent_trait.chain(traits_from_env).chain(resolver.traits_in_scope(db).into_iter());
349 'traits: for t in traits { 386 'traits: for t in traits {
350 let data = db.trait_data(t); 387 let data = db.trait_data(t);
351 388
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 9ab43644e..2ca78c927 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -53,13 +53,16 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Ty
53} 53}
54 54
55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { 55fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) {
56 let mut seen_methods = FxHashSet::default(); 56 if let Some(krate) = ctx.module.map(|it| it.krate()) {
57 ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { 57 let mut seen_methods = FxHashSet::default();
58 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { 58 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
59 acc.add_function(ctx, func); 59 receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
60 } 60 if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
61 None::<()> 61 acc.add_function(ctx, func);
62 }); 62 }
63 None::<()>
64 });
65 }
63} 66}
64 67
65#[cfg(test)] 68#[cfg(test)]
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index 0dce9dc2d..af24e9f48 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -49,22 +49,24 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), 49 hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
50 _ => unreachable!(), 50 _ => unreachable!(),
51 }; 51 };
52 ctx.analyzer.iterate_path_candidates(ctx.db, &ty, None, |_ty, item| {
53 match item {
54 hir::AssocItem::Function(func) => {
55 if !func.has_self_param(ctx.db) {
56 acc.add_function(ctx, func);
57 }
58 }
59 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
60 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
61 }
62 None::<()>
63 });
64 // Iterate assoc types separately 52 // Iterate assoc types separately
65 // FIXME: complete T::AssocType 53 // FIXME: complete T::AssocType
66 let krate = ctx.module.map(|m| m.krate()); 54 let krate = ctx.module.map(|m| m.krate());
67 if let Some(krate) = krate { 55 if let Some(krate) = krate {
56 let traits_in_scope = ctx.analyzer.traits_in_scope(ctx.db);
57 ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
58 match item {
59 hir::AssocItem::Function(func) => {
60 if !func.has_self_param(ctx.db) {
61 acc.add_function(ctx, func);
62 }
63 }
64 hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
65 hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
66 }
67 None::<()>
68 });
69
68 ty.iterate_impl_items(ctx.db, krate, |item| { 70 ty.iterate_impl_items(ctx.db, krate, |item| {
69 match item { 71 match item {
70 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {} 72 hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}