aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs3
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs60
-rw-r--r--crates/ra_hir/src/ty/tests.rs12
3 files changed, 54 insertions, 21 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 5fd602a9e..573115321 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -821,7 +821,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
821 } 821 }
822 Expr::MethodCall { receiver, args, method_name, generic_args } => { 822 Expr::MethodCall { receiver, args, method_name, generic_args } => {
823 let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); 823 let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
824 let resolved = receiver_ty.clone().lookup_method(self.db, method_name); 824 let resolved =
825 receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver);
825 let (derefed_receiver_ty, method_ty, def_generics) = match resolved { 826 let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
826 Some((ty, func)) => { 827 Some((ty, func)) => {
827 self.write_method_resolution(tgt_expr, func); 828 self.write_method_resolution(tgt_expr, func);
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index b1684acf9..708a435b4 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -11,7 +11,7 @@ use crate::{
11 ids::TraitId, 11 ids::TraitId,
12 impl_block::{ImplId, ImplBlock, ImplItem}, 12 impl_block::{ImplId, ImplBlock, ImplItem},
13 ty::{Ty, TypeCtor}, 13 ty::{Ty, TypeCtor},
14 nameres::CrateModuleId, 14 nameres::CrateModuleId, resolve::Resolver, traits::TraitItem
15 15
16}; 16};
17 17
@@ -73,18 +73,18 @@ impl CrateImplBlocks {
73 73
74 let target_ty = impl_block.target_ty(db); 74 let target_ty = impl_block.target_ty(db);
75 75
76 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
77 self.impls
78 .entry(target_ty_fp)
79 .or_insert_with(Vec::new)
80 .push((module.module_id, impl_id));
81 }
82
83 if let Some(tr) = impl_block.target_trait(db) { 76 if let Some(tr) = impl_block.target_trait(db) {
84 self.impls_by_trait 77 self.impls_by_trait
85 .entry(tr.id) 78 .entry(tr.id)
86 .or_insert_with(Vec::new) 79 .or_insert_with(Vec::new)
87 .push((module.module_id, impl_id)); 80 .push((module.module_id, impl_id));
81 } else {
82 if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) {
83 self.impls
84 .entry(target_ty_fp)
85 .or_insert_with(Vec::new)
86 .push((module.module_id, impl_id));
87 }
88 } 88 }
89 } 89 }
90 90
@@ -120,20 +120,52 @@ fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> {
120} 120}
121 121
122impl Ty { 122impl Ty {
123 // FIXME: cache this as a query?
124 // - if so, what signature? (TyFingerprint, Name)?
125 // - or maybe cache all names and def_ids of methods per fingerprint?
126 /// Look up the method with the given name, returning the actual autoderefed 123 /// Look up the method with the given name, returning the actual autoderefed
127 /// receiver type (but without autoref applied yet). 124 /// receiver type (but without autoref applied yet).
128 pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<(Ty, Function)> { 125 pub fn lookup_method(
129 self.iterate_methods(db, |ty, f| { 126 self,
127 db: &impl HirDatabase,
128 name: &Name,
129 resolver: &Resolver,
130 ) -> Option<(Ty, Function)> {
131 // FIXME: what has priority, an inherent method that needs autoderefs or a trait method?
132 let inherent_method = self.clone().iterate_methods(db, |ty, f| {
130 let sig = f.signature(db); 133 let sig = f.signature(db);
131 if sig.name() == name && sig.has_self_param() { 134 if sig.name() == name && sig.has_self_param() {
132 Some((ty.clone(), f)) 135 Some((ty.clone(), f))
133 } else { 136 } else {
134 None 137 None
135 } 138 }
136 }) 139 });
140 inherent_method.or_else(|| self.lookup_trait_method(db, name, resolver))
141 }
142
143 fn lookup_trait_method(
144 self,
145 db: &impl HirDatabase,
146 name: &Name,
147 resolver: &Resolver,
148 ) -> Option<(Ty, Function)> {
149 let mut candidates = Vec::new();
150 for t in resolver.traits_in_scope() {
151 let data = t.trait_data(db);
152 for item in data.items() {
153 match item {
154 &TraitItem::Function(m) => {
155 let sig = m.signature(db);
156 if sig.name() == name && sig.has_self_param() {
157 candidates.push((t, m));
158 }
159 }
160 _ => {}
161 }
162 }
163 }
164 // FIXME the implements check may result in other obligations or unifying variables?
165 candidates.retain(|(_t, _m)| /* self implements t */ true);
166 // FIXME what happens if there are still multiple potential candidates?
167 let (_chosen_trait, chosen_method) = candidates.first()?;
168 Some((self.clone(), *chosen_method))
137 } 169 }
138 170
139 // This would be nicer if it just returned an iterator, but that runs into 171 // This would be nicer if it just returned an iterator, but that runs into
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 3aedba243..971043266 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1272,8 +1272,8 @@ fn test() {
1272[241; 252) 'Struct::FOO': u32 1272[241; 252) 'Struct::FOO': u32
1273[262; 263) 'y': u32 1273[262; 263) 'y': u32
1274[266; 275) 'Enum::BAR': u32 1274[266; 275) 'Enum::BAR': u32
1275[285; 286) 'z': u32 1275[285; 286) 'z': {unknown}
1276[289; 302) 'TraitTest::ID': u32"### 1276[289; 302) 'TraitTest::ID': {unknown}"###
1277 ); 1277 );
1278} 1278}
1279 1279
@@ -1918,9 +1918,9 @@ fn test() {
1918[110; 114) 'self': &{unknown} 1918[110; 114) 'self': &{unknown}
1919[170; 228) '{ ...i128 }': () 1919[170; 228) '{ ...i128 }': ()
1920[176; 178) 'S1': S1 1920[176; 178) 'S1': S1
1921[176; 187) 'S1.method()': {unknown} 1921[176; 187) 'S1.method()': u32
1922[203; 205) 'S2': S2 1922[203; 205) 'S2': S2
1923[203; 214) 'S2.method()': {unknown}"### 1923[203; 214) 'S2.method()': u32"###
1924 ); 1924 );
1925} 1925}
1926 1926
@@ -1964,10 +1964,10 @@ mod bar_test {
1964[169; 173) 'self': &{unknown} 1964[169; 173) 'self': &{unknown}
1965[300; 337) '{ ... }': () 1965[300; 337) '{ ... }': ()
1966[310; 311) 'S': S 1966[310; 311) 'S': S
1967[310; 320) 'S.method()': {unknown} 1967[310; 320) 'S.method()': u32
1968[416; 454) '{ ... }': () 1968[416; 454) '{ ... }': ()
1969[426; 427) 'S': S 1969[426; 427) 'S': S
1970[426; 436) 'S.method()': {unknown}"### 1970[426; 436) 'S.method()': i128"###
1971 ); 1971 );
1972} 1972}
1973 1973