diff options
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 74 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 70 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 26 |
4 files changed, 102 insertions, 85 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 | }; |
23 | use hir_ty::{ | 23 | use 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 | }; |
27 | use ra_db::{CrateId, Edition, FileId}; | 27 | use ra_db::{CrateId, Edition, FileId}; |
28 | use ra_prof::profile; | 28 | use ra_prof::profile; |
@@ -120,7 +120,8 @@ impl_froms!( | |||
120 | BuiltinType | 120 | BuiltinType |
121 | ); | 121 | ); |
122 | 122 | ||
123 | pub use hir_def::{attr::Attrs, visibility::Visibility}; | 123 | pub use hir_def::{attr::Attrs, visibility::Visibility, AssocItemId}; |
124 | use rustc_hash::FxHashSet; | ||
124 | 125 | ||
125 | impl Module { | 126 | impl 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 5707a5696..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 | }; |
21 | use hir_expand::{ | 21 | use hir_expand::{ |
22 | hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, | 22 | hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, |
23 | }; | 23 | }; |
24 | use hir_ty::{method_resolution, Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty}; | 24 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; |
25 | use ra_prof::profile; | 25 | use ra_prof::profile; |
26 | use ra_syntax::{ | 26 | use 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 | }; |
32 | use rustc_hash::FxHashSet; | ||
32 | 33 | ||
33 | use crate::{ | 34 | use 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,63 +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 | |||
362 | let env = TraitEnvironment::lower(db, &self.resolver); | ||
363 | let krate = self.resolver.krate()?; | ||
364 | let traits_in_scope = self.resolver.traits_in_scope(db); | ||
365 | |||
366 | method_resolution::iterate_method_candidates( | ||
367 | &canonical, | ||
368 | db, | ||
369 | env, | ||
370 | krate, | ||
371 | &traits_in_scope, | ||
372 | name, | ||
373 | method_resolution::LookupMode::MethodCall, | ||
374 | |ty, it| match it { | ||
375 | AssocItemId::FunctionId(f) => callback(ty, f.into()), | ||
376 | _ => None, | ||
377 | }, | ||
378 | ) | ||
379 | } | ||
380 | |||
381 | pub fn iterate_path_candidates<T>( | ||
382 | &self, | ||
383 | db: &impl HirDatabase, | ||
384 | ty: &Type, | ||
385 | name: Option<&Name>, | ||
386 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | ||
387 | ) -> Option<T> { | ||
388 | // There should be no inference vars in types passed here | ||
389 | // FIXME check that? | ||
390 | // FIXME replace Unknown by bound vars here | ||
391 | let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 }; | ||
392 | |||
393 | let env = TraitEnvironment::lower(db, &self.resolver); | ||
394 | let krate = self.resolver.krate()?; | ||
395 | let traits_in_scope = self.resolver.traits_in_scope(db); | ||
396 | |||
397 | method_resolution::iterate_method_candidates( | ||
398 | &canonical, | ||
399 | db, | ||
400 | env, | ||
401 | krate, | ||
402 | &traits_in_scope, | ||
403 | name, | ||
404 | method_resolution::LookupMode::Path, | ||
405 | |ty, it| callback(ty, it.into()), | ||
406 | ) | ||
407 | } | 353 | } |
408 | 354 | ||
409 | pub fn expand( | 355 | pub fn expand( |
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 | ||
55 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { | 55 | fn 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(_) => {} |