diff options
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index a177cebca..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, ApplicationTy, Canonical, InEnvironment, | 24 | autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy, |
25 | 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 { |
@@ -878,6 +879,28 @@ impl Type { | |||
878 | } | 879 | } |
879 | } | 880 | } |
880 | 881 | ||
882 | /// Checks that particular type `ty` implements `std::future::Future`. | ||
883 | /// This function is used in `.await` syntax completion. | ||
884 | pub fn impls_future(&self, db: &impl HirDatabase) -> bool { | ||
885 | let krate = self.krate; | ||
886 | |||
887 | let std_future_trait = | ||
888 | db.lang_item(krate, "future_trait".into()).and_then(|it| it.as_trait()); | ||
889 | let std_future_trait = match std_future_trait { | ||
890 | Some(it) => it, | ||
891 | None => return false, | ||
892 | }; | ||
893 | |||
894 | let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 }; | ||
895 | method_resolution::implements_trait( | ||
896 | &canonical_ty, | ||
897 | db, | ||
898 | self.ty.environment.clone(), | ||
899 | krate, | ||
900 | std_future_trait, | ||
901 | ) | ||
902 | } | ||
903 | |||
881 | // 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. |
882 | pub fn as_callable(&self) -> Option<CallableDef> { | 905 | pub fn as_callable(&self) -> Option<CallableDef> { |
883 | Some(self.ty.value.as_callable()?.0) | 906 | Some(self.ty.value.as_callable()?.0) |
@@ -986,6 +1009,65 @@ impl Type { | |||
986 | None | 1009 | None |
987 | } | 1010 | } |
988 | 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 | |||
989 | pub fn as_adt(&self) -> Option<Adt> { | 1071 | pub fn as_adt(&self) -> Option<Adt> { |
990 | let (adt, _subst) = self.ty.value.as_adt()?; | 1072 | let (adt, _subst) = self.ty.value.as_adt()?; |
991 | Some(adt.into()) | 1073 | Some(adt.into()) |