Skip to content

Commit 6e830c3

Browse files
committed
Arbitrary self types v2: search less for shadows.
This commit applies constraints to the searches we perform when searching for potential shadows, in order to make that search quicker.
1 parent 899663d commit 6e830c3

File tree

1 file changed

+73
-11
lines changed
  • compiler/rustc_hir_typeck/src/method

1 file changed

+73
-11
lines changed

compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,30 @@ impl AutorefOrPtrAdjustment {
158158
}
159159
}
160160

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+
161185
#[derive(Debug, Clone)]
162186
pub struct Pick<'tcx> {
163187
pub item: ty::AssocItem,
@@ -180,7 +204,6 @@ pub struct Pick<'tcx> {
180204

181205
/// Number of jumps along the Receiver::target chain we followed
182206
/// to identify this method. Used only for deshadowing errors.
183-
#[allow(dead_code)]
184207
pub receiver_trait_derefs: usize,
185208
}
186209

@@ -1156,6 +1179,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11561179
self_ty,
11571180
hir::Mutability::Not,
11581181
unstable_candidates.as_deref_mut(),
1182+
None,
11591183
);
11601184
// Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
11611185
if let Some(autoref_pick) = autoref_pick {
@@ -1202,6 +1226,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12021226
self_ty,
12031227
hir::Mutability::Mut,
12041228
unstable_candidates.as_deref_mut(),
1229+
None,
12051230
)
12061231
.or_else(|| {
12071232
self.pick_const_ptr_method(step, self_ty, unstable_candidates.as_deref_mut())
@@ -1226,7 +1251,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12261251
/// Report an error in this case.
12271252
fn check_for_shadowed_autorefd_method(
12281253
&self,
1229-
_possible_shadower: &Pick<'tcx>,
1254+
possible_shadower: &Pick<'tcx>,
12301255
step: &CandidateStep<'tcx>,
12311256
self_ty: Ty<'tcx>,
12321257
mutbl: hir::Mutability,
@@ -1235,8 +1260,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12351260
let mut empty_vec = vec![];
12361261
let unstable_candidates_for_shadow_probe =
12371262
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+
);
12401282

12411283
// At the moment, this function does no checks. A future
12421284
// commit will fill out the body here.
@@ -1259,7 +1301,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12591301
return None;
12601302
}
12611303

1262-
self.pick_method(self_ty, unstable_candidates).map(|r| {
1304+
self.pick_method(self_ty, unstable_candidates, None).map(|r| {
12631305
r.map(|mut pick| {
12641306
pick.autoderefs = step.autoderefs;
12651307

@@ -1283,14 +1325,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12831325
self_ty: Ty<'tcx>,
12841326
mutbl: hir::Mutability,
12851327
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1328+
pick_constraints: Option<&PickConstraintsForShadowed>,
12861329
) -> Option<PickResult<'tcx>> {
12871330
let tcx = self.tcx;
12881331

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+
12891338
// In general, during probing we erase regions.
12901339
let region = tcx.lifetimes.re_erased;
12911340

12921341
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| {
12941343
r.map(|mut pick| {
12951344
pick.autoderefs = step.autoderefs;
12961345
pick.autoref_or_ptr_adjustment =
@@ -1319,7 +1368,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13191368
};
13201369

13211370
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| {
13231372
r.map(|mut pick| {
13241373
pick.autoderefs = step.autoderefs;
13251374
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr);
@@ -1332,6 +1381,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13321381
&self,
13331382
self_ty: Ty<'tcx>,
13341383
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1384+
pick_constraints: Option<&PickConstraintsForShadowed>,
13351385
) -> Option<PickResult<'tcx>> {
13361386
debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
13371387

@@ -1346,6 +1396,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13461396
candidates,
13471397
&mut possibly_unsatisfied_predicates,
13481398
unstable_candidates.as_deref_mut(),
1399+
pick_constraints,
13491400
);
13501401
if let Some(pick) = res {
13511402
return Some(pick);
@@ -1354,16 +1405,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13541405

13551406
if self.private_candidate.get().is_none() {
13561407
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)
13581409
{
13591410
self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
13601411
}
13611412
}
13621413

13631414
// `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() {
13671418
self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
13681419
}
13691420
None
@@ -1379,9 +1430,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13791430
Option<ObligationCause<'tcx>>,
13801431
)>,
13811432
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1433+
pick_constraints: Option<&PickConstraintsForShadowed>,
13821434
) -> Option<PickResult<'tcx>> {
13831435
let mut applicable_candidates: Vec<_> = candidates
13841436
.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+
})
13851447
.map(|probe| {
13861448
(probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
13871449
})

0 commit comments

Comments
 (0)