From dfa2e249154f2c57bedf5d50e549e32f1c87d6fc Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:49:45 +0200 Subject: [PATCH 1/3] Enable diagnostic::on_const for local impls --- .../traits/fulfillment_errors.rs | 70 +++++++++---------- .../on_const/auxiliary/const_trait.rs | 10 --- .../on_const/auxiliary/non_const_impl.rs | 15 ++++ .../on_const/it_works_foreign.rs | 15 ++++ .../on_const/it_works_foreign.stderr | 22 ++++++ .../on_const/it_works_local.rs | 25 +++++++ .../on_const/it_works_local.stderr | 15 ++++ 7 files changed, 124 insertions(+), 48 deletions(-) delete mode 100644 tests/ui/diagnostic_namespace/on_const/auxiliary/const_trait.rs create mode 100644 tests/ui/diagnostic_namespace/on_const/auxiliary/non_const_impl.rs create mode 100644 tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs create mode 100644 tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr create mode 100644 tests/ui/diagnostic_namespace/on_const/it_works_local.rs create mode 100644 tests/ui/diagnostic_namespace/on_const/it_works_local.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 3d7db3ed25b0a..3254496cf0e96 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -882,55 +882,49 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let trait_name = self.tcx.item_name(trait_did); if self.tcx.is_const_trait(trait_did) && !self.tcx.is_const_trait_impl(impl_did) { - if let Some(impl_did) = impl_did.as_local() - && let item = self.tcx.hir_expect_item(impl_did) - && let hir::ItemKind::Impl(item) = item.kind - && let Some(of_trait) = item.of_trait - { - // trait is const, impl is local and not const - diag.span_suggestion_verbose( - of_trait.trait_ref.path.span.shrink_to_lo(), - format!("make the `impl` of trait `{trait_name}` `const`"), - "const ".to_string(), - Applicability::MaybeIncorrect, - ); - } else { + if !impl_did.is_local() { diag.span_note( impl_span, format!("trait `{trait_name}` is implemented but not `const`"), ); + } - let (condition_options, format_args) = self.on_unimplemented_components( + if let Some(command) = + find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref()) + .flatten() + { + let (_, format_args) = self.on_unimplemented_components( trait_ref, main_obligation, diag.long_ty_path(), ); + let CustomDiagnostic { message, label, notes, parent_label } = + command.eval(None, &format_args); - if let Some(command) = find_attr!(self.tcx, impl_did, OnConst {directive, ..} => directive.as_deref()).flatten(){ - let note = command.eval( - Some(&condition_options), - &format_args, - ); - let CustomDiagnostic { - message, - label, - notes, - parent_label, - } = note; - - if let Some(message) = message { - diag.primary_message(message); - } - if let Some(label) = label { - diag.span_label(impl_span, label); - } - for note in notes { - diag.note(note); - } - if let Some(parent_label) = parent_label { - diag.span_label(impl_span, parent_label); - } + if let Some(message) = message { + diag.primary_message(message); + } + if let Some(label) = label { + diag.span_label(impl_span, label); + } + for note in notes { + diag.note(note); } + if let Some(parent_label) = parent_label { + diag.span_label(impl_span, parent_label); + } + } else if let Some(impl_did) = impl_did.as_local() + && let item = self.tcx.hir_expect_item(impl_did) + && let hir::ItemKind::Impl(item) = item.kind + && let Some(of_trait) = item.of_trait + { + // trait is const, impl is local and not const + diag.span_suggestion_verbose( + of_trait.trait_ref.path.span.shrink_to_lo(), + format!("make the `impl` of trait `{trait_name}` `const`"), + "const ".to_string(), + Applicability::MaybeIncorrect, + ); } } } diff --git a/tests/ui/diagnostic_namespace/on_const/auxiliary/const_trait.rs b/tests/ui/diagnostic_namespace/on_const/auxiliary/const_trait.rs deleted file mode 100644 index cf854a9072a6a..0000000000000 --- a/tests/ui/diagnostic_namespace/on_const/auxiliary/const_trait.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(diagnostic_on_const)] - -pub struct X; - -#[diagnostic::on_const(message = "message", label = "label", note = "note")] -impl PartialEq for X { - fn eq(&self, _other: &X) -> bool { - true - } -} diff --git a/tests/ui/diagnostic_namespace/on_const/auxiliary/non_const_impl.rs b/tests/ui/diagnostic_namespace/on_const/auxiliary/non_const_impl.rs new file mode 100644 index 0000000000000..3501d0ee9ec57 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/auxiliary/non_const_impl.rs @@ -0,0 +1,15 @@ +#![feature(diagnostic_on_const)] + +pub struct X; + +#[diagnostic::on_const( + message = "their message", + label = "their label", + note = "their note", + note = "their other note" +)] +impl PartialEq for X { + fn eq(&self, _other: &X) -> bool { + true + } +} diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs new file mode 100644 index 0000000000000..a56487e71de08 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs @@ -0,0 +1,15 @@ +//@ aux-build: non_const_impl.rs +#![crate_type = "lib"] + +extern crate non_const_impl; + +use non_const_impl::X; + +const _: () = { + let x = X; + x == x; + //~^ ERROR: their message + //~| NOTE: trait `PartialEq` is implemented but not `const` + //~| NOTE: their note + //~| NOTE: their other note +}; diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr new file mode 100644 index 0000000000000..12d0472443d35 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr @@ -0,0 +1,22 @@ +error[E0277]: their message + --> $DIR/it_works_foreign.rs:10:5 + | +LL | x == x; + | ^^^^^^ + | + ::: $DIR/auxiliary/non_const_impl.rs:11:1 + | +LL | impl PartialEq for X { + | -------------------- their label + | +note: trait `PartialEq` is implemented but not `const` + --> $DIR/auxiliary/non_const_impl.rs:11:1 + | +LL | impl PartialEq for X { + | ^^^^^^^^^^^^^^^^^^^^ + = note: their note + = note: their other note + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_local.rs b/tests/ui/diagnostic_namespace/on_const/it_works_local.rs new file mode 100644 index 0000000000000..9e7feb7330d46 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/it_works_local.rs @@ -0,0 +1,25 @@ +#![crate_type = "lib"] +#![feature(diagnostic_on_const)] + +pub struct X; + +#[diagnostic::on_const( + message = "my message", + label = "my label", + note = "my note", + note = "my other note" +)] +impl PartialEq for X { + //~^NOTE: my label + fn eq(&self, _other: &X) -> bool { + true + } +} + +const _: () = { + let x = X; + x == x; + //~^ ERROR: my message + //~| NOTE: my note + //~| NOTE: my other note +}; diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr b/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr new file mode 100644 index 0000000000000..14a3d446e1925 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr @@ -0,0 +1,15 @@ +error[E0277]: my message + --> $DIR/it_works_local.rs:21:5 + | +LL | impl PartialEq for X { + | -------------------- my label +... +LL | x == x; + | ^^^^^^ + | + = note: my note + = note: my other note + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 14ab39c42f6e990d7b41b34e1d3220ab21b6b29a Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 30 Mar 2026 23:05:35 +0200 Subject: [PATCH 2/3] on_const doesn't support parent_label --- .../src/error_reporting/traits/fulfillment_errors.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 3254496cf0e96..2ab907de7e2d8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -898,7 +898,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { main_obligation, diag.long_ty_path(), ); - let CustomDiagnostic { message, label, notes, parent_label } = + let CustomDiagnostic { message, label, notes, parent_label: _ } = command.eval(None, &format_args); if let Some(message) = message { @@ -910,9 +910,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { for note in notes { diag.note(note); } - if let Some(parent_label) = parent_label { - diag.span_label(impl_span, parent_label); - } } else if let Some(impl_did) = impl_did.as_local() && let item = self.tcx.hir_expect_item(impl_did) && let hir::ItemKind::Impl(item) = item.kind From 4bc2a5510871ef17eaf9b7d28714f0dee4f48316 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 6 Apr 2026 19:01:10 +0200 Subject: [PATCH 3/3] Fix diagnostic::on_const label span --- .../src/error_reporting/traits/fulfillment_errors.rs | 2 +- tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs | 1 + .../diagnostic_namespace/on_const/it_works_foreign.stderr | 7 +------ tests/ui/diagnostic_namespace/on_const/it_works_local.rs | 2 +- .../ui/diagnostic_namespace/on_const/it_works_local.stderr | 7 ++----- 5 files changed, 6 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 2ab907de7e2d8..a376ce2d30acb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -905,7 +905,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { diag.primary_message(message); } if let Some(label) = label { - diag.span_label(impl_span, label); + diag.span_label(span, label); } for note in notes { diag.note(note); diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs index a56487e71de08..0888ee096ff4f 100644 --- a/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs +++ b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs @@ -9,6 +9,7 @@ const _: () = { let x = X; x == x; //~^ ERROR: their message + //~| NOTE: their label //~| NOTE: trait `PartialEq` is implemented but not `const` //~| NOTE: their note //~| NOTE: their other note diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr index 12d0472443d35..ad9b2364f21f3 100644 --- a/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr +++ b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr @@ -2,12 +2,7 @@ error[E0277]: their message --> $DIR/it_works_foreign.rs:10:5 | LL | x == x; - | ^^^^^^ - | - ::: $DIR/auxiliary/non_const_impl.rs:11:1 - | -LL | impl PartialEq for X { - | -------------------- their label + | ^^^^^^ their label | note: trait `PartialEq` is implemented but not `const` --> $DIR/auxiliary/non_const_impl.rs:11:1 diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_local.rs b/tests/ui/diagnostic_namespace/on_const/it_works_local.rs index 9e7feb7330d46..176fe8d01d353 100644 --- a/tests/ui/diagnostic_namespace/on_const/it_works_local.rs +++ b/tests/ui/diagnostic_namespace/on_const/it_works_local.rs @@ -10,7 +10,6 @@ pub struct X; note = "my other note" )] impl PartialEq for X { - //~^NOTE: my label fn eq(&self, _other: &X) -> bool { true } @@ -20,6 +19,7 @@ const _: () = { let x = X; x == x; //~^ ERROR: my message + //~| NOTE: my label //~| NOTE: my note //~| NOTE: my other note }; diff --git a/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr b/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr index 14a3d446e1925..0db90fac1639e 100644 --- a/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr +++ b/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr @@ -1,11 +1,8 @@ error[E0277]: my message - --> $DIR/it_works_local.rs:21:5 + --> $DIR/it_works_local.rs:20:5 | -LL | impl PartialEq for X { - | -------------------- my label -... LL | x == x; - | ^^^^^^ + | ^^^^^^ my label | = note: my note = note: my other note