@@ -191,13 +191,13 @@ pub fn iterate_method_candidates<T>(
191
191
let ty = InEnvironment { value : ty. clone ( ) , environment } ;
192
192
let krate = resolver. krate ( ) ?;
193
193
194
- // We have to be careful about the order of operations here.
195
- // Consider the case where we're resolving `x.clone()` where `x:
196
- // &Vec<_>`. This resolves to the clone method with self type
197
- // `Vec<_>`, *not* `&_`. I.e. we need to consider methods where the
198
- // receiver type exactly matches before cases where we have to do
199
- // autoref. But in the autoderef steps, the `&_` self type comes up
200
- // *before* the `Vec<_>` self type.
194
+ // 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()`
196
+ // where `x: &Vec<_>`. This resolves to the clone method with self
197
+ // type `Vec<_>`, *not* `&_`. I.e. we need to consider methods where
198
+ // the receiver type exactly matches before cases where we have to
199
+ // do autoref. But in the autoderef steps, the `&_` self type comes
200
+ // up *before* the `Vec<_>` self type.
201
201
//
202
202
// On the other hand, we don't want to just pick any by-value method
203
203
// before any by-autoref method; it's just that we need to consider
@@ -206,7 +206,7 @@ pub fn iterate_method_candidates<T>(
206
206
207
207
let deref_chain: Vec < _ > = autoderef:: autoderef ( db, Some ( krate) , ty. clone ( ) ) . collect ( ) ;
208
208
for i in 0 ..deref_chain. len ( ) {
209
- if let Some ( result) = iterate_method_candidates_autoref (
209
+ if let Some ( result) = iterate_method_candidates_with_autoref (
210
210
& deref_chain[ i..] ,
211
211
db,
212
212
resolver,
@@ -220,12 +220,12 @@ pub fn iterate_method_candidates<T>(
220
220
}
221
221
LookupMode :: Path => {
222
222
// No autoderef for path lookups
223
- iterate_method_candidates_inner ( & ty, db, resolver, name, None , & mut callback)
223
+ iterate_method_candidates_for_self_ty ( & ty, db, resolver, name, & mut callback)
224
224
}
225
225
}
226
226
}
227
227
228
- fn iterate_method_candidates_autoref < T > (
228
+ fn iterate_method_candidates_with_autoref < T > (
229
229
deref_chain : & [ Canonical < Ty > ] ,
230
230
db : & impl HirDatabase ,
231
231
resolver : & Resolver ,
@@ -275,18 +275,25 @@ fn iterate_method_candidates_autoref<T>(
275
275
276
276
fn iterate_method_candidates_by_receiver < T > (
277
277
receiver_ty : & Canonical < Ty > ,
278
- deref_chain : & [ Canonical < Ty > ] ,
278
+ rest_of_deref_chain : & [ Canonical < Ty > ] ,
279
279
db : & impl HirDatabase ,
280
280
resolver : & Resolver ,
281
281
name : Option < & Name > ,
282
282
mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
283
283
) -> Option < T > {
284
- // TODO: do we need to do the whole loop for inherents before traits?
285
284
// We're looking for methods with *receiver* type receiver_ty. These could
286
285
// be found in any of the derefs of receiver_ty, so we have to go through
287
286
// that.
288
- for self_ty in std:: iter:: once ( receiver_ty) . chain ( deref_chain) {
289
- if let Some ( result) = iterate_method_candidates_inner (
287
+ let krate = resolver. krate ( ) ?;
288
+ for self_ty in std:: iter:: once ( receiver_ty) . chain ( rest_of_deref_chain) {
289
+ if let Some ( result) =
290
+ iterate_inherent_methods ( self_ty, db, name, Some ( receiver_ty) , krate, & mut callback)
291
+ {
292
+ return Some ( result) ;
293
+ }
294
+ }
295
+ for self_ty in std:: iter:: once ( receiver_ty) . chain ( rest_of_deref_chain) {
296
+ if let Some ( result) = iterate_trait_method_candidates (
290
297
self_ty,
291
298
db,
292
299
resolver,
@@ -300,22 +307,19 @@ fn iterate_method_candidates_by_receiver<T>(
300
307
None
301
308
}
302
309
303
- fn iterate_method_candidates_inner < T > (
310
+ fn iterate_method_candidates_for_self_ty < T > (
304
311
self_ty : & Canonical < Ty > ,
305
312
db : & impl HirDatabase ,
306
313
resolver : & Resolver ,
307
314
name : Option < & Name > ,
308
- receiver_ty : Option < & Canonical < Ty > > ,
309
315
mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
310
316
) -> Option < T > {
311
317
let krate = resolver. krate ( ) ?;
312
- if let Some ( result) =
313
- iterate_inherent_methods ( self_ty, db, name, receiver_ty, krate, & mut callback)
314
- {
318
+ if let Some ( result) = iterate_inherent_methods ( self_ty, db, name, None , krate, & mut callback) {
315
319
return Some ( result) ;
316
320
}
317
321
if let Some ( result) =
318
- iterate_trait_method_candidates ( self_ty, db, resolver, name, receiver_ty , & mut callback)
322
+ iterate_trait_method_candidates ( self_ty, db, resolver, name, None , & mut callback)
319
323
{
320
324
return Some ( result) ;
321
325
}
@@ -412,29 +416,11 @@ fn is_valid_candidate(
412
416
if !data. has_self_param {
413
417
return false ;
414
418
}
415
- let substs = match m. lookup ( db) . container {
416
- hir_def:: ContainerId :: TraitId ( _) => Substs :: build_for_def ( db, item)
417
- . push ( self_ty. value . clone ( ) )
418
- . fill_with_unknown ( )
419
- . build ( ) ,
420
- hir_def:: ContainerId :: ImplId ( impl_id) => {
421
- let vars =
422
- Substs :: build_for_def ( db, impl_id) . fill_with_bound_vars ( 0 ) . build ( ) ;
423
- let self_ty_with_vars = db. impl_self_ty ( impl_id) . subst ( & vars) ;
424
- let self_ty_with_vars =
425
- Canonical { num_vars : vars. len ( ) , value : & self_ty_with_vars } ;
426
- if let Some ( substs) = super :: infer:: unify ( self_ty_with_vars, & self_ty. value )
427
- {
428
- substs
429
- } else {
430
- return false ;
431
- }
432
- }
433
- hir_def:: ContainerId :: ModuleId ( _) => unreachable ! ( ) ,
419
+ let transformed_receiver_ty = match transform_receiver_ty ( db, m, self_ty) {
420
+ Some ( ty) => ty,
421
+ None => return false ,
434
422
} ;
435
- let sig = db. callable_item_signature ( m. into ( ) ) ;
436
- let receiver = sig. params ( ) [ 0 ] . clone ( ) . subst ( & substs) ;
437
- if receiver != receiver_ty. value {
423
+ if transformed_receiver_ty != receiver_ty. value {
438
424
return false ;
439
425
}
440
426
}
@@ -448,6 +434,34 @@ fn is_valid_candidate(
448
434
}
449
435
}
450
436
437
+ pub ( crate ) fn inherent_impl_substs (
438
+ db : & impl HirDatabase ,
439
+ impl_id : ImplId ,
440
+ self_ty : & Ty ,
441
+ ) -> Option < Substs > {
442
+ let vars = Substs :: build_for_def ( db, impl_id) . fill_with_bound_vars ( 0 ) . build ( ) ;
443
+ let self_ty_with_vars = db. impl_self_ty ( impl_id) . subst ( & vars) ;
444
+ let self_ty_with_vars = Canonical { num_vars : vars. len ( ) , value : & self_ty_with_vars } ;
445
+ super :: infer:: unify ( self_ty_with_vars, self_ty)
446
+ }
447
+
448
+ fn transform_receiver_ty (
449
+ db : & impl HirDatabase ,
450
+ function_id : FunctionId ,
451
+ self_ty : & Canonical < Ty > ,
452
+ ) -> Option < Ty > {
453
+ let substs = match function_id. lookup ( db) . container {
454
+ hir_def:: ContainerId :: TraitId ( _) => Substs :: build_for_def ( db, function_id)
455
+ . push ( self_ty. value . clone ( ) )
456
+ . fill_with_unknown ( )
457
+ . build ( ) ,
458
+ hir_def:: ContainerId :: ImplId ( impl_id) => inherent_impl_substs ( db, impl_id, & self_ty. value ) ?,
459
+ hir_def:: ContainerId :: ModuleId ( _) => unreachable ! ( ) ,
460
+ } ;
461
+ let sig = db. callable_item_signature ( function_id. into ( ) ) ;
462
+ Some ( sig. params ( ) [ 0 ] . clone ( ) . subst ( & substs) )
463
+ }
464
+
451
465
pub fn implements_trait (
452
466
ty : & Canonical < Ty > ,
453
467
db : & impl HirDatabase ,
0 commit comments