Skip to content

Commit da6d23b

Browse files
committed
fix: ignore unsafe ops from .await desugaring
1 parent 8938bb2 commit da6d23b

File tree

3 files changed

+149
-31
lines changed

3 files changed

+149
-31
lines changed

clippy_lints/src/multiple_unsafe_ops_per_block.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use clippy_utils::desugar_await;
12
use clippy_utils::diagnostics::span_lint_and_then;
23
use clippy_utils::visitors::{Descend, Visitable, for_each_expr};
34
use core::ops::ControlFlow::Continue;
@@ -97,6 +98,13 @@ fn collect_unsafe_exprs<'tcx>(
9798
) {
9899
for_each_expr(cx, node, |expr| {
99100
match expr.kind {
101+
// The `await` itself will desugar to two unsafe calls, but we should ignore those.
102+
// Instead, check the expression that is `await`ed
103+
_ if let Some(e) = desugar_await(expr) => {
104+
collect_unsafe_exprs(cx, e, unsafe_ops);
105+
return Continue(Descend::No);
106+
},
107+
100108
ExprKind::InlineAsm(_) => unsafe_ops.push(("inline assembly used here", expr.span)),
101109

102110
ExprKind::Field(e, _) => {

tests/ui/multiple_unsafe_ops_per_block.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
//@needs-asm-support
22
//@aux-build:proc_macros.rs
3-
#![expect(clippy::unnecessary_operation, dropping_copy_types)]
3+
#![expect(
4+
dropping_copy_types,
5+
clippy::unnecessary_operation,
6+
clippy::unnecessary_literal_unwrap
7+
)]
48
#![warn(clippy::multiple_unsafe_ops_per_block)]
59

610
extern crate proc_macros;
@@ -162,4 +166,47 @@ async fn issue11312() {
162166
helper().await;
163167
}
164168

169+
async fn issue13879() {
170+
async fn foo() {}
171+
172+
// no lint: nothing unsafe beyond the `await` which we ignore
173+
unsafe {
174+
foo().await;
175+
}
176+
177+
// no lint: only one unsafe call beyond the `await`
178+
unsafe {
179+
not_very_safe();
180+
foo().await;
181+
}
182+
183+
// lint: two unsafe calls beyond the `await`
184+
unsafe {
185+
//~^ multiple_unsafe_ops_per_block
186+
not_very_safe();
187+
STATIC += 1;
188+
foo().await;
189+
}
190+
191+
async unsafe fn foo_unchecked() {}
192+
193+
// no lint: only one unsafe call in the `await`ed expr
194+
unsafe {
195+
foo_unchecked().await;
196+
}
197+
198+
// lint: one unsafe call in the `await`ed expr, and one outside
199+
unsafe {
200+
//~^ multiple_unsafe_ops_per_block
201+
not_very_safe();
202+
foo_unchecked().await;
203+
}
204+
205+
// lint: two unsafe calls in the `await`ed expr
206+
unsafe {
207+
//~^ multiple_unsafe_ops_per_block
208+
Some(foo_unchecked()).unwrap_unchecked().await;
209+
}
210+
}
211+
165212
fn main() {}
Lines changed: 93 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: this `unsafe` block contains 2 unsafe operations, expected only one
2-
--> tests/ui/multiple_unsafe_ops_per_block.rs:34:5
2+
--> tests/ui/multiple_unsafe_ops_per_block.rs:38:5
33
|
44
LL | / unsafe {
55
LL | |
@@ -9,20 +9,20 @@ LL | | }
99
| |_____^
1010
|
1111
note: modification of a mutable static occurs here
12-
--> tests/ui/multiple_unsafe_ops_per_block.rs:36:9
12+
--> tests/ui/multiple_unsafe_ops_per_block.rs:40:9
1313
|
1414
LL | STATIC += 1;
1515
| ^^^^^^^^^^^
1616
note: unsafe function call occurs here
17-
--> tests/ui/multiple_unsafe_ops_per_block.rs:37:9
17+
--> tests/ui/multiple_unsafe_ops_per_block.rs:41:9
1818
|
1919
LL | not_very_safe();
2020
| ^^^^^^^^^^^^^^^
2121
= note: `-D clippy::multiple-unsafe-ops-per-block` implied by `-D warnings`
2222
= help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]`
2323

2424
error: this `unsafe` block contains 2 unsafe operations, expected only one
25-
--> tests/ui/multiple_unsafe_ops_per_block.rs:44:5
25+
--> tests/ui/multiple_unsafe_ops_per_block.rs:48:5
2626
|
2727
LL | / unsafe {
2828
LL | |
@@ -32,18 +32,18 @@ LL | | }
3232
| |_____^
3333
|
3434
note: union field access occurs here
35-
--> tests/ui/multiple_unsafe_ops_per_block.rs:46:14
35+
--> tests/ui/multiple_unsafe_ops_per_block.rs:50:14
3636
|
3737
LL | drop(u.u);
3838
| ^^^
3939
note: raw pointer dereference occurs here
40-
--> tests/ui/multiple_unsafe_ops_per_block.rs:47:9
40+
--> tests/ui/multiple_unsafe_ops_per_block.rs:51:9
4141
|
4242
LL | *raw_ptr();
4343
| ^^^^^^^^^^
4444

4545
error: this `unsafe` block contains 3 unsafe operations, expected only one
46-
--> tests/ui/multiple_unsafe_ops_per_block.rs:52:5
46+
--> tests/ui/multiple_unsafe_ops_per_block.rs:56:5
4747
|
4848
LL | / unsafe {
4949
LL | |
@@ -54,23 +54,23 @@ LL | | }
5454
| |_____^
5555
|
5656
note: inline assembly used here
57-
--> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
57+
--> tests/ui/multiple_unsafe_ops_per_block.rs:58:9
5858
|
5959
LL | asm!("nop");
6060
| ^^^^^^^^^^^
6161
note: unsafe method call occurs here
62-
--> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
62+
--> tests/ui/multiple_unsafe_ops_per_block.rs:59:9
6363
|
6464
LL | sample.not_very_safe();
6565
| ^^^^^^^^^^^^^^^^^^^^^^
6666
note: modification of a mutable static occurs here
67-
--> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
67+
--> tests/ui/multiple_unsafe_ops_per_block.rs:60:9
6868
|
6969
LL | STATIC = 0;
7070
| ^^^^^^^^^^
7171

7272
error: this `unsafe` block contains 6 unsafe operations, expected only one
73-
--> tests/ui/multiple_unsafe_ops_per_block.rs:62:5
73+
--> tests/ui/multiple_unsafe_ops_per_block.rs:66:5
7474
|
7575
LL | / unsafe {
7676
LL | |
@@ -82,55 +82,55 @@ LL | | }
8282
| |_____^
8383
|
8484
note: union field access occurs here
85-
--> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
85+
--> tests/ui/multiple_unsafe_ops_per_block.rs:68:14
8686
|
8787
LL | drop(u.u);
8888
| ^^^
8989
note: access of a mutable static occurs here
90-
--> tests/ui/multiple_unsafe_ops_per_block.rs:65:14
90+
--> tests/ui/multiple_unsafe_ops_per_block.rs:69:14
9191
|
9292
LL | drop(STATIC);
9393
| ^^^^^^
9494
note: unsafe method call occurs here
95-
--> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
95+
--> tests/ui/multiple_unsafe_ops_per_block.rs:70:9
9696
|
9797
LL | sample.not_very_safe();
9898
| ^^^^^^^^^^^^^^^^^^^^^^
9999
note: unsafe function call occurs here
100-
--> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
100+
--> tests/ui/multiple_unsafe_ops_per_block.rs:71:9
101101
|
102102
LL | not_very_safe();
103103
| ^^^^^^^^^^^^^^^
104104
note: raw pointer dereference occurs here
105-
--> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
105+
--> tests/ui/multiple_unsafe_ops_per_block.rs:72:9
106106
|
107107
LL | *raw_ptr();
108108
| ^^^^^^^^^^
109109
note: inline assembly used here
110-
--> tests/ui/multiple_unsafe_ops_per_block.rs:69:9
110+
--> tests/ui/multiple_unsafe_ops_per_block.rs:73:9
111111
|
112112
LL | asm!("nop");
113113
| ^^^^^^^^^^^
114114

115115
error: this `unsafe` block contains 2 unsafe operations, expected only one
116-
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:9
116+
--> tests/ui/multiple_unsafe_ops_per_block.rs:110:9
117117
|
118118
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
119119
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
120120
|
121121
note: unsafe function call occurs here
122-
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:18
122+
--> tests/ui/multiple_unsafe_ops_per_block.rs:110:18
123123
|
124124
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
125125
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
126126
note: raw pointer dereference occurs here
127-
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:43
127+
--> tests/ui/multiple_unsafe_ops_per_block.rs:110:43
128128
|
129129
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
130130
| ^^^^^^^^^^^^^^^^^^
131131

132132
error: this `unsafe` block contains 2 unsafe operations, expected only one
133-
--> tests/ui/multiple_unsafe_ops_per_block.rs:127:9
133+
--> tests/ui/multiple_unsafe_ops_per_block.rs:131:9
134134
|
135135
LL | / unsafe {
136136
LL | |
@@ -140,18 +140,18 @@ LL | | }
140140
| |_________^
141141
|
142142
note: unsafe function call occurs here
143-
--> tests/ui/multiple_unsafe_ops_per_block.rs:129:13
143+
--> tests/ui/multiple_unsafe_ops_per_block.rs:133:13
144144
|
145145
LL | x();
146146
| ^^^
147147
note: unsafe function call occurs here
148-
--> tests/ui/multiple_unsafe_ops_per_block.rs:130:13
148+
--> tests/ui/multiple_unsafe_ops_per_block.rs:134:13
149149
|
150150
LL | x();
151151
| ^^^
152152

153153
error: this `unsafe` block contains 2 unsafe operations, expected only one
154-
--> tests/ui/multiple_unsafe_ops_per_block.rs:139:13
154+
--> tests/ui/multiple_unsafe_ops_per_block.rs:143:13
155155
|
156156
LL | / unsafe {
157157
LL | |
@@ -161,18 +161,18 @@ LL | | }
161161
| |_____________^
162162
|
163163
note: unsafe function call occurs here
164-
--> tests/ui/multiple_unsafe_ops_per_block.rs:141:17
164+
--> tests/ui/multiple_unsafe_ops_per_block.rs:145:17
165165
|
166166
LL | T::X();
167167
| ^^^^^^
168168
note: unsafe function call occurs here
169-
--> tests/ui/multiple_unsafe_ops_per_block.rs:142:17
169+
--> tests/ui/multiple_unsafe_ops_per_block.rs:146:17
170170
|
171171
LL | T::X();
172172
| ^^^^^^
173173

174174
error: this `unsafe` block contains 2 unsafe operations, expected only one
175-
--> tests/ui/multiple_unsafe_ops_per_block.rs:150:9
175+
--> tests/ui/multiple_unsafe_ops_per_block.rs:154:9
176176
|
177177
LL | / unsafe {
178178
LL | |
@@ -182,15 +182,78 @@ LL | | }
182182
| |_________^
183183
|
184184
note: unsafe function call occurs here
185-
--> tests/ui/multiple_unsafe_ops_per_block.rs:152:13
185+
--> tests/ui/multiple_unsafe_ops_per_block.rs:156:13
186186
|
187187
LL | x.0();
188188
| ^^^^^
189189
note: unsafe function call occurs here
190-
--> tests/ui/multiple_unsafe_ops_per_block.rs:153:13
190+
--> tests/ui/multiple_unsafe_ops_per_block.rs:157:13
191191
|
192192
LL | x.0();
193193
| ^^^^^
194194

195-
error: aborting due to 8 previous errors
195+
error: this `unsafe` block contains 2 unsafe operations, expected only one
196+
--> tests/ui/multiple_unsafe_ops_per_block.rs:184:5
197+
|
198+
LL | / unsafe {
199+
LL | |
200+
LL | | not_very_safe();
201+
LL | | STATIC += 1;
202+
LL | | foo().await;
203+
LL | | }
204+
| |_____^
205+
|
206+
note: unsafe function call occurs here
207+
--> tests/ui/multiple_unsafe_ops_per_block.rs:186:9
208+
|
209+
LL | not_very_safe();
210+
| ^^^^^^^^^^^^^^^
211+
note: modification of a mutable static occurs here
212+
--> tests/ui/multiple_unsafe_ops_per_block.rs:187:9
213+
|
214+
LL | STATIC += 1;
215+
| ^^^^^^^^^^^
216+
217+
error: this `unsafe` block contains 2 unsafe operations, expected only one
218+
--> tests/ui/multiple_unsafe_ops_per_block.rs:199:5
219+
|
220+
LL | / unsafe {
221+
LL | |
222+
LL | | not_very_safe();
223+
LL | | foo_unchecked().await;
224+
LL | | }
225+
| |_____^
226+
|
227+
note: unsafe function call occurs here
228+
--> tests/ui/multiple_unsafe_ops_per_block.rs:201:9
229+
|
230+
LL | not_very_safe();
231+
| ^^^^^^^^^^^^^^^
232+
note: unsafe function call occurs here
233+
--> tests/ui/multiple_unsafe_ops_per_block.rs:202:9
234+
|
235+
LL | foo_unchecked().await;
236+
| ^^^^^^^^^^^^^^^
237+
238+
error: this `unsafe` block contains 2 unsafe operations, expected only one
239+
--> tests/ui/multiple_unsafe_ops_per_block.rs:206:5
240+
|
241+
LL | / unsafe {
242+
LL | |
243+
LL | | Some(foo_unchecked()).unwrap_unchecked().await;
244+
LL | | }
245+
| |_____^
246+
|
247+
note: unsafe method call occurs here
248+
--> tests/ui/multiple_unsafe_ops_per_block.rs:208:9
249+
|
250+
LL | Some(foo_unchecked()).unwrap_unchecked().await;
251+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
252+
note: unsafe function call occurs here
253+
--> tests/ui/multiple_unsafe_ops_per_block.rs:208:14
254+
|
255+
LL | Some(foo_unchecked()).unwrap_unchecked().await;
256+
| ^^^^^^^^^^^^^^^
257+
258+
error: aborting due to 11 previous errors
196259

0 commit comments

Comments
 (0)