diff options
| author | bors <bors@rust-lang.org> | 2024-02-28 19:13:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-02-28 19:13:13 +0000 |
| commit | 139191b8b7b5ed181249e4a88bc3d7f7c01cce3c (patch) | |
| tree | 7cc0b3b71f516fab8a84e64277865b2442aeb553 | |
| parent | af91e6ea8c1e1bd2a6ccc52e34741805209f1a21 (diff) | |
| parent | 0d5934590782b96de8be1c975834847639fac453 (diff) | |
Auto merge of #12380 - Ethiraric:fix-12358, r=llogiq
[`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
----
changelog: [`redundant_closure_call`]: If `x!()` returns a closure, don't suggest replacing `x!()()` with `x!()`
| -rw-r--r-- | clippy_lints/src/redundant_closure_call.rs | 9 | ||||
| -rw-r--r-- | tests/ui/redundant_closure_call_fixable.fixed | 17 | ||||
| -rw-r--r-- | tests/ui/redundant_closure_call_fixable.rs | 17 |
3 files changed, 43 insertions, 0 deletions
diff --git a/clippy_lints/src/redundant_closure_call.rs b/clippy_lints/src/redundant_closure_call.rs index e3f0ce2a922..f61527cc0a9 100644 --- a/clippy_lints/src/redundant_closure_call.rs +++ b/clippy_lints/src/redundant_closure_call.rs @@ -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. diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index ce5c7f2600b..191f7719904 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -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)(); +} diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index ac09390e6ea..33a3b90f9cf 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -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)(); +} |
