Skip to content

Commit 6ac03a4

Browse files
committed
change catagory to pedantic & add a test case & api adjustments
1 parent e4d4563 commit 6ac03a4

File tree

3 files changed

+49
-14
lines changed

3 files changed

+49
-14
lines changed

clippy_lints/src/unnecessary_blocking_ops.rs

+40-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use clippy_utils::{def_path_def_ids, fn_def_id, is_lint_allowed};
55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_errors::{Applicability, Diagnostic};
77
use rustc_hir::def_id::DefId;
8-
use rustc_hir::{Body, CoroutineKind, Expr, ExprKind};
8+
use rustc_hir::{
9+
Body, BodyId, Closure, ClosureKind, CoroutineDesugaring, CoroutineKind, Expr, ExprKind, ImplItem, ImplItemKind,
10+
Item, ItemKind, Node, TraitItem, TraitItemKind,
11+
};
912
use rustc_lint::{LateContext, LateLintPass};
1013
use rustc_session::impl_lint_pass;
1114
use rustc_span::Span;
@@ -40,23 +43,24 @@ declare_clippy_lint! {
4043
/// ```
4144
#[clippy::version = "1.74.0"]
4245
pub UNNECESSARY_BLOCKING_OPS,
43-
nursery,
46+
pedantic,
4447
"blocking operations in an async context"
4548
}
4649

4750
pub(crate) struct UnnecessaryBlockingOps {
4851
blocking_ops: Vec<DisallowedPath>,
4952
/// Map of resolved funtion def_id with suggestion string after checking crate
5053
id_with_suggs: FxHashMap<DefId, Option<String>>,
51-
is_in_async: bool,
54+
/// Tracking whether a body is async after entering it.
55+
body_asyncness: Vec<bool>,
5256
}
5357

5458
impl UnnecessaryBlockingOps {
5559
pub(crate) fn new(blocking_ops: Vec<DisallowedPath>) -> Self {
5660
Self {
5761
blocking_ops,
5862
id_with_suggs: FxHashMap::default(),
59-
is_in_async: false,
63+
body_asyncness: vec![],
6064
}
6165
}
6266
}
@@ -108,14 +112,11 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryBlockingOps {
108112
if is_lint_allowed(cx, UNNECESSARY_BLOCKING_OPS, body.value.hir_id) {
109113
return;
110114
}
111-
112-
if let Some(CoroutineKind::Async(_)) = body.coroutine_kind() {
113-
self.is_in_async = true;
114-
}
115+
self.body_asyncness.push(in_async_body(cx, body.id()));
115116
}
116117

117118
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
118-
if self.is_in_async
119+
if matches!(self.body_asyncness.last(), Some(true))
119120
&& let ExprKind::Call(call, _) = &expr.kind
120121
&& let Some(call_did) = fn_def_id(cx, expr)
121122
&& let Some(maybe_sugg) = self.id_with_suggs.get(&call_did)
@@ -134,10 +135,8 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryBlockingOps {
134135
}
135136
}
136137

137-
fn check_body_post(&mut self, _: &LateContext<'tcx>, body: &'tcx Body<'tcx>) {
138-
if !matches!(body.coroutine_kind(), Some(CoroutineKind::Async(_))) {
139-
self.is_in_async = false;
140-
}
138+
fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx Body<'tcx>) {
139+
self.body_asyncness.pop();
141140
}
142141
}
143142

@@ -153,3 +152,31 @@ fn make_suggestion(diag: &mut Diagnostic, cx: &LateContext<'_>, expr: &Expr<'_>,
153152
Applicability::Unspecified,
154153
);
155154
}
155+
156+
fn in_async_body(cx: &LateContext<'_>, body_id: BodyId) -> bool {
157+
let Some(parent_node) = cx.tcx.hir().find_parent(body_id.hir_id) else {
158+
return false;
159+
};
160+
match parent_node {
161+
Node::Expr(expr) => matches!(
162+
expr.kind,
163+
ExprKind::Closure(Closure {
164+
kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, _)),
165+
..
166+
})
167+
),
168+
Node::Item(Item {
169+
kind: ItemKind::Fn(fn_sig, ..),
170+
..
171+
})
172+
| Node::ImplItem(ImplItem {
173+
kind: ImplItemKind::Fn(fn_sig, _),
174+
..
175+
})
176+
| Node::TraitItem(TraitItem {
177+
kind: TraitItemKind::Fn(fn_sig, _),
178+
..
179+
}) => fn_sig.header.is_async(),
180+
_ => false,
181+
}
182+
}

tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.rs

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub async fn async_fn() {
3030
//~^ ERROR: blocking function call detected in an async body
3131
fs::create_dir("").unwrap();
3232
//~^ ERROR: blocking function call detected in an async body
33+
blocking_mod::sleep(Duration::from_secs(1));
34+
//~^ ERROR: blocking function call detected in an async body
3335
}
3436

3537
fn main() {}

tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,11 @@ error: blocking function call detected in an async body
4747
LL | fs::create_dir("").unwrap();
4848
| ^^^^^^^^^^^^^^
4949

50-
error: aborting due to 6 previous errors
50+
error: blocking function call detected in an async body
51+
--> $DIR/unnecessary_blocking_ops.rs:33:5
52+
|
53+
LL | blocking_mod::sleep(Duration::from_secs(1));
54+
| ^^^^^^^^^^^^^^^^^^^
55+
56+
error: aborting due to 7 previous errors
5157

0 commit comments

Comments
 (0)