diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 12 |
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 | ||
122 | impl Ty { | 122 | impl 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 | ||