@@ -92,7 +92,7 @@ impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> {
92
92
}
93
93
}
94
94
95
- #[ derive( Debug ) ]
95
+ #[ derive( Debug , Clone ) ]
96
96
struct Candidate < ' tcx > {
97
97
// Candidates are (I'm not quite sure, but they are mostly) basically
98
98
// some metadata on top of a `ty::AssocItem` (without substs).
@@ -132,7 +132,7 @@ struct Candidate<'tcx> {
132
132
import_ids : SmallVec < [ LocalDefId ; 1 ] > ,
133
133
}
134
134
135
- #[ derive( Debug ) ]
135
+ #[ derive( Debug , Clone ) ]
136
136
enum CandidateKind < ' tcx > {
137
137
InherentImplCandidate (
138
138
SubstsRef < ' tcx > ,
@@ -1102,13 +1102,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1102
1102
}
1103
1103
1104
1104
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
+ }
1106
1112
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 ( ) ;
1108
1132
steps
1109
1133
. iter ( )
1110
1134
. filter ( |step| {
1111
- debug ! ( "pick_core : step={:?}" , step) ;
1135
+ debug ! ( "pick_all_method : step={:?}" , step) ;
1112
1136
// skip types that are from a type error or that would require dereferencing
1113
1137
// a raw pointer
1114
1138
!step. self_ty . references_error ( ) && !step. from_unsafe_deref
@@ -1124,11 +1148,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1124
1148
. unwrap_or_else ( |_| {
1125
1149
span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
1126
1150
} ) ;
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
+ } )
1132
1175
} )
1133
1176
. next ( )
1134
1177
}
@@ -1143,12 +1186,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1143
1186
& mut self ,
1144
1187
step : & CandidateStep < ' tcx > ,
1145
1188
self_ty : Ty < ' tcx > ,
1189
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1146
1190
) -> Option < PickResult < ' tcx > > {
1147
1191
if step. unsize {
1148
1192
return None ;
1149
1193
}
1150
1194
1151
- self . pick_method ( self_ty) . map ( |r| {
1195
+ self . pick_method ( self_ty, unstable_candidates ) . map ( |r| {
1152
1196
r. map ( |mut pick| {
1153
1197
pick. autoderefs = step. autoderefs ;
1154
1198
@@ -1171,14 +1215,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1171
1215
step : & CandidateStep < ' tcx > ,
1172
1216
self_ty : Ty < ' tcx > ,
1173
1217
mutbl : hir:: Mutability ,
1218
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1174
1219
) -> Option < PickResult < ' tcx > > {
1175
1220
let tcx = self . tcx ;
1176
1221
1177
1222
// In general, during probing we erase regions.
1178
1223
let region = tcx. lifetimes . re_erased ;
1179
1224
1180
1225
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| {
1182
1227
r. map ( |mut pick| {
1183
1228
pick. autoderefs = step. autoderefs ;
1184
1229
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
@@ -1197,6 +1242,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1197
1242
& mut self ,
1198
1243
step : & CandidateStep < ' tcx > ,
1199
1244
self_ty : Ty < ' tcx > ,
1245
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1200
1246
) -> Option < PickResult < ' tcx > > {
1201
1247
// Don't convert an unsized reference to ptr
1202
1248
if step. unsize {
@@ -1210,7 +1256,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1210
1256
1211
1257
let const_self_ty = ty:: TypeAndMut { ty, mutbl : hir:: Mutability :: Not } ;
1212
1258
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| {
1214
1260
r. map ( |mut pick| {
1215
1261
pick. autoderefs = step. autoderefs ;
1216
1262
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1219,8 +1265,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1219
1265
} )
1220
1266
}
1221
1267
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) ) ;
1224
1270
1225
1271
let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
1226
1272
let mut unstable_candidates = Vec :: new ( ) ;
@@ -1252,7 +1298,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1252
1298
debug ! ( "searching unstable candidates" ) ;
1253
1299
let res = self . consider_candidates (
1254
1300
self_ty,
1255
- unstable_candidates. into_iter ( ) . map ( |( c, _) | c) ,
1301
+ unstable_candidates. iter ( ) . map ( |( c, _) | c) ,
1256
1302
& mut possibly_unsatisfied_predicates,
1257
1303
None ,
1258
1304
) ;
@@ -1262,6 +1308,42 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1262
1308
res
1263
1309
}
1264
1310
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
+
1265
1347
fn consider_candidates < ' b , ProbesIter > (
1266
1348
& self ,
1267
1349
self_ty : Ty < ' tcx > ,
@@ -1270,10 +1352,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1270
1352
ty:: Predicate < ' tcx > ,
1271
1353
Option < ty:: Predicate < ' tcx > > ,
1272
1354
) > ,
1273
- unstable_candidates : Option < & mut Vec < ( & ' b Candidate < ' tcx > , Symbol ) > > ,
1355
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1274
1356
) -> Option < PickResult < ' tcx > >
1275
1357
where
1276
1358
ProbesIter : Iterator < Item = & ' b Candidate < ' tcx > > + Clone ,
1359
+ ' tcx : ' b ,
1277
1360
{
1278
1361
let mut applicable_candidates: Vec < _ > = probes
1279
1362
. clone ( )
@@ -1298,7 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1298
1381
if let stability:: EvalResult :: Deny { feature, .. } =
1299
1382
self . tcx . eval_stability ( p. item . def_id , None , self . span , None )
1300
1383
{
1301
- uc. push ( ( p, feature) ) ;
1384
+ uc. push ( ( p. clone ( ) , feature) ) ;
1302
1385
return false ;
1303
1386
}
1304
1387
true
@@ -1322,7 +1405,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1322
1405
fn emit_unstable_name_collision_hint (
1323
1406
& self ,
1324
1407
stable_pick : & Pick < ' _ > ,
1325
- unstable_candidates : & [ ( & Candidate < ' tcx > , Symbol ) ] ,
1408
+ unstable_candidates : & [ ( Candidate < ' tcx > , Symbol ) ] ,
1326
1409
) {
1327
1410
self . tcx . struct_span_lint_hir (
1328
1411
lint:: builtin:: UNSTABLE_NAME_COLLISIONS ,
0 commit comments