Skip to content

Commit 1ee0614

Browse files
committed
Equate candidates modulo constness
1 parent a0cd8a2 commit 1ee0614

File tree

5 files changed

+36
-9
lines changed

5 files changed

+36
-9
lines changed

compiler/rustc_infer/src/traits/project.rs

+1
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
228228
/// type information (in which case, the "fully resolved" key will
229229
/// be different).
230230
pub fn ambiguous(&mut self, key: ProjectionCacheKey<'tcx>) {
231+
debug!(?key, "ambiguous");
231232
let fresh = self.map().insert(key, ProjectionCacheEntry::Ambiguous);
232233
assert!(!fresh, "never started projecting `{:?}`", key);
233234
}

compiler/rustc_middle/src/ty/print/pretty.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1824,12 +1824,13 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
18241824
GenericArgKind::Lifetime(r) => !r.is_erased(),
18251825
_ => false,
18261826
});
1827-
let args = args.iter().cloned().filter(|arg| match arg.unpack() {
1827+
let mut args = args.iter().cloned().filter(|arg| match arg.unpack() {
18281828
GenericArgKind::Lifetime(_) => print_regions,
1829+
GenericArgKind::Constness(_) => false,
18291830
_ => true,
1830-
});
1831+
}).peekable();
18311832

1832-
if args.clone().next().is_some() {
1833+
if args.peek().is_some() {
18331834
if self.in_value {
18341835
write!(self, "::")?;
18351836
}

compiler/rustc_middle/src/ty/sty.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ use rustc_type_ir::sty::TyKind::*;
3232
use rustc_type_ir::RegionKind as IrRegionKind;
3333
use rustc_type_ir::TyKind as IrTyKind;
3434

35+
use super::GenericArgKind;
36+
3537
// Re-export the `TyKind` from `rustc_type_ir` here for convenience
3638
#[rustc_diagnostic_item = "TyKind"]
3739
pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
@@ -849,13 +851,19 @@ impl<'tcx> TraitRef<'tcx> {
849851
pub fn with_const(mut self, tcx: TyCtxt<'tcx>) -> Self {
850852
if self.constness() != ty::ConstnessArg::Const {
851853
self.substs = tcx.mk_substs(self.substs.iter().map(|arg| match arg.unpack() {
852-
ty::subst::GenericArgKind::Constness(_) => ty::ConstnessArg::Const.into(),
854+
GenericArgKind::Constness(_) => ty::ConstnessArg::Const.into(),
853855
_ => arg,
854856
}));
855857
}
856858

857859
self
858860
}
861+
862+
pub fn eq_modulo_constness(&self, other: &TraitRef<'tcx>) -> bool {
863+
let f = |s: &GenericArg<'_>| !matches!(s.unpack(), GenericArgKind::Constness(_));
864+
self.def_id == other.def_id
865+
&& self.substs.iter().filter(f).eq(other.substs.iter().filter(f))
866+
}
859867
}
860868

861869
pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>;
@@ -887,6 +895,11 @@ impl<'tcx> PolyTraitRef<'tcx> {
887895
pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Self {
888896
self.map_bound(|tr| tr.without_const(tcx))
889897
}
898+
899+
pub fn eq_modulo_constness(&self, other: &Self) -> bool {
900+
self.bound_vars() == other.bound_vars()
901+
&& self.skip_binder().eq_modulo_constness(other.as_ref().skip_binder())
902+
}
890903
}
891904

892905
/// An existential reference to a trait, where `Self` is erased.

compiler/rustc_trait_selection/src/traits/project.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
9191
// Returns true if the push was successful, or false if the candidate
9292
// was discarded -- this could be because of ambiguity, or because
9393
// a higher-priority candidate is already there.
94-
fn push_candidate(&mut self, candidate: ProjectionCandidate<'tcx>) -> bool {
94+
#[tracing::instrument(level = "debug", skip(self, tcx))]
95+
fn push_candidate(&mut self, tcx: TyCtxt<'tcx>, candidate: ProjectionCandidate<'tcx>) -> bool {
9596
use self::ProjectionCandidate::*;
9697
use self::ProjectionCandidateSet::*;
9798

@@ -126,6 +127,15 @@ impl<'tcx> ProjectionCandidateSet<'tcx> {
126127
// clauses are the safer choice. See the comment on
127128
// `select::SelectionCandidate` and #21974 for more details.
128129
match (current, candidate) {
130+
// HACK(fee1-dead)
131+
// If both candidates are the same, except for the constness argument, it is not an ambiguity
132+
(ParamEnv(a), ParamEnv(b))
133+
if a.required_poly_trait_ref(tcx)
134+
.eq_modulo_constness(&b.required_poly_trait_ref(tcx))
135+
&& a.term() == b.term() =>
136+
{
137+
return false;
138+
}
129139
(ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
130140
(ParamEnv(..), _) => return false,
131141
(_, ParamEnv(..)) => unreachable!(),
@@ -1365,7 +1375,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
13651375

13661376
match is_match {
13671377
ProjectionMatchesProjection::Yes => {
1368-
candidate_set.push_candidate(ctor(data));
1378+
candidate_set.push_candidate(infcx.tcx, ctor(data));
13691379

13701380
if potentially_unnormalized_candidates
13711381
&& !obligation.predicate.has_infer_types_or_consts()
@@ -1635,7 +1645,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
16351645
};
16361646

16371647
if eligible {
1638-
if candidate_set.push_candidate(ProjectionCandidate::Select(impl_source)) {
1648+
if candidate_set.push_candidate(selcx.tcx(), ProjectionCandidate::Select(impl_source)) {
16391649
Ok(())
16401650
} else {
16411651
Err(())

compiler/rustc_trait_selection/src/traits/select/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1645,7 +1645,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16451645
(ParamCandidate(other), ParamCandidate(victim)) => {
16461646
let same_except_bound_vars = other.skip_binder().trait_ref
16471647
== victim.skip_binder().trait_ref
1648-
&& other.skip_binder().constness() == victim.skip_binder().constness()
16491648
&& other.skip_binder().polarity == victim.skip_binder().polarity
16501649
&& !other.skip_binder().trait_ref.has_escaping_bound_vars();
16511650
if same_except_bound_vars {
@@ -1655,7 +1654,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16551654
// probably best characterized as a "hack", since we might prefer to just do our
16561655
// best to *not* create essentially duplicate candidates in the first place.
16571656
other.bound_vars().len() <= victim.bound_vars().len()
1658-
} else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
1657+
} else if other
1658+
.skip_binder()
1659+
.trait_ref
1660+
.eq_modulo_constness(&victim.skip_binder().trait_ref)
16591661
&& victim.skip_binder().constness() == ty::ConstnessArg::Not
16601662
&& other.skip_binder().polarity == victim.skip_binder().polarity
16611663
{

0 commit comments

Comments
 (0)