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

Emit error when user writes incorrect format for display attribute #160

Merged
merged 4 commits into from
May 11, 2021

Conversation

magurotuna
Copy link
Contributor

@magurotuna magurotuna commented May 7, 2021

What's done in this PR

Resolves #127

The compiler emit an error when a user writes incorrect format for display attribute, for example:

#[derive(Display)]
#[display()] // `fmt = "..."` missing
enum Enum {}

#[derive(Display)]
#[display("struct")] // `fmt = ` missing
struct Struct;

#[derive(Display)]
#[display("custom {}", x)] // `fmt = ` missing
struct StructA {
    x: i32,
}

#[derive(Display)]
enum EnumVariantA {
    #[display(foo)] // unknown format
    A,
}

#[derive(Display)]
enum EnumVariantB {
    #[display("b", bar)] // unknown format
    B,
}

for the above examples, errors that the compiler emits look like:

error: The format for this attribute cannot be parsed. Correct format: `#[display(fmt = "...")]`
  --> tests/display.rs:62:3
   |
62 | #[display()]
   |   ^^^^^^^

error: The format for this attribute cannot be parsed. Correct format: `#[display(fmt = "...")]`
  --> tests/display.rs:66:3
   |
66 | #[display("struct")]
   |   ^^^^^^^

error: The format for this attribute cannot be parsed. Correct format: `#[display(fmt = "...")]`
  --> tests/display.rs:70:3
   |
70 | #[display("custom {}", x)]
   |   ^^^^^^^

error: The format for this attribute cannot be parsed. Correct format: `#[display(fmt = "...")]`
  --> tests/display.rs:77:7
   |
77 |     #[display(foo)]
   |       ^^^^^^^

error: The format for this attribute cannot be parsed. Correct format: `#[display(fmt = "...")]`
  --> tests/display.rs:83:7
   |
83 |     #[display("b", bar)]
   |       ^^^^^^^

Motivation

I use Display macro and I'm really happy with it. But the other day I mistakenly wrote a code like:

#[derive(Display)]
enum Foo {
    #[display("Hello Bar!")] // forgot to write `fmt = `!
    Bar,
}

I had expected it to be displayed as "Hello Bar!" and unfortunately the code review passed and it landed.
As you know, actually Foo::Bar.to_string() was evaluated as "Bar", not "Hello Bar!", since fmt = is missing.

This made me think that it would be very helpful for the compiler to emit errors for invalid format at compile-time.
I'm aware that #[display] is a valid format, but if users write parens after display like #[display()], then it most likely implies that they intend to pass fmt = "..." argument but just forget to.

Hope this patch will get landed :)

@tyranron
Copy link
Collaborator

tyranron commented May 7, 2021

@magurotuna thanks! Would you be so kind to adjust Clippy?

@magurotuna
Copy link
Contributor Author

@tyranron Sure, done it :)

@magurotuna
Copy link
Contributor Author

Oh I didn't realize that MSRV is 1.36.0. I'll address it.

@magurotuna
Copy link
Contributor Author

@tyranron
Removed matches! and made some refinement around Clippy.

  • set clippy's MSRV to 1.36.0 in clippy.toml and remove allow(clippy::match_like_matches_macro) attribute
  • fix clippy option on CI. Currently --all flag is present, which is alias for --workspace, but it doesn't look like derive_more uses workspace. So just replaced this flag with --all-features. Also, -D clippy::all is subset of -D warnings according to clippy's readme, so I removed it.

Copy link
Collaborator

@tyranron tyranron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magurotuna thanks! 🍻

@tyranron tyranron merged commit a5d0005 into JelteF:master May 11, 2021
@magurotuna magurotuna deleted the display-error branch May 11, 2021 14:16
@magurotuna
Copy link
Contributor Author

@tyranron thanks for merging!
Any plan to publish the next version? I don't mean to rush you, but I would be more than happy to have the next version available, because I don't want to make mistakes of forgetting to write fmt = anymore.

@tyranron
Copy link
Collaborator

cc @JelteF

@JelteF
Copy link
Owner

JelteF commented May 11, 2021 via email

@JelteF
Copy link
Owner

JelteF commented May 22, 2021

In case you didn't notice I created a release last weekend: v0.99.14

magurotuna added a commit to magurotuna/deno_lint that referenced this pull request May 23, 2021
We are using `Display` macro from `derive_more` crate to easily
implement `std::fmt::Display` trait for each lint's message and hint.
This macro was a bit tricky; even if passed arguments are invalid format,
it _does_ compile, which results in getting unexpected diagnostic outputs.
This is why the issue denoland#666 happened.

However, in `derive_more` v0.99.14, the macro has been refined so it now
rejects arguments in invalid format at compile-time. This is so useful
for us not to make a mistake.
Ref: JelteF/derive_more#160
@magurotuna
Copy link
Contributor Author

Awesome! Thanks so much ❤️

bartlomieju pushed a commit to denoland/deno_lint that referenced this pull request May 23, 2021
We are using `Display` macro from `derive_more` crate to easily
implement `std::fmt::Display` trait for each lint's message and hint.
This macro was a bit tricky; even if passed arguments are invalid format,
it _does_ compile, which results in getting unexpected diagnostic outputs.
This is why the issue #666 happened.

However, in `derive_more` v0.99.14, the macro has been refined so it now
rejects arguments in invalid format at compile-time. This is so useful
for us not to make a mistake.
Ref: JelteF/derive_more#160
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Derive fails silently when missing fmt =
3 participants