rust-lang / rust-lang/rust

`unused_parens` false positives and false negatives in code containing macro calls

Open
#119,426 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-lints A-macros C-bug L-unused_parens T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
macro_rules! m1 {
    () => {
        1
    };
}

pub fn f1() -> u8 {
    // Lint says parens are not needed, but they are.
    (m1! {} + 1)
}

macro_rules! m2 {
    () => {
        loop { break 1; }
    };
}

pub fn f2() -> u8 {
    // Lint says parens are needed, but they are not.
    (m2!() + 1)
}
Current output
warning: unnecessary parentheses around block return value
 --> src/lib.rs:9:5
  |
9 |     (m1! {} + 1)
  |     ^          ^
  |
  = note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
  |
9 -     (m1! {} + 1)
9 +     m1! {} + 1
  |
Desired output
warning: unnecessary parentheses around block return value
 --> src/lib.rs:20:5
   |
20 |     (m2!() + 1)
   |     ^         ^
   |
   = note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
   |
20 -     (m2!() + 1)
20 +     m2!() + 1
   |
Rationale and extra context

The code suggested by rustc does not compile, because that pair of parentheses really is required.

error: leading `+` is not supported
 --> src/lib.rs:9:12
  |
9 |     m1! {} + 1
  |            ^ unexpected `+`
  |
help: try removing the `+`
  |
9 -     m1! {} + 1
9 +     m1! {}  1
  |

error[E0308]: mismatched types
 --> src/lib.rs:3:9
  |
3 |         1
  |         ^ expected `()`, found integer
...
9 |     m1! {} + 1
  |     ------ in this macro invocation
  |
  = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info)
Anything else?

I found a partly related issue https://github.com/rust-lang/rust/issues/113563, in which @Nilstrieb writes:

I don't think it's easy to fix this. The lint works on the finalized AST and can't really take into account the details of how the macro was expanded. The easiest solution here is to just put an #[allow()] inside the macro for now (which you've probably done already).

However, I have filed this as a distinct issue because I am hopeful that the case in this issue might be easier to fix than the other one, because this one involves parentheses that come from outside the macro call, as opposed to parentheses that come from inside the macro definition.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the unused_parens diagnostics from the macro-call examples in src/lib.rs, comparing the m1! and m2! cases. Trace how the lint handles parentheses around macro calls; done means it no longer suggests invalid removal for m1!, while still producing the valid warning and suggestion for m2!.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.