@@ -92,7 +92,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
9292 }
9393}
9494
95- #[ derive( Debug ) ]
95+ #[ derive( Debug , Clone ) ]
9696struct Candidate < ' tcx > {
9797 // Candidates are (I'm not quite sure, but they are mostly) basically
9898 // some metadata on top of a `ty::AssocItem` (without substs).
@@ -132,7 +132,7 @@ struct Candidate<'tcx> {
132132 import_ids : SmallVec < [ LocalDefId ; 1 ] > ,
133133}
134134
135- #[ derive( Debug ) ]
135+ #[ derive( Debug , Clone ) ]
136136enum CandidateKind < ' tcx > {
137137 InherentImplCandidate (
138138 SubstsRef < ' tcx > ,
@@ -204,6 +204,7 @@ pub struct Pick<'tcx> {
204204 /// Indicates that we want to add an autoref (and maybe also unsize it), or if the receiver is
205205 /// `*mut T`, convert it to `*const T`.
206206 pub autoref_or_ptr_adjustment : Option < AutorefOrPtrAdjustment < ' tcx > > ,
207+ pub self_ty : Ty < ' tcx > ,
207208}
208209
209210#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -1101,13 +1102,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11011102 }
11021103
11031104 fn pick_core ( & mut self ) -> Option < PickResult < ' tcx > > {
1104- let steps = self . steps . clone ( ) ;
1105+ let mut unstable_candidates = Vec :: new ( ) ;
1106+ let pick = self . pick_all_method ( Some ( & mut unstable_candidates) ) ;
1107+
1108+ // In this case unstable picking is done by `pick_method`.
1109+ if !self . tcx . sess . opts . debugging_opts . pick_stable_methods_before_any_unstable {
1110+ return pick;
1111+ }
11051112
1106- // find the first step that works
1113+ match pick {
1114+ // Emit a lint if there are unstable candidates alongside the stable ones.
1115+ //
1116+ // We suppress warning if we're picking the method only because it is a
1117+ // suggestion.
1118+ Some ( Ok ( ref p) ) if !self . is_suggestion . 0 && !unstable_candidates. is_empty ( ) => {
1119+ self . emit_unstable_name_collision_hint ( p, & unstable_candidates) ;
1120+ pick
1121+ }
1122+ Some ( _) => pick,
1123+ None => self . pick_all_method ( None ) ,
1124+ }
1125+ }
1126+
1127+ fn pick_all_method (
1128+ & mut self ,
1129+ mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1130+ ) -> Option < PickResult < ' tcx > > {
1131+ let steps = self . steps . clone ( ) ;
11071132 steps
11081133 . iter ( )
11091134 . filter ( |step| {
1110- debug ! ( "pick_core : step={:?}" , step) ;
1135+ debug ! ( "pick_all_method : step={:?}" , step) ;
11111136 // skip types that are from a type error or that would require dereferencing
11121137 // a raw pointer
11131138 !step. self_ty . references_error ( ) && !step. from_unsafe_deref
@@ -1123,11 +1148,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11231148 . unwrap_or_else ( |_| {
11241149 span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
11251150 } ) ;
1126- self . pick_by_value_method ( step, self_ty) . or_else ( || {
1127- self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Not )
1128- . or_else ( || self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Mut ) )
1129- . or_else ( || self . pick_const_ptr_method ( step, self_ty) )
1130- } )
1151+ self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1152+ . or_else ( || {
1153+ self . pick_autorefd_method (
1154+ step,
1155+ self_ty,
1156+ hir:: Mutability :: Not ,
1157+ unstable_candidates. as_deref_mut ( ) ,
1158+ )
1159+ . or_else ( || {
1160+ self . pick_autorefd_method (
1161+ step,
1162+ self_ty,
1163+ hir:: Mutability :: Mut ,
1164+ unstable_candidates. as_deref_mut ( ) ,
1165+ )
1166+ } )
1167+ . or_else ( || {
1168+ self . pick_const_ptr_method (
1169+ step,
1170+ self_ty,
1171+ unstable_candidates. as_deref_mut ( ) ,
1172+ )
1173+ } )
1174+ } )
11311175 } )
11321176 . next ( )
11331177 }
@@ -1142,12 +1186,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11421186 & mut self ,
11431187 step : & CandidateStep < ' tcx > ,
11441188 self_ty : Ty < ' tcx > ,
1189+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
11451190 ) -> Option < PickResult < ' tcx > > {
11461191 if step. unsize {
11471192 return None ;
11481193 }
11491194
1150- self . pick_method ( self_ty) . map ( |r| {
1195+ self . pick_method ( self_ty, unstable_candidates ) . map ( |r| {
11511196 r. map ( |mut pick| {
11521197 pick. autoderefs = step. autoderefs ;
11531198
@@ -1170,14 +1215,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11701215 step : & CandidateStep < ' tcx > ,
11711216 self_ty : Ty < ' tcx > ,
11721217 mutbl : hir:: Mutability ,
1218+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
11731219 ) -> Option < PickResult < ' tcx > > {
11741220 let tcx = self . tcx ;
11751221
11761222 // In general, during probing we erase regions.
11771223 let region = tcx. lifetimes . re_erased ;
11781224
11791225 let autoref_ty = tcx. mk_ref ( region, ty:: TypeAndMut { ty : self_ty, mutbl } ) ;
1180- self . pick_method ( autoref_ty) . map ( |r| {
1226+ self . pick_method ( autoref_ty, unstable_candidates ) . map ( |r| {
11811227 r. map ( |mut pick| {
11821228 pick. autoderefs = step. autoderefs ;
11831229 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
@@ -1196,6 +1242,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11961242 & mut self ,
11971243 step : & CandidateStep < ' tcx > ,
11981244 self_ty : Ty < ' tcx > ,
1245+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
11991246 ) -> Option < PickResult < ' tcx > > {
12001247 // Don't convert an unsized reference to ptr
12011248 if step. unsize {
@@ -1209,7 +1256,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12091256
12101257 let const_self_ty = ty:: TypeAndMut { ty, mutbl : hir:: Mutability :: Not } ;
12111258 let const_ptr_ty = self . tcx . mk_ptr ( const_self_ty) ;
1212- self . pick_method ( const_ptr_ty) . map ( |r| {
1259+ self . pick_method ( const_ptr_ty, unstable_candidates ) . map ( |r| {
12131260 r. map ( |mut pick| {
12141261 pick. autoderefs = step. autoderefs ;
12151262 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1218,8 +1265,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12181265 } )
12191266 }
12201267
1221- fn pick_method ( & mut self , self_ty : Ty < ' tcx > ) -> Option < PickResult < ' tcx > > {
1222- debug ! ( "pick_method (self_ty={})" , self . ty_to_string( self_ty) ) ;
1268+ fn pick_method_with_unstable ( & mut self , self_ty : Ty < ' tcx > ) -> Option < PickResult < ' tcx > > {
1269+ debug ! ( "pick_method_with_unstable (self_ty={})" , self . ty_to_string( self_ty) ) ;
12231270
12241271 let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
12251272 let mut unstable_candidates = Vec :: new ( ) ;
@@ -1241,7 +1288,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12411288 //
12421289 // We suppress warning if we're picking the method only because it is a
12431290 // suggestion.
1244- self . emit_unstable_name_collision_hint ( p, & unstable_candidates, self_ty ) ;
1291+ self . emit_unstable_name_collision_hint ( p, & unstable_candidates) ;
12451292 }
12461293 }
12471294 return Some ( pick) ;
@@ -1251,7 +1298,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12511298 debug ! ( "searching unstable candidates" ) ;
12521299 let res = self . consider_candidates (
12531300 self_ty,
1254- unstable_candidates. into_iter ( ) . map ( |( c, _) | c) ,
1301+ unstable_candidates. iter ( ) . map ( |( c, _) | c) ,
12551302 & mut possibly_unsatisfied_predicates,
12561303 None ,
12571304 ) ;
@@ -1261,6 +1308,42 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12611308 res
12621309 }
12631310
1311+ fn pick_method (
1312+ & mut self ,
1313+ self_ty : Ty < ' tcx > ,
1314+ mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1315+ ) -> Option < PickResult < ' tcx > > {
1316+ if !self . tcx . sess . opts . debugging_opts . pick_stable_methods_before_any_unstable {
1317+ return self . pick_method_with_unstable ( self_ty) ;
1318+ }
1319+
1320+ debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
1321+
1322+ let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
1323+
1324+ for ( kind, candidates) in
1325+ & [ ( "inherent" , & self . inherent_candidates ) , ( "extension" , & self . extension_candidates ) ]
1326+ {
1327+ debug ! ( "searching {} candidates" , kind) ;
1328+ let res = self . consider_candidates (
1329+ self_ty,
1330+ candidates. iter ( ) ,
1331+ & mut possibly_unsatisfied_predicates,
1332+ unstable_candidates. as_deref_mut ( ) ,
1333+ ) ;
1334+ if let Some ( pick) = res {
1335+ return Some ( pick) ;
1336+ }
1337+ }
1338+
1339+ // `pick_method` may be called twice for the same self_ty if no stable methods
1340+ // match. Only extend once.
1341+ if unstable_candidates. is_some ( ) {
1342+ self . unsatisfied_predicates . extend ( possibly_unsatisfied_predicates) ;
1343+ }
1344+ None
1345+ }
1346+
12641347 fn consider_candidates < ' b , ProbesIter > (
12651348 & self ,
12661349 self_ty : Ty < ' tcx > ,
@@ -1269,10 +1352,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12691352 ty:: Predicate < ' tcx > ,
12701353 Option < ty:: Predicate < ' tcx > > ,
12711354 ) > ,
1272- unstable_candidates : Option < & mut Vec < ( & ' b Candidate < ' tcx > , Symbol ) > > ,
1355+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
12731356 ) -> Option < PickResult < ' tcx > >
12741357 where
12751358 ProbesIter : Iterator < Item = & ' b Candidate < ' tcx > > + Clone ,
1359+ ' tcx : ' b ,
12761360 {
12771361 let mut applicable_candidates: Vec < _ > = probes
12781362 . clone ( )
@@ -1285,7 +1369,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12851369 debug ! ( "applicable_candidates: {:?}" , applicable_candidates) ;
12861370
12871371 if applicable_candidates. len ( ) > 1 {
1288- if let Some ( pick) = self . collapse_candidates_to_trait_pick ( & applicable_candidates[ ..] ) {
1372+ if let Some ( pick) =
1373+ self . collapse_candidates_to_trait_pick ( self_ty, & applicable_candidates[ ..] )
1374+ {
12891375 return Some ( Ok ( pick) ) ;
12901376 }
12911377 }
@@ -1295,7 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12951381 if let stability:: EvalResult :: Deny { feature, .. } =
12961382 self . tcx . eval_stability ( p. item . def_id , None , self . span , None )
12971383 {
1298- uc. push ( ( p, feature) ) ;
1384+ uc. push ( ( p. clone ( ) , feature) ) ;
12991385 return false ;
13001386 }
13011387 true
@@ -1309,7 +1395,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13091395
13101396 applicable_candidates. pop ( ) . map ( |( probe, status) | {
13111397 if status == ProbeResult :: Match {
1312- Ok ( probe. to_unadjusted_pick ( ) )
1398+ Ok ( probe. to_unadjusted_pick ( self_ty ) )
13131399 } else {
13141400 Err ( MethodError :: BadReturnType )
13151401 }
@@ -1319,8 +1405,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13191405 fn emit_unstable_name_collision_hint (
13201406 & self ,
13211407 stable_pick : & Pick < ' _ > ,
1322- unstable_candidates : & [ ( & Candidate < ' tcx > , Symbol ) ] ,
1323- self_ty : Ty < ' tcx > ,
1408+ unstable_candidates : & [ ( Candidate < ' tcx > , Symbol ) ] ,
13241409 ) {
13251410 self . tcx . struct_span_lint_hir (
13261411 lint:: builtin:: UNSTABLE_NAME_COLLISIONS ,
@@ -1351,7 +1436,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13511436 "use the fully qualified path to the associated const" ,
13521437 format ! (
13531438 "<{} as {}>::{}" ,
1354- self_ty,
1439+ stable_pick . self_ty,
13551440 self . tcx. def_path_str( def_id) ,
13561441 stable_pick. item. ident
13571442 ) ,
@@ -1591,6 +1676,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
15911676 /// use, so it's ok to just commit to "using the method from the trait Foo".
15921677 fn collapse_candidates_to_trait_pick (
15931678 & self ,
1679+ self_ty : Ty < ' tcx > ,
15941680 probes : & [ ( & Candidate < ' tcx > , ProbeResult ) ] ,
15951681 ) -> Option < Pick < ' tcx > > {
15961682 // Do all probes correspond to the same trait?
@@ -1610,6 +1696,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
16101696 import_ids : probes[ 0 ] . 0 . import_ids . clone ( ) ,
16111697 autoderefs : 0 ,
16121698 autoref_or_ptr_adjustment : None ,
1699+ self_ty,
16131700 } )
16141701 }
16151702
@@ -1828,7 +1915,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18281915}
18291916
18301917impl < ' tcx > Candidate < ' tcx > {
1831- fn to_unadjusted_pick ( & self ) -> Pick < ' tcx > {
1918+ fn to_unadjusted_pick ( & self , self_ty : Ty < ' tcx > ) -> Pick < ' tcx > {
18321919 Pick {
18331920 item : self . item ,
18341921 kind : match self . kind {
@@ -1852,6 +1939,7 @@ impl<'tcx> Candidate<'tcx> {
18521939 import_ids : self . import_ids . clone ( ) ,
18531940 autoderefs : 0 ,
18541941 autoref_or_ptr_adjustment : None ,
1942+ self_ty,
18551943 }
18561944 }
18571945}
0 commit comments