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 4d051a370c065..28b23bd37485a 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 @@ -448,9 +448,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some((msg, span)) = type_def { err.span_label(span, msg); } - for note in notes { - // If it has a custom `#[rustc_on_unimplemented]` note, let's display it - err.note(note); + // `#[rustc_on_unimplemented]` notes for derivable traits (e.g. `Debug`'s + // "add `#[derive(Debug)]` to `X` or manually `impl Debug for X`") duplicate + // the `consider annotating X with #[derive(..)]` suggestion that + // `suggest_derive` emits below, so skip them when that suggestion will be + // shown. We keep the note otherwise (e.g. when a field isn't `Debug`, so + // the derive can't be suggested) to avoid leaving the diagnostic without + // actionable guidance. + let derive_suggestion_will_be_shown = main_trait_predicate + == leaf_trait_predicate + && self.can_suggest_derive(&obligation, leaf_trait_predicate); + if !derive_suggestion_will_be_shown { + for note in notes { + // If it has a custom `#[rustc_on_unimplemented]` note, let's display + // it. + err.note(note); + } } if let Some(s) = parent_label { let body = obligation.cause.body_id; diff --git a/tests/ui/derives/debug/derives-span-Debug.stderr b/tests/ui/derives/debug/derives-span-Debug.stderr index e4a2560db4512..0f322e37b05c3 100644 --- a/tests/ui/derives/debug/derives-span-Debug.stderr +++ b/tests/ui/derives/debug/derives-span-Debug.stderr @@ -7,7 +7,6 @@ LL | #[derive(Debug)] LL | x: Error, | ^^^^^^^^ the trait `Debug` is not implemented for `Error` | - = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] @@ -23,7 +22,6 @@ LL | #[derive(Debug)] LL | Error, | ^^^^^ the trait `Debug` is not implemented for `Error` | - = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] @@ -39,7 +37,6 @@ LL | struct Struct { LL | x: Error, | ^^^^^^^^ the trait `Debug` is not implemented for `Error` | - = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] @@ -55,7 +52,6 @@ LL | struct TupleStruct( LL | Error, | ^^^^^ the trait `Debug` is not implemented for `Error` | - = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/derives/redundant-derive-note-on-unimplemented.rs b/tests/ui/derives/redundant-derive-note-on-unimplemented.rs new file mode 100644 index 0000000000000..f708d3a48359c --- /dev/null +++ b/tests/ui/derives/redundant-derive-note-on-unimplemented.rs @@ -0,0 +1,15 @@ +// Regression test for the redundant `note: add `#[derive(Debug)]` to `X` or manually +// `impl Debug for X`` that was emitted alongside the `consider annotating X with +// `#[derive(Debug)]`` suggestion. When the derive suggestion is shown, the note is +// redundant and should be suppressed. +// +// See https://github.com/rust-lang/rust/issues/157118 + +#[derive(Debug)] +struct S(T); + +struct X; + +fn main() { + println!("{:?}", S(X)); //~ ERROR `X` doesn't implement `Debug` +} diff --git a/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr b/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr new file mode 100644 index 0000000000000..dcb1639593a58 --- /dev/null +++ b/tests/ui/derives/redundant-derive-note-on-unimplemented.stderr @@ -0,0 +1,31 @@ +error[E0277]: `X` doesn't implement `Debug` + --> $DIR/redundant-derive-note-on-unimplemented.rs:14:22 + | +LL | println!("{:?}", S(X)); + | ---- ^^^^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | | + | required by this formatting parameter + | + = help: the trait `Debug` is not implemented for `X` +help: the trait `Debug` is implemented for `S` + --> $DIR/redundant-derive-note-on-unimplemented.rs:8:10 + | +LL | #[derive(Debug)] + | ^^^^^ +note: required for `S` to implement `Debug` + --> $DIR/redundant-derive-note-on-unimplemented.rs:9:8 + | +LL | #[derive(Debug)] + | ----- in this derive macro expansion +LL | struct S(T); + | ^ - type parameter would need to implement `Debug` + = help: consider manually implementing `Debug` to avoid undesired bounds +help: consider annotating `X` with `#[derive(Debug)]` + | +LL + #[derive(Debug)] +LL | struct X; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/fmt/format-args-argument-span.stderr b/tests/ui/fmt/format-args-argument-span.stderr index a486abe821b74..76fc178bb3d44 100644 --- a/tests/ui/fmt/format-args-argument-span.stderr +++ b/tests/ui/fmt/format-args-argument-span.stderr @@ -25,7 +25,6 @@ LL | println!("{x} {x:?} {x}"); | ^^^^^ `DisplayOnly` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `DisplayOnly` - = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly` help: consider annotating `DisplayOnly` with `#[derive(Debug)]` | LL + #[derive(Debug)] @@ -41,7 +40,6 @@ LL | println!("{x} {x:?} {x}", x = DisplayOnly); | required by this formatting parameter | = help: the trait `Debug` is not implemented for `DisplayOnly` - = note: add `#[derive(Debug)]` to `DisplayOnly` or manually `impl Debug for DisplayOnly` help: consider annotating `DisplayOnly` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/fmt/non-source-literals.stderr b/tests/ui/fmt/non-source-literals.stderr index 953a4a64fd8dc..39dc35653618f 100644 --- a/tests/ui/fmt/non-source-literals.stderr +++ b/tests/ui/fmt/non-source-literals.stderr @@ -31,7 +31,6 @@ LL | let _ = format!(concat!("{:", "?}"), NonDebug); | ^^^^^^^^ `NonDebug` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `NonDebug` - = note: add `#[derive(Debug)]` to `NonDebug` or manually `impl Debug for NonDebug` help: consider annotating `NonDebug` with `#[derive(Debug)]` | LL + #[derive(Debug)] @@ -45,7 +44,6 @@ LL | let _ = format!(concat!("{", "0", ":?}"), NonDebug); | ^^^^^^^^ `NonDebug` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `NonDebug` - = note: add `#[derive(Debug)]` to `NonDebug` or manually `impl Debug for NonDebug` help: consider annotating `NonDebug` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr index 23bc9dc0f844e..ce63a69b927c5 100644 --- a/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/tests/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -4,7 +4,6 @@ error[E0277]: `Foo` doesn't implement `Debug` LL | a.unwrap(); | ^^^^^^ the trait `Debug` is not implemented for `Foo` | - = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` note: required by a bound in `Result::::unwrap` --> $SRC_DIR/core/src/result.rs:LL:COL help: consider annotating `Foo` with `#[derive(Debug)]` diff --git a/tests/ui/modules/issue-107649.stderr b/tests/ui/modules/issue-107649.stderr index 40dda93ad015c..d41fcced9be4a 100644 --- a/tests/ui/modules/issue-107649.stderr +++ b/tests/ui/modules/issue-107649.stderr @@ -4,7 +4,6 @@ error[E0277]: `Dummy` doesn't implement `Debug` 105 | dbg!(lib::Dummy); | ^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `Dummy` | - = note: add `#[derive(Debug)]` to `Dummy` or manually `impl Debug for Dummy` help: consider annotating `Dummy` with `#[derive(Debug)]` --> $DIR/auxiliary/dummy_lib.rs:2:1 | diff --git a/tests/ui/on-unimplemented/no-debug.stderr b/tests/ui/on-unimplemented/no-debug.stderr index 3c3b8d2e20541..c078e0fd42531 100644 --- a/tests/ui/on-unimplemented/no-debug.stderr +++ b/tests/ui/on-unimplemented/no-debug.stderr @@ -7,7 +7,6 @@ LL | println!("{:?} {:?}", Foo, Bar); | required by this formatting parameter | = help: the trait `Debug` is not implemented for `Foo` - = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo` help: consider annotating `Foo` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr index 4cdeb184bd915..f8699f9e55e24 100644 --- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr +++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr @@ -4,7 +4,6 @@ error[E0277]: `NotDebug` doesn't implement `Debug` LL | let _: NotDebug = dbg!(NotDebug); | ^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `NotDebug` | - = note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug` help: consider annotating `NotDebug` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/span/issue-71363.stderr b/tests/ui/span/issue-71363.stderr index d2f780bdbcb43..96c45d285e8d0 100644 --- a/tests/ui/span/issue-71363.stderr +++ b/tests/ui/span/issue-71363.stderr @@ -18,7 +18,6 @@ error[E0277]: `MyError` doesn't implement `Debug` 4 | impl std::error::Error for MyError {} | ^^^^^^^ the trait `Debug` is not implemented for `MyError` | - = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError` note: required by a bound in `std::error::Error` --> $SRC_DIR/core/src/error.rs:LL:COL help: consider annotating `MyError` with `#[derive(Debug)]` diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr index b28f39ced542d..0d05bd9d91bbf 100644 --- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -6,7 +6,6 @@ LL | #[derive(Debug)] LL | struct Outer(Inner); | ^^^^^^^^ the trait `Debug` is not implemented for `a::Inner` | - = note: add `#[derive(Debug)]` to `a::Inner` or manually `impl Debug for a::Inner` help: consider annotating `a::Inner` with `#[derive(Debug)]` | LL + #[derive(Debug)]