diff options
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 103 |
1 files changed, 70 insertions, 33 deletions
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 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use hir_def::{ | 8 | use 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 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use ra_db::CrateId; | 13 | use ra_db::CrateId; |
14 | use ra_prof::profile; | 14 | use ra_prof::profile; |
15 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
16 | 16 | ||
17 | use super::Substs; | 17 | use super::Substs; |
18 | use crate::{ | 18 | use crate::{ |
@@ -144,14 +144,24 @@ impl Ty { | |||
144 | pub(crate) fn lookup_method( | 144 | pub(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 { | |||
172 | pub fn iterate_method_candidates<T>( | 182 | pub 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>( | |||
228 | fn iterate_method_candidates_with_autoref<T>( | 248 | fn 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>( | |||
310 | fn iterate_method_candidates_for_self_ty<T>( | 341 | fn 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>( | |||
329 | fn iterate_trait_method_candidates<T>( | 368 | fn 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 | ||