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..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 @@ -882,55 +882,46 @@ 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(span, label); + } + for note in notes { + diag.note(note); } + } 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..0888ee096ff4f --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.rs @@ -0,0 +1,16 @@ +//@ 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: 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 new file mode 100644 index 0000000000000..ad9b2364f21f3 --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/it_works_foreign.stderr @@ -0,0 +1,17 @@ +error[E0277]: their message + --> $DIR/it_works_foreign.rs:10:5 + | +LL | x == 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..176fe8d01d353 --- /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 { + fn eq(&self, _other: &X) -> bool { + true + } +} + +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 new file mode 100644 index 0000000000000..0db90fac1639e --- /dev/null +++ b/tests/ui/diagnostic_namespace/on_const/it_works_local.stderr @@ -0,0 +1,12 @@ +error[E0277]: my message + --> $DIR/it_works_local.rs:20:5 + | +LL | x == x; + | ^^^^^^ my label + | + = note: my note + = note: my other note + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.