Skip to content

Commit 87963f0

Browse files
committed
Auto merge of rust-lang#9987 - Jarcho:issue_9957, r=flip1995
Don't cross contexts while building the suggestion for `redundant_closure_call` fixes rust-lang#9957 changelog: `redundant_closure_call`: Don't cross macro contexts while building the suggestion
2 parents 78589ff + e0eba9c commit 87963f0

File tree

7 files changed

+122
-43
lines changed

7 files changed

+122
-43
lines changed

clippy_lints/src/collapsible_if.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,13 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
160160
if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.kind;
161161
// Prevent triggering on `if c { if let a = b { .. } }`.
162162
if !matches!(check_inner.kind, ast::ExprKind::Let(..));
163-
if expr.span.ctxt() == inner.span.ctxt();
163+
let ctxt = expr.span.ctxt();
164+
if inner.span.ctxt() == ctxt;
164165
then {
165166
span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this `if` statement can be collapsed", |diag| {
166-
let lhs = Sugg::ast(cx, check, "..");
167-
let rhs = Sugg::ast(cx, check_inner, "..");
167+
let mut app = Applicability::MachineApplicable;
168+
let lhs = Sugg::ast(cx, check, "..", ctxt, &mut app);
169+
let rhs = Sugg::ast(cx, check_inner, "..", ctxt, &mut app);
168170
diag.span_suggestion(
169171
expr.span,
170172
"collapse nested if block",
@@ -173,7 +175,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
173175
lhs.and(&rhs),
174176
snippet_block(cx, content.span, "..", Some(expr.span)),
175177
),
176-
Applicability::MachineApplicable, // snippet
178+
app, // snippet
177179
);
178180
});
179181
}

clippy_lints/src/redundant_closure_call.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ impl EarlyLintPass for RedundantClosureCall {
8181
"try not to call a closure in the expression where it is declared",
8282
|diag| {
8383
if fn_decl.inputs.is_empty() {
84-
let app = Applicability::MachineApplicable;
85-
let mut hint = Sugg::ast(cx, body, "..");
84+
let mut app = Applicability::MachineApplicable;
85+
let mut hint = Sugg::ast(cx, body, "..", closure.span.ctxt(), &mut app);
8686

8787
if asyncness.is_async() {
8888
// `async x` is a syntax error, so it becomes `async { x }`

clippy_utils/src/source.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use rustc_errors::Applicability;
66
use rustc_hir::{Expr, ExprKind};
77
use rustc_lint::{LateContext, LintContext};
8+
use rustc_session::Session;
89
use rustc_span::hygiene;
910
use rustc_span::source_map::{original_sp, SourceMap};
1011
use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
@@ -204,11 +205,20 @@ pub fn snippet_with_applicability<'a, T: LintContext>(
204205
span: Span,
205206
default: &'a str,
206207
applicability: &mut Applicability,
208+
) -> Cow<'a, str> {
209+
snippet_with_applicability_sess(cx.sess(), span, default, applicability)
210+
}
211+
212+
fn snippet_with_applicability_sess<'a>(
213+
sess: &Session,
214+
span: Span,
215+
default: &'a str,
216+
applicability: &mut Applicability,
207217
) -> Cow<'a, str> {
208218
if *applicability != Applicability::Unspecified && span.from_expansion() {
209219
*applicability = Applicability::MaybeIncorrect;
210220
}
211-
snippet_opt(cx, span).map_or_else(
221+
snippet_opt_sess(sess, span).map_or_else(
212222
|| {
213223
if *applicability == Applicability::MachineApplicable {
214224
*applicability = Applicability::HasPlaceholders;
@@ -226,8 +236,12 @@ pub fn snippet_with_macro_callsite<'a, T: LintContext>(cx: &T, span: Span, defau
226236
}
227237

228238
/// Converts a span to a code snippet. Returns `None` if not available.
229-
pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
230-
cx.sess().source_map().span_to_snippet(span).ok()
239+
pub fn snippet_opt(cx: &impl LintContext, span: Span) -> Option<String> {
240+
snippet_opt_sess(cx.sess(), span)
241+
}
242+
243+
fn snippet_opt_sess(sess: &Session, span: Span) -> Option<String> {
244+
sess.source_map().span_to_snippet(span).ok()
231245
}
232246

233247
/// Converts a span (from a block) to a code snippet if available, otherwise use default.
@@ -277,8 +291,8 @@ pub fn snippet_block<'a, T: LintContext>(
277291

278292
/// Same as `snippet_block`, but adapts the applicability level by the rules of
279293
/// `snippet_with_applicability`.
280-
pub fn snippet_block_with_applicability<'a, T: LintContext>(
281-
cx: &T,
294+
pub fn snippet_block_with_applicability<'a>(
295+
cx: &impl LintContext,
282296
span: Span,
283297
default: &'a str,
284298
indent_relative_to: Option<Span>,
@@ -299,7 +313,17 @@ pub fn snippet_block_with_applicability<'a, T: LintContext>(
299313
///
300314
/// This will also return whether or not the snippet is a macro call.
301315
pub fn snippet_with_context<'a>(
302-
cx: &LateContext<'_>,
316+
cx: &impl LintContext,
317+
span: Span,
318+
outer: SyntaxContext,
319+
default: &'a str,
320+
applicability: &mut Applicability,
321+
) -> (Cow<'a, str>, bool) {
322+
snippet_with_context_sess(cx.sess(), span, outer, default, applicability)
323+
}
324+
325+
fn snippet_with_context_sess<'a>(
326+
sess: &Session,
303327
span: Span,
304328
outer: SyntaxContext,
305329
default: &'a str,
@@ -318,7 +342,7 @@ pub fn snippet_with_context<'a>(
318342
);
319343

320344
(
321-
snippet_with_applicability(cx, span, default, applicability),
345+
snippet_with_applicability_sess(sess, span, default, applicability),
322346
is_macro_call,
323347
)
324348
}

clippy_utils/src/sugg.rs

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -176,25 +176,28 @@ impl<'a> Sugg<'a> {
176176
}
177177

178178
/// Prepare a suggestion from an expression.
179-
pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
179+
pub fn ast(
180+
cx: &EarlyContext<'_>,
181+
expr: &ast::Expr,
182+
default: &'a str,
183+
ctxt: SyntaxContext,
184+
app: &mut Applicability,
185+
) -> Self {
180186
use rustc_ast::ast::RangeLimits;
181187

182-
let snippet_without_expansion = |cx, span: Span, default| {
183-
if span.from_expansion() {
184-
snippet_with_macro_callsite(cx, span, default)
185-
} else {
186-
snippet(cx, span, default)
187-
}
188-
};
189-
188+
#[expect(clippy::match_wildcard_for_single_variants)]
190189
match expr.kind {
190+
_ if expr.span.ctxt() != ctxt => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
191191
ast::ExprKind::AddrOf(..)
192192
| ast::ExprKind::Box(..)
193193
| ast::ExprKind::Closure { .. }
194194
| ast::ExprKind::If(..)
195195
| ast::ExprKind::Let(..)
196196
| ast::ExprKind::Unary(..)
197-
| ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet_without_expansion(cx, expr.span, default)),
197+
| ast::ExprKind::Match(..) => match snippet_with_context(cx, expr.span, ctxt, default, app) {
198+
(snip, false) => Sugg::MaybeParen(snip),
199+
(snip, true) => Sugg::NonParen(snip),
200+
},
198201
ast::ExprKind::Async(..)
199202
| ast::ExprKind::Block(..)
200203
| ast::ExprKind::Break(..)
@@ -224,45 +227,49 @@ impl<'a> Sugg<'a> {
224227
| ast::ExprKind::Array(..)
225228
| ast::ExprKind::While(..)
226229
| ast::ExprKind::Await(..)
227-
| ast::ExprKind::Err => Sugg::NonParen(snippet_without_expansion(cx, expr.span, default)),
230+
| ast::ExprKind::Err => Sugg::NonParen(snippet_with_context(cx, expr.span, ctxt, default, app).0),
228231
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
229232
AssocOp::DotDot,
230-
lhs.as_ref()
231-
.map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
232-
rhs.as_ref()
233-
.map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
233+
lhs.as_ref().map_or("".into(), |lhs| {
234+
snippet_with_context(cx, lhs.span, ctxt, default, app).0
235+
}),
236+
rhs.as_ref().map_or("".into(), |rhs| {
237+
snippet_with_context(cx, rhs.span, ctxt, default, app).0
238+
}),
234239
),
235240
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
236241
AssocOp::DotDotEq,
237-
lhs.as_ref()
238-
.map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
239-
rhs.as_ref()
240-
.map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
242+
lhs.as_ref().map_or("".into(), |lhs| {
243+
snippet_with_context(cx, lhs.span, ctxt, default, app).0
244+
}),
245+
rhs.as_ref().map_or("".into(), |rhs| {
246+
snippet_with_context(cx, rhs.span, ctxt, default, app).0
247+
}),
241248
),
242249
ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
243250
AssocOp::Assign,
244-
snippet_without_expansion(cx, lhs.span, default),
245-
snippet_without_expansion(cx, rhs.span, default),
251+
snippet_with_context(cx, lhs.span, ctxt, default, app).0,
252+
snippet_with_context(cx, rhs.span, ctxt, default, app).0,
246253
),
247254
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
248255
astbinop2assignop(op),
249-
snippet_without_expansion(cx, lhs.span, default),
250-
snippet_without_expansion(cx, rhs.span, default),
256+
snippet_with_context(cx, lhs.span, ctxt, default, app).0,
257+
snippet_with_context(cx, rhs.span, ctxt, default, app).0,
251258
),
252259
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
253260
AssocOp::from_ast_binop(op.node),
254-
snippet_without_expansion(cx, lhs.span, default),
255-
snippet_without_expansion(cx, rhs.span, default),
261+
snippet_with_context(cx, lhs.span, ctxt, default, app).0,
262+
snippet_with_context(cx, rhs.span, ctxt, default, app).0,
256263
),
257264
ast::ExprKind::Cast(ref lhs, ref ty) => Sugg::BinOp(
258265
AssocOp::As,
259-
snippet_without_expansion(cx, lhs.span, default),
260-
snippet_without_expansion(cx, ty.span, default),
266+
snippet_with_context(cx, lhs.span, ctxt, default, app).0,
267+
snippet_with_context(cx, ty.span, ctxt, default, app).0,
261268
),
262269
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
263270
AssocOp::Colon,
264-
snippet_without_expansion(cx, lhs.span, default),
265-
snippet_without_expansion(cx, ty.span, default),
271+
snippet_with_context(cx, lhs.span, ctxt, default, app).0,
272+
snippet_with_context(cx, ty.span, ctxt, default, app).0,
266273
),
267274
}
268275
}

tests/ui/redundant_closure_call_fixable.fixed

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,16 @@ fn main() {
2525
x * y
2626
};
2727
let d = async { something().await };
28+
29+
macro_rules! m {
30+
() => {
31+
0
32+
};
33+
}
34+
macro_rules! m2 {
35+
() => {
36+
m!()
37+
};
38+
}
39+
m2!();
2840
}

tests/ui/redundant_closure_call_fixable.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,16 @@ fn main() {
2525
x * y
2626
})();
2727
let d = (async || something().await)();
28+
29+
macro_rules! m {
30+
() => {
31+
(|| 0)()
32+
};
33+
}
34+
macro_rules! m2 {
35+
() => {
36+
(|| m!())()
37+
};
38+
}
39+
m2!();
2840
}

tests/ui/redundant_closure_call_fixable.stderr

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,27 @@ error: try not to call a closure in the expression where it is declared
5252
LL | let d = (async || something().await)();
5353
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `async { something().await }`
5454

55-
error: aborting due to 4 previous errors
55+
error: try not to call a closure in the expression where it is declared
56+
--> $DIR/redundant_closure_call_fixable.rs:36:13
57+
|
58+
LL | (|| m!())()
59+
| ^^^^^^^^^^^ help: try doing something like: `m!()`
60+
...
61+
LL | m2!();
62+
| ----- in this macro invocation
63+
|
64+
= note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
65+
66+
error: try not to call a closure in the expression where it is declared
67+
--> $DIR/redundant_closure_call_fixable.rs:31:13
68+
|
69+
LL | (|| 0)()
70+
| ^^^^^^^^ help: try doing something like: `0`
71+
...
72+
LL | m2!();
73+
| ----- in this macro invocation
74+
|
75+
= note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info)
76+
77+
error: aborting due to 6 previous errors
5678

0 commit comments

Comments
 (0)