about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-10-14 17:06:36 +0200
committerGitHub <noreply@github.com>2024-10-14 17:06:36 +0200
commit32062b4b8e95ce38302dd7a3e804e5fe1e8bb943 (patch)
treea8e1f107001838e704213e35a3326a9c2c6b5b2a /tests
parent43bf4f1fd361ad898a3580188d158fc88b28a4a8 (diff)
parenta3606d7ee3dd9d910578a81b2992e61521b1ce21 (diff)
downloadrust-32062b4b8e95ce38302dd7a3e804e5fe1e8bb943.tar.gz
rust-32062b4b8e95ce38302dd7a3e804e5fe1e8bb943.zip
Rollup merge of #131384 - saethlin:precondition-tests, r=ibraheemdev
Update precondition tests (especially for zero-size access to null)

I don't much like the current way I've updated the precondition check helpers, but I couldn't come up with anything better. Ideas welcome.

I've organized `tests/ui/precondition-checks` mostly with one file per function that has `assert_unsafe_precondition` in it, with revisions that check each precondition. The important new test is `tests/ui/precondition-checks/zero-size-null.rs`.
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/precondition-checks/alignment.rs11
-rw-r--r--tests/ui/precondition-checks/ascii-char-digit_unchecked.rs11
-rw-r--r--tests/ui/precondition-checks/assert_unchecked.rs9
-rw-r--r--tests/ui/precondition-checks/char-from_u32_unchecked.rs9
-rw-r--r--tests/ui/precondition-checks/copy-nonoverlapping.rs25
-rw-r--r--tests/ui/precondition-checks/copy.rs23
-rw-r--r--tests/ui/precondition-checks/layout.rs15
-rw-r--r--tests/ui/precondition-checks/misaligned-slice.rs10
-rw-r--r--tests/ui/precondition-checks/nonnull.rs9
-rw-r--r--tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs12
-rw-r--r--tests/ui/precondition-checks/nonzero-new_unchecked.rs9
-rw-r--r--tests/ui/precondition-checks/null-slice.rs10
-rw-r--r--tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs11
-rw-r--r--tests/ui/precondition-checks/read.rs18
-rw-r--r--tests/ui/precondition-checks/read_volatile.rs17
-rw-r--r--tests/ui/precondition-checks/replace.rs17
-rw-r--r--tests/ui/precondition-checks/slice-from-raw-parts-mut.rs16
-rw-r--r--tests/ui/precondition-checks/slice-from-raw-parts.rs15
-rw-r--r--tests/ui/precondition-checks/slice-get_unchecked.rs20
-rw-r--r--tests/ui/precondition-checks/slice-get_unchecked_mut.rs20
-rw-r--r--tests/ui/precondition-checks/slice-swap_unchecked.rs14
-rw-r--r--tests/ui/precondition-checks/str-get_unchecked.rs18
-rw-r--r--tests/ui/precondition-checks/str-get_unchecked_mut.rs19
-rw-r--r--tests/ui/precondition-checks/swap-nonoverlapping.rs25
-rw-r--r--tests/ui/precondition-checks/unchecked_add.rs9
-rw-r--r--tests/ui/precondition-checks/unchecked_mul.rs9
-rw-r--r--tests/ui/precondition-checks/unchecked_shl.rs11
-rw-r--r--tests/ui/precondition-checks/unchecked_shr.rs11
-rw-r--r--tests/ui/precondition-checks/unchecked_sub.rs9
-rw-r--r--tests/ui/precondition-checks/unreachable_unchecked.rs9
-rw-r--r--tests/ui/precondition-checks/write.rs18
-rw-r--r--tests/ui/precondition-checks/write_bytes.rs18
-rw-r--r--tests/ui/precondition-checks/write_volatile.rs17
-rw-r--r--tests/ui/precondition-checks/zero-size-null.rs21
34 files changed, 464 insertions, 31 deletions
diff --git a/tests/ui/precondition-checks/alignment.rs b/tests/ui/precondition-checks/alignment.rs
new file mode 100644
index 00000000000..92400528fa0
--- /dev/null
+++ b/tests/ui/precondition-checks/alignment.rs
@@ -0,0 +1,11 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: Alignment::new_unchecked requires
+
+#![feature(ptr_alignment_type)]
+
+fn main() {
+    unsafe {
+        std::ptr::Alignment::new_unchecked(0);
+    }
+}
diff --git a/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
new file mode 100644
index 00000000000..30c6f79fb08
--- /dev/null
+++ b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
@@ -0,0 +1,11 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: `ascii::Char::digit_unchecked` input cannot exceed 9
+
+#![feature(ascii_char)]
+
+fn main() {
+    unsafe {
+        std::ascii::Char::digit_unchecked(b'a');
+    }
+}
diff --git a/tests/ui/precondition-checks/assert_unchecked.rs b/tests/ui/precondition-checks/assert_unchecked.rs
new file mode 100644
index 00000000000..22b2b414550
--- /dev/null
+++ b/tests/ui/precondition-checks/assert_unchecked.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: hint::assert_unchecked must never be called when the condition is false
+
+fn main() {
+    unsafe {
+        std::hint::assert_unchecked(false);
+    }
+}
diff --git a/tests/ui/precondition-checks/char-from_u32_unchecked.rs b/tests/ui/precondition-checks/char-from_u32_unchecked.rs
new file mode 100644
index 00000000000..d950f20c772
--- /dev/null
+++ b/tests/ui/precondition-checks/char-from_u32_unchecked.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: invalid value for `char`
+
+fn main() {
+    unsafe {
+        char::from_u32_unchecked(0xD801);
+    }
+}
diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs
new file mode 100644
index 00000000000..81018e4bff3
--- /dev/null
+++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs
@@ -0,0 +1,25 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires
+//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
+
+use std::ptr;
+
+fn main() {
+    let src = [0u16; 3];
+    let mut dst = [0u16; 3];
+    let src = src.as_ptr();
+    let dst = dst.as_mut_ptr();
+    unsafe {
+        #[cfg(null_src)]
+        ptr::copy_nonoverlapping(ptr::null(), dst, 1);
+        #[cfg(null_dst)]
+        ptr::copy_nonoverlapping(src, ptr::null_mut(), 1);
+        #[cfg(misaligned_src)]
+        ptr::copy_nonoverlapping(src.byte_add(1), dst, 1);
+        #[cfg(misaligned_dst)]
+        ptr::copy_nonoverlapping(src, dst.byte_add(1), 1);
+        #[cfg(overlapping)]
+        ptr::copy_nonoverlapping(dst, dst.add(1), 2);
+    }
+}
diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs
new file mode 100644
index 00000000000..694853f950a
--- /dev/null
+++ b/tests/ui/precondition-checks/copy.rs
@@ -0,0 +1,23 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::copy requires
+//@ revisions: null_src null_dst misaligned_src misaligned_dst
+
+use std::ptr;
+
+fn main() {
+    let src = [0u16; 3];
+    let mut dst = [0u16; 3];
+    let src = src.as_ptr();
+    let dst = dst.as_mut_ptr();
+    unsafe {
+        #[cfg(null_src)]
+        ptr::copy(ptr::null(), dst, 1);
+        #[cfg(null_dst)]
+        ptr::copy(src, ptr::null_mut(), 1);
+        #[cfg(misaligned_src)]
+        ptr::copy(src.byte_add(1), dst, 1);
+        #[cfg(misaligned_dst)]
+        ptr::copy(src, dst.byte_add(1), 1);
+    }
+}
diff --git a/tests/ui/precondition-checks/layout.rs b/tests/ui/precondition-checks/layout.rs
new file mode 100644
index 00000000000..4fd1bbc4a99
--- /dev/null
+++ b/tests/ui/precondition-checks/layout.rs
@@ -0,0 +1,15 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: Layout::from_size_align_unchecked requires
+//@ revisions: toolarge badalign
+//@[toolarge] compile-flags: --cfg toolarge
+//@[badalign] compile-flags: --cfg badalign
+
+fn main() {
+    unsafe {
+        #[cfg(toolarge)]
+        std::alloc::Layout::from_size_align_unchecked(isize::MAX as usize, 2);
+        #[cfg(badalign)]
+        std::alloc::Layout::from_size_align_unchecked(1, 3);
+    }
+}
diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs
deleted file mode 100644
index 2963a0b5e63..00000000000
--- a/tests/ui/precondition-checks/misaligned-slice.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ run-fail
-//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
-//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
-//@ ignore-debug
-
-fn main() {
-    unsafe {
-        let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0);
-    }
-}
diff --git a/tests/ui/precondition-checks/nonnull.rs b/tests/ui/precondition-checks/nonnull.rs
new file mode 100644
index 00000000000..6b8edd4e582
--- /dev/null
+++ b/tests/ui/precondition-checks/nonnull.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: NonNull::new_unchecked requires
+
+fn main() {
+    unsafe {
+        std::ptr::NonNull::new_unchecked(std::ptr::null_mut::<u8>());
+    }
+}
diff --git a/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
new file mode 100644
index 00000000000..46ce7dc356f
--- /dev/null
+++ b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
@@ -0,0 +1,12 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: NonZero::from_mut_unchecked requires
+
+#![feature(nonzero_from_mut)]
+
+fn main() {
+    unsafe {
+        let mut num = 0u8;
+        std::num::NonZeroU8::from_mut_unchecked(&mut num);
+    }
+}
diff --git a/tests/ui/precondition-checks/nonzero-new_unchecked.rs b/tests/ui/precondition-checks/nonzero-new_unchecked.rs
new file mode 100644
index 00000000000..7827a42844f
--- /dev/null
+++ b/tests/ui/precondition-checks/nonzero-new_unchecked.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: NonZero::new_unchecked requires
+
+fn main() {
+    unsafe {
+        std::num::NonZeroU8::new_unchecked(0);
+    }
+}
diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs
deleted file mode 100644
index 280960358b7..00000000000
--- a/tests/ui/precondition-checks/null-slice.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ run-fail
-//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
-//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
-//@ ignore-debug
-
-fn main() {
-    unsafe {
-        let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0);
-    }
-}
diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
deleted file mode 100644
index 011e92183fa..00000000000
--- a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ run-fail
-//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
-//@ error-pattern: slice::get_unchecked requires
-//@ ignore-debug
-
-fn main() {
-    unsafe {
-        let sli: &[u8] = &[0];
-        sli.get_unchecked(1);
-    }
-}
diff --git a/tests/ui/precondition-checks/read.rs b/tests/ui/precondition-checks/read.rs
new file mode 100644
index 00000000000..ab9921a0cee
--- /dev/null
+++ b/tests/ui/precondition-checks/read.rs
@@ -0,0 +1,18 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::read requires
+//@ revisions: null misaligned
+//@ ignore-test
+
+use std::ptr;
+
+fn main() {
+    let src = [0u16; 2];
+    let src = src.as_ptr();
+    unsafe {
+        #[cfg(null)]
+        ptr::read(ptr::null::<u8>());
+        #[cfg(misaligned)]
+        ptr::read(src.byte_add(1));
+    }
+}
diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs
new file mode 100644
index 00000000000..e14881d0290
--- /dev/null
+++ b/tests/ui/precondition-checks/read_volatile.rs
@@ -0,0 +1,17 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
+//@ revisions: null misaligned
+
+use std::ptr;
+
+fn main() {
+    let src = [0u16; 2];
+    let src = src.as_ptr();
+    unsafe {
+        #[cfg(null)]
+        ptr::read_volatile(ptr::null::<u8>());
+        #[cfg(misaligned)]
+        ptr::read_volatile(src.byte_add(1));
+    }
+}
diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs
new file mode 100644
index 00000000000..2808cee7b64
--- /dev/null
+++ b/tests/ui/precondition-checks/replace.rs
@@ -0,0 +1,17 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::replace requires
+//@ revisions: null misaligned
+
+use std::ptr;
+
+fn main() {
+    let mut dst = [0u16; 2];
+    let dst = dst.as_mut_ptr();
+    unsafe {
+        #[cfg(null)]
+        ptr::replace(ptr::null_mut::<u8>(), 1);
+        #[cfg(misaligned)]
+        ptr::replace(dst.byte_add(1), 1u16);
+    }
+}
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
new file mode 100644
index 00000000000..3801639e255
--- /dev/null
+++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
@@ -0,0 +1,16 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires
+//@ revisions: null misaligned toolarge
+
+fn main() {
+    unsafe {
+        #[cfg(null)]
+        let _s: &mut [u8] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0);
+        #[cfg(misaligned)]
+        let _s: &mut [u16] = std::slice::from_raw_parts_mut(1usize as *mut u16, 0);
+        #[cfg(toolarge)]
+        let _s: &mut [u16] =
+            std::slice::from_raw_parts_mut(2usize as *mut u16, isize::MAX as usize);
+    }
+}
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs
new file mode 100644
index 00000000000..a3690fa045e
--- /dev/null
+++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs
@@ -0,0 +1,15 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires
+//@ revisions: null misaligned toolarge
+
+fn main() {
+    unsafe {
+        #[cfg(null)]
+        let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0);
+        #[cfg(misaligned)]
+        let _s: &[u16] = std::slice::from_raw_parts(1usize as *const u16, 0);
+        #[cfg(toolarge)]
+        let _s: &[u16] = std::slice::from_raw_parts(2usize as *const u16, isize::MAX as usize);
+    }
+}
diff --git a/tests/ui/precondition-checks/slice-get_unchecked.rs b/tests/ui/precondition-checks/slice-get_unchecked.rs
new file mode 100644
index 00000000000..1d8188fb953
--- /dev/null
+++ b/tests/ui/precondition-checks/slice-get_unchecked.rs
@@ -0,0 +1,20 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked requires
+//@ revisions: usize range range_to range_from backwards_range
+
+fn main() {
+    unsafe {
+        let s = &[0];
+        #[cfg(usize)]
+        s.get_unchecked(1);
+        #[cfg(range)]
+        s.get_unchecked(1..2);
+        #[cfg(range_to)]
+        s.get_unchecked(..2);
+        #[cfg(range_from)]
+        s.get_unchecked(2..);
+        #[cfg(backwards_range)]
+        s.get_unchecked(1..0);
+     }
+}
diff --git a/tests/ui/precondition-checks/slice-get_unchecked_mut.rs b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
new file mode 100644
index 00000000000..34c1454af43
--- /dev/null
+++ b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
@@ -0,0 +1,20 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked_mut requires
+//@ revisions: usize range range_to range_from backwards_range
+
+fn main() {
+    unsafe {
+        let mut s = &mut [0];
+        #[cfg(usize)]
+        s.get_unchecked_mut(1);
+        #[cfg(range)]
+        s.get_unchecked_mut(1..2);
+        #[cfg(range_to)]
+        s.get_unchecked_mut(..2);
+        #[cfg(range_from)]
+        s.get_unchecked_mut(2..);
+        #[cfg(backwards_range)]
+        s.get_unchecked_mut(1..0);
+     }
+}
diff --git a/tests/ui/precondition-checks/slice-swap_unchecked.rs b/tests/ui/precondition-checks/slice-swap_unchecked.rs
new file mode 100644
index 00000000000..227a49091ec
--- /dev/null
+++ b/tests/ui/precondition-checks/slice-swap_unchecked.rs
@@ -0,0 +1,14 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: index out of bounds: the len is 2 but the index is 2
+//@ revisions: oob_a oob_b
+
+fn main() {
+    let mut pair = [0u8; 2];
+    unsafe {
+        #[cfg(oob_a)]
+        pair.swap(0, 2);
+        #[cfg(oob_b)]
+        pair.swap(2, 0);
+    }
+}
diff --git a/tests/ui/precondition-checks/str-get_unchecked.rs b/tests/ui/precondition-checks/str-get_unchecked.rs
new file mode 100644
index 00000000000..14d17f997ec
--- /dev/null
+++ b/tests/ui/precondition-checks/str-get_unchecked.rs
@@ -0,0 +1,18 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked requires
+//@ revisions: range range_to range_from backwards_range
+
+fn main() {
+    unsafe {
+        let s = "💅";
+        #[cfg(range)]
+        s.get_unchecked(4..5);
+        #[cfg(range_to)]
+        s.get_unchecked(..5);
+        #[cfg(range_from)]
+        s.get_unchecked(5..);
+        #[cfg(backwards_range)]
+        s.get_unchecked(1..0);
+    }
+}
diff --git a/tests/ui/precondition-checks/str-get_unchecked_mut.rs b/tests/ui/precondition-checks/str-get_unchecked_mut.rs
new file mode 100644
index 00000000000..ca1b1690055
--- /dev/null
+++ b/tests/ui/precondition-checks/str-get_unchecked_mut.rs
@@ -0,0 +1,19 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: str::get_unchecked_mut requires
+//@ revisions: range range_to range_from backwards_range
+
+fn main() {
+    unsafe {
+        let mut s: String = "💅".chars().collect();
+        let mut s: &mut str = &mut s;
+        #[cfg(range)]
+        s.get_unchecked_mut(4..5);
+        #[cfg(range_to)]
+        s.get_unchecked_mut(..5);
+        #[cfg(range_from)]
+        s.get_unchecked_mut(5..);
+        #[cfg(backwards_range)]
+        s.get_unchecked_mut(1..0);
+    }
+}
diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs
new file mode 100644
index 00000000000..52e4a3c870b
--- /dev/null
+++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs
@@ -0,0 +1,25 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires
+//@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
+
+use std::ptr;
+
+fn main() {
+    let mut src = [0u16; 3];
+    let mut dst = [0u16; 3];
+    let src = src.as_mut_ptr();
+    let dst = dst.as_mut_ptr();
+    unsafe {
+        #[cfg(null_src)]
+        ptr::swap_nonoverlapping(ptr::null_mut(), dst, 1);
+        #[cfg(null_dst)]
+        ptr::swap_nonoverlapping(src, ptr::null_mut(), 1);
+        #[cfg(misaligned_src)]
+        ptr::swap_nonoverlapping(src.byte_add(1), dst, 1);
+        #[cfg(misaligned_dst)]
+        ptr::swap_nonoverlapping(src, dst.byte_add(1), 1);
+        #[cfg(overlapping)]
+        ptr::swap_nonoverlapping(dst, dst.add(1), 2);
+    }
+}
diff --git a/tests/ui/precondition-checks/unchecked_add.rs b/tests/ui/precondition-checks/unchecked_add.rs
new file mode 100644
index 00000000000..f44a6ea32ad
--- /dev/null
+++ b/tests/ui/precondition-checks/unchecked_add.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
+
+fn main() {
+    unsafe {
+        1u8.unchecked_add(u8::MAX);
+    }
+}
diff --git a/tests/ui/precondition-checks/unchecked_mul.rs b/tests/ui/precondition-checks/unchecked_mul.rs
new file mode 100644
index 00000000000..66655dda136
--- /dev/null
+++ b/tests/ui/precondition-checks/unchecked_mul.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
+
+fn main() {
+    unsafe {
+        2u8.unchecked_add(u8::MAX);
+    }
+}
diff --git a/tests/ui/precondition-checks/unchecked_shl.rs b/tests/ui/precondition-checks/unchecked_shl.rs
new file mode 100644
index 00000000000..1c96db0b1ec
--- /dev/null
+++ b/tests/ui/precondition-checks/unchecked_shl.rs
@@ -0,0 +1,11 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shl cannot overflow
+
+#![feature(unchecked_shifts)]
+
+fn main() {
+    unsafe {
+        0u8.unchecked_shl(u8::BITS);
+    }
+}
diff --git a/tests/ui/precondition-checks/unchecked_shr.rs b/tests/ui/precondition-checks/unchecked_shr.rs
new file mode 100644
index 00000000000..4a6d9ffb1d3
--- /dev/null
+++ b/tests/ui/precondition-checks/unchecked_shr.rs
@@ -0,0 +1,11 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shr cannot overflow
+
+#![feature(unchecked_shifts)]
+
+fn main() {
+    unsafe {
+        0u8.unchecked_shr(u8::BITS);
+    }
+}
diff --git a/tests/ui/precondition-checks/unchecked_sub.rs b/tests/ui/precondition-checks/unchecked_sub.rs
new file mode 100644
index 00000000000..545dde0e278
--- /dev/null
+++ b/tests/ui/precondition-checks/unchecked_sub.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_sub cannot overflow
+
+fn main() {
+    unsafe {
+        0u8.unchecked_sub(1u8);
+    }
+}
diff --git a/tests/ui/precondition-checks/unreachable_unchecked.rs b/tests/ui/precondition-checks/unreachable_unchecked.rs
new file mode 100644
index 00000000000..2435450c4b5
--- /dev/null
+++ b/tests/ui/precondition-checks/unreachable_unchecked.rs
@@ -0,0 +1,9 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: hint::unreachable_unchecked must never be reached
+
+fn main() {
+    unsafe {
+        std::hint::unreachable_unchecked();
+    }
+}
diff --git a/tests/ui/precondition-checks/write.rs b/tests/ui/precondition-checks/write.rs
new file mode 100644
index 00000000000..f76e776fcf3
--- /dev/null
+++ b/tests/ui/precondition-checks/write.rs
@@ -0,0 +1,18 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::write requires
+//@ revisions: null misaligned
+//@ ignore-test
+
+use std::ptr;
+
+fn main() {
+    let mut dst = [0u16; 2];
+    let mut dst = dst.as_mut_ptr();
+    unsafe {
+        #[cfg(null)]
+        ptr::write(ptr::null_mut::<u8>(), 1u8);
+        #[cfg(misaligned)]
+        ptr::write(dst.byte_add(1), 1u16);
+    }
+}
diff --git a/tests/ui/precondition-checks/write_bytes.rs b/tests/ui/precondition-checks/write_bytes.rs
new file mode 100644
index 00000000000..3f64be9d1ee
--- /dev/null
+++ b/tests/ui/precondition-checks/write_bytes.rs
@@ -0,0 +1,18 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::write requires
+//@ revisions: null misaligned
+//@ ignore-test
+
+use std::ptr;
+
+fn main() {
+    let mut dst = [0u16; 2];
+    let mut dst = dst.as_mut_ptr();
+    unsafe {
+        #[cfg(null)]
+        ptr::write_bytes(ptr::null_mut::<u8>(), 1u8, 2);
+        #[cfg(misaligned)]
+        ptr::write_bytes(dst.byte_add(1), 1u8, 2);
+    }
+}
diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs
new file mode 100644
index 00000000000..ac0b89b5ecf
--- /dev/null
+++ b/tests/ui/precondition-checks/write_volatile.rs
@@ -0,0 +1,17 @@
+//@ run-fail
+//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
+//@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
+//@ revisions: null misaligned
+
+use std::ptr;
+
+fn main() {
+    let mut dst = [0u16; 2];
+    let mut dst = dst.as_mut_ptr();
+    unsafe {
+        #[cfg(null)]
+        ptr::write_volatile(ptr::null_mut::<u8>(), 1u8);
+        #[cfg(misaligned)]
+        ptr::write_volatile(dst.byte_add(1), 1u16);
+    }
+}
diff --git a/tests/ui/precondition-checks/zero-size-null.rs b/tests/ui/precondition-checks/zero-size-null.rs
new file mode 100644
index 00000000000..43a81175f94
--- /dev/null
+++ b/tests/ui/precondition-checks/zero-size-null.rs
@@ -0,0 +1,21 @@
+// Test that none of the precondition checks panic on zero-sized reads or writes through null.
+
+//@ run-pass
+//@ compile-flags: -Zmir-opt-level=0 -Copt-level=0 -Cdebug-assertions=yes
+
+use std::ptr;
+
+fn main() {
+    unsafe {
+        ptr::copy_nonoverlapping::<u8>(ptr::null(), ptr::null_mut(), 0);
+        ptr::copy_nonoverlapping::<()>(ptr::null(), ptr::null_mut(), 123);
+        ptr::copy::<u8>(ptr::null(), ptr::null_mut(), 0);
+        ptr::copy::<()>(ptr::null(), ptr::null_mut(), 123);
+        ptr::swap::<()>(ptr::null_mut(), ptr::null_mut());
+        ptr::replace::<()>(ptr::null_mut(), ());
+        ptr::read::<()>(ptr::null());
+        ptr::write::<()>(ptr::null_mut(), ());
+        ptr::read_volatile::<()>(ptr::null());
+        ptr::write_volatile::<()>(ptr::null_mut(), ());
+    }
+}