@@ -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 > ,
@@ -204,6 +204,7 @@ pub struct Pick<'tcx> {
204
204
/// Indicates that we want to add an autoref (and maybe also unsize it), or if the receiver is
205
205
/// `*mut T`, convert it to `*const T`.
206
206
pub autoref_or_ptr_adjustment : Option < AutorefOrPtrAdjustment < ' tcx > > ,
207
+ pub self_ty : Ty < ' tcx > ,
207
208
}
208
209
209
210
#[ derive( Clone , Debug , PartialEq , Eq ) ]
@@ -1101,13 +1102,37 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1101
1102
}
1102
1103
1103
1104
fn pick_core ( & mut self ) -> Option < PickResult < ' tcx > > {
1104
- 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
+ }
1105
1112
1106
- // 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 ( ) ;
1107
1132
steps
1108
1133
. iter ( )
1109
1134
. filter ( |step| {
1110
- debug ! ( "pick_core : step={:?}" , step) ;
1135
+ debug ! ( "pick_all_method : step={:?}" , step) ;
1111
1136
// skip types that are from a type error or that would require dereferencing
1112
1137
// a raw pointer
1113
1138
!step. self_ty . references_error ( ) && !step. from_unsafe_deref
@@ -1123,11 +1148,30 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1123
1148
. unwrap_or_else ( |_| {
1124
1149
span_bug ! ( self . span, "{:?} was applicable but now isn't?" , step. self_ty)
1125
1150
} ) ;
1126
- self . pick_by_value_method ( step, self_ty) . or_else ( || {
1127
- self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Not )
1128
- . or_else ( || self . pick_autorefd_method ( step, self_ty, hir:: Mutability :: Mut ) )
1129
- . or_else ( || self . pick_const_ptr_method ( step, self_ty) )
1130
- } )
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
+ } )
1131
1175
} )
1132
1176
. next ( )
1133
1177
}
@@ -1142,12 +1186,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1142
1186
& mut self ,
1143
1187
step : & CandidateStep < ' tcx > ,
1144
1188
self_ty : Ty < ' tcx > ,
1189
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1145
1190
) -> Option < PickResult < ' tcx > > {
1146
1191
if step. unsize {
1147
1192
return None ;
1148
1193
}
1149
1194
1150
- self . pick_method ( self_ty) . map ( |r| {
1195
+ self . pick_method ( self_ty, unstable_candidates ) . map ( |r| {
1151
1196
r. map ( |mut pick| {
1152
1197
pick. autoderefs = step. autoderefs ;
1153
1198
@@ -1170,14 +1215,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1170
1215
step : & CandidateStep < ' tcx > ,
1171
1216
self_ty : Ty < ' tcx > ,
1172
1217
mutbl : hir:: Mutability ,
1218
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1173
1219
) -> Option < PickResult < ' tcx > > {
1174
1220
let tcx = self . tcx ;
1175
1221
1176
1222
// In general, during probing we erase regions.
1177
1223
let region = tcx. lifetimes . re_erased ;
1178
1224
1179
1225
let autoref_ty = tcx. mk_ref ( region, ty:: TypeAndMut { ty : self_ty, mutbl } ) ;
1180
- self . pick_method ( autoref_ty) . map ( |r| {
1226
+ self . pick_method ( autoref_ty, unstable_candidates ) . map ( |r| {
1181
1227
r. map ( |mut pick| {
1182
1228
pick. autoderefs = step. autoderefs ;
1183
1229
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
@@ -1196,6 +1242,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1196
1242
& mut self ,
1197
1243
step : & CandidateStep < ' tcx > ,
1198
1244
self_ty : Ty < ' tcx > ,
1245
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1199
1246
) -> Option < PickResult < ' tcx > > {
1200
1247
// Don't convert an unsized reference to ptr
1201
1248
if step. unsize {
@@ -1209,7 +1256,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1209
1256
1210
1257
let const_self_ty = ty:: TypeAndMut { ty, mutbl : hir:: Mutability :: Not } ;
1211
1258
let const_ptr_ty = self . tcx . mk_ptr ( const_self_ty) ;
1212
- self . pick_method ( const_ptr_ty) . map ( |r| {
1259
+ self . pick_method ( const_ptr_ty, unstable_candidates ) . map ( |r| {
1213
1260
r. map ( |mut pick| {
1214
1261
pick. autoderefs = step. autoderefs ;
1215
1262
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1218,8 +1265,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1218
1265
} )
1219
1266
}
1220
1267
1221
- fn pick_method ( & mut self , self_ty : Ty < ' tcx > ) -> Option < PickResult < ' tcx > > {
1222
- 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) ) ;
1223
1270
1224
1271
let mut possibly_unsatisfied_predicates = Vec :: new ( ) ;
1225
1272
let mut unstable_candidates = Vec :: new ( ) ;
@@ -1241,7 +1288,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1241
1288
//
1242
1289
// We suppress warning if we're picking the method only because it is a
1243
1290
// suggestion.
1244
- self . emit_unstable_name_collision_hint ( p, & unstable_candidates, self_ty ) ;
1291
+ self . emit_unstable_name_collision_hint ( p, & unstable_candidates) ;
1245
1292
}
1246
1293
}
1247
1294
return Some ( pick) ;
@@ -1251,7 +1298,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1251
1298
debug ! ( "searching unstable candidates" ) ;
1252
1299
let res = self . consider_candidates (
1253
1300
self_ty,
1254
- unstable_candidates. into_iter ( ) . map ( |( c, _) | c) ,
1301
+ unstable_candidates. iter ( ) . map ( |( c, _) | c) ,
1255
1302
& mut possibly_unsatisfied_predicates,
1256
1303
None ,
1257
1304
) ;
@@ -1261,6 +1308,42 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1261
1308
res
1262
1309
}
1263
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
+
1264
1347
fn consider_candidates < ' b , ProbesIter > (
1265
1348
& self ,
1266
1349
self_ty : Ty < ' tcx > ,
@@ -1269,10 +1352,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1269
1352
ty:: Predicate < ' tcx > ,
1270
1353
Option < ty:: Predicate < ' tcx > > ,
1271
1354
) > ,
1272
- unstable_candidates : Option < & mut Vec < ( & ' b Candidate < ' tcx > , Symbol ) > > ,
1355
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1273
1356
) -> Option < PickResult < ' tcx > >
1274
1357
where
1275
1358
ProbesIter : Iterator < Item = & ' b Candidate < ' tcx > > + Clone ,
1359
+ ' tcx : ' b ,
1276
1360
{
1277
1361
let mut applicable_candidates: Vec < _ > = probes
1278
1362
. clone ( )
@@ -1285,7 +1369,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1285
1369
debug ! ( "applicable_candidates: {:?}" , applicable_candidates) ;
1286
1370
1287
1371
if applicable_candidates. len ( ) > 1 {
1288
- if let Some ( pick) = self . collapse_candidates_to_trait_pick ( & applicable_candidates[ ..] ) {
1372
+ if let Some ( pick) =
1373
+ self . collapse_candidates_to_trait_pick ( self_ty, & applicable_candidates[ ..] )
1374
+ {
1289
1375
return Some ( Ok ( pick) ) ;
1290
1376
}
1291
1377
}
@@ -1295,7 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1295
1381
if let stability:: EvalResult :: Deny { feature, .. } =
1296
1382
self . tcx . eval_stability ( p. item . def_id , None , self . span , None )
1297
1383
{
1298
- uc. push ( ( p, feature) ) ;
1384
+ uc. push ( ( p. clone ( ) , feature) ) ;
1299
1385
return false ;
1300
1386
}
1301
1387
true
@@ -1309,7 +1395,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1309
1395
1310
1396
applicable_candidates. pop ( ) . map ( |( probe, status) | {
1311
1397
if status == ProbeResult :: Match {
1312
- Ok ( probe. to_unadjusted_pick ( ) )
1398
+ Ok ( probe. to_unadjusted_pick ( self_ty ) )
1313
1399
} else {
1314
1400
Err ( MethodError :: BadReturnType )
1315
1401
}
@@ -1319,8 +1405,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1319
1405
fn emit_unstable_name_collision_hint (
1320
1406
& self ,
1321
1407
stable_pick : & Pick < ' _ > ,
1322
- unstable_candidates : & [ ( & Candidate < ' tcx > , Symbol ) ] ,
1323
- self_ty : Ty < ' tcx > ,
1408
+ unstable_candidates : & [ ( Candidate < ' tcx > , Symbol ) ] ,
1324
1409
) {
1325
1410
self . tcx . struct_span_lint_hir (
1326
1411
lint:: builtin:: UNSTABLE_NAME_COLLISIONS ,
@@ -1351,7 +1436,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1351
1436
"use the fully qualified path to the associated const" ,
1352
1437
format ! (
1353
1438
"<{} as {}>::{}" ,
1354
- self_ty,
1439
+ stable_pick . self_ty,
1355
1440
self . tcx. def_path_str( def_id) ,
1356
1441
stable_pick. item. ident
1357
1442
) ,
@@ -1591,6 +1676,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1591
1676
/// use, so it's ok to just commit to "using the method from the trait Foo".
1592
1677
fn collapse_candidates_to_trait_pick (
1593
1678
& self ,
1679
+ self_ty : Ty < ' tcx > ,
1594
1680
probes : & [ ( & Candidate < ' tcx > , ProbeResult ) ] ,
1595
1681
) -> Option < Pick < ' tcx > > {
1596
1682
// Do all probes correspond to the same trait?
@@ -1610,6 +1696,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1610
1696
import_ids : probes[ 0 ] . 0 . import_ids . clone ( ) ,
1611
1697
autoderefs : 0 ,
1612
1698
autoref_or_ptr_adjustment : None ,
1699
+ self_ty,
1613
1700
} )
1614
1701
}
1615
1702
@@ -1828,7 +1915,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1828
1915
}
1829
1916
1830
1917
impl < ' tcx > Candidate < ' tcx > {
1831
- fn to_unadjusted_pick ( & self ) -> Pick < ' tcx > {
1918
+ fn to_unadjusted_pick ( & self , self_ty : Ty < ' tcx > ) -> Pick < ' tcx > {
1832
1919
Pick {
1833
1920
item : self . item ,
1834
1921
kind : match self . kind {
@@ -1852,6 +1939,7 @@ impl<'tcx> Candidate<'tcx> {
1852
1939
import_ids : self . import_ids . clone ( ) ,
1853
1940
autoderefs : 0 ,
1854
1941
autoref_or_ptr_adjustment : None ,
1942
+ self_ty,
1855
1943
}
1856
1944
}
1857
1945
}
0 commit comments