@@ -158,6 +158,30 @@ impl AutorefOrPtrAdjustment {
158
158
}
159
159
}
160
160
161
+ /// Criteria to apply when searching for a given Pick. This is used during
162
+ /// the search for potentially shadowed methods to ensure we don't search
163
+ /// more candidates than strictly necessary.
164
+ #[ derive( Debug ) ]
165
+ struct PickConstraintsForShadowed {
166
+ autoderefs : usize ,
167
+ receiver_trait_derefs : usize ,
168
+ def_id : DefId ,
169
+ }
170
+
171
+ impl PickConstraintsForShadowed {
172
+ fn may_shadow_based_on_autoderefs ( & self , autoderefs : usize ) -> bool {
173
+ autoderefs == self . autoderefs
174
+ }
175
+
176
+ fn may_shadow_based_on_receiver_trait_derefs ( & self , receiver_trait_derefs : usize ) -> bool {
177
+ receiver_trait_derefs != self . receiver_trait_derefs
178
+ }
179
+
180
+ fn may_shadow_based_on_defid ( & self , def_id : DefId ) -> bool {
181
+ def_id != self . def_id
182
+ }
183
+ }
184
+
161
185
#[ derive( Debug , Clone ) ]
162
186
pub struct Pick < ' tcx > {
163
187
pub item : ty:: AssocItem ,
@@ -180,7 +204,6 @@ pub struct Pick<'tcx> {
180
204
181
205
/// Number of jumps along the Receiver::target chain we followed
182
206
/// to identify this method. Used only for deshadowing errors.
183
- #[ allow( dead_code) ]
184
207
pub receiver_trait_derefs : usize ,
185
208
}
186
209
@@ -1156,6 +1179,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1156
1179
self_ty,
1157
1180
hir:: Mutability :: Not ,
1158
1181
unstable_candidates. as_deref_mut ( ) ,
1182
+ None ,
1159
1183
) ;
1160
1184
// Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
1161
1185
if let Some ( autoref_pick) = autoref_pick {
@@ -1202,6 +1226,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1202
1226
self_ty,
1203
1227
hir:: Mutability :: Mut ,
1204
1228
unstable_candidates. as_deref_mut ( ) ,
1229
+ None ,
1205
1230
)
1206
1231
. or_else ( || {
1207
1232
self . pick_const_ptr_method ( step, self_ty, unstable_candidates. as_deref_mut ( ) )
@@ -1226,7 +1251,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1226
1251
/// Report an error in this case.
1227
1252
fn check_for_shadowed_autorefd_method (
1228
1253
& self ,
1229
- _possible_shadower : & Pick < ' tcx > ,
1254
+ possible_shadower : & Pick < ' tcx > ,
1230
1255
step : & CandidateStep < ' tcx > ,
1231
1256
self_ty : Ty < ' tcx > ,
1232
1257
mutbl : hir:: Mutability ,
@@ -1235,8 +1260,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1235
1260
let mut empty_vec = vec ! [ ] ;
1236
1261
let unstable_candidates_for_shadow_probe =
1237
1262
if tracking_unstable_candidates { Some ( & mut empty_vec) } else { None } ;
1238
- let _potentially_shadowed_pick =
1239
- self . pick_autorefd_method ( step, self_ty, mutbl, unstable_candidates_for_shadow_probe) ;
1263
+ // Set criteria for how we find methods possibly shadowed by 'possible_shadower'
1264
+ let pick_constraints = PickConstraintsForShadowed {
1265
+ // It's the same `self` type, other than any autoreffing...
1266
+ autoderefs : possible_shadower. autoderefs ,
1267
+ // ... but the method was found in an impl block determined
1268
+ // by searching further along the Receiver chain than the other,
1269
+ // showing that it's arbitrary self types causing the problem...
1270
+ receiver_trait_derefs : possible_shadower. receiver_trait_derefs ,
1271
+ // ... and they don't end up pointing to the same item in the
1272
+ // first place (could happen with things like blanket impls for T)
1273
+ def_id : possible_shadower. item . def_id ,
1274
+ } ;
1275
+ let _potentially_shadowed_pick = self . pick_autorefd_method (
1276
+ step,
1277
+ self_ty,
1278
+ mutbl,
1279
+ unstable_candidates_for_shadow_probe,
1280
+ Some ( & pick_constraints) ,
1281
+ ) ;
1240
1282
1241
1283
// At the moment, this function does no checks. A future
1242
1284
// commit will fill out the body here.
@@ -1259,7 +1301,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1259
1301
return None ;
1260
1302
}
1261
1303
1262
- self . pick_method ( self_ty, unstable_candidates) . map ( |r| {
1304
+ self . pick_method ( self_ty, unstable_candidates, None ) . map ( |r| {
1263
1305
r. map ( |mut pick| {
1264
1306
pick. autoderefs = step. autoderefs ;
1265
1307
@@ -1283,14 +1325,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1283
1325
self_ty : Ty < ' tcx > ,
1284
1326
mutbl : hir:: Mutability ,
1285
1327
unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1328
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1286
1329
) -> Option < PickResult < ' tcx > > {
1287
1330
let tcx = self . tcx ;
1288
1331
1332
+ if let Some ( pick_constraints) = pick_constraints {
1333
+ if !pick_constraints. may_shadow_based_on_autoderefs ( step. autoderefs ) {
1334
+ return None ;
1335
+ }
1336
+ }
1337
+
1289
1338
// In general, during probing we erase regions.
1290
1339
let region = tcx. lifetimes . re_erased ;
1291
1340
1292
1341
let autoref_ty = Ty :: new_ref ( tcx, region, self_ty, mutbl) ;
1293
- self . pick_method ( autoref_ty, unstable_candidates) . map ( |r| {
1342
+ self . pick_method ( autoref_ty, unstable_candidates, pick_constraints ) . map ( |r| {
1294
1343
r. map ( |mut pick| {
1295
1344
pick. autoderefs = step. autoderefs ;
1296
1345
pick. autoref_or_ptr_adjustment =
@@ -1319,7 +1368,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1319
1368
} ;
1320
1369
1321
1370
let const_ptr_ty = Ty :: new_imm_ptr ( self . tcx , ty) ;
1322
- self . pick_method ( const_ptr_ty, unstable_candidates) . map ( |r| {
1371
+ self . pick_method ( const_ptr_ty, unstable_candidates, None ) . map ( |r| {
1323
1372
r. map ( |mut pick| {
1324
1373
pick. autoderefs = step. autoderefs ;
1325
1374
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1332,6 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1332
1381
& self ,
1333
1382
self_ty : Ty < ' tcx > ,
1334
1383
mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1384
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1335
1385
) -> Option < PickResult < ' tcx > > {
1336
1386
debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
1337
1387
@@ -1346,6 +1396,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1346
1396
candidates,
1347
1397
& mut possibly_unsatisfied_predicates,
1348
1398
unstable_candidates. as_deref_mut ( ) ,
1399
+ pick_constraints,
1349
1400
) ;
1350
1401
if let Some ( pick) = res {
1351
1402
return Some ( pick) ;
@@ -1354,16 +1405,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1354
1405
1355
1406
if self . private_candidate . get ( ) . is_none ( ) {
1356
1407
if let Some ( Ok ( pick) ) =
1357
- self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None )
1408
+ self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None , None )
1358
1409
{
1359
1410
self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
1360
1411
}
1361
1412
}
1362
1413
1363
1414
// `pick_method` may be called twice for the same self_ty if no stable methods
1364
- // match. Only extend once.
1365
- // FIXME: this shouldn't be done when we're probing just for shadowing possibilities .
1366
- if unstable_candidates. is_some ( ) {
1415
+ // match. Only extend once. And don't extend if we're just doing a search for
1416
+ // shadowed methods, which will result in a Some pick_constraints .
1417
+ if unstable_candidates. is_some ( ) && pick_constraints . is_none ( ) {
1367
1418
self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
1368
1419
}
1369
1420
None
@@ -1379,9 +1430,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1379
1430
Option < ObligationCause < ' tcx > > ,
1380
1431
) > ,
1381
1432
mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1433
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1382
1434
) -> Option < PickResult < ' tcx > > {
1383
1435
let mut applicable_candidates: Vec < _ > = candidates
1384
1436
. iter ( )
1437
+ . filter ( |candidate| {
1438
+ pick_constraints
1439
+ . map ( |pick_constraints| {
1440
+ pick_constraints. may_shadow_based_on_defid ( candidate. item . def_id )
1441
+ && pick_constraints. may_shadow_based_on_receiver_trait_derefs (
1442
+ candidate. receiver_trait_derefs ,
1443
+ )
1444
+ } )
1445
+ . unwrap_or ( true )
1446
+ } )
1385
1447
. map ( |probe| {
1386
1448
( probe, self . consider_probe ( self_ty, probe, possibly_unsatisfied_predicates) )
1387
1449
} )
0 commit comments