@@ -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 ( ) )
@@ -1230,7 +1255,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1230
1255
/// Report an error in this case.
1231
1256
fn check_for_shadowed_autorefd_method (
1232
1257
& self ,
1233
- _possible_shadower : & Pick < ' tcx > ,
1258
+ possible_shadower : & Pick < ' tcx > ,
1234
1259
step : & CandidateStep < ' tcx > ,
1235
1260
self_ty : Ty < ' tcx > ,
1236
1261
mutbl : hir:: Mutability ,
@@ -1239,8 +1264,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1239
1264
let mut empty_vec = vec ! [ ] ;
1240
1265
let unstable_candidates_for_shadow_probe =
1241
1266
if tracking_unstable_candidates { Some ( & mut empty_vec) } else { None } ;
1242
- let _potentially_shadowed_pick =
1243
- self . pick_autorefd_method ( step, self_ty, mutbl, unstable_candidates_for_shadow_probe) ;
1267
+ // Set criteria for how we find methods possibly shadowed by 'possible_shadower'
1268
+ let pick_constraints = PickConstraintsForShadowed {
1269
+ // It's the same `self` type, other than any autoreffing...
1270
+ autoderefs : possible_shadower. autoderefs ,
1271
+ // ... but the method was found in an impl block determined
1272
+ // by searching further along the Receiver chain than the other,
1273
+ // showing that it's arbitrary self types causing the problem...
1274
+ receiver_trait_derefs : possible_shadower. receiver_trait_derefs ,
1275
+ // ... and they don't end up pointing to the same item in the
1276
+ // first place (could happen with things like blanket impls for T)
1277
+ def_id : possible_shadower. item . def_id ,
1278
+ } ;
1279
+ let _potentially_shadowed_pick = self . pick_autorefd_method (
1280
+ step,
1281
+ self_ty,
1282
+ mutbl,
1283
+ unstable_candidates_for_shadow_probe,
1284
+ Some ( & pick_constraints) ,
1285
+ ) ;
1244
1286
1245
1287
// At the moment, this function does no checks. A future
1246
1288
// commit will fill out the body here.
@@ -1263,7 +1305,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1263
1305
return None ;
1264
1306
}
1265
1307
1266
- self . pick_method ( self_ty, unstable_candidates) . map ( |r| {
1308
+ self . pick_method ( self_ty, unstable_candidates, None ) . map ( |r| {
1267
1309
r. map ( |mut pick| {
1268
1310
pick. autoderefs = step. autoderefs ;
1269
1311
@@ -1287,14 +1329,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1287
1329
self_ty : Ty < ' tcx > ,
1288
1330
mutbl : hir:: Mutability ,
1289
1331
unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1332
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1290
1333
) -> Option < PickResult < ' tcx > > {
1291
1334
let tcx = self . tcx ;
1292
1335
1336
+ if let Some ( pick_constraints) = pick_constraints {
1337
+ if !pick_constraints. may_shadow_based_on_autoderefs ( step. autoderefs ) {
1338
+ return None ;
1339
+ }
1340
+ }
1341
+
1293
1342
// In general, during probing we erase regions.
1294
1343
let region = tcx. lifetimes . re_erased ;
1295
1344
1296
1345
let autoref_ty = Ty :: new_ref ( tcx, region, self_ty, mutbl) ;
1297
- self . pick_method ( autoref_ty, unstable_candidates) . map ( |r| {
1346
+ self . pick_method ( autoref_ty, unstable_candidates, pick_constraints ) . map ( |r| {
1298
1347
r. map ( |mut pick| {
1299
1348
pick. autoderefs = step. autoderefs ;
1300
1349
pick. autoref_or_ptr_adjustment =
@@ -1323,7 +1372,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1323
1372
} ;
1324
1373
1325
1374
let const_ptr_ty = Ty :: new_imm_ptr ( self . tcx , ty) ;
1326
- self . pick_method ( const_ptr_ty, unstable_candidates) . map ( |r| {
1375
+ self . pick_method ( const_ptr_ty, unstable_candidates, None ) . map ( |r| {
1327
1376
r. map ( |mut pick| {
1328
1377
pick. autoderefs = step. autoderefs ;
1329
1378
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1336,6 +1385,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1336
1385
& self ,
1337
1386
self_ty : Ty < ' tcx > ,
1338
1387
mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1388
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1339
1389
) -> Option < PickResult < ' tcx > > {
1340
1390
debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
1341
1391
@@ -1350,6 +1400,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1350
1400
candidates,
1351
1401
& mut possibly_unsatisfied_predicates,
1352
1402
unstable_candidates. as_deref_mut ( ) ,
1403
+ pick_constraints,
1353
1404
) ;
1354
1405
if let Some ( pick) = res {
1355
1406
return Some ( pick) ;
@@ -1358,16 +1409,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1358
1409
1359
1410
if self . private_candidate . get ( ) . is_none ( ) {
1360
1411
if let Some ( Ok ( pick) ) =
1361
- self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None )
1412
+ self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , None , None )
1362
1413
{
1363
1414
self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
1364
1415
}
1365
1416
}
1366
1417
1367
1418
// `pick_method` may be called twice for the same self_ty if no stable methods
1368
- // match. Only extend once.
1369
- // FIXME: this shouldn't be done when we're probing just for shadowing possibilities .
1370
- if unstable_candidates. is_some ( ) {
1419
+ // match. Only extend once. And don't extend if we're just doing a search for
1420
+ // shadowed methods, which will result in a Some pick_constraints .
1421
+ if unstable_candidates. is_some ( ) && pick_constraints . is_none ( ) {
1371
1422
self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
1372
1423
}
1373
1424
None
@@ -1383,9 +1434,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1383
1434
Option < ObligationCause < ' tcx > > ,
1384
1435
) > ,
1385
1436
mut unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1437
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1386
1438
) -> Option < PickResult < ' tcx > > {
1387
1439
let mut applicable_candidates: Vec < _ > = candidates
1388
1440
. iter ( )
1441
+ . filter ( |candidate| {
1442
+ pick_constraints
1443
+ . map ( |pick_constraints| {
1444
+ pick_constraints. may_shadow_based_on_defid ( candidate. item . def_id )
1445
+ && pick_constraints. may_shadow_based_on_receiver_trait_derefs (
1446
+ candidate. receiver_trait_derefs ,
1447
+ )
1448
+ } )
1449
+ . unwrap_or ( true )
1450
+ } )
1389
1451
. map ( |probe| {
1390
1452
( probe, self . consider_probe ( self_ty, probe, possibly_unsatisfied_predicates) )
1391
1453
} )
0 commit comments