Skip to content

unused_parens false positives and false negatives in code containing macro calls #119426

@dtolnay

Description

@dtolnay

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 #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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.L-unused_parensLint: unused_parensT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions