Skip to content

Commit 3194a51

Browse files
committed
change catagory to pedantic & add a test case & api adjustments
1 parent 2424df0 commit 3194a51

File tree

6 files changed

+84
-33
lines changed

6 files changed

+84
-33
lines changed

clippy_lints/src/unnecessary_blocking_ops.rs

+45-16
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::source::snippet_with_applicability;
44
use clippy_utils::{def_path_def_ids, fn_def_id, is_lint_allowed};
55
use rustc_data_structures::fx::FxHashMap;
6-
use rustc_errors::{Applicability, Diagnostic};
6+
use rustc_errors::{Applicability, Diag};
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>,
49-
/// Map of resolved funtion def_id with suggestion string after checking crate
52+
/// 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,14 +135,12 @@ 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

144-
fn make_suggestion(diag: &mut Diagnostic, cx: &LateContext<'_>, expr: &Expr<'_>, fn_span: Span, sugg_fn_path: &str) {
143+
fn make_suggestion(diag: &mut Diag<'_, ()>, cx: &LateContext<'_>, expr: &Expr<'_>, fn_span: Span, sugg_fn_path: &str) {
145144
let mut applicability = Applicability::Unspecified;
146145
let args_span = expr.span.with_lo(fn_span.hi());
147146
let args_snippet = snippet_with_applicability(cx, args_span, "..", &mut applicability);
@@ -153,3 +152,33 @@ fn make_suggestion(diag: &mut Diagnostic, cx: &LateContext<'_>, expr: &Expr<'_>,
153152
Applicability::Unspecified,
154153
);
155154
}
155+
156+
/// Check whether a body is from an async function/closure.
157+
fn in_async_body(cx: &LateContext<'_>, body_id: BodyId) -> bool {
158+
let parent_node = cx.tcx.parent_hir_node(body_id.hir_id);
159+
match parent_node {
160+
Node::Expr(expr) => matches!(
161+
expr.kind,
162+
ExprKind::Closure(Closure {
163+
kind: ClosureKind::Coroutine(CoroutineKind::Desugared(
164+
CoroutineDesugaring::Async | CoroutineDesugaring::AsyncGen,
165+
_
166+
)),
167+
..
168+
})
169+
),
170+
Node::Item(Item {
171+
kind: ItemKind::Fn(fn_sig, ..),
172+
..
173+
})
174+
| Node::ImplItem(ImplItem {
175+
kind: ImplItemKind::Fn(fn_sig, _),
176+
..
177+
})
178+
| Node::TraitItem(TraitItem {
179+
kind: TraitItemKind::Fn(fn_sig, _),
180+
..
181+
}) => fn_sig.header.is_async(),
182+
_ => false,
183+
}
184+
}

tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
183183
avoid-breaking-exported-api
184184
await-holding-invalid-types
185185
blacklisted-names
186+
blocking-ops
186187
cargo-ignore-publish
187188
check-private-items
188189
cognitive-complexity-threshold

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() {}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: blocking function call detected in an async body
2-
--> $DIR/unnecessary_blocking_ops.rs:19:5
2+
--> tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.rs:19:5
33
|
44
LL | sleep(Duration::from_secs(1));
55
| ^^^^^------------------------
@@ -10,42 +10,48 @@ LL | sleep(Duration::from_secs(1));
1010
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_blocking_ops)]`
1111

1212
error: blocking function call detected in an async body
13-
--> $DIR/unnecessary_blocking_ops.rs:21:5
13+
--> tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.rs:21:5
1414
|
1515
LL | fs::remove_dir("").unwrap();
1616
| ^^^^^^^^^^^^^^----
1717
| |
1818
| help: try using its async counterpart: `tokio::fs::remove_dir("").await`
1919

2020
error: blocking function call detected in an async body
21-
--> $DIR/unnecessary_blocking_ops.rs:23:5
21+
--> tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.rs:23:5
2222
|
2323
LL | fs::copy("", "_").unwrap();
2424
| ^^^^^^^^---------
2525
| |
2626
| help: try using its async counterpart: `tokio::fs::copy("", "_").await`
2727

2828
error: blocking function call detected in an async body
29-
--> $DIR/unnecessary_blocking_ops.rs:27:5
29+
--> tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.rs:27:5
3030
|
3131
LL | io::copy(&mut r, &mut w).unwrap();
3232
| ^^^^^^^^----------------
3333
| |
3434
| help: try using its async counterpart: `tokio::io::copy(&mut r, &mut w).await`
3535

3636
error: blocking function call detected in an async body
37-
--> $DIR/unnecessary_blocking_ops.rs:29:17
37+
--> tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.rs:29:17
3838
|
3939
LL | let _cont = io::read_to_string(io::stdin()).unwrap();
4040
| ^^^^^^^^^^^^^^^^^^-------------
4141
| |
4242
| help: try using its async counterpart: `unnecessary_blocking_ops::async_mod::read_to_string(io::stdin()).await`
4343

4444
error: blocking function call detected in an async body
45-
--> $DIR/unnecessary_blocking_ops.rs:31:5
45+
--> tests/ui-toml/unnecessary_blocking_ops/unnecessary_blocking_ops.rs:31:5
4646
|
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+
--> tests/ui-toml/unnecessary_blocking_ops/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

tests/ui/unnecessary_blocking_ops.rs

+7
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,11 @@ fn closures() {
6969
};
7070
}
7171

72+
fn thread_spawn() {
73+
std::thread::spawn(|| sleep(Duration::from_secs(1)));
74+
std::thread::spawn(async || {});
75+
std::thread::spawn(async || sleep(Duration::from_secs(1)));
76+
//~^ ERROR: blocking function call detected in an async body
77+
}
78+
7279
fn main() {}
+16-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: blocking function call detected in an async body
2-
--> $DIR/unnecessary_blocking_ops.rs:14:5
2+
--> tests/ui/unnecessary_blocking_ops.rs:14:5
33
|
44
LL | sleep(Duration::from_secs(1));
55
| ^^^^^
@@ -8,52 +8,58 @@ LL | sleep(Duration::from_secs(1));
88
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_blocking_ops)]`
99

1010
error: blocking function call detected in an async body
11-
--> $DIR/unnecessary_blocking_ops.rs:16:5
11+
--> tests/ui/unnecessary_blocking_ops.rs:16:5
1212
|
1313
LL | fs::remove_dir("").unwrap();
1414
| ^^^^^^^^^^^^^^
1515

1616
error: blocking function call detected in an async body
17-
--> $DIR/unnecessary_blocking_ops.rs:18:5
17+
--> tests/ui/unnecessary_blocking_ops.rs:18:5
1818
|
1919
LL | fs::copy("", "_").unwrap();
2020
| ^^^^^^^^
2121

2222
error: blocking function call detected in an async body
23-
--> $DIR/unnecessary_blocking_ops.rs:20:13
23+
--> tests/ui/unnecessary_blocking_ops.rs:20:13
2424
|
2525
LL | let _ = fs::canonicalize("");
2626
| ^^^^^^^^^^^^^^^^
2727

2828
error: blocking function call detected in an async body
29-
--> $DIR/unnecessary_blocking_ops.rs:24:9
29+
--> tests/ui/unnecessary_blocking_ops.rs:24:9
3030
|
3131
LL | fs::write("", "").unwrap();
3232
| ^^^^^^^^^
3333

3434
error: blocking function call detected in an async body
35-
--> $DIR/unnecessary_blocking_ops.rs:31:5
35+
--> tests/ui/unnecessary_blocking_ops.rs:31:5
3636
|
3737
LL | io::copy(&mut r, &mut w).unwrap();
3838
| ^^^^^^^^
3939

4040
error: blocking function call detected in an async body
41-
--> $DIR/unnecessary_blocking_ops.rs:50:9
41+
--> tests/ui/unnecessary_blocking_ops.rs:50:9
4242
|
4343
LL | sleep(Duration::from_secs(self.0 as _));
4444
| ^^^^^
4545

4646
error: blocking function call detected in an async body
47-
--> $DIR/unnecessary_blocking_ops.rs:58:22
47+
--> tests/ui/unnecessary_blocking_ops.rs:58:22
4848
|
4949
LL | let _ = async || sleep(Duration::from_secs(1));
5050
| ^^^^^
5151

5252
error: blocking function call detected in an async body
53-
--> $DIR/unnecessary_blocking_ops.rs:63:9
53+
--> tests/ui/unnecessary_blocking_ops.rs:63:9
5454
|
5555
LL | sleep(Duration::from_secs(1));
5656
| ^^^^^
5757

58-
error: aborting due to 9 previous errors
58+
error: blocking function call detected in an async body
59+
--> tests/ui/unnecessary_blocking_ops.rs:75:33
60+
|
61+
LL | std::thread::spawn(async || sleep(Duration::from_secs(1)));
62+
| ^^^^^
63+
64+
error: aborting due to 10 previous errors
5965

0 commit comments

Comments
 (0)