@@ -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,21 @@ impl AutorefOrPtrAdjustment {
162156 }
163157}
164158
159+ /// Extra information required only for error reporting.
160+ #[ derive( Debug ) ]
161+ struct PickDiagHints < ' a , ' tcx > {
162+ /// Unstable candidates alongside the stable ones.
163+ unstable_candidates : Option < Vec < ( Candidate < ' tcx > , Symbol ) > > ,
164+
165+ /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
166+ /// for error reporting
167+ unsatisfied_predicates : & ' a mut Vec < (
168+ ty:: Predicate < ' tcx > ,
169+ Option < ty:: Predicate < ' tcx > > ,
170+ Option < ObligationCause < ' tcx > > ,
171+ ) > ,
172+ }
173+
165174#[ derive( Debug , Clone ) ]
166175pub ( crate ) struct Pick < ' tcx > {
167176 pub item : ty:: AssocItem ,
@@ -647,7 +656,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
647656 private_candidates : Vec :: new ( ) ,
648657 private_candidate : Cell :: new ( None ) ,
649658 static_candidates : RefCell :: new ( Vec :: new ( ) ) ,
650- unsatisfied_predicates : RefCell :: new ( Vec :: new ( ) ) ,
651659 scope_expr_id,
652660 is_suggestion,
653661 }
@@ -660,7 +668,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
660668 self . private_candidates . clear ( ) ;
661669 self . private_candidate . set ( None ) ;
662670 self . static_candidates . borrow_mut ( ) . clear ( ) ;
663- self . unsatisfied_predicates . borrow_mut ( ) . clear ( ) ;
664671 }
665672
666673 /// When we're looking up a method by path (UFCS), we relate the receiver
@@ -1036,7 +1043,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10361043 fn pick ( mut self ) -> PickResult < ' tcx > {
10371044 assert ! ( self . method_name. is_some( ) ) ;
10381045
1039- if let Some ( r) = self . pick_core ( ) {
1046+ let mut unsatisfied_predicates = Vec :: new ( ) ;
1047+
1048+ if let Some ( r) = self . pick_core ( & mut unsatisfied_predicates) {
10401049 return r;
10411050 }
10421051
@@ -1056,7 +1065,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10561065
10571066 let static_candidates = std:: mem:: take ( self . static_candidates . get_mut ( ) ) ;
10581067 let private_candidate = self . private_candidate . take ( ) ;
1059- let unsatisfied_predicates = std:: mem:: take ( self . unsatisfied_predicates . get_mut ( ) ) ;
10601068
10611069 // things failed, so lets look at all traits, for diagnostic purposes now:
10621070 self . reset ( ) ;
@@ -1066,7 +1074,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10661074
10671075 self . assemble_extension_candidates_for_all_traits ( ) ;
10681076
1069- let out_of_scope_traits = match self . pick_core ( ) {
1077+ let out_of_scope_traits = match self . pick_core ( & mut Vec :: new ( ) ) {
10701078 Some ( Ok ( p) ) => vec ! [ p. item. container_id( self . tcx) ] ,
10711079 Some ( Err ( MethodError :: Ambiguity ( v) ) ) => v
10721080 . into_iter ( )
@@ -1101,14 +1109,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11011109 } ) )
11021110 }
11031111
1104- fn pick_core ( & self ) -> Option < PickResult < ' tcx > > {
1112+ fn pick_core (
1113+ & self ,
1114+ unsatisfied_predicates : & mut Vec < (
1115+ ty:: Predicate < ' tcx > ,
1116+ Option < ty:: Predicate < ' tcx > > ,
1117+ Option < ObligationCause < ' tcx > > ,
1118+ ) > ,
1119+ ) -> Option < PickResult < ' tcx > > {
11051120 // Pick stable methods only first, and consider unstable candidates if not found.
1106- self . pick_all_method ( Some ( & mut vec ! [ ] ) ) . or_else ( || self . pick_all_method ( None ) )
1121+ self . pick_all_method ( & mut PickDiagHints {
1122+ // This first cycle, maintain a list of unstable candidates which
1123+ // we encounter. This will end up in the Pick for diagnostics.
1124+ unstable_candidates : Some ( Vec :: new ( ) ) ,
1125+ // Contribute to the list of unsatisfied predicates which may
1126+ // also be used for diagnostics.
1127+ unsatisfied_predicates,
1128+ } )
1129+ . or_else ( || {
1130+ self . pick_all_method ( & mut PickDiagHints {
1131+ // On the second search, don't provide a special list of unstable
1132+ // candidates. This indicates to the picking code that it should
1133+ // in fact include such unstable candidates in the actual
1134+ // search.
1135+ unstable_candidates : None ,
1136+ // And there's no need to duplicate ourselves in the
1137+ // unsatisifed predicates list. Provide a throwaway list.
1138+ unsatisfied_predicates : & mut Vec :: new ( ) ,
1139+ } )
1140+ } )
11071141 }
11081142
1109- fn pick_all_method (
1143+ fn pick_all_method < ' b > (
11101144 & self ,
1111- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1145+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
11121146 ) -> Option < PickResult < ' tcx > > {
11131147 self . steps
11141148 . iter ( )
@@ -1133,37 +1167,19 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11331167 . unwrap_or_else ( |_| {
11341168 span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
11351169 } ) ;
1136- self . pick_by_value_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
1137- . or_else ( || {
1138- self . pick_autorefd_method (
1139- step,
1140- self_ty,
1141- hir:: Mutability :: Not ,
1142- unstable_candidates. as_deref_mut ( ) ,
1143- )
1170+ self . pick_by_value_method ( step, self_ty, pick_diag_hints) . or_else ( || {
1171+ self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Not , pick_diag_hints)
11441172 . or_else ( || {
11451173 self . pick_autorefd_method (
11461174 step,
11471175 self_ty,
11481176 hir:: Mutability :: Mut ,
1149- unstable_candidates . as_deref_mut ( ) ,
1177+ pick_diag_hints ,
11501178 )
11511179 } )
1152- . or_else ( || {
1153- self . pick_const_ptr_method (
1154- step,
1155- self_ty,
1156- unstable_candidates. as_deref_mut ( ) ,
1157- )
1158- } )
1159- . or_else ( || {
1160- self . pick_reborrow_pin_method (
1161- step,
1162- self_ty,
1163- unstable_candidates. as_deref_mut ( ) ,
1164- )
1165- } )
1166- } )
1180+ . or_else ( || self . pick_const_ptr_method ( step, self_ty, pick_diag_hints) )
1181+ . or_else ( || self . pick_reborrow_pin_method ( step, self_ty, pick_diag_hints) )
1182+ } )
11671183 } )
11681184 }
11691185
@@ -1177,13 +1193,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11771193 & self ,
11781194 step : & CandidateStep < ' tcx > ,
11791195 self_ty : Ty < ' tcx > ,
1180- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1196+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
11811197 ) -> Option < PickResult < ' tcx > > {
11821198 if step. unsize {
11831199 return None ;
11841200 }
11851201
1186- self . pick_method ( self_ty, unstable_candidates ) . map ( |r| {
1202+ self . pick_method ( self_ty, pick_diag_hints ) . map ( |r| {
11871203 r. map ( |mut pick| {
11881204 pick. autoderefs = step. autoderefs ;
11891205
@@ -1221,15 +1237,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12211237 step : & CandidateStep < ' tcx > ,
12221238 self_ty : Ty < ' tcx > ,
12231239 mutbl : hir:: Mutability ,
1224- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1240+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
12251241 ) -> Option < PickResult < ' tcx > > {
12261242 let tcx = self . tcx ;
12271243
12281244 // In general, during probing we erase regions.
12291245 let region = tcx. lifetimes . re_erased ;
12301246
12311247 let autoref_ty = Ty :: new_ref ( tcx, region, self_ty, mutbl) ;
1232- self . pick_method ( autoref_ty, unstable_candidates ) . map ( |r| {
1248+ self . pick_method ( autoref_ty, pick_diag_hints ) . map ( |r| {
12331249 r. map ( |mut pick| {
12341250 pick. autoderefs = step. autoderefs ;
12351251 pick. autoref_or_ptr_adjustment =
@@ -1240,12 +1256,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12401256 }
12411257
12421258 /// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`.
1243- #[ instrument( level = "debug" , skip( self , step, unstable_candidates ) ) ]
1259+ #[ instrument( level = "debug" , skip( self , step, pick_diag_hints ) ) ]
12441260 fn pick_reborrow_pin_method (
12451261 & self ,
12461262 step : & CandidateStep < ' tcx > ,
12471263 self_ty : Ty < ' tcx > ,
1248- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1264+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
12491265 ) -> Option < PickResult < ' tcx > > {
12501266 if !self . tcx . features ( ) . pin_ergonomics ( ) {
12511267 return None ;
@@ -1266,7 +1282,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12661282
12671283 let region = self . tcx . lifetimes . re_erased ;
12681284 let autopin_ty = Ty :: new_pinned_ref ( self . tcx , region, inner_ty, hir:: Mutability :: Not ) ;
1269- self . pick_method ( autopin_ty, unstable_candidates ) . map ( |r| {
1285+ self . pick_method ( autopin_ty, pick_diag_hints ) . map ( |r| {
12701286 r. map ( |mut pick| {
12711287 pick. autoderefs = step. autoderefs ;
12721288 pick. autoref_or_ptr_adjustment =
@@ -1283,7 +1299,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12831299 & self ,
12841300 step : & CandidateStep < ' tcx > ,
12851301 self_ty : Ty < ' tcx > ,
1286- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1302+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
12871303 ) -> Option < PickResult < ' tcx > > {
12881304 // Don't convert an unsized reference to ptr
12891305 if step. unsize {
@@ -1295,7 +1311,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12951311 } ;
12961312
12971313 let const_ptr_ty = Ty :: new_imm_ptr ( self . tcx , ty) ;
1298- self . pick_method ( const_ptr_ty, unstable_candidates ) . map ( |r| {
1314+ self . pick_method ( const_ptr_ty, pick_diag_hints ) . map ( |r| {
12991315 r. map ( |mut pick| {
13001316 pick. autoderefs = step. autoderefs ;
13011317 pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1307,58 +1323,50 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13071323 fn pick_method (
13081324 & self ,
13091325 self_ty : Ty < ' tcx > ,
1310- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1326+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
13111327 ) -> Option < PickResult < ' tcx > > {
13121328 debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
13131329
1314- let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
1315-
13161330 for ( kind, candidates) in
13171331 [ ( "inherent" , & self . inherent_candidates ) , ( "extension" , & self . extension_candidates ) ]
13181332 {
13191333 debug ! ( "searching {} candidates" , kind) ;
1320- let res = self . consider_candidates (
1321- self_ty,
1322- candidates,
1323- & mut possibly_unsatisfied_predicates,
1324- unstable_candidates. as_deref_mut ( ) ,
1325- ) ;
1334+ let res = self . consider_candidates ( self_ty, candidates, pick_diag_hints) ;
13261335 if let Some ( pick) = res {
13271336 return Some ( pick) ;
13281337 }
13291338 }
13301339
13311340 if self . private_candidate . get ( ) . is_none ( ) {
13321341 if let Some ( Ok ( pick) ) =
1333- self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None )
1342+ self . consider_candidates ( self_ty, & self . private_candidates , & mut PickDiagHints {
1343+ unstable_candidates : None ,
1344+ unsatisfied_predicates : & mut vec ! [ ] ,
1345+ } )
13341346 {
13351347 self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
13361348 }
13371349 }
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 . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
1343- }
13441350 None
13451351 }
13461352
13471353 fn consider_candidates (
13481354 & self ,
13491355 self_ty : Ty < ' tcx > ,
13501356 candidates : & [ Candidate < ' tcx > ] ,
1351- possibly_unsatisfied_predicates : & mut Vec < (
1352- ty:: Predicate < ' tcx > ,
1353- Option < ty:: Predicate < ' tcx > > ,
1354- Option < ObligationCause < ' tcx > > ,
1355- ) > ,
1356- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1357+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
13571358 ) -> Option < PickResult < ' tcx > > {
13581359 let mut applicable_candidates: Vec < _ > = candidates
13591360 . iter ( )
13601361 . map ( |probe| {
1361- ( probe, self . consider_probe ( self_ty, probe, possibly_unsatisfied_predicates) )
1362+ (
1363+ probe,
1364+ self . consider_probe (
1365+ self_ty,
1366+ probe,
1367+ & mut pick_diag_hints. unsatisfied_predicates ,
1368+ ) ,
1369+ )
13621370 } )
13631371 . filter ( |& ( _, status) | status != ProbeResult :: NoMatch )
13641372 . collect ( ) ;
@@ -1373,7 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13731381 }
13741382 }
13751383
1376- if let Some ( uc) = & mut unstable_candidates {
1384+ if let Some ( uc) = & mut pick_diag_hints . unstable_candidates {
13771385 applicable_candidates. retain ( |& ( candidate, _) | {
13781386 if let stability:: EvalResult :: Deny { feature, .. } =
13791387 self . tcx . eval_stability ( candidate. item . def_id , None , self . span , None )
@@ -1391,10 +1399,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13911399 }
13921400
13931401 applicable_candidates. pop ( ) . map ( |( probe, status) | match status {
1394- ProbeResult :: Match => {
1395- Ok ( probe
1396- . to_unadjusted_pick ( self_ty , unstable_candidates. cloned ( ) . unwrap_or_default ( ) ) )
1397- }
1402+ ProbeResult :: Match => Ok ( probe . to_unadjusted_pick (
1403+ self_ty ,
1404+ pick_diag_hints . unstable_candidates . clone ( ) . unwrap_or_default ( ) ,
1405+ ) ) ,
13981406 ProbeResult :: NoMatch | ProbeResult :: BadReturnType => Err ( MethodError :: BadReturnType ) ,
13991407 } )
14001408 }
@@ -1859,7 +1867,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
18591867 pcx. method_name = Some ( method_name) ;
18601868 pcx. assemble_inherent_candidates ( ) ;
18611869 pcx. assemble_extension_candidates_for_all_traits ( ) ;
1862- pcx. pick_core ( ) . and_then ( |pick| pick. ok ( ) ) . map ( |pick| pick. item )
1870+ pcx. pick_core ( & mut Vec :: new ( ) ) . and_then ( |pick| pick. ok ( ) ) . map ( |pick| pick. item )
18631871 } )
18641872 . collect ( ) ;
18651873
0 commit comments