@@ -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 > ,
@@ -1102,13 +1102,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11021102 }
11031103
11041104 fn pick_core ( & mut self ) -> Option < PickResult < ' tcx > > {
1105- 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+ }
11061112
1107- // 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 ( ) ;
11081132 steps
11091133 . iter ( )
11101134 . filter ( |step| {
1111- debug ! ( "pick_core : step={:?}" , step) ;
1135+ debug ! ( "pick_all_method : step={:?}" , step) ;
11121136 // skip types that are from a type error or that would require dereferencing
11131137 // a raw pointer
11141138 !step. self_ty . references_error ( ) && !step. from_unsafe_deref
@@ -1124,11 +1148,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11241148 . unwrap_or_else ( |_| {
11251149 span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
11261150 } ) ;
1127- self . pick_by_value_method ( step, self_ty) . or_else ( || {
1128- self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Not )
1129- . or_else ( || self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Mut ) )
1130- . or_else ( || self . pick_const_ptr_method ( step, self_ty) )
1131- } )
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+ } )
11321175 } )
11331176 . next ( )
11341177 }
@@ -1143,12 +1186,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11431186 & mut self ,
11441187 step : & CandidateStep < ' tcx > ,
11451188 self_ty : Ty < ' tcx > ,
1189+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
11461190 ) -> Option < PickResult < ' tcx > > {
11471191 if step. unsize {
11481192 return None ;
11491193 }
11501194
1151- self . pick_method ( self_ty) . map ( |r| {
1195+ self . pick_method ( self_ty, unstable_candidates ) . map ( |r| {
11521196 r. map ( |mut pick| {
11531197 pick. autoderefs = step. autoderefs ;
11541198
@@ -1171,14 +1215,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11711215 step : & CandidateStep < ' tcx > ,
11721216 self_ty : Ty < ' tcx > ,
11731217 mutbl : hir:: Mutability ,
1218+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
11741219 ) -> Option < PickResult < ' tcx > > {
11751220 let tcx = self . tcx ;
11761221
11771222 // In general, during probing we erase regions.
11781223 let region = tcx. lifetimes . re_erased ;
11791224
11801225 let autoref_ty = tcx. mk_ref ( region, ty:: TypeAndMut { ty : self_ty, mutbl } ) ;
1181- self . pick_method ( autoref_ty) . map ( |r| {
1226+ self . pick_method ( autoref_ty, unstable_candidates ) . map ( |r| {
11821227 r. map ( |mut pick| {
11831228 pick. autoderefs = step. autoderefs ;
11841229 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
@@ -1197,6 +1242,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11971242 & mut self ,
11981243 step : & CandidateStep < ' tcx > ,
11991244 self_ty : Ty < ' tcx > ,
1245+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
12001246 ) -> Option < PickResult < ' tcx > > {
12011247 // Don't convert an unsized reference to ptr
12021248 if step. unsize {
@@ -1210,7 +1256,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12101256
12111257 let const_self_ty = ty:: TypeAndMut { ty, mutbl : hir:: Mutability :: Not } ;
12121258 let const_ptr_ty = self . tcx . mk_ptr ( const_self_ty) ;
1213- self . pick_method ( const_ptr_ty) . map ( |r| {
1259+ self . pick_method ( const_ptr_ty, unstable_candidates ) . map ( |r| {
12141260 r. map ( |mut pick| {
12151261 pick. autoderefs = step. autoderefs ;
12161262 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1219,8 +1265,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12191265 } )
12201266 }
12211267
1222- fn pick_method ( & mut self , self_ty : Ty < ' tcx > ) -> Option < PickResult < ' tcx > > {
1223- 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) ) ;
12241270
12251271 let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
12261272 let mut unstable_candidates = Vec :: new ( ) ;
@@ -1252,7 +1298,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12521298 debug ! ( "searching unstable candidates" ) ;
12531299 let res = self . consider_candidates (
12541300 self_ty,
1255- unstable_candidates. into_iter ( ) . map ( |( c, _) | c) ,
1301+ unstable_candidates. iter ( ) . map ( |( c, _) | c) ,
12561302 & mut possibly_unsatisfied_predicates,
12571303 None ,
12581304 ) ;
@@ -1262,6 +1308,42 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12621308 res
12631309 }
12641310
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+
12651347 fn consider_candidates < ' b , ProbesIter > (
12661348 & self ,
12671349 self_ty : Ty < ' tcx > ,
@@ -1270,10 +1352,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12701352 ty:: Predicate < ' tcx > ,
12711353 Option < ty:: Predicate < ' tcx > > ,
12721354 ) > ,
1273- unstable_candidates : Option < & mut Vec < ( & ' b Candidate < ' tcx > , Symbol ) > > ,
1355+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
12741356 ) -> Option < PickResult < ' tcx > >
12751357 where
12761358 ProbesIter : Iterator < Item = & ' b Candidate < ' tcx > > + Clone ,
1359+ ' tcx : ' b ,
12771360 {
12781361 let mut applicable_candidates: Vec < _ > = probes
12791362 . clone ( )
@@ -1298,7 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12981381 if let stability:: EvalResult :: Deny { feature, .. } =
12991382 self . tcx . eval_stability ( p. item . def_id , None , self . span , None )
13001383 {
1301- uc. push ( ( p, feature) ) ;
1384+ uc. push ( ( p. clone ( ) , feature) ) ;
13021385 return false ;
13031386 }
13041387 true
@@ -1322,7 +1405,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13221405 fn emit_unstable_name_collision_hint (
13231406 & self ,
13241407 stable_pick : & Pick < ' _ > ,
1325- unstable_candidates : & [ ( & Candidate < ' tcx > , Symbol ) ] ,
1408+ unstable_candidates : & [ ( Candidate < ' tcx > , Symbol ) ] ,
13261409 ) {
13271410 self . tcx . struct_span_lint_hir (
13281411 lint:: builtin:: UNSTABLE_NAME_COLLISIONS ,
0 commit comments