about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-19 13:58:09 +0000
committerbors <bors@rust-lang.org>2023-01-19 13:58:09 +0000
commitaa0eb7fb1cc27d59375645b0f34c59dc85afb1ec (patch)
tree1367f7042f146cc29593e52e39655347ccf65cc8 /tests
parent36e3e26464c1db3be35bd8ff8872d96a97eb8c5e (diff)
parent875e36f7e459776d3e51b7c089ab89b0821b6122 (diff)
downloadrust-aa0eb7fb1cc27d59375645b0f34c59dc85afb1ec.tar.gz
rust-aa0eb7fb1cc27d59375645b0f34c59dc85afb1ec.zip
Auto merge of #10206 - Niki4tap:one_unsafe_op_per_block, r=Alexendoo
Add `multiple_unsafe_ops_per_block` lint

Adds a lint, which restricts an `unsafe` block to only one unsafe operation.

Closes #10064

---

changelog: New lint: [`multiple_unsafe_ops_per_block`]
[#10206](https://github.com/rust-lang/rust-clippy/pull/10206)
<!-- changelog_checked -->
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/multiple_unsafe_ops_per_block.rs110
-rw-r--r--tests/ui/multiple_unsafe_ops_per_block.stderr129
2 files changed, 239 insertions, 0 deletions
diff --git a/tests/ui/multiple_unsafe_ops_per_block.rs b/tests/ui/multiple_unsafe_ops_per_block.rs
new file mode 100644
index 00000000000..41263535df6
--- /dev/null
+++ b/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -0,0 +1,110 @@
+#![allow(unused)]
+#![allow(deref_nullptr)]
+#![allow(clippy::unnecessary_operation)]
+#![allow(clippy::drop_copy)]
+#![warn(clippy::multiple_unsafe_ops_per_block)]
+
+use core::arch::asm;
+
+fn raw_ptr() -> *const () {
+    core::ptr::null()
+}
+
+unsafe fn not_very_safe() {}
+
+struct Sample;
+
+impl Sample {
+    unsafe fn not_very_safe(&self) {}
+}
+
+#[allow(non_upper_case_globals)]
+const sample: Sample = Sample;
+
+union U {
+    i: i32,
+    u: u32,
+}
+
+static mut STATIC: i32 = 0;
+
+fn test1() {
+    unsafe {
+        STATIC += 1;
+        not_very_safe();
+    }
+}
+
+fn test2() {
+    let u = U { i: 0 };
+
+    unsafe {
+        drop(u.u);
+        *raw_ptr();
+    }
+}
+
+fn test3() {
+    unsafe {
+        asm!("nop");
+        sample.not_very_safe();
+        STATIC = 0;
+    }
+}
+
+fn test_all() {
+    let u = U { i: 0 };
+    unsafe {
+        drop(u.u);
+        drop(STATIC);
+        sample.not_very_safe();
+        not_very_safe();
+        *raw_ptr();
+        asm!("nop");
+    }
+}
+
+// no lint
+fn correct1() {
+    unsafe {
+        STATIC += 1;
+    }
+}
+
+// no lint
+fn correct2() {
+    unsafe {
+        STATIC += 1;
+    }
+
+    unsafe {
+        *raw_ptr();
+    }
+}
+
+// no lint
+fn correct3() {
+    let u = U { u: 0 };
+
+    unsafe {
+        not_very_safe();
+    }
+
+    unsafe {
+        drop(u.i);
+    }
+}
+
+// tests from the issue (https://github.com/rust-lang/rust-clippy/issues/10064)
+
+unsafe fn read_char_bad(ptr: *const u8) -> char {
+    unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+}
+
+// no lint
+unsafe fn read_char_good(ptr: *const u8) -> char {
+    let int_value = unsafe { *ptr.cast::<u32>() };
+    unsafe { core::char::from_u32_unchecked(int_value) }
+}
+
+fn main() {}
diff --git a/tests/ui/multiple_unsafe_ops_per_block.stderr b/tests/ui/multiple_unsafe_ops_per_block.stderr
new file mode 100644
index 00000000000..f6b8341795d
--- /dev/null
+++ b/tests/ui/multiple_unsafe_ops_per_block.stderr
@@ -0,0 +1,129 @@
+error: this `unsafe` block contains 2 unsafe operations, expected only one
+  --> $DIR/multiple_unsafe_ops_per_block.rs:32:5
+   |
+LL | /     unsafe {
+LL | |         STATIC += 1;
+LL | |         not_very_safe();
+LL | |     }
+   | |_____^
+   |
+note: modification of a mutable static occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:33:9
+   |
+LL |         STATIC += 1;
+   |         ^^^^^^^^^^^
+note: unsafe function call occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:34:9
+   |
+LL |         not_very_safe();
+   |         ^^^^^^^^^^^^^^^
+   = note: `-D clippy::multiple-unsafe-ops-per-block` implied by `-D warnings`
+
+error: this `unsafe` block contains 2 unsafe operations, expected only one
+  --> $DIR/multiple_unsafe_ops_per_block.rs:41:5
+   |
+LL | /     unsafe {
+LL | |         drop(u.u);
+LL | |         *raw_ptr();
+LL | |     }
+   | |_____^
+   |
+note: union field access occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:42:14
+   |
+LL |         drop(u.u);
+   |              ^^^
+note: raw pointer dereference occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:43:9
+   |
+LL |         *raw_ptr();
+   |         ^^^^^^^^^^
+
+error: this `unsafe` block contains 3 unsafe operations, expected only one
+  --> $DIR/multiple_unsafe_ops_per_block.rs:48:5
+   |
+LL | /     unsafe {
+LL | |         asm!("nop");
+LL | |         sample.not_very_safe();
+LL | |         STATIC = 0;
+LL | |     }
+   | |_____^
+   |
+note: inline assembly used here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:49:9
+   |
+LL |         asm!("nop");
+   |         ^^^^^^^^^^^
+note: unsafe method call occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:50:9
+   |
+LL |         sample.not_very_safe();
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+note: modification of a mutable static occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:51:9
+   |
+LL |         STATIC = 0;
+   |         ^^^^^^^^^^
+
+error: this `unsafe` block contains 6 unsafe operations, expected only one
+  --> $DIR/multiple_unsafe_ops_per_block.rs:57:5
+   |
+LL | /     unsafe {
+LL | |         drop(u.u);
+LL | |         drop(STATIC);
+LL | |         sample.not_very_safe();
+...  |
+LL | |         asm!("nop");
+LL | |     }
+   | |_____^
+   |
+note: union field access occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:58:14
+   |
+LL |         drop(u.u);
+   |              ^^^
+note: access of a mutable static occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:59:14
+   |
+LL |         drop(STATIC);
+   |              ^^^^^^
+note: unsafe method call occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:60:9
+   |
+LL |         sample.not_very_safe();
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+note: unsafe function call occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:61:9
+   |
+LL |         not_very_safe();
+   |         ^^^^^^^^^^^^^^^
+note: raw pointer dereference occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:62:9
+   |
+LL |         *raw_ptr();
+   |         ^^^^^^^^^^
+note: inline assembly used here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:63:9
+   |
+LL |         asm!("nop");
+   |         ^^^^^^^^^^^
+
+error: this `unsafe` block contains 2 unsafe operations, expected only one
+  --> $DIR/multiple_unsafe_ops_per_block.rs:101:5
+   |
+LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: unsafe function call occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:101:14
+   |
+LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: raw pointer dereference occurs here
+  --> $DIR/multiple_unsafe_ops_per_block.rs:101:39
+   |
+LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
+   |                                       ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+