@@ -135,6 +135,7 @@ pub(crate) struct Candidate<'tcx> {
135
135
pub ( crate ) item : ty:: AssocItem ,
136
136
pub ( crate ) kind : CandidateKind < ' tcx > ,
137
137
pub ( crate ) import_ids : SmallVec < [ LocalDefId ; 1 ] > ,
138
+ depth : usize ,
138
139
}
139
140
140
141
#[ derive( Debug , Clone ) ]
@@ -670,11 +671,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
670
671
671
672
fn assemble_inherent_candidates ( & mut self ) {
672
673
for step in self . steps . iter ( ) {
673
- self . assemble_probe ( & step. self_ty ) ;
674
+ self . assemble_probe ( & step. self_ty , step . autoderefs ) ;
674
675
}
675
676
}
676
677
677
- fn assemble_probe ( & mut self , self_ty : & Canonical < ' tcx , QueryResponse < ' tcx , Ty < ' tcx > > > ) {
678
+ fn assemble_probe (
679
+ & mut self ,
680
+ self_ty : & Canonical < ' tcx , QueryResponse < ' tcx , Ty < ' tcx > > > ,
681
+ depth : usize ,
682
+ ) {
678
683
debug ! ( "assemble_probe: self_ty={:?}" , self_ty) ;
679
684
let raw_self_ty = self_ty. value . value ;
680
685
match * raw_self_ty. kind ( ) {
@@ -699,27 +704,27 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
699
704
let ( QueryResponse { value : generalized_self_ty, .. } , _ignored_var_values) =
700
705
self . fcx . instantiate_canonical_with_fresh_inference_vars ( self . span , self_ty) ;
701
706
702
- self . assemble_inherent_candidates_from_object ( generalized_self_ty) ;
703
- self . assemble_inherent_impl_candidates_for_type ( p. def_id ( ) ) ;
707
+ self . assemble_inherent_candidates_from_object ( generalized_self_ty, depth ) ;
708
+ self . assemble_inherent_impl_candidates_for_type ( p. def_id ( ) , depth ) ;
704
709
if self . tcx . has_attr ( p. def_id ( ) , sym:: rustc_has_incoherent_inherent_impls) {
705
- self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty) ;
710
+ self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty, depth ) ;
706
711
}
707
712
}
708
713
ty:: Adt ( def, _) => {
709
714
let def_id = def. did ( ) ;
710
- self . assemble_inherent_impl_candidates_for_type ( def_id) ;
715
+ self . assemble_inherent_impl_candidates_for_type ( def_id, depth ) ;
711
716
if self . tcx . has_attr ( def_id, sym:: rustc_has_incoherent_inherent_impls) {
712
- self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty) ;
717
+ self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty, depth ) ;
713
718
}
714
719
}
715
720
ty:: Foreign ( did) => {
716
- self . assemble_inherent_impl_candidates_for_type ( did) ;
721
+ self . assemble_inherent_impl_candidates_for_type ( did, depth ) ;
717
722
if self . tcx . has_attr ( did, sym:: rustc_has_incoherent_inherent_impls) {
718
- self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty) ;
723
+ self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty, depth ) ;
719
724
}
720
725
}
721
726
ty:: Param ( p) => {
722
- self . assemble_inherent_candidates_from_param ( p) ;
727
+ self . assemble_inherent_candidates_from_param ( p, depth ) ;
723
728
}
724
729
ty:: Bool
725
730
| ty:: Char
@@ -732,28 +737,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
732
737
| ty:: RawPtr ( _)
733
738
| ty:: Ref ( ..)
734
739
| ty:: Never
735
- | ty:: Tuple ( ..) => self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty) ,
740
+ | ty:: Tuple ( ..) => self . assemble_inherent_candidates_for_incoherent_ty ( raw_self_ty, depth ) ,
736
741
_ => { }
737
742
}
738
743
}
739
744
740
- fn assemble_inherent_candidates_for_incoherent_ty ( & mut self , self_ty : Ty < ' tcx > ) {
745
+ fn assemble_inherent_candidates_for_incoherent_ty ( & mut self , self_ty : Ty < ' tcx > , depth : usize ) {
741
746
let Some ( simp) = simplify_type ( self . tcx , self_ty, TreatParams :: AsCandidateKey ) else {
742
747
bug ! ( "unexpected incoherent type: {:?}" , self_ty)
743
748
} ;
744
749
for & impl_def_id in self . tcx . incoherent_impls ( simp) {
745
- self . assemble_inherent_impl_probe ( impl_def_id) ;
750
+ self . assemble_inherent_impl_probe ( impl_def_id, depth ) ;
746
751
}
747
752
}
748
753
749
- fn assemble_inherent_impl_candidates_for_type ( & mut self , def_id : DefId ) {
754
+ fn assemble_inherent_impl_candidates_for_type ( & mut self , def_id : DefId , depth : usize ) {
750
755
let impl_def_ids = self . tcx . at ( self . span ) . inherent_impls ( def_id) ;
751
756
for & impl_def_id in impl_def_ids. iter ( ) {
752
- self . assemble_inherent_impl_probe ( impl_def_id) ;
757
+ self . assemble_inherent_impl_probe ( impl_def_id, depth ) ;
753
758
}
754
759
}
755
760
756
- fn assemble_inherent_impl_probe ( & mut self , impl_def_id : DefId ) {
761
+ fn assemble_inherent_impl_probe ( & mut self , impl_def_id : DefId , depth : usize ) {
757
762
if !self . impl_dups . insert ( impl_def_id) {
758
763
return ; // already visited
759
764
}
@@ -801,13 +806,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
801
806
item,
802
807
kind : InherentImplCandidate ( impl_args, obligations) ,
803
808
import_ids : smallvec ! [ ] ,
809
+ depth,
804
810
} ,
805
811
true ,
806
812
) ;
807
813
}
808
814
}
809
815
810
- fn assemble_inherent_candidates_from_object ( & mut self , self_ty : Ty < ' tcx > ) {
816
+ fn assemble_inherent_candidates_from_object ( & mut self , self_ty : Ty < ' tcx > , depth : usize ) {
811
817
debug ! ( "assemble_inherent_candidates_from_object(self_ty={:?})" , self_ty) ;
812
818
813
819
let principal = match self_ty. kind ( ) {
@@ -850,13 +856,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
850
856
item,
851
857
kind : ObjectCandidate ,
852
858
import_ids : smallvec ! [ ] ,
859
+ depth,
853
860
} ,
854
861
true ,
855
862
) ;
856
863
} ) ;
857
864
}
858
865
859
- fn assemble_inherent_candidates_from_param ( & mut self , param_ty : ty:: ParamTy ) {
866
+ fn assemble_inherent_candidates_from_param ( & mut self , param_ty : ty:: ParamTy , depth : usize ) {
860
867
// FIXME: do we want to commit to this behavior for param bounds?
861
868
debug ! ( "assemble_inherent_candidates_from_param(param_ty={:?})" , param_ty) ;
862
869
@@ -897,6 +904,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
897
904
item,
898
905
kind : WhereClauseCandidate ( poly_trait_ref) ,
899
906
import_ids : smallvec ! [ ] ,
907
+ depth,
900
908
} ,
901
909
true ,
902
910
) ;
@@ -1014,6 +1022,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1014
1022
item,
1015
1023
import_ids : import_ids. clone ( ) ,
1016
1024
kind : TraitCandidate ( new_trait_ref) ,
1025
+ depth : 0usize ,
1017
1026
} ,
1018
1027
false ,
1019
1028
) ;
@@ -1042,6 +1051,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1042
1051
item,
1043
1052
import_ids : import_ids. clone ( ) ,
1044
1053
kind : TraitCandidate ( trait_ref) ,
1054
+ depth : 0usize ,
1045
1055
} ,
1046
1056
false ,
1047
1057
) ;
@@ -1361,6 +1371,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1361
1371
} ) ;
1362
1372
}
1363
1373
1374
+ // We want to avoid compatibility breaks if we have SmartPtr<Concrete>,
1375
+ // the user is calling smart_ptr.wardrobe() expecting to call
1376
+ // Concrete::wardrobe(), but then SmartPtr adds a wardrobe() method.
1377
+ // So if there are multiple applicable candidates, and a single one
1378
+ // of them involved more deref/receiver chain hops than all the others,
1379
+ // we pick that one: but show a warning.
1380
+ if applicable_candidates. len ( ) > 1 {
1381
+ let greatest_depth =
1382
+ applicable_candidates. iter ( ) . map ( |( candidate, _) | candidate. depth ) . max ( ) . unwrap ( ) ;
1383
+ let number_of_candidates_with_greatest_depth = applicable_candidates
1384
+ . iter ( )
1385
+ . filter ( |( candidate, _) | candidate. depth == greatest_depth)
1386
+ . count ( ) ;
1387
+ if number_of_candidates_with_greatest_depth == 1 {
1388
+ // FIXME: emit warning here, unless this is something we should
1389
+ // have done earlier e.g. in wfcheck.rs
1390
+ info ! ( "Multiple candidates detected, picking the innermost" ) ;
1391
+ // Emit a warning, and retain a single candidate
1392
+ applicable_candidates. retain ( |( candidate, _) | candidate. depth == greatest_depth) ;
1393
+ }
1394
+ }
1395
+
1364
1396
if applicable_candidates. len ( ) > 1 {
1365
1397
let sources = candidates. iter ( ) . map ( |p| self . candidate_source ( p, self_ty) ) . collect ( ) ;
1366
1398
return Some ( Err ( MethodError :: Ambiguity ( sources) ) ) ;
0 commit comments