@@ -241,7 +241,7 @@ impl LookupContext {
241
241
loop {
242
242
match get ( self_ty) . sty {
243
243
ty_param( p) => {
244
- self . push_inherent_candidates_from_param ( p) ;
244
+ self . push_inherent_candidates_from_param ( self_ty , p) ;
245
245
}
246
246
ty_trait( did, ref substs, vstore) => {
247
247
self . push_inherent_candidates_from_trait (
@@ -305,16 +305,18 @@ impl LookupContext {
305
305
}
306
306
}
307
307
308
- fn push_inherent_candidates_from_param ( & self , param_ty : param_ty ) {
308
+ fn push_inherent_candidates_from_param ( & self , rcvr_ty : ty:: t ,
309
+ param_ty : param_ty ) {
309
310
debug ! ( "push_inherent_candidates_from_param(param_ty=%?)" ,
310
311
param_ty) ;
311
312
let _indenter = indenter ( ) ;
312
313
313
314
let tcx = self . tcx ( ) ;
314
315
let mut next_bound_idx = 0 ; // count only trait bounds
315
316
let bounds = tcx. ty_param_bounds . get ( param_ty. def_id . node ) ;
317
+
316
318
for vec:: each( * bounds) |bound| {
317
- let bound_t = match * bound {
319
+ let bound_trait_ty = match * bound {
318
320
ty:: bound_trait( bound_t) => bound_t,
319
321
320
322
ty:: bound_copy | ty:: bound_send |
@@ -323,56 +325,64 @@ impl LookupContext {
323
325
}
324
326
} ;
325
327
326
- let this_bound_idx = next_bound_idx;
327
- next_bound_idx += 1 ;
328
328
329
- let ( trait_id , bound_substs) = match ty:: get ( bound_t ) . sty {
330
- ty:: ty_trait( i , substs, _) => ( i , substs) ,
329
+ let bound_substs = match ty:: get ( bound_trait_ty ) . sty {
330
+ ty:: ty_trait( _ , substs, _) => substs,
331
331
_ => {
332
332
self . bug ( fmt ! ( "add_candidates_from_param: \
333
333
non-trait bound %s",
334
- self . ty_to_str( bound_t ) ) ) ;
334
+ self . ty_to_str( bound_trait_ty ) ) ) ;
335
335
}
336
336
} ;
337
337
338
+
338
339
// Loop over the trait and all of its supertraits.
339
- let worklist = dvec:: DVec ( ) ;
340
- worklist. push ( ( trait_id, move bound_substs) ) ;
340
+ let mut worklist = ~[ ] ;
341
+
342
+ let init_trait_ty = bound_trait_ty;
343
+ let init_substs = bound_substs;
344
+
345
+ // Replace any appearance of `self` with the type of the
346
+ // generic parameter itself. Note that this is the only
347
+ // case where this replacement is necessary: in all other
348
+ // cases, we are either invoking a method directly from an
349
+ // impl or class (where the self type is not permitted),
350
+ // or from a trait type (in which case methods that refer
351
+ // to self are not permitted).
352
+ let init_substs = { self_ty : Some ( rcvr_ty) , ..init_substs} ;
353
+
354
+ worklist. push ( ( init_trait_ty, init_substs) ) ;
341
355
342
356
let mut i = 0 ;
343
357
while i < worklist. len ( ) {
344
- let ( trait_id , bound_substs ) = worklist[ i] ;
358
+ let ( init_trait_ty , init_substs ) = worklist[ i] ;
345
359
i += 1 ;
346
360
347
- // Replace any appearance of `self` with the type of the
348
- // generic parameter itself. Note that this is the only
349
- // case where this replacement is necessary: in all other
350
- // cases, we are either invoking a method directly from an
351
- // impl or class (where the self type is not permitted),
352
- // or from a trait type (in which case methods that refer
353
- // to self are not permitted).
354
- let rcvr_ty = ty:: mk_param ( tcx, param_ty. idx ,
355
- param_ty. def_id ) ;
356
- let rcvr_substs = { self_ty : Some ( rcvr_ty) , ..bound_substs} ;
361
+ let init_trait_id = ty:: ty_to_def_id ( init_trait_ty) . get ( ) ;
357
362
358
363
// Add all the supertraits of this trait to the worklist.
359
- debug ! ( "finding supertraits for %d:%d" , trait_id. crate ,
360
- trait_id. node) ;
361
- let instantiated_trait_refs = ty:: trait_supertraits (
362
- tcx, trait_id) ;
363
- for instantiated_trait_refs. each |instantiated_trait_ref| {
364
- debug ! ( "adding supertrait" ) ;
364
+ let supertraits = ty:: trait_supertraits ( tcx,
365
+ init_trait_id) ;
366
+ for supertraits. each |supertrait| {
367
+ debug ! ( "adding supertrait: %?" ,
368
+ supertrait. def_id) ;
365
369
366
370
let new_substs = ty:: subst_substs (
367
371
tcx,
368
- & instantiated_trait_ref. tpt . substs ,
369
- & rcvr_substs) ;
372
+ & supertrait. tpt . substs ,
373
+ & init_substs) ;
374
+
375
+ // Again replacing the self type
376
+ let new_substs = { self_ty : Some ( rcvr_ty) , ..new_substs} ;
370
377
371
- worklist. push (
372
- ( instantiated_trait_ref. def_id , new_substs) ) ;
378
+ worklist. push ( ( supertrait. tpt . ty , new_substs) ) ;
373
379
}
374
380
375
- let trait_methods = ty:: trait_methods ( tcx, trait_id) ;
381
+
382
+ let this_bound_idx = next_bound_idx;
383
+ next_bound_idx += 1 ;
384
+
385
+ let trait_methods = ty:: trait_methods ( tcx, init_trait_id) ;
376
386
let pos = {
377
387
// FIXME #3453 can't use trait_methods.position
378
388
match vec:: position ( * trait_methods,
@@ -381,6 +391,8 @@ impl LookupContext {
381
391
{
382
392
Some ( pos) => pos,
383
393
None => {
394
+ debug ! ( "trait doesn't contain method: %?" ,
395
+ init_trait_id) ;
384
396
loop ; // check next trait or bound
385
397
}
386
398
}
@@ -389,18 +401,21 @@ impl LookupContext {
389
401
390
402
let ( rcvr_ty, rcvr_substs) =
391
403
self . create_rcvr_ty_and_substs_for_method (
392
- method. self_ty , rcvr_ty, move rcvr_substs ) ;
404
+ method. self_ty , rcvr_ty, move init_substs ) ;
393
405
394
- self . inherent_candidates . push ( Candidate {
406
+ let cand = Candidate {
395
407
rcvr_ty : rcvr_ty,
396
408
rcvr_substs : rcvr_substs,
397
409
num_method_tps : method. tps . len ( ) ,
398
410
self_mode : get_mode_from_self_type ( method. self_ty ) ,
399
- origin : method_param( { trait_id: trait_id ,
411
+ origin : method_param( { trait_id: init_trait_id ,
400
412
method_num : pos,
401
413
param_num : param_ty. idx ,
402
414
bound_num : this_bound_idx} )
403
- } ) ;
415
+ } ;
416
+
417
+ debug ! ( "pushing inherent candidate for param: %?" , cand) ;
418
+ self . inherent_candidates . push ( cand) ;
404
419
}
405
420
}
406
421
}
@@ -775,6 +790,8 @@ impl LookupContext {
775
790
let relevant_candidates =
776
791
candidates. filter_to_vec ( |c| self . is_relevant ( self_ty, & c) ) ;
777
792
793
+ let relevant_candidates = self . merge_candidates ( relevant_candidates) ;
794
+
778
795
if relevant_candidates. len ( ) == 0 {
779
796
return None ;
780
797
}
@@ -791,6 +808,52 @@ impl LookupContext {
791
808
Some ( self . confirm_candidate ( self_ty, & relevant_candidates[ 0 ] ) )
792
809
}
793
810
811
+ fn merge_candidates ( & self , candidates : & [ Candidate ] ) -> ~[ Candidate ] {
812
+ let mut merged = ~[ ] ;
813
+ let mut i = 0 ;
814
+ while i < candidates. len ( ) {
815
+ let candidate_a = candidates[ i] ;
816
+
817
+ let mut skip = false ;
818
+
819
+ let mut j = i + 1 ;
820
+ while j < candidates. len ( ) {
821
+ let candidate_b = candidates[ j] ;
822
+ debug ! ( "attempting to merge %? and %?" ,
823
+ candidate_a, candidate_b) ;
824
+ let candidates_same = match ( & candidate_a. origin ,
825
+ & candidate_b. origin ) {
826
+ ( & method_param( p1) , & method_param( p2) ) => {
827
+ let same_trait = p1. trait_id == p2. trait_id ;
828
+ let same_method = p1. method_num == p2. method_num ;
829
+ let same_param = p1. param_num == p2. param_num ;
830
+ // The bound number may be different because
831
+ // multiple bounds may lead to the same trait
832
+ // impl
833
+ same_trait && same_method && same_param
834
+ }
835
+ _ => false
836
+ } ;
837
+ if candidates_same {
838
+ skip = true ;
839
+ break ;
840
+ }
841
+ j += 1 ;
842
+ }
843
+
844
+ i += 1 ;
845
+
846
+ if skip {
847
+ // There are more than one of these and we need only one
848
+ loop ;
849
+ } else {
850
+ merged. push ( candidate_a) ;
851
+ }
852
+ }
853
+
854
+ return merged;
855
+ }
856
+
794
857
fn confirm_candidate( & self ,
795
858
self_ty : ty:: t ,
796
859
candidate : & Candidate )
0 commit comments