about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/relate/combine.rs39
-rw-r--r--compiler/rustc_middle/src/query/mod.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs21
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs1
-rw-r--r--tests/crashes/119381.rs6
-rw-r--r--tests/crashes/121585-1.rs13
-rw-r--r--tests/crashes/121585-2.rs30
-rw-r--r--tests/crashes/121858-2.rs20
-rw-r--r--tests/crashes/124151.rs14
-rw-r--r--tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs12
-rw-r--r--tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr15
-rw-r--r--tests/ui/const-generics/bad-subst-const-kind.rs2
-rw-r--r--tests/ui/const-generics/bad-subst-const-kind.stderr15
-rw-r--r--tests/ui/const-generics/generic_const_exprs/type_mismatch.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr14
-rw-r--r--tests/ui/const-generics/issues/issue-105821.rs8
-rw-r--r--tests/ui/const-generics/issues/issue-105821.stderr8
-rw-r--r--tests/ui/consts/eval_type_mismatch.rs (renamed from tests/crashes/121858.rs)7
-rw-r--r--tests/ui/consts/eval_type_mismatch.stderr34
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs3
-rw-r--r--tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr36
21 files changed, 129 insertions, 180 deletions
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 101598c5951..7e7d4f43c7c 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -22,11 +22,11 @@ use super::glb::Glb;
 use super::lub::Lub;
 use super::type_relating::TypeRelating;
 use super::StructurallyRelateAliases;
-use crate::infer::{DefineOpaqueTypes, InferCtxt, TypeTrace};
+use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, TypeTrace};
 use crate::traits::{Obligation, PredicateObligations};
 use rustc_middle::bug;
-use rustc_middle::infer::canonical::OriginalQueryValues;
 use rustc_middle::infer::unify_key::EffectVarValue;
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::relate::{RelateResult, TypeRelation};
 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitableExt, Upcast};
@@ -159,36 +159,11 @@ impl<'tcx> InferCtxt<'tcx> {
         let a = self.shallow_resolve_const(a);
         let b = self.shallow_resolve_const(b);
 
-        // We should never have to relate the `ty` field on `Const` as it is checked elsewhere that consts have the
-        // correct type for the generic param they are an argument for. However there have been a number of cases
-        // historically where asserting that the types are equal has found bugs in the compiler so this is valuable
-        // to check even if it is a bit nasty impl wise :(
-        //
-        // This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
-        // ourselves with a check to find bugs being required for code to compile because it made inference progress.
-        self.probe(|_| {
-            if a.ty() == b.ty() {
-                return;
-            }
-
-            // We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
-            // two const param's types are able to be equal has to go through a canonical query with the actual logic
-            // in `rustc_trait_selection`.
-            let canonical = self.canonicalize_query(
-                relation.param_env().and((a.ty(), b.ty())),
-                &mut OriginalQueryValues::default(),
-            );
-            self.tcx.check_tys_might_be_eq(canonical).unwrap_or_else(|_| {
-                // The error will only be reported later. If we emit an ErrorGuaranteed
-                // here, then we will never get to the code that actually emits the error.
-                self.tcx.dcx().delayed_bug(format!(
-                    "cannot relate consts of different types (a={a:?}, b={b:?})",
-                ));
-                // We treat these constants as if they were of the same type, so that any
-                // such constants being used in impls make these impls match barring other mismatches.
-                // This helps with diagnostics down the road.
-            });
-        });
+        // It is always an error if the types of two constants that are related are not equal.
+        let InferOk { value: (), obligations } = self
+            .at(&ObligationCause::dummy_with_span(relation.span()), relation.param_env())
+            .eq(DefineOpaqueTypes::No, a.ty(), b.ty())?;
+        relation.register_obligations(obligations);
 
         match (a.kind(), b.kind()) {
             (
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 5a6decc4f94..8ca7a465c2a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2218,15 +2218,6 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    /// Used in `super_combine_consts` to ICE if the type of the two consts are definitely not going to end up being
-    /// equal to eachother. This might return `Ok` even if the types are not equal, but will never return `Err` if
-    /// the types might be equal.
-    query check_tys_might_be_eq(
-        arg: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>
-    ) -> Result<(), NoSolution> {
-        desc { "check whether two const param are definitely not equal to eachother"}
-    }
-
     /// Get all item paths that were stripped by a `#[cfg]` in a particular crate.
     /// Should not be called for the local crate before the resolver outputs are created, as it
     /// is only fed there.
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index da2b004761f..a1094d98276 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -1,17 +1,14 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
 use crate::regions::InferCtxtRegionExt;
-use crate::traits::{self, ObligationCause, ObligationCtxt};
+use crate::traits::{self, ObligationCause};
 
 use hir::LangItem;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
-use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
-use rustc_infer::traits::query::NoSolution;
 use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::DUMMY_SP;
 
 use super::outlives_bounds::InferCtxtExt;
 
@@ -207,19 +204,3 @@ pub fn all_fields_implement_trait<'tcx>(
 
     if infringing.is_empty() { Ok(()) } else { Err(infringing) }
 }
-
-pub fn check_tys_might_be_eq<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    canonical: Canonical<'tcx, ty::ParamEnvAnd<'tcx, (Ty<'tcx>, Ty<'tcx>)>>,
-) -> Result<(), NoSolution> {
-    let (infcx, key, _) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical);
-    let (param_env, (ty_a, ty_b)) = key.into_parts();
-    let ocx = ObligationCtxt::new(&infcx);
-
-    let result = ocx.eq(&ObligationCause::dummy(), param_env, ty_a, ty_b);
-    // use `select_where_possible` instead of `select_all_or_error` so that
-    // we don't get errors from obligations being ambiguous.
-    let errors = ocx.select_where_possible();
-
-    if errors.len() > 0 || result.is_err() { Err(NoSolution) } else { Ok(()) }
-}
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 204bb487c86..f6003a25028 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -551,7 +551,6 @@ pub fn provide(providers: &mut Providers) {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
         instantiate_and_check_impossible_predicates,
-        check_tys_might_be_eq: misc::check_tys_might_be_eq,
         is_impossible_associated_item,
         ..*providers
     };
diff --git a/tests/crashes/119381.rs b/tests/crashes/119381.rs
deleted file mode 100644
index 51d1d084ba2..00000000000
--- a/tests/crashes/119381.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//@ known-bug: #119381
-
-#![feature(with_negative_coherence)]
-trait Trait {}
-impl<const N: u8> Trait for [(); N] {}
-impl<const N: i8> Trait for [(); N] {}
diff --git a/tests/crashes/121585-1.rs b/tests/crashes/121585-1.rs
deleted file mode 100644
index 2a4638efcab..00000000000
--- a/tests/crashes/121585-1.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ known-bug: #121585
-#![feature(generic_const_exprs)]
-
-trait Trait {}
-
-struct HasCastInTraitImpl<const N: usize, const M: u128>;
-impl<const O: f64> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-
-pub fn use_trait_impl() {
-    fn assert_impl<T: Trait>() {}
-
-    assert_impl::<HasCastInTraitImpl<13, 13>>();
-}
diff --git a/tests/crashes/121585-2.rs b/tests/crashes/121585-2.rs
deleted file mode 100644
index 99cc8f79195..00000000000
--- a/tests/crashes/121585-2.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-//@ known-bug: #121585
-//@ check-pass
-#![feature(generic_const_exprs)]
-#![allow(incomplete_features)]
-
-trait Trait {}
-pub struct EvaluatableU128<const N: u128>;
-
-struct HasCastInTraitImpl<const N: usize, const M: u128>;
-impl<const O: f64> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-
-pub fn use_trait_impl<const N: usize>() where EvaluatableU128<{N as u128}>:, {
-    fn assert_impl<T: Trait>() {}
-
-    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
-    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
-    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>();
-    assert_impl::<HasCastInTraitImpl<13, 13>>();
-}
-pub fn use_trait_impl_2<const N: usize>() where EvaluatableU128<{N as _}>:, {
-    fn assert_impl<T: Trait>() {}
-
-    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
-    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
-    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>()const NUM: u8 = xyz();
-    assert_impl::<HasCastInTraitImpl<13, 13>>();
-}
-
-
-fn main() {}
diff --git a/tests/crashes/121858-2.rs b/tests/crashes/121858-2.rs
deleted file mode 100644
index cb80c081cff..00000000000
--- a/tests/crashes/121858-2.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ known-bug: #121858
-#![allow(named_arguments_used_positionally)]
-#![feature(generic_const_exprs)]
-struct Inner<const N: usize, const M: usize>;
-impl<const N: usize, const M: usize> Inner<N, M> where [(); N + M]: {
-    fn i() -> Self {
-        Self
-    }
-}
-
-struct Outer<const A: i64, const B: usize>(Inner<A, { B * 2 }>) where [(); A + (B * 2)]:;
-impl<const A: usize, const B: usize> Outer<A, B> where [(); A + (B * 2)]: {
-    fn o() -> Union {
-        Self(Inner::i())
-    }
-}
-
-fn main() {
-    Outer::<1, 1>::o();
-}
diff --git a/tests/crashes/124151.rs b/tests/crashes/124151.rs
deleted file mode 100644
index 5e55ac2aa94..00000000000
--- a/tests/crashes/124151.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ known-bug: #124151
-#![feature(generic_const_exprs)]
-
-use std::ops::Add;
-
-pub struct Dimension;
-
-pub struct Quantity<S, const D: Dimension>(S);
-
-impl<const D: Dimension, LHS, RHS> Add<LHS, D> for Quantity<LHS, { Dimension }> {}
-
-pub fn add<const U: Dimension>(x: Quantity<f32, U>) -> Quantity<f32, U> {
-    x + y
-}
diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs
new file mode 100644
index 00000000000..89d0b74d403
--- /dev/null
+++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.rs
@@ -0,0 +1,12 @@
+//! This test used to ICE (#119381), because relating the `u8` and `i8` generic
+//! const with the array length of the `Self` type was succeeding under the
+//! assumption that an error had already been reported.
+
+#![feature(with_negative_coherence)]
+trait Trait {}
+impl<const N: u8> Trait for [(); N] {}
+//~^ ERROR: mismatched types
+impl<const N: i8> Trait for [(); N] {}
+//~^ ERROR: mismatched types
+
+fn main() {}
diff --git a/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr
new file mode 100644
index 00000000000..d1950254660
--- /dev/null
+++ b/tests/ui/coherence/negative-coherence/generic_const_type_mismatch.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/generic_const_type_mismatch.rs:7:34
+   |
+LL | impl<const N: u8> Trait for [(); N] {}
+   |                                  ^ expected `usize`, found `u8`
+
+error[E0308]: mismatched types
+  --> $DIR/generic_const_type_mismatch.rs:9:34
+   |
+LL | impl<const N: i8> Trait for [(); N] {}
+   |                                  ^ expected `usize`, found `i8`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/bad-subst-const-kind.rs b/tests/ui/const-generics/bad-subst-const-kind.rs
index ca5522a2ddf..88f98a54b6e 100644
--- a/tests/ui/const-generics/bad-subst-const-kind.rs
+++ b/tests/ui/const-generics/bad-subst-const-kind.rs
@@ -11,4 +11,4 @@ impl<const N: u64> Q for [u8; N] {
 }
 
 pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
-//~^ ERROR: the constant `13` is not of type `u64`
+//~^ ERROR: `[u8; 13]: Q` is not satisfied
diff --git a/tests/ui/const-generics/bad-subst-const-kind.stderr b/tests/ui/const-generics/bad-subst-const-kind.stderr
index c04a05573be..6cf9fa743b3 100644
--- a/tests/ui/const-generics/bad-subst-const-kind.stderr
+++ b/tests/ui/const-generics/bad-subst-const-kind.stderr
@@ -1,16 +1,10 @@
-error: the constant `13` is not of type `u64`
+error[E0277]: the trait bound `[u8; 13]: Q` is not satisfied
   --> $DIR/bad-subst-const-kind.rs:13:24
    |
 LL | pub fn test() -> [u8; <[u8; 13] as Q>::ASSOC] { todo!() }
-   |                        ^^^^^^^^ expected `u64`, found `usize`
+   |                        ^^^^^^^^ the trait `Q` is not implemented for `[u8; 13]`
    |
-note: required for `[u8; 13]` to implement `Q`
-  --> $DIR/bad-subst-const-kind.rs:8:20
-   |
-LL | impl<const N: u64> Q for [u8; N] {
-   |      ------------  ^     ^^^^^^^
-   |      |
-   |      unsatisfied trait bound introduced here
+   = help: the trait `Q` is implemented for `[u8; N]`
 
 error[E0308]: mismatched types
   --> $DIR/bad-subst-const-kind.rs:8:31
@@ -20,4 +14,5 @@ LL | impl<const N: u64> Q for [u8; N] {
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs
index 6b0d9e047db..285f9dee6c2 100644
--- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs
+++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.rs
@@ -10,7 +10,7 @@ impl<const N: u64> Q for [u8; N] {}
 //~| ERROR mismatched types
 
 pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
-//~^ ERROR the constant `13` is not of type `u64`
+//~^ ERROR `[u8; 13]: Q` is not satisfied
 //~| ERROR mismatched types
 
 pub fn main() {}
diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
index bb6d650b7ab..a63a56dd675 100644
--- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
@@ -7,19 +7,13 @@ LL |     const ASSOC: usize;
 LL | impl<const N: u64> Q for [u8; N] {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `ASSOC` in implementation
 
-error: the constant `13` is not of type `u64`
+error[E0277]: the trait bound `[u8; 13]: Q` is not satisfied
   --> $DIR/type_mismatch.rs:12:26
    |
 LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
-   |                          ^^^^^^^^ expected `u64`, found `usize`
+   |                          ^^^^^^^^ the trait `Q` is not implemented for `[u8; 13]`
    |
-note: required for `[u8; 13]` to implement `Q`
-  --> $DIR/type_mismatch.rs:8:20
-   |
-LL | impl<const N: u64> Q for [u8; N] {}
-   |      ------------  ^     ^^^^^^^
-   |      |
-   |      unsatisfied trait bound introduced here
+   = help: the trait `Q` is implemented for `[u8; N]`
 
 error[E0308]: mismatched types
   --> $DIR/type_mismatch.rs:12:20
@@ -37,5 +31,5 @@ LL | impl<const N: u64> Q for [u8; N] {}
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0046, E0308.
+Some errors have detailed explanations: E0046, E0277, E0308.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/const-generics/issues/issue-105821.rs b/tests/ui/const-generics/issues/issue-105821.rs
index a0a98103b2c..282cbe9249d 100644
--- a/tests/ui/const-generics/issues/issue-105821.rs
+++ b/tests/ui/const-generics/issues/issue-105821.rs
@@ -1,4 +1,10 @@
-//@ check-pass
+//@ failure-status: 101
+//@ known-bug: unknown
+//@ normalize-stderr-test "note: .*\n\n" -> ""
+//@ normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
+//@ normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
+//@ normalize-stderr-test "delayed at .*" -> ""
+//@ rustc-env:RUST_BACKTRACE=0
 
 #![allow(incomplete_features)]
 #![feature(adt_const_params, generic_const_exprs)]
diff --git a/tests/ui/const-generics/issues/issue-105821.stderr b/tests/ui/const-generics/issues/issue-105821.stderr
new file mode 100644
index 00000000000..1f0fc0f33ce
--- /dev/null
+++ b/tests/ui/const-generics/issues/issue-105821.stderr
@@ -0,0 +1,8 @@
+error: internal compiler error: compiler/rustc_borrowck/src/universal_regions.rs:LL:CC: cannot convert `'{erased}` to a region vid
+
+query stack during panic:
+#0 [mir_borrowck] borrow-checking `<impl at $DIR/issue-105821.rs:21:1: 23:24>::R`
+#1 [analysis] running analysis passes on this crate
+end of query stack
+error: aborting due to 1 previous error
+
diff --git a/tests/crashes/121858.rs b/tests/ui/consts/eval_type_mismatch.rs
index 7d5bae37f84..3d821ab538e 100644
--- a/tests/crashes/121858.rs
+++ b/tests/ui/consts/eval_type_mismatch.rs
@@ -1,14 +1,17 @@
-//@ known-bug: #121858
 #![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
 
 struct Outer<const A: i64, const B: usize>();
 impl<const A: usize, const B: usize> Outer<A, B>
+//~^ ERROR: `A` is not of type `i64`
+//~| ERROR: mismatched types
 where
     [(); A + (B * 2)]:,
 {
-    fn o() -> Union {}
+    fn o() {}
 }
 
 fn main() {
     Outer::<1, 1>::o();
+    //~^ ERROR: no function or associated item named `o` found
 }
diff --git a/tests/ui/consts/eval_type_mismatch.stderr b/tests/ui/consts/eval_type_mismatch.stderr
new file mode 100644
index 00000000000..38d6e33d406
--- /dev/null
+++ b/tests/ui/consts/eval_type_mismatch.stderr
@@ -0,0 +1,34 @@
+error: the constant `A` is not of type `i64`
+  --> $DIR/eval_type_mismatch.rs:5:38
+   |
+LL | impl<const A: usize, const B: usize> Outer<A, B>
+   |                                      ^^^^^^^^^^^ expected `i64`, found `usize`
+   |
+note: required by a bound in `Outer`
+  --> $DIR/eval_type_mismatch.rs:4:14
+   |
+LL | struct Outer<const A: i64, const B: usize>();
+   |              ^^^^^^^^^^^^ required by this bound in `Outer`
+
+error[E0599]: no function or associated item named `o` found for struct `Outer<1, 1>` in the current scope
+  --> $DIR/eval_type_mismatch.rs:15:20
+   |
+LL | struct Outer<const A: i64, const B: usize>();
+   | ------------------------------------------ function or associated item `o` not found for this struct
+...
+LL |     Outer::<1, 1>::o();
+   |                    ^ function or associated item not found in `Outer<1, 1>`
+   |
+   = note: the function or associated item was found for
+           - `Outer<A, B>`
+
+error[E0308]: mismatched types
+  --> $DIR/eval_type_mismatch.rs:5:44
+   |
+LL | impl<const A: usize, const B: usize> Outer<A, B>
+   |                                            ^ expected `i64`, found `usize`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0599.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
index f89a463bc58..4d1cd4332fe 100644
--- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.rs
@@ -7,7 +7,8 @@ struct S<const L: usize>;
 
 impl<const N: i32> Copy for S<N> {}
 //~^ ERROR: mismatched types
+//~| ERROR: the trait bound `S<N>: Clone` is not satisfied
+//~| ERROR: the constant `N` is not of type `usize`
 impl<const M: usize> Copy for S<M> {}
-//~^ ERROR: conflicting implementations of trait `Copy` for type `S<_>`
 
 fn main() {}
diff --git a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
index 1dac58e1f69..716a4787948 100644
--- a/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
+++ b/tests/ui/specialization/min_specialization/bad-const-wf-doesnt-specialize.stderr
@@ -1,11 +1,29 @@
-error[E0119]: conflicting implementations of trait `Copy` for type `S<_>`
-  --> $DIR/bad-const-wf-doesnt-specialize.rs:10:1
+error[E0277]: the trait bound `S<N>: Clone` is not satisfied
+  --> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
    |
 LL | impl<const N: i32> Copy for S<N> {}
-   | -------------------------------- first implementation here
-LL |
-LL | impl<const M: usize> Copy for S<M> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S<_>`
+   |                             ^^^^ the trait `Clone` is not implemented for `S<N>`
+   |
+   = help: the trait `Clone` is implemented for `S<L>`
+note: required by a bound in `Copy`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+help: consider annotating `S<N>` with `#[derive(Clone)]`
+   |
+LL + #[derive(Clone)]
+LL | struct S<const L: usize>;
+   |
+
+error: the constant `N` is not of type `usize`
+  --> $DIR/bad-const-wf-doesnt-specialize.rs:8:29
+   |
+LL | impl<const N: i32> Copy for S<N> {}
+   |                             ^^^^ expected `usize`, found `i32`
+   |
+note: required by a bound in `S`
+  --> $DIR/bad-const-wf-doesnt-specialize.rs:6:10
+   |
+LL | struct S<const L: usize>;
+   |          ^^^^^^^^^^^^^^ required by this bound in `S`
 
 error[E0308]: mismatched types
   --> $DIR/bad-const-wf-doesnt-specialize.rs:8:31
@@ -13,7 +31,7 @@ error[E0308]: mismatched types
 LL | impl<const N: i32> Copy for S<N> {}
    |                               ^ expected `usize`, found `i32`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0119, E0308.
-For more information about an error, try `rustc --explain E0119`.
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.