Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit aa049af

Browse files
committedAug 8, 2024
Auto merge of #128548 - adetaylor:receiver_trait_with_target_deshadowing_probes_v2, r=<try>
Arbitrary self types v2: probe for more methods, take two This is a new version of #127812. Here's what I said last time, which still applies: This PR is one of the first steps towards arbitrary self types v2, RFC [3519](rust-lang/rfcs#3519) (#44874). Specifically, it is [step 2 of the plan outlined here](#44874 (comment)). That says: > 1. **Search for potentially conflicting method candidates** per the [deshadowing part of the RFC](https://github.com/rust-lang/rfcs/blob/master/text/3519-arbitrary-self-types-v2.md#compiler-changes-deshadowing). This is the riskiest part - per > the production of errors requires us to interrogate more candidates to look for potential conflicts, so this could have a compile-time performance penalty which we should measure > let's attempt to land this first and see if performance issues show up. If so, it's back to the drawing board. So - this commit isn't useful in itself but we need to determine its performance and any unexpected compatibility problems. That's what this PR is for. We shouldn't necessarily merge it. Here's what this PR does. Rust prioritizes method candidates in this order: 1. By value; 2. By reference; 3. By mutable reference; 4. By const ptr. Previously, if a suitable candidate was found in one of these earlier categories, Rust wouldn't even move onto probing the other categories. As part of the arbitrary self types work, we're going to need to change that - even if we choose a method from one of the earlier categories, we will sometimes need to probe later categories to search for methods that we may be shadowing. This commit adds those extra searches for shadowing, but it does not yet produce an error when such shadowing problems are found. That will come in a subsequent commit, by filling out the 'check_for_shadowing' method. We're adding the extra searches in a preliminary commit because they are the risky bit. We want to find any functional or performance problems from these extra searches before we proceed with the actual work on arbitrary self types and specifically on extra deshadowing errors. -- What's different this time relative to #127812? Well, this is a more invasive change to the probing algorithm which hopefully minimizes the amount of work done during the extra probing for shadowed methods. Specifically, we only need to warn about potentially shadowed methods if three conditions are true: * the shadowed method is not the same as the shadower (different `DefId`s) * the potential shadower involves the same `self` type as the shadowed method * the potential shadower has been found at a different position along the chain of `Receiver` traits than the shadowed. Previously, we checked these conditions only when a potentially shadowed pick was found. We now apply them during the search process, which should minimize the amount of work required.
2 parents d3a3939 + 7f90c11 commit aa049af

File tree

1 file changed

+254
-43
lines changed
  • compiler/rustc_hir_typeck/src/method

1 file changed

+254
-43
lines changed
 

‎compiler/rustc_hir_typeck/src/method/probe.rs

Lines changed: 254 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ pub(crate) struct Candidate<'tcx> {
104104
pub(crate) item: ty::AssocItem,
105105
pub(crate) kind: CandidateKind<'tcx>,
106106
pub(crate) import_ids: SmallVec<[LocalDefId; 1]>,
107+
receiver_trait_derefs: usize,
107108
}
108109

109110
#[derive(Debug, Clone)]
@@ -157,6 +158,30 @@ impl AutorefOrPtrAdjustment {
157158
}
158159
}
159160

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+
160185
#[derive(Debug, Clone)]
161186
pub struct Pick<'tcx> {
162187
pub item: ty::AssocItem,
@@ -176,6 +201,10 @@ pub struct Pick<'tcx> {
176201

177202
/// Unstable candidates alongside the stable ones.
178203
unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>,
204+
205+
/// Number of jumps along the Receiver::target chain we followed
206+
/// to identify this method. Used only for deshadowing errors.
207+
pub receiver_trait_derefs: usize,
179208
}
180209

181210
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -497,6 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
497526
item,
498527
kind: CandidateKind::TraitCandidate(ty::Binder::dummy(trait_ref)),
499528
import_ids: smallvec![],
529+
receiver_trait_derefs: 0usize,
500530
},
501531
false,
502532
);
@@ -646,12 +676,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
646676

647677
fn assemble_inherent_candidates(&mut self) {
648678
for step in self.steps.iter() {
649-
self.assemble_probe(&step.self_ty);
679+
self.assemble_probe(&step.self_ty, step.autoderefs);
650680
}
651681
}
652682

653683
#[instrument(level = "debug", skip(self))]
654-
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
684+
fn assemble_probe(
685+
&mut self,
686+
self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
687+
receiver_trait_derefs: usize,
688+
) {
655689
let raw_self_ty = self_ty.value.value;
656690
match *raw_self_ty.kind() {
657691
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
@@ -675,27 +709,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
675709
let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) =
676710
self.fcx.instantiate_canonical(self.span, self_ty);
677711

678-
self.assemble_inherent_candidates_from_object(generalized_self_ty);
679-
self.assemble_inherent_impl_candidates_for_type(p.def_id());
712+
self.assemble_inherent_candidates_from_object(
713+
generalized_self_ty,
714+
receiver_trait_derefs,
715+
);
716+
self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_trait_derefs);
680717
if self.tcx.has_attr(p.def_id(), sym::rustc_has_incoherent_inherent_impls) {
681-
self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty);
718+
self.assemble_inherent_candidates_for_incoherent_ty(
719+
raw_self_ty,
720+
receiver_trait_derefs,
721+
);
682722
}
683723
}
684724
ty::Adt(def, _) => {
685725
let def_id = def.did();
686-
self.assemble_inherent_impl_candidates_for_type(def_id);
726+
self.assemble_inherent_impl_candidates_for_type(def_id, receiver_trait_derefs);
687727
if self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
688-
self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty);
728+
self.assemble_inherent_candidates_for_incoherent_ty(
729+
raw_self_ty,
730+
receiver_trait_derefs,
731+
);
689732
}
690733
}
691734
ty::Foreign(did) => {
692-
self.assemble_inherent_impl_candidates_for_type(did);
735+
self.assemble_inherent_impl_candidates_for_type(did, receiver_trait_derefs);
693736
if self.tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
694-
self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty);
737+
self.assemble_inherent_candidates_for_incoherent_ty(
738+
raw_self_ty,
739+
receiver_trait_derefs,
740+
);
695741
}
696742
}
697743
ty::Param(p) => {
698-
self.assemble_inherent_candidates_from_param(p);
744+
self.assemble_inherent_candidates_from_param(p, receiver_trait_derefs);
699745
}
700746
ty::Bool
701747
| ty::Char
@@ -708,29 +754,38 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
708754
| ty::RawPtr(_, _)
709755
| ty::Ref(..)
710756
| ty::Never
711-
| ty::Tuple(..) => self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty),
757+
| ty::Tuple(..) => self
758+
.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_trait_derefs),
712759
_ => {}
713760
}
714761
}
715762

716-
fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) {
763+
fn assemble_inherent_candidates_for_incoherent_ty(
764+
&mut self,
765+
self_ty: Ty<'tcx>,
766+
receiver_trait_derefs: usize,
767+
) {
717768
let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsCandidateKey) else {
718769
bug!("unexpected incoherent type: {:?}", self_ty)
719770
};
720771
for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
721-
self.assemble_inherent_impl_probe(impl_def_id);
772+
self.assemble_inherent_impl_probe(impl_def_id, receiver_trait_derefs);
722773
}
723774
}
724775

725-
fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
776+
fn assemble_inherent_impl_candidates_for_type(
777+
&mut self,
778+
def_id: DefId,
779+
receiver_trait_derefs: usize,
780+
) {
726781
let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten();
727782
for &impl_def_id in impl_def_ids {
728-
self.assemble_inherent_impl_probe(impl_def_id);
783+
self.assemble_inherent_impl_probe(impl_def_id, receiver_trait_derefs);
729784
}
730785
}
731786

732787
#[instrument(level = "debug", skip(self))]
733-
fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
788+
fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId, receiver_trait_derefs: usize) {
734789
if !self.impl_dups.insert(impl_def_id) {
735790
return; // already visited
736791
}
@@ -746,14 +801,19 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
746801
item,
747802
kind: InherentImplCandidate(impl_def_id),
748803
import_ids: smallvec![],
804+
receiver_trait_derefs,
749805
},
750806
true,
751807
);
752808
}
753809
}
754810

755811
#[instrument(level = "debug", skip(self))]
756-
fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
812+
fn assemble_inherent_candidates_from_object(
813+
&mut self,
814+
self_ty: Ty<'tcx>,
815+
receiver_trait_derefs: usize,
816+
) {
757817
let principal = match self_ty.kind() {
758818
ty::Dynamic(ref data, ..) => Some(data),
759819
_ => None,
@@ -782,6 +842,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
782842
item,
783843
kind: ObjectCandidate(new_trait_ref),
784844
import_ids: smallvec![],
845+
receiver_trait_derefs,
785846
},
786847
true,
787848
);
@@ -790,7 +851,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
790851
}
791852

792853
#[instrument(level = "debug", skip(self))]
793-
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
854+
fn assemble_inherent_candidates_from_param(
855+
&mut self,
856+
param_ty: ty::ParamTy,
857+
receiver_trait_derefs: usize,
858+
) {
794859
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
795860
let bound_predicate = predicate.kind();
796861
match bound_predicate.skip_binder() {
@@ -817,6 +882,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
817882
item,
818883
kind: WhereClauseCandidate(poly_trait_ref),
819884
import_ids: smallvec![],
885+
receiver_trait_derefs,
820886
},
821887
true,
822888
);
@@ -910,6 +976,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
910976
item,
911977
import_ids: import_ids.clone(),
912978
kind: TraitCandidate(bound_trait_ref),
979+
receiver_trait_derefs: 0usize,
913980
},
914981
false,
915982
);
@@ -933,6 +1000,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
9331000
item,
9341001
import_ids: import_ids.clone(),
9351002
kind: TraitCandidate(ty::Binder::dummy(trait_ref)),
1003+
receiver_trait_derefs: 0usize,
9361004
},
9371005
false,
9381006
);
@@ -1075,33 +1143,152 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
10751143
.unwrap_or_else(|_| {
10761144
span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty)
10771145
});
1078-
self.pick_by_value_method(step, self_ty, unstable_candidates.as_deref_mut())
1079-
.or_else(|| {
1080-
self.pick_autorefd_method(
1081-
step,
1082-
self_ty,
1083-
hir::Mutability::Not,
1084-
unstable_candidates.as_deref_mut(),
1085-
)
1086-
.or_else(|| {
1087-
self.pick_autorefd_method(
1146+
1147+
let by_value_pick =
1148+
self.pick_by_value_method(step, self_ty, unstable_candidates.as_deref_mut());
1149+
1150+
// Check for shadowing of a by-reference method by a by-value method (see comments on check_for_shadowing)
1151+
if let Some(by_value_pick) = by_value_pick {
1152+
if let Ok(by_value_pick) = by_value_pick.as_ref() {
1153+
if by_value_pick.kind == PickKind::InherentImplPick {
1154+
if let Err(e) = self.check_for_shadowed_autorefd_method(
1155+
by_value_pick,
1156+
step,
1157+
self_ty,
1158+
hir::Mutability::Not,
1159+
unstable_candidates.is_some(),
1160+
) {
1161+
return Some(Err(e));
1162+
}
1163+
if let Err(e) = self.check_for_shadowed_autorefd_method(
1164+
by_value_pick,
10881165
step,
10891166
self_ty,
10901167
hir::Mutability::Mut,
1091-
unstable_candidates.as_deref_mut(),
1092-
)
1093-
})
1094-
.or_else(|| {
1095-
self.pick_const_ptr_method(
1168+
unstable_candidates.is_some(),
1169+
) {
1170+
return Some(Err(e));
1171+
}
1172+
}
1173+
}
1174+
return Some(by_value_pick);
1175+
}
1176+
1177+
let autoref_pick = self.pick_autorefd_method(
1178+
step,
1179+
self_ty,
1180+
hir::Mutability::Not,
1181+
unstable_candidates.as_deref_mut(),
1182+
None,
1183+
);
1184+
// Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing)
1185+
if let Some(autoref_pick) = autoref_pick {
1186+
if let Ok(autoref_pick) = autoref_pick.as_ref() {
1187+
// Check we're not shadowing others
1188+
if autoref_pick.kind == PickKind::InherentImplPick {
1189+
if let Err(e) = self.check_for_shadowed_autorefd_method(
1190+
autoref_pick,
10961191
step,
10971192
self_ty,
1098-
unstable_candidates.as_deref_mut(),
1099-
)
1100-
})
1101-
})
1193+
hir::Mutability::Mut,
1194+
unstable_candidates.is_some(),
1195+
) {
1196+
return Some(Err(e));
1197+
}
1198+
}
1199+
}
1200+
return Some(autoref_pick);
1201+
}
1202+
1203+
// Note that no shadowing errors are produced from here on,
1204+
// as we consider const ptr methods.
1205+
// We allow new methods that take *mut T to shadow
1206+
// methods which took *const T, so there is no entry in
1207+
// this list for the results of `pick_const_ptr_method`.
1208+
// The reason is that the standard pointer cast method
1209+
// (on a mutable pointer) always already shadows the
1210+
// cast method (on a const pointer). So, if we added
1211+
// `pick_const_ptr_method` to this method, the anti-
1212+
// shadowing algorithm would always complain about
1213+
// the conflict between *const::cast and *mut::cast.
1214+
// In practice therefore this does constrain us:
1215+
// we cannot add new
1216+
// self: *mut Self
1217+
// methods to types such as NonNull or anything else
1218+
// which implements Receiver, because this might in future
1219+
// shadow existing methods taking
1220+
// self: *const NonNull<Self>
1221+
// in the pointee. In practice, methods taking raw pointers
1222+
// are rare, and it seems that it should be easily possible
1223+
// to avoid such compatibility breaks.
1224+
self.pick_autorefd_method(
1225+
step,
1226+
self_ty,
1227+
hir::Mutability::Mut,
1228+
unstable_candidates.as_deref_mut(),
1229+
None,
1230+
)
1231+
.or_else(|| {
1232+
self.pick_const_ptr_method(step, self_ty, unstable_candidates.as_deref_mut())
1233+
})
11021234
})
11031235
}
11041236

1237+
/// Check for cases where arbitrary self types allows shadowing
1238+
/// of methods that might be a compatibility break. Specifically,
1239+
/// we have something like:
1240+
/// ```compile_fail
1241+
/// # use std::ptr::NonNull;
1242+
/// struct A;
1243+
/// impl A {
1244+
/// fn foo(self: &NonNull<A>) {}
1245+
/// // note this is by reference
1246+
/// }
1247+
/// ```
1248+
/// then we've come along and added this method to `NonNull`:
1249+
/// ```
1250+
/// # struct NonNull;
1251+
/// # impl NonNull {
1252+
/// fn foo(self) {} // note this is by value
1253+
/// # }
1254+
/// ```
1255+
/// Report an error in this case.
1256+
fn check_for_shadowed_autorefd_method(
1257+
&self,
1258+
possible_shadower: &Pick<'tcx>,
1259+
step: &CandidateStep<'tcx>,
1260+
self_ty: Ty<'tcx>,
1261+
mutbl: hir::Mutability,
1262+
tracking_unstable_candidates: bool,
1263+
) -> Result<(), MethodError<'tcx>> {
1264+
let mut empty_vec = vec![];
1265+
let unstable_candidates_for_shadow_probe =
1266+
if tracking_unstable_candidates { Some(&mut empty_vec) } else { None };
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+
);
1286+
1287+
// At the moment, this function does no checks. A future
1288+
// commit will fill out the body here.
1289+
Ok(())
1290+
}
1291+
11051292
/// For each type `T` in the step list, this attempts to find a method where
11061293
/// the (transformed) self type is exactly `T`. We do however do one
11071294
/// transformation on the adjustment: if we are passing a region pointer in,
@@ -1118,7 +1305,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11181305
return None;
11191306
}
11201307

1121-
self.pick_method(self_ty, unstable_candidates).map(|r| {
1308+
self.pick_method(self_ty, unstable_candidates, None).map(|r| {
11221309
r.map(|mut pick| {
11231310
pick.autoderefs = step.autoderefs;
11241311

@@ -1142,14 +1329,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11421329
self_ty: Ty<'tcx>,
11431330
mutbl: hir::Mutability,
11441331
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1332+
pick_constraints: Option<&PickConstraintsForShadowed>,
11451333
) -> Option<PickResult<'tcx>> {
11461334
let tcx = self.tcx;
11471335

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

11511345
let autoref_ty = Ty::new_ref(tcx, region, self_ty, mutbl);
1152-
self.pick_method(autoref_ty, unstable_candidates).map(|r| {
1346+
self.pick_method(autoref_ty, unstable_candidates, pick_constraints).map(|r| {
11531347
r.map(|mut pick| {
11541348
pick.autoderefs = step.autoderefs;
11551349
pick.autoref_or_ptr_adjustment =
@@ -1178,7 +1372,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11781372
};
11791373

11801374
let const_ptr_ty = Ty::new_imm_ptr(self.tcx, ty);
1181-
self.pick_method(const_ptr_ty, unstable_candidates).map(|r| {
1375+
self.pick_method(const_ptr_ty, unstable_candidates, None).map(|r| {
11821376
r.map(|mut pick| {
11831377
pick.autoderefs = step.autoderefs;
11841378
pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr);
@@ -1191,6 +1385,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11911385
&self,
11921386
self_ty: Ty<'tcx>,
11931387
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1388+
pick_constraints: Option<&PickConstraintsForShadowed>,
11941389
) -> Option<PickResult<'tcx>> {
11951390
debug!("pick_method(self_ty={})", self.ty_to_string(self_ty));
11961391

@@ -1205,6 +1400,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12051400
candidates,
12061401
&mut possibly_unsatisfied_predicates,
12071402
unstable_candidates.as_deref_mut(),
1403+
pick_constraints,
12081404
);
12091405
if let Some(pick) = res {
12101406
return Some(pick);
@@ -1213,15 +1409,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12131409

12141410
if self.private_candidate.get().is_none() {
12151411
if let Some(Ok(pick)) =
1216-
self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None)
1412+
self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None, None)
12171413
{
12181414
self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id)));
12191415
}
12201416
}
12211417

12221418
// `pick_method` may be called twice for the same self_ty if no stable methods
1223-
// match. Only extend once.
1224-
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() {
12251422
self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates);
12261423
}
12271424
None
@@ -1237,9 +1434,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
12371434
Option<ObligationCause<'tcx>>,
12381435
)>,
12391436
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
1437+
pick_constraints: Option<&PickConstraintsForShadowed>,
12401438
) -> Option<PickResult<'tcx>> {
12411439
let mut applicable_candidates: Vec<_> = candidates
12421440
.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+
})
12431451
.map(|probe| {
12441452
(probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates))
12451453
})
@@ -1307,6 +1515,7 @@ impl<'tcx> Pick<'tcx> {
13071515
autoref_or_ptr_adjustment: _,
13081516
self_ty,
13091517
unstable_candidates: _,
1518+
receiver_trait_derefs: _,
13101519
} = *self;
13111520
self_ty != other.self_ty || def_id != other.item.def_id
13121521
}
@@ -1676,6 +1885,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
16761885
autoref_or_ptr_adjustment: None,
16771886
self_ty,
16781887
unstable_candidates: vec![],
1888+
receiver_trait_derefs: 0,
16791889
})
16801890
}
16811891

@@ -1969,6 +2179,7 @@ impl<'tcx> Candidate<'tcx> {
19692179
autoref_or_ptr_adjustment: None,
19702180
self_ty,
19712181
unstable_candidates,
2182+
receiver_trait_derefs: self.receiver_trait_derefs,
19722183
}
19732184
}
19742185
}

0 commit comments

Comments
 (0)
Please sign in to comment.