@@ -79,12 +79,6 @@ pub(crate) struct ProbeContext<'a, 'tcx> {
79
79
/// used for error reporting
80
80
static_candidates : RefCell < Vec < CandidateSource > > ,
81
81
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
-
88
82
scope_expr_id : HirId ,
89
83
90
84
/// Is this probe being done for a diagnostic? This will skip some error reporting
@@ -162,6 +156,21 @@ impl AutorefOrPtrAdjustment {
162
156
}
163
157
}
164
158
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
+
165
174
#[ derive( Debug , Clone ) ]
166
175
pub ( crate ) struct Pick < ' tcx > {
167
176
pub item : ty:: AssocItem ,
@@ -647,7 +656,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
647
656
private_candidates : Vec :: new ( ) ,
648
657
private_candidate : Cell :: new ( None ) ,
649
658
static_candidates : RefCell :: new ( Vec :: new ( ) ) ,
650
- unsatisfied_predicates : RefCell :: new ( Vec :: new ( ) ) ,
651
659
scope_expr_id,
652
660
is_suggestion,
653
661
}
@@ -660,7 +668,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
660
668
self . private_candidates . clear ( ) ;
661
669
self . private_candidate . set ( None ) ;
662
670
self . static_candidates . borrow_mut ( ) . clear ( ) ;
663
- self . unsatisfied_predicates . borrow_mut ( ) . clear ( ) ;
664
671
}
665
672
666
673
/// When we're looking up a method by path (UFCS), we relate the receiver
@@ -1036,7 +1043,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1036
1043
fn pick ( mut self ) -> PickResult < ' tcx > {
1037
1044
assert ! ( self . method_name. is_some( ) ) ;
1038
1045
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) {
1040
1049
return r;
1041
1050
}
1042
1051
@@ -1056,7 +1065,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1056
1065
1057
1066
let static_candidates = std:: mem:: take ( self . static_candidates . get_mut ( ) ) ;
1058
1067
let private_candidate = self . private_candidate . take ( ) ;
1059
- let unsatisfied_predicates = std:: mem:: take ( self . unsatisfied_predicates . get_mut ( ) ) ;
1060
1068
1061
1069
// things failed, so lets look at all traits, for diagnostic purposes now:
1062
1070
self . reset ( ) ;
@@ -1066,7 +1074,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1066
1074
1067
1075
self . assemble_extension_candidates_for_all_traits ( ) ;
1068
1076
1069
- let out_of_scope_traits = match self . pick_core ( ) {
1077
+ let out_of_scope_traits = match self . pick_core ( & mut Vec :: new ( ) ) {
1070
1078
Some ( Ok ( p) ) => vec ! [ p. item. container_id( self . tcx) ] ,
1071
1079
Some ( Err ( MethodError :: Ambiguity ( v) ) ) => v
1072
1080
. into_iter ( )
@@ -1101,14 +1109,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1101
1109
} ) )
1102
1110
}
1103
1111
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 > > {
1105
1120
// 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
+ } )
1107
1141
}
1108
1142
1109
- fn pick_all_method (
1143
+ fn pick_all_method < ' b > (
1110
1144
& self ,
1111
- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1145
+ pick_diag_hints : & mut PickDiagHints < ' b , ' tcx > ,
1112
1146
) -> Option < PickResult < ' tcx > > {
1113
1147
self . steps
1114
1148
. iter ( )
@@ -1133,37 +1167,19 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1133
1167
. unwrap_or_else ( |_| {
1134
1168
span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
1135
1169
} ) ;
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)
1144
1172
. or_else ( || {
1145
1173
self . pick_autorefd_method (
1146
1174
step,
1147
1175
self_ty,
1148
1176
hir:: Mutability :: Mut ,
1149
- unstable_candidates . as_deref_mut ( ) ,
1177
+ pick_diag_hints ,
1150
1178
)
1151
1179
} )
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
+ } )
1167
1183
} )
1168
1184
}
1169
1185
@@ -1177,13 +1193,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1177
1193
& self ,
1178
1194
step : & CandidateStep < ' tcx > ,
1179
1195
self_ty : Ty < ' tcx > ,
1180
- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1196
+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
1181
1197
) -> Option < PickResult < ' tcx > > {
1182
1198
if step. unsize {
1183
1199
return None ;
1184
1200
}
1185
1201
1186
- self . pick_method ( self_ty, unstable_candidates ) . map ( |r| {
1202
+ self . pick_method ( self_ty, pick_diag_hints ) . map ( |r| {
1187
1203
r. map ( |mut pick| {
1188
1204
pick. autoderefs = step. autoderefs ;
1189
1205
@@ -1221,15 +1237,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1221
1237
step : & CandidateStep < ' tcx > ,
1222
1238
self_ty : Ty < ' tcx > ,
1223
1239
mutbl : hir:: Mutability ,
1224
- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1240
+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
1225
1241
) -> Option < PickResult < ' tcx > > {
1226
1242
let tcx = self . tcx ;
1227
1243
1228
1244
// In general, during probing we erase regions.
1229
1245
let region = tcx. lifetimes . re_erased ;
1230
1246
1231
1247
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| {
1233
1249
r. map ( |mut pick| {
1234
1250
pick. autoderefs = step. autoderefs ;
1235
1251
pick. autoref_or_ptr_adjustment =
@@ -1240,12 +1256,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1240
1256
}
1241
1257
1242
1258
/// 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 ) ) ]
1244
1260
fn pick_reborrow_pin_method (
1245
1261
& self ,
1246
1262
step : & CandidateStep < ' tcx > ,
1247
1263
self_ty : Ty < ' tcx > ,
1248
- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1264
+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
1249
1265
) -> Option < PickResult < ' tcx > > {
1250
1266
if !self . tcx . features ( ) . pin_ergonomics ( ) {
1251
1267
return None ;
@@ -1266,7 +1282,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1266
1282
1267
1283
let region = self . tcx . lifetimes . re_erased ;
1268
1284
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| {
1270
1286
r. map ( |mut pick| {
1271
1287
pick. autoderefs = step. autoderefs ;
1272
1288
pick. autoref_or_ptr_adjustment =
@@ -1283,7 +1299,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1283
1299
& self ,
1284
1300
step : & CandidateStep < ' tcx > ,
1285
1301
self_ty : Ty < ' tcx > ,
1286
- unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1302
+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
1287
1303
) -> Option < PickResult < ' tcx > > {
1288
1304
// Don't convert an unsized reference to ptr
1289
1305
if step. unsize {
@@ -1295,7 +1311,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1295
1311
} ;
1296
1312
1297
1313
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| {
1299
1315
r. map ( |mut pick| {
1300
1316
pick. autoderefs = step. autoderefs ;
1301
1317
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1307,58 +1323,50 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1307
1323
fn pick_method (
1308
1324
& self ,
1309
1325
self_ty : Ty < ' tcx > ,
1310
- mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1326
+ pick_diag_hints : & mut PickDiagHints < ' _ , ' tcx > ,
1311
1327
) -> Option < PickResult < ' tcx > > {
1312
1328
debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
1313
1329
1314
- let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
1315
-
1316
1330
for ( kind, candidates) in
1317
1331
[ ( "inherent" , & self . inherent_candidates ) , ( "extension" , & self . extension_candidates ) ]
1318
1332
{
1319
1333
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) ;
1326
1335
if let Some ( pick) = res {
1327
1336
return Some ( pick) ;
1328
1337
}
1329
1338
}
1330
1339
1331
1340
if self . private_candidate . get ( ) . is_none ( ) {
1332
1341
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
+ } )
1334
1346
{
1335
1347
self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
1336
1348
}
1337
1349
}
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
- }
1344
1350
None
1345
1351
}
1346
1352
1347
1353
fn consider_candidates (
1348
1354
& self ,
1349
1355
self_ty : Ty < ' tcx > ,
1350
1356
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 > ,
1357
1358
) -> Option < PickResult < ' tcx > > {
1358
1359
let mut applicable_candidates: Vec < _ > = candidates
1359
1360
. iter ( )
1360
1361
. 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
+ )
1362
1370
} )
1363
1371
. filter ( |& ( _, status) | status != ProbeResult :: NoMatch )
1364
1372
. collect ( ) ;
@@ -1373,7 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1373
1381
}
1374
1382
}
1375
1383
1376
- if let Some ( uc) = & mut unstable_candidates {
1384
+ if let Some ( uc) = & mut pick_diag_hints . unstable_candidates {
1377
1385
applicable_candidates. retain ( |& ( candidate, _) | {
1378
1386
if let stability:: EvalResult :: Deny { feature, .. } =
1379
1387
self . tcx . eval_stability ( candidate. item . def_id , None , self . span , None )
@@ -1391,10 +1399,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1391
1399
}
1392
1400
1393
1401
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
+ ) ) ,
1398
1406
ProbeResult :: NoMatch | ProbeResult :: BadReturnType => Err ( MethodError :: BadReturnType ) ,
1399
1407
} )
1400
1408
}
@@ -1859,7 +1867,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1859
1867
pcx. method_name = Some ( method_name) ;
1860
1868
pcx. assemble_inherent_candidates ( ) ;
1861
1869
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 )
1863
1871
} )
1864
1872
. collect ( ) ;
1865
1873
0 commit comments