Skip to content

Commit 2948678

Browse files
authored
Fix dbg_macro fail to handle async coroutine desugar (#14937)
Closes rust-lang/rust-clippy#14914 ---- changelog: [`dbg_macro`]: fix mishandling of async coroutine desugar
2 parents 010c2d3 + 7631648 commit 2948678

File tree

4 files changed

+122
-46
lines changed

4 files changed

+122
-46
lines changed

clippy_lints/src/dbg_macro.rs

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clippy_utils::macros::{MacroCall, macro_backtrace};
55
use clippy_utils::source::snippet_with_applicability;
66
use rustc_data_structures::fx::FxHashSet;
77
use rustc_errors::Applicability;
8-
use rustc_hir::{Expr, ExprKind, Node};
8+
use rustc_hir::{Closure, ClosureKind, CoroutineKind, Expr, ExprKind, LetStmt, LocalSource, Node, Stmt, StmtKind};
99
use rustc_lint::{LateContext, LateLintPass, LintContext};
1010
use rustc_session::impl_lint_pass;
1111
use rustc_span::{Span, SyntaxContext, sym};
@@ -60,6 +60,8 @@ impl LateLintPass<'_> for DbgMacro {
6060
if cur_syntax_ctxt != self.prev_ctxt &&
6161
let Some(macro_call) = first_dbg_macro_in_expansion(cx, expr.span) &&
6262
!macro_call.span.in_external_macro(cx.sess().source_map()) &&
63+
// avoids exprs generated by the desugaring of coroutines
64+
!is_coroutine_desugar(expr) &&
6365
self.checked_dbg_call_site.insert(macro_call.span) &&
6466
// allows `dbg!` in test code if allow-dbg-in-test is set to true in clippy.toml
6567
!(self.allow_dbg_in_tests && is_in_test(cx.tcx, expr.hir_id))
@@ -73,50 +75,51 @@ impl LateLintPass<'_> for DbgMacro {
7375
"the `dbg!` macro is intended as a debugging tool",
7476
|diag| {
7577
let mut applicability = Applicability::MachineApplicable;
76-
77-
let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
78-
// dbg!()
79-
ExprKind::Block(..) => {
80-
// If the `dbg!` macro is a "free" statement and not contained within other expressions,
81-
// remove the whole statement.
82-
if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
83-
&& let Some(semi_span) = cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
84-
{
85-
(macro_call.span.to(semi_span), String::new())
86-
} else {
87-
(macro_call.span, String::from("()"))
88-
}
89-
},
90-
// dbg!(1)
91-
ExprKind::Match(val, ..) => (
92-
macro_call.span,
93-
snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
94-
.to_string(),
95-
),
96-
// dbg!(2, 3)
97-
ExprKind::Tup(
98-
[
99-
Expr {
100-
kind: ExprKind::Match(first, ..),
101-
..
102-
},
103-
..,
104-
Expr {
105-
kind: ExprKind::Match(last, ..),
106-
..
107-
},
108-
],
109-
) => {
110-
let snippet = snippet_with_applicability(
111-
cx,
112-
first.span.source_callsite().to(last.span.source_callsite()),
113-
"..",
114-
&mut applicability,
115-
);
116-
(macro_call.span, format!("({snippet})"))
117-
},
118-
_ => unreachable!(),
119-
};
78+
let (sugg_span, suggestion) =
79+
match is_async_move_desugar(expr).unwrap_or(expr).peel_drop_temps().kind {
80+
// dbg!()
81+
ExprKind::Block(..) => {
82+
// If the `dbg!` macro is a "free" statement and not contained within other expressions,
83+
// remove the whole statement.
84+
if let Node::Stmt(_) = cx.tcx.parent_hir_node(expr.hir_id)
85+
&& let Some(semi_span) =
86+
cx.sess().source_map().mac_call_stmt_semi_span(macro_call.span)
87+
{
88+
(macro_call.span.to(semi_span), String::new())
89+
} else {
90+
(macro_call.span, String::from("()"))
91+
}
92+
},
93+
// dbg!(1)
94+
ExprKind::Match(val, ..) => (
95+
macro_call.span,
96+
snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability)
97+
.to_string(),
98+
),
99+
// dbg!(2, 3)
100+
ExprKind::Tup(
101+
[
102+
Expr {
103+
kind: ExprKind::Match(first, ..),
104+
..
105+
},
106+
..,
107+
Expr {
108+
kind: ExprKind::Match(last, ..),
109+
..
110+
},
111+
],
112+
) => {
113+
let snippet = snippet_with_applicability(
114+
cx,
115+
first.span.source_callsite().to(last.span.source_callsite()),
116+
"..",
117+
&mut applicability,
118+
);
119+
(macro_call.span, format!("({snippet})"))
120+
},
121+
_ => unreachable!(),
122+
};
120123

121124
diag.span_suggestion(
122125
sugg_span,
@@ -134,6 +137,35 @@ impl LateLintPass<'_> for DbgMacro {
134137
}
135138
}
136139

140+
fn is_coroutine_desugar(expr: &Expr<'_>) -> bool {
141+
matches!(
142+
expr.kind,
143+
ExprKind::Closure(Closure {
144+
kind: ClosureKind::Coroutine(CoroutineKind::Desugared(..)) | ClosureKind::CoroutineClosure(..),
145+
..
146+
})
147+
)
148+
}
149+
150+
fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
151+
if let ExprKind::Block(block, _) = expr.kind
152+
&& let [
153+
Stmt {
154+
kind:
155+
StmtKind::Let(LetStmt {
156+
source: LocalSource::AsyncFn,
157+
..
158+
}),
159+
..
160+
},
161+
] = block.stmts
162+
{
163+
return block.expr;
164+
}
165+
166+
None
167+
}
168+
137169
fn first_dbg_macro_in_expansion(cx: &LateContext<'_>, span: Span) -> Option<MacroCall> {
138170
macro_backtrace(span).find(|mc| cx.tcx.is_diagnostic_item(sym::dbg_macro, mc.def_id))
139171
}

tests/ui/dbg_macro/dbg_macro.fixed

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,19 @@ mod issue12131 {
123123
//~^ dbg_macro
124124
}
125125
}
126+
127+
mod issue14914 {
128+
use std::future::Future;
129+
130+
fn takes_async_fn<F, Fut>(_f: F)
131+
where
132+
F: FnOnce(i32) -> Fut,
133+
Fut: Future<Output = i32>,
134+
{
135+
}
136+
137+
fn should_not_panic() {
138+
takes_async_fn(async |val| val);
139+
//~^ dbg_macro
140+
}
141+
}

tests/ui/dbg_macro/dbg_macro.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,19 @@ mod issue12131 {
123123
//~^ dbg_macro
124124
}
125125
}
126+
127+
mod issue14914 {
128+
use std::future::Future;
129+
130+
fn takes_async_fn<F, Fut>(_f: F)
131+
where
132+
F: FnOnce(i32) -> Fut,
133+
Fut: Future<Output = i32>,
134+
{
135+
}
136+
137+
fn should_not_panic() {
138+
takes_async_fn(async |val| dbg!(val));
139+
//~^ dbg_macro
140+
}
141+
}

tests/ui/dbg_macro/dbg_macro.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,17 @@ LL - print!("{}", dbg!(s));
230230
LL + print!("{}", s);
231231
|
232232

233-
error: aborting due to 19 previous errors
233+
error: the `dbg!` macro is intended as a debugging tool
234+
--> tests/ui/dbg_macro/dbg_macro.rs:138:36
235+
|
236+
LL | takes_async_fn(async |val| dbg!(val));
237+
| ^^^^^^^^^
238+
|
239+
help: remove the invocation before committing it to a version control system
240+
|
241+
LL - takes_async_fn(async |val| dbg!(val));
242+
LL + takes_async_fn(async |val| val);
243+
|
244+
245+
error: aborting due to 20 previous errors
234246

0 commit comments

Comments
 (0)