-
-
Notifications
You must be signed in to change notification settings - Fork 205
Unhelpful error message if the error attribute and fmt::Display impl are missing #75
Description
Problem
This code
use thiserror::Error;
#[derive(Debug, Clone, Error, PartialEq)]
pub enum Error {
First,
Second,
}produces this compiler error
error[E0277]: `Error` doesn't implement `std::fmt::Display`
--> src/lib.rs:3:24
|
3 | #[derive(Debug, Clone, Error, PartialEq)]
| ^^^^^ `Error` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `Error`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `terr`.
To learn more, run the command again with --verbose.
It is not immediately obvious that you have to add attributes to the enum variants.
use thiserror::Error;
#[derive(Debug, Clone, Error, PartialEq)]
pub enum Error {
#[error("first")]
First,
#[error("second")]
Second,
}Suggestion
A better error message would be something like this
error[E0277]: `Error` doesn't implement `std::fmt::Display`
--> src/lib.rs:4:10
|
4 | pub enum Error {
| ^^^^^ `Error` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `Error`
= note: use the `#[error("...")]` attribute on variants to derive `std::fmt::Display`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `terr`.
To learn more, run the command again with --verbose.
Implementation
The error happens, because this if clause
Line 226 in f866fa9
| let display_impl = if input.has_display() { |
in
Line 124 in f866fa9
| fn impl_enum(input: Enum) -> TokenStream { |
returns None, if input.has_display() is false (to support structs, which implement std::fmt::Display manually?).
Line 266 in f866fa9
| None |
I know that the suggested error message is not possible (or is it?), because proc-macros operate on tokens and can therefore not know if a type implements std::fmt::Display.
It is still possible to improve the error message (a little) by returning this in the else clause:
Line 266 in f866fa9
| None |
Some(quote_spanned! {
ty.span() => struct _AssertDisplay where #ty: ::core::fmt::Display;
})which should result in this compiler error
error[E0277]: `Error` doesn't implement `std::fmt::Display`
--> src/lib.rs:4:10
|
4 | pub enum Error {
| ^^^^^ `Error` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `Error`
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `terr`.
To learn more, run the command again with --verbose.