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