@@ -7,19 +7,20 @@ use std::sync::Arc;
7
7
use arrayvec:: ArrayVec ;
8
8
use hir_def:: {
9
9
lang_item:: LangItemTarget , resolver:: Resolver , type_ref:: Mutability , AssocItemId , AstItemDef ,
10
- FunctionId , HasModule , ImplId , TraitId ,
10
+ FunctionId , HasModule , ImplId , Lookup , TraitId ,
11
11
} ;
12
12
use hir_expand:: name:: Name ;
13
13
use ra_db:: CrateId ;
14
14
use ra_prof:: profile;
15
15
use rustc_hash:: FxHashMap ;
16
16
17
+ use super :: Substs ;
17
18
use crate :: {
18
19
autoderef,
19
20
db:: HirDatabase ,
20
21
primitive:: { FloatBitness , Uncertain } ,
21
22
utils:: all_super_traits,
22
- Canonical , InEnvironment , TraitEnvironment , TraitRef , Ty , TypeCtor ,
23
+ Canonical , InEnvironment , TraitEnvironment , TraitRef , Ty , TypeCtor , TypeWalk ,
23
24
} ;
24
25
25
26
/// This is used as a key for indexing impls.
@@ -231,21 +232,42 @@ fn iterate_method_candidates_autoref<T>(
231
232
name : Option < & Name > ,
232
233
mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
233
234
) -> Option < T > {
234
- if let Some ( result) = iterate_method_candidates_by_receiver ( & deref_chain[ 0 ] , & deref_chain[ 1 ..] , db, resolver, name, & mut callback) {
235
+ if let Some ( result) = iterate_method_candidates_by_receiver (
236
+ & deref_chain[ 0 ] ,
237
+ & deref_chain[ 1 ..] ,
238
+ db,
239
+ resolver,
240
+ name,
241
+ & mut callback,
242
+ ) {
235
243
return Some ( result) ;
236
244
}
237
245
let refed = Canonical {
238
246
num_vars : deref_chain[ 0 ] . num_vars ,
239
247
value : Ty :: apply_one ( TypeCtor :: Ref ( Mutability :: Shared ) , deref_chain[ 0 ] . value . clone ( ) ) ,
240
248
} ;
241
- if let Some ( result) = iterate_method_candidates_by_receiver ( & refed, deref_chain, db, resolver, name, & mut callback) {
249
+ if let Some ( result) = iterate_method_candidates_by_receiver (
250
+ & refed,
251
+ deref_chain,
252
+ db,
253
+ resolver,
254
+ name,
255
+ & mut callback,
256
+ ) {
242
257
return Some ( result) ;
243
258
}
244
259
let ref_muted = Canonical {
245
260
num_vars : deref_chain[ 0 ] . num_vars ,
246
261
value : Ty :: apply_one ( TypeCtor :: Ref ( Mutability :: Mut ) , deref_chain[ 0 ] . value . clone ( ) ) ,
247
262
} ;
248
- if let Some ( result) = iterate_method_candidates_by_receiver ( & ref_muted, deref_chain, db, resolver, name, & mut callback) {
263
+ if let Some ( result) = iterate_method_candidates_by_receiver (
264
+ & ref_muted,
265
+ deref_chain,
266
+ db,
267
+ resolver,
268
+ name,
269
+ & mut callback,
270
+ ) {
249
271
return Some ( result) ;
250
272
}
251
273
None
@@ -264,7 +286,14 @@ fn iterate_method_candidates_by_receiver<T>(
264
286
// be found in any of the derefs of receiver_ty, so we have to go through
265
287
// that.
266
288
for self_ty in std:: iter:: once ( receiver_ty) . chain ( deref_chain) {
267
- if let Some ( result) = iterate_method_candidates_inner ( self_ty, db, resolver, name, Some ( receiver_ty) , & mut callback) {
289
+ if let Some ( result) = iterate_method_candidates_inner (
290
+ self_ty,
291
+ db,
292
+ resolver,
293
+ name,
294
+ Some ( receiver_ty) ,
295
+ & mut callback,
296
+ ) {
268
297
return Some ( result) ;
269
298
}
270
299
}
@@ -280,7 +309,9 @@ fn iterate_method_candidates_inner<T>(
280
309
mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > ,
281
310
) -> Option < T > {
282
311
let krate = resolver. krate ( ) ?;
283
- if let Some ( result) = iterate_inherent_methods ( self_ty, db, name, receiver_ty, krate, & mut callback) {
312
+ if let Some ( result) =
313
+ iterate_inherent_methods ( self_ty, db, name, receiver_ty, krate, & mut callback)
314
+ {
284
315
return Some ( result) ;
285
316
}
286
317
if let Some ( result) =
@@ -381,7 +412,31 @@ fn is_valid_candidate(
381
412
if !data. has_self_param {
382
413
return false ;
383
414
}
384
- // TODO compare receiver ty
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 ! ( ) ,
434
+ } ;
435
+ let sig = db. callable_item_signature ( m. into ( ) ) ;
436
+ let receiver = sig. params ( ) [ 0 ] . clone ( ) . subst ( & substs) ;
437
+ if receiver != receiver_ty. value {
438
+ return false ;
439
+ }
385
440
}
386
441
true
387
442
}
0 commit comments