Skip to content

Commit 8cb207a

Browse files
committed
Auto merge of #86386 - inquisitivecrystal:better-errors-for-display-traits-v3, r=estebank
Better errors for Debug and Display traits Currently, if someone tries to pass value that does not implement `Debug` or `Display` to a formatting macro, they get a very verbose and confusing error message. This PR changes the error messages for missing `Debug` and `Display` impls to be less overwhelming in this case, as suggested by #85844. I was a little less aggressive in changing the error message than that issue proposed. Still, this implementation would be enough to reduce the number of messages to be much more manageable. After this PR, information on the cause of an error involving a `Debug` or `Display` implementation would suppressed if the requirement originated within a standard library macro. My reasoning was that errors originating from within a macro are confusing when they mention details that the programmer can't see, and this is particularly problematic for `Debug` and `Display`, which are most often used via macros. It is possible that either a broader or a narrower criterion would be better. I'm quite open to any feedback. Fixes #85844.
2 parents 574c9dd + 20ea5fe commit 8cb207a

14 files changed

+33
-44
lines changed

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ symbols! {
478478
discriminant_type,
479479
discriminant_value,
480480
dispatch_from_dyn,
481+
display_trait,
481482
div,
482483
div_assign,
483484
doc,

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
514514
}
515515
}
516516

517+
// Return early if the trait is Debug or Display and the invocation
518+
// originates within a standard library macro, because the output
519+
// is otherwise overwhelming and unhelpful (see #85844 for an
520+
// example).
521+
522+
let trait_is_debug =
523+
self.tcx.is_diagnostic_item(sym::debug_trait, trait_ref.def_id());
524+
let trait_is_display =
525+
self.tcx.is_diagnostic_item(sym::display_trait, trait_ref.def_id());
526+
527+
let in_std_macro =
528+
match obligation.cause.span.ctxt().outer_expn_data().macro_def_id {
529+
Some(macro_def_id) => {
530+
let crate_name = tcx.crate_name(macro_def_id.krate);
531+
crate_name == sym::std || crate_name == sym::core
532+
}
533+
None => false,
534+
};
535+
536+
if in_std_macro && (trait_is_debug || trait_is_display) {
537+
err.emit();
538+
return;
539+
}
540+
517541
err
518542
}
519543

library/core/src/fmt/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ impl Display for Arguments<'_> {
564564
on(
565565
crate_local,
566566
label = "`{Self}` cannot be formatted using `{{:?}}`",
567-
note = "add `#[derive(Debug)]` or manually implement `{Debug}`"
567+
note = "add `#[derive(Debug)]` to `{Self}` or manually `impl {Debug} for {Self}`"
568568
),
569569
message = "`{Self}` doesn't implement `{Debug}`",
570570
label = "`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`"
@@ -662,6 +662,7 @@ pub use macros::Debug;
662662
note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead"
663663
)]
664664
#[doc(alias = "{}")]
665+
#[rustc_diagnostic_item = "display_trait"]
665666
#[stable(feature = "rust1", since = "1.0.0")]
666667
pub trait Display {
667668
/// Formats the value using the given formatter.

src/test/ui/binop/issue-77910-1.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug`
1414
|
1515
LL | assert_eq!(foo, y);
1616
| ^^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
17-
|
18-
::: $SRC_DIR/core/src/panicking.rs:LL:COL
19-
|
20-
LL | T: fmt::Debug + ?Sized,
21-
| ---------- required by this bound in `core::panicking::assert_failed`
2217
|
2318
= help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
2419
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

src/test/ui/bound-suggestions.stderr

-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ error[E0277]: `impl Sized` doesn't implement `Debug`
44
LL | println!("{:?}", t);
55
| ^ `impl Sized` cannot be formatted using `{:?}` because it doesn't implement `Debug`
66
|
7-
= note: required by `std::fmt::Debug::fmt`
87
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
98
help: consider further restricting this bound
109
|
@@ -17,7 +16,6 @@ error[E0277]: `T` doesn't implement `Debug`
1716
LL | println!("{:?}", t);
1817
| ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
1918
|
20-
= note: required by `std::fmt::Debug::fmt`
2119
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
2220
help: consider restricting type parameter `T`
2321
|
@@ -30,7 +28,6 @@ error[E0277]: `T` doesn't implement `Debug`
3028
LL | println!("{:?}", t);
3129
| ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
3230
|
33-
= note: required by `std::fmt::Debug::fmt`
3431
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
3532
help: consider further restricting this bound
3633
|
@@ -43,7 +40,6 @@ error[E0277]: `Y` doesn't implement `Debug`
4340
LL | println!("{:?} {:?}", x, y);
4441
| ^ `Y` cannot be formatted using `{:?}` because it doesn't implement `Debug`
4542
|
46-
= note: required by `std::fmt::Debug::fmt`
4743
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
4844
help: consider further restricting type parameter `Y`
4945
|
@@ -56,7 +52,6 @@ error[E0277]: `X` doesn't implement `Debug`
5652
LL | println!("{:?}", x);
5753
| ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
5854
|
59-
= note: required by `std::fmt::Debug::fmt`
6055
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
6156
help: consider further restricting this bound
6257
|
@@ -69,7 +64,6 @@ error[E0277]: `X` doesn't implement `Debug`
6964
LL | println!("{:?}", x);
7065
| ^ `X` cannot be formatted using `{:?}` because it doesn't implement `Debug`
7166
|
72-
= note: required by `std::fmt::Debug::fmt`
7367
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
7468
help: consider further restricting type parameter `X`
7569
|

src/test/ui/derives/derives-span-Debug-enum-struct-variant.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ LL | x: Error
55
| ^^^^^^^^ `Error` cannot be formatted using `{:?}`
66
|
77
= help: the trait `Debug` is not implemented for `Error`
8-
= note: add `#[derive(Debug)]` or manually implement `Debug`
9-
= note: required because of the requirements on the impl of `Debug` for `&Error`
10-
= note: required for the cast to the object type `dyn Debug`
8+
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
119
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
1210

1311
error: aborting due to previous error

src/test/ui/derives/derives-span-Debug-enum.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ LL | Error
55
| ^^^^^ `Error` cannot be formatted using `{:?}`
66
|
77
= help: the trait `Debug` is not implemented for `Error`
8-
= note: add `#[derive(Debug)]` or manually implement `Debug`
9-
= note: required because of the requirements on the impl of `Debug` for `&Error`
10-
= note: required for the cast to the object type `dyn Debug`
8+
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
119
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
1210

1311
error: aborting due to previous error

src/test/ui/derives/derives-span-Debug-struct.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ LL | x: Error
55
| ^^^^^^^^ `Error` cannot be formatted using `{:?}`
66
|
77
= help: the trait `Debug` is not implemented for `Error`
8-
= note: add `#[derive(Debug)]` or manually implement `Debug`
9-
= note: required because of the requirements on the impl of `Debug` for `&Error`
10-
= note: required for the cast to the object type `dyn Debug`
8+
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
119
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
1210

1311
error: aborting due to previous error

src/test/ui/derives/derives-span-Debug-tuple-struct.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ LL | Error
55
| ^^^^^ `Error` cannot be formatted using `{:?}`
66
|
77
= help: the trait `Debug` is not implemented for `Error`
8-
= note: add `#[derive(Debug)]` or manually implement `Debug`
9-
= note: required because of the requirements on the impl of `Debug` for `&Error`
10-
= note: required for the cast to the object type `dyn Debug`
8+
= note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error`
119
= note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
1210

1311
error: aborting due to previous error

src/test/ui/issues/issue-59488.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,6 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
8484
|
8585
LL | assert_eq!(Foo::Bar, i);
8686
| ^^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
87-
|
88-
::: $SRC_DIR/core/src/panicking.rs:LL:COL
89-
|
90-
LL | T: fmt::Debug + ?Sized,
91-
| ---------- required by this bound in `core::panicking::assert_failed`
9287
|
9388
= help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
9489
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,6 @@ LL | fn a() -> i32 {
2828
...
2929
LL | assert_eq!(a, 0);
3030
| ^^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
31-
|
32-
::: $SRC_DIR/core/src/panicking.rs:LL:COL
33-
|
34-
LL | T: fmt::Debug + ?Sized,
35-
| ---------- required by this bound in `core::panicking::assert_failed`
3631
|
3732
= help: the trait `Debug` is not implemented for `fn() -> i32 {a}`
3833
= help: use parentheses to call the function: `a()`

src/test/ui/on-unimplemented/no-debug.stderr

+1-5
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ LL | println!("{:?} {:?}", Foo, Bar);
55
| ^^^ `Foo` cannot be formatted using `{:?}`
66
|
77
= help: the trait `Debug` is not implemented for `Foo`
8-
= note: add `#[derive(Debug)]` or manually implement `Debug`
9-
= note: required by `std::fmt::Debug::fmt`
8+
= note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
109
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
1110

1211
error[E0277]: `Bar` doesn't implement `Debug`
@@ -16,7 +15,6 @@ LL | println!("{:?} {:?}", Foo, Bar);
1615
| ^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug`
1716
|
1817
= help: the trait `Debug` is not implemented for `Bar`
19-
= note: required by `std::fmt::Debug::fmt`
2018
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
2119

2220
error[E0277]: `Foo` doesn't implement `std::fmt::Display`
@@ -27,7 +25,6 @@ LL | println!("{} {}", Foo, Bar);
2725
|
2826
= help: the trait `std::fmt::Display` is not implemented for `Foo`
2927
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
30-
= note: required by `std::fmt::Display::fmt`
3128
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
3229

3330
error[E0277]: `Bar` doesn't implement `std::fmt::Display`
@@ -38,7 +35,6 @@ LL | println!("{} {}", Foo, Bar);
3835
|
3936
= help: the trait `std::fmt::Display` is not implemented for `Bar`
4037
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
41-
= note: required by `std::fmt::Display::fmt`
4238
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
4339

4440
error: aborting due to 4 previous errors

src/test/ui/rfc-2361-dbg-macro/dbg-macro-requires-debug.stderr

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ LL | let _: NotDebug = dbg!(NotDebug);
55
| ^^^^^^^^^^^^^^ `NotDebug` cannot be formatted using `{:?}`
66
|
77
= help: the trait `Debug` is not implemented for `NotDebug`
8-
= note: add `#[derive(Debug)]` or manually implement `Debug`
9-
= note: required because of the requirements on the impl of `Debug` for `&NotDebug`
10-
= note: required by `std::fmt::Debug::fmt`
8+
= note: add `#[derive(Debug)]` to `NotDebug` or manually `impl Debug for NotDebug`
119
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
1210

1311
error: aborting due to previous error

src/test/ui/suggestions/path-display.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ LL | println!("{}", path);
66
|
77
= help: the trait `std::fmt::Display` is not implemented for `Path`
88
= note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data
9-
= note: required because of the requirements on the impl of `std::fmt::Display` for `&Path`
10-
= note: required by `std::fmt::Display::fmt`
119
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
1210

1311
error: aborting due to previous error

0 commit comments

Comments
 (0)