@@ -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
& mut unstable_candidates,
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
& mut unstable_candidates,
1229
+ None ,
1205
1230
)
1206
1231
. or_else ( || self . pick_const_ptr_method ( step, self_ty, & mut unstable_candidates) )
1207
1232
} )
@@ -1224,19 +1249,32 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1224
1249
/// Report an error in this case.
1225
1250
fn check_for_shadowed_autorefd_method (
1226
1251
& self ,
1227
- _possible_shadower : & Pick < ' tcx > ,
1252
+ possible_shadower : & Pick < ' tcx > ,
1228
1253
step : & CandidateStep < ' tcx > ,
1229
1254
self_ty : Ty < ' tcx > ,
1230
1255
mutbl : hir:: Mutability ,
1231
1256
tracking_unstable_candidates : bool ,
1232
1257
) -> Result < ( ) , MethodError < ' tcx > > {
1233
1258
let mut unstable_candidates_for_shadow_probe =
1234
1259
if tracking_unstable_candidates { Some ( vec ! [ ] ) } else { None } ;
1260
+ // Set criteria for how we find methods possibly shadowed by 'possible_shadower'
1261
+ let pick_constraints = PickConstraintsForShadowed {
1262
+ // It's the same `self` type, other than any autoreffing...
1263
+ autoderefs : possible_shadower. autoderefs ,
1264
+ // ... but the method was found in an impl block determined
1265
+ // by searching further along the Receiver chain than the other,
1266
+ // showing that it's arbitrary self types causing the problem...
1267
+ receiver_trait_derefs : possible_shadower. receiver_trait_derefs ,
1268
+ // ... and they don't end up pointing to the same item in the
1269
+ // first place (could happen with things like blanket impls for T)
1270
+ def_id : possible_shadower. item . def_id ,
1271
+ } ;
1235
1272
let _potentially_shadowed_pick = self . pick_autorefd_method (
1236
1273
step,
1237
1274
self_ty,
1238
1275
mutbl,
1239
1276
& mut unstable_candidates_for_shadow_probe,
1277
+ Some ( & pick_constraints) ,
1240
1278
) ;
1241
1279
1242
1280
// At the moment, this function does no checks. A future
@@ -1260,7 +1298,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1260
1298
return None ;
1261
1299
}
1262
1300
1263
- self . pick_method ( self_ty, unstable_candidates) . map ( |r| {
1301
+ self . pick_method ( self_ty, unstable_candidates, None ) . map ( |r| {
1264
1302
r. map ( |mut pick| {
1265
1303
pick. autoderefs = step. autoderefs ;
1266
1304
@@ -1284,14 +1322,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1284
1322
self_ty : Ty < ' tcx > ,
1285
1323
mutbl : hir:: Mutability ,
1286
1324
unstable_candidates : & mut Option < Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1325
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1287
1326
) -> Option < PickResult < ' tcx > > {
1288
1327
let tcx = self . tcx ;
1289
1328
1329
+ if let Some ( pick_constraints) = pick_constraints {
1330
+ if !pick_constraints. may_shadow_based_on_autoderefs ( step. autoderefs ) {
1331
+ return None ;
1332
+ }
1333
+ }
1334
+
1290
1335
// In general, during probing we erase regions.
1291
1336
let region = tcx. lifetimes . re_erased ;
1292
1337
1293
1338
let autoref_ty = Ty :: new_ref ( tcx, region, self_ty, mutbl) ;
1294
- self . pick_method ( autoref_ty, unstable_candidates) . map ( |r| {
1339
+ self . pick_method ( autoref_ty, unstable_candidates, pick_constraints ) . map ( |r| {
1295
1340
r. map ( |mut pick| {
1296
1341
pick. autoderefs = step. autoderefs ;
1297
1342
pick. autoref_or_ptr_adjustment =
@@ -1320,7 +1365,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1320
1365
} ;
1321
1366
1322
1367
let const_ptr_ty = Ty :: new_imm_ptr ( self . tcx , ty) ;
1323
- self . pick_method ( const_ptr_ty, unstable_candidates) . map ( |r| {
1368
+ self . pick_method ( const_ptr_ty, unstable_candidates, None ) . map ( |r| {
1324
1369
r. map ( |mut pick| {
1325
1370
pick. autoderefs = step. autoderefs ;
1326
1371
pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: ToConstPtr ) ;
@@ -1333,6 +1378,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1333
1378
& self ,
1334
1379
self_ty : Ty < ' tcx > ,
1335
1380
unstable_candidates : & mut Option < Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1381
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1336
1382
) -> Option < PickResult < ' tcx > > {
1337
1383
debug ! ( "pick_method(self_ty={})" , self . ty_to_string( self_ty) ) ;
1338
1384
@@ -1347,24 +1393,29 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1347
1393
candidates,
1348
1394
& mut possibly_unsatisfied_predicates,
1349
1395
unstable_candidates,
1396
+ pick_constraints,
1350
1397
) ;
1351
1398
if let Some ( pick) = res {
1352
1399
return Some ( pick) ;
1353
1400
}
1354
1401
}
1355
1402
1356
1403
if self . private_candidate . get ( ) . is_none ( ) {
1357
- if let Some ( Ok ( pick) ) =
1358
- self . consider_candidates ( self_ty, & self . private_candidates , & mut vec ! [ ] , & mut None )
1359
- {
1404
+ if let Some ( Ok ( pick) ) = self . consider_candidates (
1405
+ self_ty,
1406
+ & self . private_candidates ,
1407
+ & mut vec ! [ ] ,
1408
+ & mut None ,
1409
+ None ,
1410
+ ) {
1360
1411
self . private_candidate . set ( Some ( ( pick. item . kind . as_def_kind ( ) , pick. item . def_id ) ) ) ;
1361
1412
}
1362
1413
}
1363
1414
1364
1415
// `pick_method` may be called twice for the same self_ty if no stable methods
1365
- // match. Only extend once.
1366
- // FIXME: this shouldn't be done when we're probing just for shadowing possibilities .
1367
- if unstable_candidates. is_some ( ) {
1416
+ // match. Only extend once. And don't extend if we're just doing a search for
1417
+ // shadowed methods, which will result in a Some pick_constraints .
1418
+ if unstable_candidates. is_some ( ) && pick_constraints . is_none ( ) {
1368
1419
self . unsatisfied_predicates . borrow_mut ( ) . extend ( possibly_unsatisfied_predicates) ;
1369
1420
}
1370
1421
None
@@ -1380,9 +1431,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1380
1431
Option < ObligationCause < ' tcx > > ,
1381
1432
) > ,
1382
1433
unstable_candidates : & mut Option < Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1434
+ pick_constraints : Option < & PickConstraintsForShadowed > ,
1383
1435
) -> Option < PickResult < ' tcx > > {
1384
1436
let mut applicable_candidates: Vec < _ > = candidates
1385
1437
. iter ( )
1438
+ . filter ( |candidate| {
1439
+ pick_constraints
1440
+ . map ( |pick_constraints| {
1441
+ pick_constraints. may_shadow_based_on_defid ( candidate. item . def_id )
1442
+ && pick_constraints. may_shadow_based_on_receiver_trait_derefs (
1443
+ candidate. receiver_trait_derefs ,
1444
+ )
1445
+ } )
1446
+ . unwrap_or ( true )
1447
+ } )
1386
1448
. map ( |probe| {
1387
1449
( probe, self . consider_probe ( self_ty, probe, possibly_unsatisfied_predicates) )
1388
1450
} )
0 commit comments