diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 8c296289fef0c..34b75f52fe764 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -752,24 +752,40 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { // // FIXME: replace the StructurallyRelateAliases::Yes branch with // `structurally_relate_consts` once it is fully structural. - ty::ConstKind::Unevaluated(uv) => 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() => { - self.generalize_alias_term(uv.into()).map(|v| v.expect_const()) - } - _ => { - let ty::UnevaluatedConst { kind, args, .. } = uv; - let args = self.relate_with_variance( - ty::Invariant, - ty::VarianceDiagInfo::default(), - args, - args, - )?; - Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(tcx, kind, args))) + ty::ConstKind::Unevaluated(uv) => { + // a normalizable const in coherence mode misses overlaps; see #157937 + // assoc const is now anon const, so unwrap with `expand_abstract_consts` + let defer_in_coherence = self.infcx.typing_mode_raw().is_coherence() + && matches!( + tcx.expand_abstract_consts(c).kind(), + ty::ConstKind::Unevaluated(e) + if !matches!(e.kind, ty::UnevaluatedConstKind::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() || defer_in_coherence => + { + self.generalize_alias_term(uv.into()).map(|v| v.expect_const()) + } + _ => { + let ty::UnevaluatedConst { kind, args, .. } = uv; + let args = self.relate_with_variance( + ty::Invariant, + ty::VarianceDiagInfo::default(), + args, + args, + )?; + Ok(ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new(tcx, kind, args), + )) + } } - }, + } ty::ConstKind::Placeholder(placeholder) => { if self.for_universe.can_name(placeholder.universe) { Ok(c) 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`.