Skip to content

Commit 7f90c11

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 47a6191 commit 7f90c11

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())
@@ -1230,7 +1255,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12301255
/// Report an error in this case.
12311256
fn check_for_shadowed_autorefd_method(
12321257
&self,
1233-
_possible_shadower: &Pick<'tcx>,
1258+
possible_shadower: &Pick<'tcx>,
12341259
step: &CandidateStep<'tcx>,
12351260
self_ty: Ty<'tcx>,
12361261
mutbl: hir::Mutability,
@@ -1239,8 +1264,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12391264
let mut empty_vec = vec![];
12401265
let unstable_candidates_for_shadow_probe =
12411266
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+
);
12441286

12451287
// At the moment, this function does no checks. A future
12461288
// commit will fill out the body here.
@@ -1263,7 +1305,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12631305
return None;
12641306
}
12651307

1266-
self.pick_method(self_ty, unstable_candidates).map(|r| {
1308+
self.pick_method(self_ty, unstable_candidates, None).map(|r| {
12671309
r.map(|mut pick| {
12681310
pick.autoderefs = step.autoderefs;
12691311

@@ -1287,14 +1329,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12871329
self_ty: Ty<'tcx>,
12881330
mutbl: hir::Mutability,
12891331
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1332+
pick_constraints: Option<&PickConstraintsForShadowed>,
12901333
) -> Option<PickResult<'tcx>> {
12911334
let tcx = self.tcx;
12921335

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

12961345
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| {
12981347
r.map(|mut pick| {
12991348
pick.autoderefs = step.autoderefs;
13001349
pick.autoref_or_ptr_adjustment =
@@ -1323,7 +1372,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13231372
};
13241373

13251374
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| {
13271376
r.map(|mut pick| {
13281377
pick.autoderefs = step.autoderefs;
13291378
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr);
@@ -1336,6 +1385,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13361385
&self,
13371386
self_ty: Ty<'tcx>,
13381387
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1388+
pick_constraints: Option<&PickConstraintsForShadowed>,
13391389
) -> Option<PickResult<'tcx>> {
13401390
debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
13411391

@@ -1350,6 +1400,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13501400
candidates,
13511401
&mut possibly_unsatisfied_predicates,
13521402
unstable_candidates.as_deref_mut(),
1403+
pick_constraints,
13531404
);
13541405
if let Some(pick) = res {
13551406
return Some(pick);
@@ -1358,16 +1409,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13581409

13591410
if self.private_candidate.get().is_none() {
13601411
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)
13621413
{
13631414
self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
13641415
}
13651416
}
13661417

13671418
// `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() {
13711422
self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
13721423
}
13731424
None
@@ -1383,9 +1434,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
13831434
Option<ObligationCause<'tcx>>,
13841435
)>,
13851436
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1437+
pick_constraints: Option<&PickConstraintsForShadowed>,
13861438
) -> Option<PickResult<'tcx>> {
13871439
let mut applicable_candidates: Vec<_> = candidates
13881440
.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+
})
13891451
.map(|probe| {
13901452
(probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
13911453
})

0 commit comments

Comments
 (0)