fix: ignore unsafe ops from .await desugaring
This commit is contained in:
parent
8938bb268d
commit
da6d23b116
3 changed files with 149 additions and 31 deletions
|
|
@ -1,3 +1,4 @@
|
|||
use clippy_utils::desugar_await;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::visitors::{Descend, Visitable, for_each_expr};
|
||||
use core::ops::ControlFlow::Continue;
|
||||
|
|
@ -97,6 +98,13 @@ fn collect_unsafe_exprs<'tcx>(
|
|||
) {
|
||||
for_each_expr(cx, node, |expr| {
|
||||
match expr.kind {
|
||||
// The `await` itself will desugar to two unsafe calls, but we should ignore those.
|
||||
// Instead, check the expression that is `await`ed
|
||||
_ if let Some(e) = desugar_await(expr) => {
|
||||
collect_unsafe_exprs(cx, e, unsafe_ops);
|
||||
return Continue(Descend::No);
|
||||
},
|
||||
|
||||
ExprKind::InlineAsm(_) => unsafe_ops.push(("inline assembly used here", expr.span)),
|
||||
|
||||
ExprKind::Field(e, _) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
//@needs-asm-support
|
||||
//@aux-build:proc_macros.rs
|
||||
#![expect(clippy::unnecessary_operation, dropping_copy_types)]
|
||||
#![expect(
|
||||
dropping_copy_types,
|
||||
clippy::unnecessary_operation,
|
||||
clippy::unnecessary_literal_unwrap
|
||||
)]
|
||||
#![warn(clippy::multiple_unsafe_ops_per_block)]
|
||||
|
||||
extern crate proc_macros;
|
||||
|
|
@ -162,4 +166,47 @@ async fn issue11312() {
|
|||
helper().await;
|
||||
}
|
||||
|
||||
async fn issue13879() {
|
||||
async fn foo() {}
|
||||
|
||||
// no lint: nothing unsafe beyond the `await` which we ignore
|
||||
unsafe {
|
||||
foo().await;
|
||||
}
|
||||
|
||||
// no lint: only one unsafe call beyond the `await`
|
||||
unsafe {
|
||||
not_very_safe();
|
||||
foo().await;
|
||||
}
|
||||
|
||||
// lint: two unsafe calls beyond the `await`
|
||||
unsafe {
|
||||
//~^ multiple_unsafe_ops_per_block
|
||||
not_very_safe();
|
||||
STATIC += 1;
|
||||
foo().await;
|
||||
}
|
||||
|
||||
async unsafe fn foo_unchecked() {}
|
||||
|
||||
// no lint: only one unsafe call in the `await`ed expr
|
||||
unsafe {
|
||||
foo_unchecked().await;
|
||||
}
|
||||
|
||||
// lint: one unsafe call in the `await`ed expr, and one outside
|
||||
unsafe {
|
||||
//~^ multiple_unsafe_ops_per_block
|
||||
not_very_safe();
|
||||
foo_unchecked().await;
|
||||
}
|
||||
|
||||
// lint: two unsafe calls in the `await`ed expr
|
||||
unsafe {
|
||||
//~^ multiple_unsafe_ops_per_block
|
||||
Some(foo_unchecked()).unwrap_unchecked().await;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:34:5
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:38:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
|
|
@ -9,12 +9,12 @@ LL | | }
|
|||
| |_____^
|
||||
|
|
||||
note: modification of a mutable static occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:36:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:40:9
|
||||
|
|
||||
LL | STATIC += 1;
|
||||
| ^^^^^^^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:37:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:41:9
|
||||
|
|
||||
LL | not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
@ -22,7 +22,7 @@ LL | not_very_safe();
|
|||
= help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]`
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:44:5
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:48:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
|
|
@ -32,18 +32,18 @@ LL | | }
|
|||
| |_____^
|
||||
|
|
||||
note: union field access occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:46:14
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:50:14
|
||||
|
|
||||
LL | drop(u.u);
|
||||
| ^^^
|
||||
note: raw pointer dereference occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:47:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:51:9
|
||||
|
|
||||
LL | *raw_ptr();
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 3 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:52:5
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:56:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
|
|
@ -54,23 +54,23 @@ LL | | }
|
|||
| |_____^
|
||||
|
|
||||
note: inline assembly used here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:58:9
|
||||
|
|
||||
LL | asm!("nop");
|
||||
| ^^^^^^^^^^^
|
||||
note: unsafe method call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:59:9
|
||||
|
|
||||
LL | sample.not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: modification of a mutable static occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:60:9
|
||||
|
|
||||
LL | STATIC = 0;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 6 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:62:5
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:66:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
|
|
@ -82,55 +82,55 @@ LL | | }
|
|||
| |_____^
|
||||
|
|
||||
note: union field access occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:68:14
|
||||
|
|
||||
LL | drop(u.u);
|
||||
| ^^^
|
||||
note: access of a mutable static occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:65:14
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:69:14
|
||||
|
|
||||
LL | drop(STATIC);
|
||||
| ^^^^^^
|
||||
note: unsafe method call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:70:9
|
||||
|
|
||||
LL | sample.not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:71:9
|
||||
|
|
||||
LL | not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: raw pointer dereference occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:72:9
|
||||
|
|
||||
LL | *raw_ptr();
|
||||
| ^^^^^^^^^^
|
||||
note: inline assembly used here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:69:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:73:9
|
||||
|
|
||||
LL | asm!("nop");
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:110:9
|
||||
|
|
||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:18
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:110:18
|
||||
|
|
||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: raw pointer dereference occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:106:43
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:110:43
|
||||
|
|
||||
LL | unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:127:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:131:9
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
|
|
@ -140,18 +140,18 @@ LL | | }
|
|||
| |_________^
|
||||
|
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:129:13
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:133:13
|
||||
|
|
||||
LL | x();
|
||||
| ^^^
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:130:13
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:134:13
|
||||
|
|
||||
LL | x();
|
||||
| ^^^
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:139:13
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:143:13
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
|
|
@ -161,18 +161,18 @@ LL | | }
|
|||
| |_____________^
|
||||
|
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:141:17
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:145:17
|
||||
|
|
||||
LL | T::X();
|
||||
| ^^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:142:17
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:146:17
|
||||
|
|
||||
LL | T::X();
|
||||
| ^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:150:9
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:154:9
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
|
|
@ -182,15 +182,78 @@ LL | | }
|
|||
| |_________^
|
||||
|
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:152:13
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:156:13
|
||||
|
|
||||
LL | x.0();
|
||||
| ^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:153:13
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:157:13
|
||||
|
|
||||
LL | x.0();
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:184:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
LL | | not_very_safe();
|
||||
LL | | STATIC += 1;
|
||||
LL | | foo().await;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:186:9
|
||||
|
|
||||
LL | not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: modification of a mutable static occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:187:9
|
||||
|
|
||||
LL | STATIC += 1;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:199:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
LL | | not_very_safe();
|
||||
LL | | foo_unchecked().await;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:201:9
|
||||
|
|
||||
LL | not_very_safe();
|
||||
| ^^^^^^^^^^^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:202:9
|
||||
|
|
||||
LL | foo_unchecked().await;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: this `unsafe` block contains 2 unsafe operations, expected only one
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:206:5
|
||||
|
|
||||
LL | / unsafe {
|
||||
LL | |
|
||||
LL | | Some(foo_unchecked()).unwrap_unchecked().await;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
note: unsafe method call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:208:9
|
||||
|
|
||||
LL | Some(foo_unchecked()).unwrap_unchecked().await;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
note: unsafe function call occurs here
|
||||
--> tests/ui/multiple_unsafe_ops_per_block.rs:208:14
|
||||
|
|
||||
LL | Some(foo_unchecked()).unwrap_unchecked().await;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue