[redundant_closure_call]: Don't lint if closure origins from a macro

The following code used to trigger the lint:
```rs
 macro_rules! make_closure {
     () => {
         (|| {})
     };
 }
 make_closure!()();
```
The lint would suggest to replace `make_closure!()()` with
`make_closure!()`, which changes the code and removes the call to the
closure from the macro. This commit fixes that.

Fixes #12358
This commit is contained in:
Ethiraric 2024-02-28 19:03:12 +01:00
parent af91e6ea8c
commit 0d59345907
3 changed files with 43 additions and 0 deletions

View File

@ -159,6 +159,15 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
// ^^ we only want to lint for this call (but we walk up the calls to consider both calls).
// without this check, we'd end up linting twice.
&& !matches!(recv.kind, hir::ExprKind::Call(..))
// Check if `recv` comes from a macro expansion. If it does, make sure that it's an expansion that is
// the same as the one the call is in.
// For instance, let's assume `x!()` returns a closure:
// B ---v
// x!()()
// ^- A
// The call happens in the expansion `A`, while the closure originates from the expansion `B`.
// We don't want to suggest replacing `x!()()` with `x!()`.
&& recv.span.ctxt().outer_expn() == expr.span.ctxt().outer_expn()
&& let (full_expr, call_depth) = get_parent_call_exprs(cx, expr)
&& let Some((body, fn_decl, coroutine_kind, params)) = find_innermost_closure(cx, recv, call_depth)
// outside macros we lint properly. Inside macros, we lint only ||() style closures.

View File

@ -111,3 +111,20 @@ fn fp_11274() {
}
m!(|x| println!("{x}"));
}
// Issue #12358: When a macro expands into a closure, immediately calling the expanded closure
// triggers the lint.
fn issue_12358() {
macro_rules! make_closure {
() => {
(|| || {})
};
(x) => {
make_closure!()()
};
}
// The lint would suggest to alter the line below to `make_closure!(x)`, which is semantically
// different.
make_closure!(x)();
}

View File

@ -111,3 +111,20 @@ fn fp_11274() {
}
m!(|x| println!("{x}"));
}
// Issue #12358: When a macro expands into a closure, immediately calling the expanded closure
// triggers the lint.
fn issue_12358() {
macro_rules! make_closure {
() => {
(|| || {})
};
(x) => {
make_closure!()()
};
}
// The lint would suggest to alter the line below to `make_closure!(x)`, which is semantically
// different.
make_closure!(x)();
}