Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /