@@ -79,12 +79,6 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
7979 /// used for error reporting
8080 static_candidates : RefCell < Vec < CandidateSource > > ,
8181
82- /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
83- /// for error reporting
84- unsatisfied_predicates : RefCell <
85- Vec < ( ty:: Predicate < ' tcx > , Option < ty:: Predicate < ' tcx > > , Option < ObligationCause < ' tcx > > ) > ,
86- > ,
87-
8882 scope_expr_id : HirId ,
8983
9084 /// Is this probe being done for a diagnostic? This will skip some error reporting
@@ -162,6 +156,20 @@ impl AutorefOrPtrAdjustment {
162156 }
163157}
164158
159+ /// Extra information required only for error reporting.
160+ struct PickDiagHints < ' a , ' tcx > {
161+ /// Unstable candidates alongside the stable ones.
162+ unstable_candidates : Option < Vec < ( Candidate < ' tcx > , Symbol ) > > ,
163+
164+ /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
165+ /// for error reporting
166+ unsatisfied_predicates : & ' a mut Vec < (
167+ ty:: Predicate < ' tcx > ,
168+ Option < ty:: Predicate < ' tcx > > ,
169+ Option < ObligationCause < ' tcx > > ,
170+ ) > ,
171+ }
172+
165173#[ derive( Debug , Clone ) ]
166174pub ( crate ) struct Pick < ' tcx > {
167175 pub item : ty:: AssocItem ,
@@ -665,7 +673,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
665673 private_candidates : Vec :: new ( ) ,
666674 private_candidate : Cell :: new ( None ) ,
667675 static_candidates : RefCell :: new ( Vec :: new ( ) ) ,
668- unsatisfied_predicates : RefCell :: new ( Vec :: new ( ) ) ,
669676 scope_expr_id,
670677 is_suggestion,
671678 }
@@ -678,7 +685,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
678685 self . private_candidates . clear ( ) ;
679686 self . private_candidate . set ( None ) ;
680687 self . static_candidates . borrow_mut ( ) . clear ( ) ;
681- self . unsatisfied_predicates . borrow_mut ( ) . clear ( ) ;
682688 }
683689
684690 /// When we're looking up a method by path (UFCS), we relate the receiver
@@ -1054,7 +1060,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10541060 fn pick ( mut self ) -> PickResult < ' tcx > {
10551061 assert ! ( self . method_name. is_some( ) ) ;
10561062
1057- if let Some ( r) = self . pick_core ( ) {
1063+ let mut unsatisfied_predicates = Vec :: new ( ) ;
1064+
1065+ if let Some ( r) = self . pick_core ( & mut unsatisfied_predicates) {
10581066 return r;
10591067 }
10601068
@@ -1074,7 +1082,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10741082
10751083 let static_candidates = std:: mem:: take ( self . static_candidates . get_mut ( ) ) ;
10761084 let private_candidate = self . private_candidate . take ( ) ;
1077- let unsatisfied_predicates = std:: mem:: take ( self . unsatisfied_predicates . get_mut ( ) ) ;
10781085
10791086 // things failed, so lets look at all traits, for diagnostic purposes now:
10801087 self . reset ( ) ;
@@ -1084,7 +1091,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10841091
10851092 self . assemble_extension_candidates_for_all_traits ( ) ;
10861093
1087- let out_of_scope_traits = match self . pick_core ( ) {
1094+ let out_of_scope_traits = match self . pick_core ( & mut Vec :: new ( ) ) {
10881095 Some ( Ok ( p) ) => vec ! [ p. item. container_id( self . tcx) ] ,
10891096 Some ( Err ( MethodError :: Ambiguity ( v) ) ) => v
10901097 . into_iter ( )
@@ -1119,14 +1126,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11191126 } ) )
11201127 }
11211128
1122- fn pick_core ( & self ) -> Option < PickResult < ' tcx > > {
1129+ fn pick_core (
1130+ & self ,
1131+ unsatisfied_predicates : & mut Vec < (
1132+ ty:: Predicate < ' tcx > ,
1133+ Option < ty:: Predicate < ' tcx > > ,
1134+ Option < ObligationCause < ' tcx > > ,
1135+ ) > ,
1136+ ) -> Option < PickResult < ' tcx > > {
11231137 // Pick stable methods only first, and consider unstable candidates if not found.
1124- self . pick_all_method ( Some ( & mut vec ! [ ] ) ) . or_else ( || self . pick_all_method ( None ) )
1138+ self . pick_all_method ( & mut PickDiagHints {
1139+ // This first cycle, maintain a list of unstable candidates which
1140+ // we encounter. This will end up in the Pick for diagnostics.
1141+ unstable_candidates : Some ( Vec :: new ( ) ) ,
1142+ // Contribute to the list of unsatisfied predicates which may
1143+ // also be used for diagnostics.
1144+ unsatisfied_predicates,
1145+ } )
1146+ . or_else ( || {
1147+ self . pick_all_method ( & mut PickDiagHints {
1148+ // On the second search, don't provide a special list of unstable
1149+ // candidates. This indicates to the picking code that it should
1150+ // in fact include such unstable candidates in the actual
1151+ // search.
1152+ unstable_candidates : None ,
1153+ // And there's no need to duplicate ourselves in the
1154+ // unsatisifed predicates list. Provide a throwaway list.
1155+ unsatisfied_predicates : & mut Vec :: new ( ) ,
1156+ } )
1157+ } )
11251158 }
11261159
1127- fn pick_all_method (
1160+ fn pick_all_method < ' b > (
11281161 & self ,
1129- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1162+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
11301163 ) -> Option < PickResult < ' tcx > > {
11311164 self . steps
11321165 . iter ( )
@@ -1151,37 +1184,19 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11511184 . unwrap_or_else ( |_| {
11521185 span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
11531186 } ) ;
1154- self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1155- . or_else ( || {
1156- self . pick_autorefd_method (
1157- step,
1158- self_ty,
1159- hir:: Mutability :: Not ,
1160- unstable_candidates. as_deref_mut ( ) ,
1161- )
1187+ self . pick_by_value_method ( step, self_ty, pick_diag_hints) . or_else ( || {
1188+ self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Not , pick_diag_hints)
11621189 . or_else ( || {
11631190 self . pick_autorefd_method (
11641191 step,
11651192 self_ty,
11661193 hir:: Mutability :: Mut ,
1167- unstable_candidates. as_deref_mut ( ) ,
1168- )
1169- } )
1170- . or_else ( || {
1171- self . pick_const_ptr_method (
1172- step,
1173- self_ty,
1174- unstable_candidates. as_deref_mut ( ) ,
1175- )
1176- } )
1177- . or_else ( || {
1178- self . pick_reborrow_pin_method (
1179- step,
1180- self_ty,
1181- unstable_candidates. as_deref_mut ( ) ,
1194+ pick_diag_hints,
11821195 )
11831196 } )
1184- } )
1197+ . or_else ( || self . pick_const_ptr_method ( step, self_ty, pick_diag_hints) )
1198+ . or_else ( || self . pick_reborrow_pin_method ( step, self_ty, pick_diag_hints) )
1199+ } )
11851200 } )
11861201 }
11871202
@@ -1191,17 +1206,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11911206 /// we will potentially *reborrow* it to a shorter lifetime. This allows us
11921207 /// to transparently pass `&mut` pointers, in particular, without consuming
11931208 /// them for their entire lifetime.
1194- fn pick_by_value_method (
1209+ fn pick_by_value_method < ' b > (
11951210 & self ,
11961211 step : & CandidateStep < ' tcx > ,
11971212 self_ty : Ty < ' tcx > ,
1198- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1213+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
11991214 ) -> Option < PickResult < ' tcx > > {
12001215 if step. unsize {
12011216 return None ;
12021217 }
12031218
1204- self . pick_method ( self_ty, unstable_candidates ) . map ( |r| {
1219+ self . pick_method ( self_ty, pick_diag_hints ) . map ( |r| {
12051220 r. map ( |mut pick| {
12061221 pick. autoderefs = step. autoderefs ;
12071222
@@ -1234,20 +1249,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12341249 } )
12351250 }
12361251
1237- fn pick_autorefd_method (
1252+ fn pick_autorefd_method < ' b > (
12381253 & self ,
12391254 step : & CandidateStep < ' tcx > ,
12401255 self_ty : Ty < ' tcx > ,
12411256 mutbl : hir:: Mutability ,
1242- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1257+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
12431258 ) -> Option < PickResult < ' tcx > > {
12441259 let tcx = self . tcx ;
12451260
12461261 // In general, during probing we erase regions.
12471262 let region = tcx. lifetimes . re_erased ;
12481263
12491264 let autoref_ty = Ty :: new_ref ( tcx, region, self_ty, mutbl) ;
1250- self . pick_method ( autoref_ty, unstable_candidates ) . map ( |r| {
1265+ self . pick_method ( autoref_ty, pick_diag_hints ) . map ( |r| {
12511266 r. map ( |mut pick| {
12521267 pick. autoderefs = step. autoderefs ;
12531268 pick. autoref_or_ptr_adjustment =
@@ -1258,12 +1273,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12581273 }
12591274
12601275 /// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`.
1261- #[ instrument( level = "debug" , skip( self , step, unstable_candidates ) ) ]
1262- fn pick_reborrow_pin_method (
1276+ #[ instrument( level = "debug" , skip( self , step, pick_diag_hints ) ) ]
1277+ fn pick_reborrow_pin_method < ' b > (
12631278 & self ,
12641279 step : & CandidateStep < ' tcx > ,
12651280 self_ty : Ty < ' tcx > ,
1266- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1281+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
12671282 ) -> Option < PickResult < ' tcx > > {
12681283 if !self . tcx . features ( ) . pin_ergonomics ( ) {
12691284 return None ;
@@ -1284,7 +1299,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12841299
12851300 let region = self . tcx . lifetimes . re_erased ;
12861301 let autopin_ty = Ty :: new_pinned_ref ( self . tcx , region, inner_ty, hir:: Mutability :: Not ) ;
1287- self . pick_method ( autopin_ty, unstable_candidates ) . map ( |r| {
1302+ self . pick_method ( autopin_ty, pick_diag_hints ) . map ( |r| {
12881303 r. map ( |mut pick| {
12891304 pick. autoderefs = step. autoderefs ;
12901305 pick. autoref_or_ptr_adjustment =
@@ -1297,11 +1312,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12971312 /// If `self_ty` is `*mut T` then this picks `*const T` methods. The reason why we have a
12981313 /// special case for this is because going from `*mut T` to `*const T` with autoderefs and
12991314 /// autorefs would require dereferencing the pointer, which is not safe.
1300- fn pick_const_ptr_method (
1315+ fn pick_const_ptr_method < ' b > (
13011316 & self ,
13021317 step : & CandidateStep < ' tcx > ,
13031318 self_ty : Ty < ' tcx > ,
1304- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1319+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
13051320 ) -> Option < PickResult < ' tcx > > {
13061321 // Don't convert an unsized reference to ptr
13071322 if step. unsize {
@@ -1313,7 +1328,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13131328 } ;
13141329
13151330 let const_ptr_ty = Ty :: new_imm_ptr ( self . tcx , ty) ;
1316- self . pick_method ( const_ptr_ty, unstable_candidates ) . map ( |r| {
1331+ self . pick_method ( const_ptr_ty, pick_diag_hints ) . map ( |r| {
13171332 r. map ( |mut pick| {
13181333 pick. autoderefs = step. autoderefs ;
13191334 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1322,61 +1337,50 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13221337 } )
13231338 }
13241339
1325- fn pick_method (
1340+ fn pick_method < ' b > (
13261341 & self ,
13271342 self_ty : Ty < ' tcx > ,
1328- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1343+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
13291344 ) -> Option < PickResult < ' tcx > > {
13301345 debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
13311346
1332- let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
1333-
13341347 for ( kind, candidates) in
13351348 [ ( "inherent" , & self . inherent_candidates ) , ( "extension" , & self . extension_candidates ) ]
13361349 {
13371350 debug ! ( "searching {} candidates" , kind) ;
1338- let res = self . consider_candidates (
1339- self_ty,
1340- candidates,
1341- & mut possibly_unsatisfied_predicates,
1342- unstable_candidates. as_deref_mut ( ) ,
1343- ) ;
1351+ let res = self . consider_candidates ( self_ty, candidates, pick_diag_hints) ;
13441352 if let Some ( pick) = res {
13451353 return Some ( pick) ;
13461354 }
13471355 }
13481356
13491357 if self . private_candidate . get ( ) . is_none ( ) {
13501358 if let Some ( Ok ( pick) ) =
1351- self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None )
1359+ self . consider_candidates ( self_ty, & self . private_candidates , pick_diag_hints )
13521360 {
13531361 self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
13541362 }
13551363 }
1356-
1357- // `pick_method` may be called twice for the same self_ty if no stable methods
1358- // match. Only extend once.
1359- if unstable_candidates. is_some ( ) {
1360- self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
1361- }
13621364 None
13631365 }
13641366
1365- fn consider_candidates (
1367+ fn consider_candidates < ' b > (
13661368 & self ,
13671369 self_ty : Ty < ' tcx > ,
13681370 candidates : & [ Candidate < ' tcx > ] ,
1369- possibly_unsatisfied_predicates : & mut Vec < (
1370- ty:: Predicate < ' tcx > ,
1371- Option < ty:: Predicate < ' tcx > > ,
1372- Option < ObligationCause < ' tcx > > ,
1373- ) > ,
1374- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1371+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
13751372 ) -> Option < PickResult < ' tcx > > {
13761373 let mut applicable_candidates: Vec < _ > = candidates
13771374 . iter ( )
13781375 . map ( |probe| {
1379- ( probe, self . consider_probe ( self_ty, probe, possibly_unsatisfied_predicates) )
1376+ (
1377+ probe,
1378+ self . consider_probe (
1379+ self_ty,
1380+ probe,
1381+ & mut pick_diag_hints. unsatisfied_predicates ,
1382+ ) ,
1383+ )
13801384 } )
13811385 . filter ( |& ( _, status) | status != ProbeResult :: NoMatch )
13821386 . collect ( ) ;
@@ -1391,7 +1395,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13911395 }
13921396 }
13931397
1394- if let Some ( uc) = & mut unstable_candidates {
1398+ if let Some ( uc) = & mut pick_diag_hints . unstable_candidates {
13951399 applicable_candidates. retain ( |& ( candidate, _) | {
13961400 if let stability:: EvalResult :: Deny { feature, .. } =
13971401 self . tcx . eval_stability ( candidate. item . def_id , None , self . span , None )
@@ -1409,10 +1413,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14091413 }
14101414
14111415 applicable_candidates. pop ( ) . map ( |( probe, status) | match status {
1412- ProbeResult :: Match => {
1413- Ok ( probe
1414- . to_unadjusted_pick ( self_ty , unstable_candidates. cloned ( ) . unwrap_or_default ( ) ) )
1415- }
1416+ ProbeResult :: Match => Ok ( probe . to_unadjusted_pick (
1417+ self_ty ,
1418+ pick_diag_hints . unstable_candidates . clone ( ) . unwrap_or_default ( ) ,
1419+ ) ) ,
14161420 ProbeResult :: NoMatch | ProbeResult :: BadReturnType => Err ( MethodError :: BadReturnType ) ,
14171421 } )
14181422 }
@@ -1854,7 +1858,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18541858 pcx. method_name = Some ( method_name) ;
18551859 pcx. assemble_inherent_candidates ( ) ;
18561860 pcx. assemble_extension_candidates_for_all_traits ( ) ;
1857- pcx. pick_core ( ) . and_then ( |pick| pick. ok ( ) ) . map ( |pick| pick. item )
1861+ pcx. pick_core ( & mut Vec :: new ( ) ) . and_then ( |pick| pick. ok ( ) ) . map ( |pick| pick. item )
18581862 } )
18591863 . collect ( ) ;
18601864
0 commit comments