From 134d2ce56f81b96320f1ffb5473a3be41654e590 Mon Sep 17 00:00:00 2001 From: Yuki Okamoto Date: Sun, 21 Jun 2026 16:50:37 +0900 Subject: [PATCH] fix: defer const normalize in coherence mode --- .../src/infer/relate/generalize.rs | 13 +++++++- ...herence-overlap-const-projection-157937.rs | 33 +++++++++++++++++++ ...nce-overlap-const-projection-157937.stderr | 12 +++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.stderr diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index ee6e13250e709..ae5db4ea177c2 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -797,11 +797,22 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { // We only need to be careful with potentially normalizeable // aliases here. See `generalize_alias_term` for more information. ty::ConstKind::Alias(ty::IsRigid::No, alias_const) => { + // a normalizable const in coherence mode misses overlaps; see #157937. + // expand anon consts with `expand_abstract_consts`. + let defer_in_coherence = self.infcx.typing_mode_raw().is_coherence() + && matches!( + tcx.expand_abstract_consts(c).kind(), + ty::ConstKind::Alias(_, e) + if !matches!(e.kind, ty::AliasConstKind::Anon { .. }) + ); + match self.structurally_relate_aliases { // Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes // path), as doing this new No path breaks some GCE things. I expect GCE to be // ripped out soon so this shouldn't matter soon. - StructurallyRelateAliases::No if !tcx.features().generic_const_exprs() => { + StructurallyRelateAliases::No + if !tcx.features().generic_const_exprs() || defer_in_coherence => + { self.generalize_alias_term(alias_const.into()).map(|v| v.expect_const()) } _ => { diff --git a/tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.rs b/tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.rs new file mode 100644 index 0000000000000..7f7766dbf035e --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.rs @@ -0,0 +1,33 @@ +// Cited from [#157937](https://github.com/rust-lang/rust/issues/157937) + +#![feature(generic_const_exprs)] +trait Trait { + const CONST: usize; +} +struct A { + _marker: T, +} +impl Trait for [i8; N] { + const CONST: usize = N; +} +impl From for A<[i8; N]> { + fn from(_: usize) -> Self { + todo!() + } +} +impl From> for A { +//~^ ERROR: conflicting implementations of trait `From>` for type `A<[i8; _]>` [E0119] + fn from(_: A<[i8; T::CONST]>) -> Self { + todo!() + } +} +fn f() -> A +where + [(); T::CONST]:, +{ + let a = A::from(0); + A::from(a) +} +fn main() { + f::<[i8; 1]>(); +} diff --git a/tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.stderr b/tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.stderr new file mode 100644 index 0000000000000..8d72acec7da52 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/coherence-overlap-const-projection-157937.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `From>` for type `A<[i8; _]>` + --> $DIR/coherence-overlap-const-projection-157937.rs:18:1 + | +LL | impl From> for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl From for T; + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`.