Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unhelpful error message if the error attribute and fmt::Display impl are missing #75

Closed
Luro02 opened this issue Apr 11, 2020 · 0 comments · Fixed by #76
Closed

Unhelpful error message if the error attribute and fmt::Display impl are missing #75

Luro02 opened this issue Apr 11, 2020 · 0 comments · Fixed by #76

Comments

@Luro02
Copy link

Luro02 commented Apr 11, 2020

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

let display_impl = if input.has_display() {

in

fn impl_enum(input: Enum) -> TokenStream {

returns None, if input.has_display() is false (to support structs, which implement std::fmt::Display manually?).

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:

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant