From 448c5c220d101822d4d3acce5b89d369899a7660 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 11 Jun 2026 06:29:46 +0530 Subject: [PATCH 1/6] add auxiliary module to define Trait and type in a different crate (cherry picked from commit 64072284928e82991f7a2e9737f4699a384cc045) --- ...erence-unknowable-does-not-eagerly-normalize-dep.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/ui/traits/next-solver/coherence/auxiliary/coherence-unknowable-does-not-eagerly-normalize-dep.rs diff --git a/tests/ui/traits/next-solver/coherence/auxiliary/coherence-unknowable-does-not-eagerly-normalize-dep.rs b/tests/ui/traits/next-solver/coherence/auxiliary/coherence-unknowable-does-not-eagerly-normalize-dep.rs new file mode 100644 index 0000000000000..72f926d28ba42 --- /dev/null +++ b/tests/ui/traits/next-solver/coherence/auxiliary/coherence-unknowable-does-not-eagerly-normalize-dep.rs @@ -0,0 +1,10 @@ +// Based on this: https://rust-lang.zulipchat.com/#narrow/channel/326866-t-types.2Fnominated/topic/.23157407.3A.201.2E97.20beta.20regression.3A.20.22conflicting.20implementations.E2.80.A6/near/601113926 +pub trait Row { + type Database; +} + +pub struct PgRow; + +impl Row for PgRow { + type Database = (); +} From 3c51bd43b0c8c6133aaa89cbd914278d79055462 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 11 Jun 2026 06:30:33 +0530 Subject: [PATCH 2/6] test to see if the coherence fails, when aliases are eagerly normalized (cherry picked from commit 6a6ebb983dcd2f5f08912b26dd4c6ae59139dea6) --- ...e-unknowable-does-not-eagerly-normalize.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs diff --git a/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs b/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs new file mode 100644 index 0000000000000..13cdcc7d93e58 --- /dev/null +++ b/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs @@ -0,0 +1,28 @@ +//@ compile-flags: -Znext-solver=coherence +//@ check-pass +//@ aux-build:coherence-unknowable-does-not-eagerly-normalize-dep.rs +// +// Refer issue: https://github.com/rust-lang/rust/issues/157407 +// +// The reason this regression happened is because `::Database` +// does not get normalized to `()`, but instead +// `ActivityType: Decode<::Database>` gets treated like +// `ActivityType: Decode`, staying ambiguous. +// Now it is considered that a downstream crate may provide such an impl, even +// though `::Database` can only normalize to a local or upstream +// type, thus causing this. + +extern crate coherence_unknowable_does_not_eagerly_normalize_dep as dep; + +use dep::{PgRow, Row}; + +trait FromRow {} +trait Decode {} + +struct ActivityType; + +impl FromRow for PgRow {} + +impl FromRow for R where ActivityType: Decode {} + +fn main() {} From 51d904f3c7c6967eff38b6ecbd2622f97decccfd Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 11 Jun 2026 06:30:56 +0530 Subject: [PATCH 3/6] make sure to not normalize impl header in coherence (cherry picked from commit 91f63cb1e008faa9e578a4e06cf8610ea8e2349d) --- .../rustc_trait_selection/src/traits/coherence.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 49cc2833cd978..03a8e3af51138 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -278,10 +278,16 @@ fn overlap<'tcx>( // empty environment. let param_env = ty::ParamEnv::empty(); - let impl1_header = - fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, is_of_trait); - let impl2_header = - fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, is_of_trait); + let impl1_header = if tcx.next_trait_solver_in_coherence() { + fresh_impl_header(selcx.infcx, impl1_def_id, is_of_trait) + } else { + fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, is_of_trait) + }; + let impl2_header = if tcx.next_trait_solver_in_coherence() { + fresh_impl_header(selcx.infcx, impl2_def_id, is_of_trait) + } else { + fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, is_of_trait) + }; // Equate the headers to find their intersection (the general type, with infer vars, // that may apply both impls). From 9a2d04134ef698ec63abd55833ef2120786fd9ab Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 11 Jun 2026 06:31:12 +0530 Subject: [PATCH 4/6] updating other test error types (cherry picked from commit 063fdc0aa1a715dad4145935d1a28225858fd064) --- .../associated-types-coherence-failure.stderr | 8 ++--- .../coherence/coherence-with-closure.stderr | 4 +-- .../coherence-with-coroutine.stock.stderr | 4 +-- .../ui/coherence/normalize-for-errors.stderr | 4 +-- .../unevaluated-const-ice-119731.rs | 3 ++ .../unevaluated-const-ice-119731.stderr | 32 ++++++++++++++++--- tests/ui/const-generics/issues/issue-89304.rs | 4 +-- .../const-generics/issues/issue-89304.stderr | 21 ------------ .../default-item-normalization-ambig-1.stderr | 4 +-- .../alias_eq_substs_eq_not_intercrate.stderr | 4 +-- ...trait_ref_is_knowable-norm-overflow.stderr | 3 +- .../cycles/unproductive-in-coherence.rs | 2 +- .../cycles/unproductive-in-coherence.stderr | 2 +- .../coherence/coherence_cross_crate.stderr | 4 +-- .../coherence_different_hidden_ty.stderr | 4 +-- .../impl_trait_for_same_tait.stderr | 12 +++---- .../implied_lifetime_wf_check.error.stderr | 4 +-- .../issue-84660-unsoundness.current.stderr | 2 +- .../issue-84660-unsoundness.next.stderr | 2 +- 19 files changed, 64 insertions(+), 59 deletions(-) delete mode 100644 tests/ui/const-generics/issues/issue-89304.stderr diff --git a/tests/ui/associated-types/associated-types-coherence-failure.stderr b/tests/ui/associated-types/associated-types-coherence-failure.stderr index 211613b371492..25c22e5f82ac2 100644 --- a/tests/ui/associated-types/associated-types-coherence-failure.stderr +++ b/tests/ui/associated-types/associated-types-coherence-failure.stderr @@ -1,20 +1,20 @@ -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` --> $DIR/associated-types-coherence-failure.rs:21:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` -error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_` +error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned` --> $DIR/associated-types-coherence-failure.rs:28:1 | LL | impl<'a, B: ?Sized> IntoCow<'a, B> for ::Owned where B: ToOwned { | ----------------------------------------------------------------------------- first implementation here ... LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned` error: aborting due to 2 previous errors diff --git a/tests/ui/coherence/coherence-with-closure.stderr b/tests/ui/coherence/coherence-with-closure.stderr index e1a0b5156e4f4..37f393ceeb70a 100644 --- a/tests/ui/coherence/coherence-with-closure.stderr +++ b/tests/ui/coherence/coherence-with-closure.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<_>` +error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper` --> $DIR/coherence-with-closure.rs:12:1 | LL | impl Trait for Wrapper {} | ------------------------------------- first implementation here LL | impl Trait for Wrapper {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence-with-coroutine.stock.stderr b/tests/ui/coherence/coherence-with-coroutine.stock.stderr index 511f6d2318feb..c7af384df6d30 100644 --- a/tests/ui/coherence/coherence-with-coroutine.stock.stderr +++ b/tests/ui/coherence/coherence-with-coroutine.stock.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<_>` +error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper` --> $DIR/coherence-with-coroutine.rs:23:1 | LL | impl Trait for Wrapper {} | --------------------------------------- first implementation here LL | impl Trait for Wrapper {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<_>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper` error: aborting due to 1 previous error diff --git a/tests/ui/coherence/normalize-for-errors.stderr b/tests/ui/coherence/normalize-for-errors.stderr index 74a3015801d2b..6fbcf5b0e1aca 100644 --- a/tests/ui/coherence/normalize-for-errors.stderr +++ b/tests/ui/coherence/normalize-for-errors.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)` +error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)` --> $DIR/normalize-for-errors.rs:13:1 | LL | impl MyTrait for (T, S::Item) {} | ------------------------------------------------------ first implementation here LL | LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)` | = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs index 905e4ec4571db..99130689d7ce2 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.rs @@ -28,6 +28,9 @@ mod v20 { impl v17 { //~^ ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} //~| ERROR: maximum number of nodes exceeded in constant v20::v17::::{constant#0} pub const fn v21() -> v18 { //~^ ERROR cannot find type `v18` in this scope diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index c2df999dc7647..022074181cecd 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -1,5 +1,5 @@ error[E0432]: unresolved import `v20::v13` - --> $DIR/unevaluated-const-ice-119731.rs:39:15 + --> $DIR/unevaluated-const-ice-119731.rs:42:15 | LL | pub use v20::{v13, v17}; | ^^^ no `v13` in `v20` @@ -32,7 +32,7 @@ LL + pub const fn v21() -> v11 {} | error[E0425]: cannot find type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:32:31 + --> $DIR/unevaluated-const-ice-119731.rs:35:31 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -47,7 +47,7 @@ LL + pub const fn v21() -> v11 { | error[E0422]: cannot find struct, variant or union type `v18` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:34:13 + --> $DIR/unevaluated-const-ice-119731.rs:37:13 | LL | pub type v11 = [[usize; v4]; v4]; | --------------------------------- similarly named type alias `v11` defined here @@ -115,6 +115,30 @@ LL | impl v17 { | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} + --> $DIR/unevaluated-const-ice-119731.rs:28:37 + | +LL | impl v17 { + | ^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0592]: duplicate definitions with name `v21` --> $DIR/unevaluated-const-ice-119731.rs:23:9 | @@ -124,7 +148,7 @@ LL | pub const fn v21() -> v18 {} LL | pub const fn v21() -> v18 { | ------------------------- other definition for `v21` -error: aborting due to 11 previous errors; 2 warnings emitted +error: aborting due to 14 previous errors; 2 warnings emitted Some errors have detailed explanations: E0422, E0425, E0432, E0592. For more information about an error, try `rustc --explain E0422`. diff --git a/tests/ui/const-generics/issues/issue-89304.rs b/tests/ui/const-generics/issues/issue-89304.rs index e8167deec84e3..d5cbfc9300b1c 100644 --- a/tests/ui/const-generics/issues/issue-89304.rs +++ b/tests/ui/const-generics/issues/issue-89304.rs @@ -1,17 +1,17 @@ +//@ check-pass + #![feature(generic_const_exprs)] #![allow(incomplete_features)] struct GenericStruct { val: i64 } impl From> for GenericStruct<{T + 1}> { -//~^ ERROR: conflicting implementations of trait `From>` for type `GenericStruct<_>` fn from(other: GenericStruct) -> Self { Self { val: other.val } } } impl From> for GenericStruct { -//~^ ERROR: conflicting implementations of trait `From>` for type `GenericStruct<_>` fn from(other: GenericStruct<{T + 1}>) -> Self { Self { val: other.val } } diff --git a/tests/ui/const-generics/issues/issue-89304.stderr b/tests/ui/const-generics/issues/issue-89304.stderr deleted file mode 100644 index cac8cd32915ef..0000000000000 --- a/tests/ui/const-generics/issues/issue-89304.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0119]: conflicting implementations of trait `From>` for type `GenericStruct<_>` - --> $DIR/issue-89304.rs:6:1 - | -LL | impl From> for GenericStruct<{T + 1}> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl From for T; - -error[E0119]: conflicting implementations of trait `From>` for type `GenericStruct<_>` - --> $DIR/issue-89304.rs:13:1 - | -LL | impl From> for GenericStruct { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl From for T; - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr index 1c1364543e772..f45c4e55572bf 100644 --- a/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr +++ b/tests/ui/specialization/coherence/default-item-normalization-ambig-1.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `Y` +error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U` --> $DIR/default-item-normalization-ambig-1.rs:20:1 | LL | impl Y for <() as X>::U {} | ----------------------- first implementation here LL | impl Y for ::U {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U` error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr index 5000195883cce..8c6840f72a7ff 100644 --- a/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr +++ b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `Overlaps>` +error[E0119]: conflicting implementations of trait `Overlaps>` for type `<_ as TraitB>::Assoc` --> $DIR/alias_eq_substs_eq_not_intercrate.rs:14:1 | LL | impl Overlaps> for ::Assoc {} | --------------------------------------------------------- first implementation here LL | impl Overlaps for ::Assoc {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as TraitB>::Assoc` | = note: downstream crates may implement trait `TraitB` for type `std::boxed::Box<_>` diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index 117a6d740df2a..34a45e9363069 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -7,8 +7,7 @@ LL | struct LocalTy; LL | impl Trait for ::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation | - = note: overflow evaluating the requirement `::Assoc == _` - = note: overflow evaluating the requirement `::Assoc == _` + = note: overflow evaluating the requirement `_ == ::Assoc` = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs index d9f7cf8281410..f841a025476b8 100644 --- a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs +++ b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs @@ -16,6 +16,6 @@ impl Trait for Overflow { trait Overlap {} impl Overlap, U> for T {} impl Overlap for Overflow {} -//~^ ERROR: conflicting implementations of trait `Overlap` for type +//~^ ERROR: conflicting implementations of trait `Overlap<::Assoc, _>` for type `Overflow` [E0119] fn main() {} diff --git a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr index 430b3acec3fb1..6605a28d54771 100644 --- a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr +++ b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Overlap` for type `Overflow` +error[E0119]: conflicting implementations of trait `Overlap<::Assoc, _>` for type `Overflow` --> $DIR/unproductive-in-coherence.rs:18:1 | LL | impl Overlap, U> for T {} diff --git a/tests/ui/type-alias-impl-trait/coherence/coherence_cross_crate.stderr b/tests/ui/type-alias-impl-trait/coherence/coherence_cross_crate.stderr index c9b0bb1c9e8c9..6b251cfac73c8 100644 --- a/tests/ui/type-alias-impl-trait/coherence/coherence_cross_crate.stderr +++ b/tests/ui/type-alias-impl-trait/coherence/coherence_cross_crate.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `OtherTrait` for type `i32` +error[E0119]: conflicting implementations of trait `OtherTrait` for type `Alias` --> $DIR/coherence_cross_crate.rs:22:1 | LL | impl OtherTrait for Alias {} | ------------------------- first implementation here LL | impl OtherTrait for i32 {} - | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias` | = note: upstream crates may add a new impl of trait `coherence_cross_crate_trait_decl::SomeTrait` for type `i32` in future versions diff --git a/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr b/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr index 874a10d4919e1..ef170101b4455 100644 --- a/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr +++ b/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `(u32, i32)` +error[E0119]: conflicting implementations of trait `Trait` for type `(TAIT, TAIT)` --> $DIR/coherence_different_hidden_ty.rs:20:1 | LL | impl Trait for (TAIT, TAIT) {} | --------------------------- first implementation here LL | LL | impl Trait for (u32, i32) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(u32, i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(TAIT, TAIT)` error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr index 89710fba6f591..2f44ee481adcd 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr @@ -1,29 +1,29 @@ -error[E0119]: conflicting implementations of trait `Bop` +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` --> $DIR/impl_trait_for_same_tait.rs:18:1 | LL | impl Bop for Bar<()> {} | -------------------- first implementation here ... LL | impl Bop for Bar {} - | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` -error[E0119]: conflicting implementations of trait `Bop` +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` --> $DIR/impl_trait_for_same_tait.rs:28:1 | LL | impl Bop for Bar<()> {} | -------------------- first implementation here ... LL | impl Bop for Barr {} - | ^^^^^^^^^^^^^^^^^ conflicting implementation + | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` -error[E0119]: conflicting implementations of trait `Bop` for type `i32` +error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>` --> $DIR/impl_trait_for_same_tait.rs:32:1 | LL | impl Bop for Bar<()> {} | -------------------- first implementation here ... LL | impl Bop for i32 {} - | ^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>` error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr index be2087e11a88b..3bc6b9205ec15 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr @@ -1,11 +1,11 @@ -error[E0119]: conflicting implementations of trait `Yay` for type `i32` +error[E0119]: conflicting implementations of trait `Yay` for type `<() as HideIt>::Assoc` --> $DIR/implied_lifetime_wf_check.rs:27:1 | LL | impl Yay for <() as HideIt>::Assoc {} | ---------------------------------- first implementation here LL | #[cfg(error)] LL | impl Yay for i32 {} - | ^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | ^^^^^^^^^^^^^^^^ conflicting implementation for `<() as HideIt>::Assoc` error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr index 29be8edd44f58..577d8667a57ad 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Trait<(), _>` +error[E0119]: conflicting implementations of trait `Trait` --> $DIR/issue-84660-unsoundness.rs:31:1 | LL | impl Trait for Out { diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr index 1c07b29887b1e..3399c85a3034e 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `Trait<(), _>` +error[E0119]: conflicting implementations of trait `Trait` --> $DIR/issue-84660-unsoundness.rs:31:1 | LL | impl Trait for Out { From d2e3ae1ca616f28f72afba086d5b3bfc85fb9fc5 Mon Sep 17 00:00:00 2001 From: Hanna Kruppe Date: Sun, 21 Jun 2026 15:07:54 +0200 Subject: [PATCH 5/6] add test case for miscompilation (cherry picked from commit 5b5e4082242f20adbf6ac11f1da9a9b4c18707fb) --- ...comparison.SimplifyComparisonIntegral.diff | 28 +++++++++++++++++++ tests/mir-opt/if_condition_int.rs | 27 ++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff diff --git a/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff new file mode 100644 index 0000000000000..b3d38516dec0e --- /dev/null +++ b/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff @@ -0,0 +1,28 @@ +- // MIR for `dont_remove_moved_comparison` before SimplifyComparisonIntegral ++ // MIR for `dont_remove_moved_comparison` after SimplifyComparisonIntegral + + fn dont_remove_moved_comparison(_1: i8) -> i32 { + let mut _0: i32; + let mut _2: bool; + let mut _3: i32; + let mut _4: i32; + + bb0: { +- _2 = Eq(copy _1, const 17_i8); ++ nop; + _3 = copy _2 as i32 (IntToInt); +- switchInt(move _2) -> [1: bb1, otherwise: bb2]; ++ switchInt(copy _1) -> [17: bb1, otherwise: bb2]; + } + + bb1: { + _0 = copy _3; + return; + } + + bb2: { + _0 = Add(copy _3, const 1_i32); + return; + } + } + diff --git a/tests/mir-opt/if_condition_int.rs b/tests/mir-opt/if_condition_int.rs index 5e0961da3ccea..6950faf502005 100644 --- a/tests/mir-opt/if_condition_int.rs +++ b/tests/mir-opt/if_condition_int.rs @@ -103,6 +103,33 @@ fn dont_remove_comparison(a: i8) -> i32 { } } +// EMIT_MIR if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff +#[custom_mir(dialect = "runtime")] +fn dont_remove_moved_comparison(a: i8) -> i32 { + mir! { + let b: bool; + let c: i32; + let d: i32; + { + b = a == 17; + c = b as i32; + match Move(b) { + true => bb1, + _ => bb2, + } + + } + bb1 = { + RET = c; + Return() + } + bb2 = { + RET = c + 1; + Return() + } + } +} + // EMIT_MIR if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff // test that we do not optimize on floats fn dont_opt_floats(a: f32) -> i32 { From c93dd3ec6796d6456090fa071a52c213bf16864e Mon Sep 17 00:00:00 2001 From: Hanna Kruppe Date: Sun, 21 Jun 2026 15:22:37 +0200 Subject: [PATCH 6/6] don't try to remove assignments in SimplifyComparisonIntegral (cherry picked from commit a642d9b63c6236074005c10d52df5aef691b4815) --- .../src/simplify_comparison_integral.rs | 46 ++++++++----------- ...comparison.SimplifyComparisonIntegral.diff | 3 +- ...t.opt_char.SimplifyComparisonIntegral.diff | 3 +- ...int.opt_i8.SimplifyComparisonIntegral.diff | 3 +- ...ltiple_ifs.SimplifyComparisonIntegral.diff | 6 +-- ...t_negative.SimplifyComparisonIntegral.diff | 3 +- ...nt.opt_u32.SimplifyComparisonIntegral.diff | 3 +- tests/mir-opt/if_condition_int.rs | 11 ++++- 8 files changed, 35 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 74e5fc6f34579..0076e3ed4167c 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -76,30 +76,24 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { _ => unreachable!(), } - // delete comparison statement if it the value being switched on was moved, which means - // it can not be used later on - if opt.can_remove_bin_op_stmt { - bb.statements[opt.bin_op_stmt_idx].make_nop(true); - } else { - // if the integer being compared to a const integral is being moved into the - // comparison, e.g `_2 = Eq(move _3, const 'x');` - // we want to avoid making a double move later on in the switchInt on _3. - // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`, - // we convert the move in the comparison statement to a copy. - - // unwrap is safe as we know this statement is an assign - let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap(); - - use Operand::*; - match rhs { - Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => { - *left = Copy(opt.to_switch_on); - } - Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => { - *right = Copy(opt.to_switch_on); - } - _ => (), + // if the integer being compared to a const integral is being moved into the + // comparison, e.g `_2 = Eq(move _3, const 'x');` + // we want to avoid making a double move later on in the switchInt on _3. + // So to avoid `switchInt(move _3) -> ['x': bb2, otherwise: bb1];`, + // we convert the move in the comparison statement to a copy. + + // unwrap is safe as we know this statement is an assign + let (_, rhs) = bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap(); + + use Operand::*; + match rhs { + Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => { + *left = Copy(opt.to_switch_on); + } + Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => { + *right = Copy(opt.to_switch_on); } + _ => (), } let terminator = bb.terminator(); @@ -184,7 +178,6 @@ impl<'tcx> OptimizationFinder<'_, 'tcx> { Some(OptimizationInfo { bin_op_stmt_idx: stmt_idx, bb_idx, - can_remove_bin_op_stmt: discr.is_move(), to_switch_on, branch_value_scalar, branch_value_ty, @@ -235,11 +228,8 @@ fn find_branch_value_info<'tcx>( struct OptimizationInfo<'tcx> { /// Basic block to apply the optimization bb_idx: BasicBlock, - /// Statement index of Eq/Ne assignment that can be removed. None if the assignment can not be - /// removed - i.e the statement is used later on + /// Statement index of Eq/Ne assignment bin_op_stmt_idx: usize, - /// Can remove Eq/Ne assignment - can_remove_bin_op_stmt: bool, /// Place that needs to be switched on. This place is of type integral to_switch_on: Place<'tcx>, /// Constant to use in switch target value diff --git a/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff index b3d38516dec0e..e59e2fde016d2 100644 --- a/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff @@ -8,8 +8,7 @@ let mut _4: i32; bb0: { -- _2 = Eq(copy _1, const 17_i8); -+ nop; + _2 = Eq(copy _1, const 17_i8); _3 = copy _2 as i32 (IntToInt); - switchInt(move _2) -> [1: bb1, otherwise: bb2]; + switchInt(copy _1) -> [17: bb1, otherwise: bb2]; diff --git a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff index 22f6443a6c0f9..58c95e20975ee 100644 --- a/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 'x'); + _2 = Eq(copy _1, const 'x'); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [120: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff index d5c48fd04ca60..23dc079de01a0 100644 --- a/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 42_i8); + _2 = Eq(copy _1, const 42_i8); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff index 84d62b8136078..5baf481616186 100644 --- a/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff @@ -13,9 +13,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 42_u32); + _2 = Eq(copy _1, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } @@ -30,9 +29,8 @@ StorageLive(_4); StorageLive(_5); _5 = copy _1; -- _4 = Ne(copy _1, const 21_u32); + _4 = Ne(copy _1, const 21_u32); - switchInt(move _4) -> [0: bb4, otherwise: bb3]; -+ nop; + switchInt(copy _1) -> [21: bb4, otherwise: bb3]; } diff --git a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff index a1cbaff796b35..79c3525663c89 100644 --- a/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const -42_i32); + _2 = Eq(copy _1, const -42_i32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [4294967254: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff index 8101de8cbf381..3e950f053bc35 100644 --- a/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff +++ b/tests/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff @@ -11,9 +11,8 @@ StorageLive(_2); StorageLive(_3); _3 = copy _1; -- _2 = Eq(copy _1, const 42_u32); + _2 = Eq(copy _1, const 42_u32); - switchInt(move _2) -> [0: bb2, otherwise: bb1]; -+ nop; + switchInt(copy _1) -> [42: bb1, otherwise: bb2]; } diff --git a/tests/mir-opt/if_condition_int.rs b/tests/mir-opt/if_condition_int.rs index 6950faf502005..6eed1191ffc57 100644 --- a/tests/mir-opt/if_condition_int.rs +++ b/tests/mir-opt/if_condition_int.rs @@ -85,7 +85,7 @@ fn opt_multiple_ifs(x: u32) -> u32 { } // EMIT_MIR if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff -// test that we optimize, but do not remove the b statement, as that is used later on +// the switchInt can be optimized but the b statement can't be removed as it's used later on fn dont_remove_comparison(a: i8) -> i32 { // CHECK-LABEL: fn dont_remove_comparison( // CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8); @@ -104,8 +104,17 @@ fn dont_remove_comparison(a: i8) -> i32 { } // EMIT_MIR if_condition_int.dont_remove_moved_comparison.SimplifyComparisonIntegral.diff +// like dont_remove_comparison above, but with switchInt(move _N) - regression test for #158206 #[custom_mir(dialect = "runtime")] fn dont_remove_moved_comparison(a: i8) -> i32 { + // CHECK-LABEL: fn dont_remove_moved_comparison( + // CHECK: [[b:_.*]] = Eq(copy _1, const 17_i8); + // CHECK: [[cast:_.*]] = copy [[b]] as i32 (IntToInt); + // CHECK: switchInt(copy _1) -> [17: [[BB1:bb.*]], otherwise: [[BB2:bb.*]]]; + // CHECK: [[BB1]]: + // CHECK: _0 = copy [[cast]]; + // CHECK: [[BB2]]: + // CHECK: _0 = Add(copy [[cast]], const 1_i32); mir! { let b: bool; let c: i32;