about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2024-02-09 20:07:42 -0500
committerBen Kimock <kimockb@gmail.com>2024-02-19 20:38:09 -0500
commit581e171773a0e4bf398d4b7df0e30a7aae627f0b (patch)
treed7818ddb29570f9213dc65e3f500eaf205cd30a7
parent0395fa387ad4de63ea1b36703ca0d65017b8c2dc (diff)
downloadrust-581e171773a0e4bf398d4b7df0e30a7aae627f0b.tar.gz
rust-581e171773a0e4bf398d4b7df0e30a7aae627f0b.zip
Convert debug_assert_nounwind to intrinsics::debug_assertions
-rw-r--r--library/core/src/panic.rs29
-rw-r--r--library/core/src/ptr/alignment.rs1
-rw-r--r--library/core/src/slice/index.rs20
-rw-r--r--library/core/src/slice/mod.rs10
-rw-r--r--library/core/src/str/traits.rs4
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir78
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir78
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir104
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir104
-rw-r--r--tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs2
10 files changed, 65 insertions, 365 deletions
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 380933ce196..2bd42a4a8ca 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -139,27 +139,38 @@ pub macro unreachable_2021 {
     ),
 }
 
-/// Asserts that a boolean expression is `true`, and perform a non-unwinding panic otherwise.
+/// Like `assert_unsafe_precondition!` the defining features of this macro are that its
+/// checks are enabled when they are monomorphized with debug assertions enabled, and upon failure
+/// a non-unwinding panic is launched so that failures cannot compromise unwind safety.
 ///
-/// This macro is similar to `debug_assert!`, but is intended to be used in code that should not
-/// unwind. For example, checks in `_unchecked` functions that are intended for debugging but should
-/// not compromise unwind safety.
+/// But there are many differences from `assert_unsafe_precondition!`. This macro does not use
+/// `const_eval_select` internally, and therefore it is sound to call this with an expression
+/// that evaluates to `false`. Also unlike `assert_unsafe_precondition!` the condition being
+/// checked here is not put in an outlined function. If the check compiles to a lot of IR, this
+/// can cause code bloat if the check is monomorphized many times. But it also means that the checks
+/// from this macro can be deduplicated or otherwise optimized out.
+///
+/// In general, this macro should be used to check all public-facing preconditions. But some
+/// preconditions may be called too often or instantiated too often to make the overhead of the
+/// checks tolerable. In such cases, place `#[cfg(debug_assertions)]` on the macro call. That will
+/// disable the check in our precompiled standard library, but if a user wishes, they can still
+/// enable the check by recompiling the standard library with debug assertions enabled.
 #[doc(hidden)]
 #[unstable(feature = "panic_internals", issue = "none")]
-#[allow_internal_unstable(panic_internals, const_format_args)]
+#[allow_internal_unstable(panic_internals, delayed_debug_assertions)]
 #[rustc_macro_transparency = "semitransparent"]
 pub macro debug_assert_nounwind {
     ($cond:expr $(,)?) => {
-        if $crate::cfg!(debug_assertions) {
+        if $crate::intrinsics::debug_assertions() {
             if !$cond {
                 $crate::panicking::panic_nounwind($crate::concat!("assertion failed: ", $crate::stringify!($cond)));
             }
         }
     },
-    ($cond:expr, $($arg:tt)+) => {
-        if $crate::cfg!(debug_assertions) {
+    ($cond:expr, $message:expr) => {
+        if $crate::intrinsics::debug_assertions() {
             if !$cond {
-                $crate::panicking::panic_nounwind_fmt($crate::const_format_args!($($arg)+), false);
+                $crate::panicking::panic_nounwind($message);
             }
         }
     },
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index d2422bb80ae..6dfecb5a826 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -76,6 +76,7 @@ impl Alignment {
     #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
     pub const unsafe fn new_unchecked(align: usize) -> Self {
+        #[cfg(debug_assertions)]
         crate::panic::debug_assert_nounwind!(
             align.is_power_of_two(),
             "Alignment::new_unchecked requires a power of two"
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index fb9be396eab..86bfdcbd70c 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -13,7 +13,7 @@ where
 {
     type Output = I::Output;
 
-    #[inline]
+    #[inline(always)]
     fn index(&self, index: I) -> &I::Output {
         index.index(self)
     }
@@ -24,7 +24,7 @@ impl<T, I> ops::IndexMut<I> for [T]
 where
     I: SliceIndex<[T]>,
 {
-    #[inline]
+    #[inline(always)]
     fn index_mut(&mut self, index: I) -> &mut I::Output {
         index.index_mut(self)
     }
@@ -227,14 +227,16 @@ unsafe impl<T> SliceIndex<[T]> for usize {
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
         debug_assert_nounwind!(
             self < slice.len(),
-            "slice::get_unchecked requires that the index is within the slice",
+            "slice::get_unchecked requires that the index is within the slice"
         );
         // SAFETY: the caller guarantees that `slice` is not dangling, so it
         // cannot be longer than `isize::MAX`. They also guarantee that
         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
         // so the call to `add` is safe.
         unsafe {
-            crate::hint::assert_unchecked(self < slice.len());
+            // Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the
+            // precondition of this function twice.
+            crate::intrinsics::assume(self < slice.len());
             slice.as_ptr().add(self)
         }
     }
@@ -243,7 +245,7 @@ unsafe impl<T> SliceIndex<[T]> for usize {
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
         debug_assert_nounwind!(
             self < slice.len(),
-            "slice::get_unchecked_mut requires that the index is within the slice",
+            "slice::get_unchecked_mut requires that the index is within the slice"
         );
         // SAFETY: see comments for `get_unchecked` above.
         unsafe { slice.as_mut_ptr().add(self) }
@@ -305,8 +307,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
         debug_assert_nounwind!(
             self.end() <= slice.len(),
-            "slice::get_unchecked_mut requires that the index is within the slice",
+            "slice::get_unchecked_mut requires that the index is within the slice"
         );
+
         // SAFETY: see comments for `get_unchecked` above.
         unsafe { ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len()) }
     }
@@ -361,8 +364,9 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
         debug_assert_nounwind!(
             self.end >= self.start && self.end <= slice.len(),
-            "slice::get_unchecked requires that the range is within the slice",
+            "slice::get_unchecked requires that the range is within the slice"
         );
+
         // SAFETY: the caller guarantees that `slice` is not dangling, so it
         // cannot be longer than `isize::MAX`. They also guarantee that
         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
@@ -377,7 +381,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
         debug_assert_nounwind!(
             self.end >= self.start && self.end <= slice.len(),
-            "slice::get_unchecked_mut requires that the range is within the slice",
+            "slice::get_unchecked_mut requires that the range is within the slice"
         );
         // SAFETY: see comments for `get_unchecked` above.
         unsafe {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c948337ba6c..031666fb012 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -938,7 +938,7 @@ impl<T> [T] {
     pub const unsafe fn swap_unchecked(&mut self, a: usize, b: usize) {
         debug_assert_nounwind!(
             a < self.len() && b < self.len(),
-            "slice::swap_unchecked requires that the indices are within the slice",
+            "slice::swap_unchecked requires that the indices are within the slice"
         );
 
         let ptr = self.as_mut_ptr();
@@ -1278,7 +1278,7 @@ impl<T> [T] {
     pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
         debug_assert_nounwind!(
             N != 0 && self.len() % N == 0,
-            "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks",
+            "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks"
         );
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe { exact_div(self.len(), N) };
@@ -1432,7 +1432,7 @@ impl<T> [T] {
     pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
         debug_assert_nounwind!(
             N != 0 && self.len() % N == 0,
-            "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks",
+            "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks"
         );
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe { exact_div(self.len(), N) };
@@ -1964,7 +1964,7 @@ impl<T> [T] {
 
         debug_assert_nounwind!(
             mid <= len,
-            "slice::split_at_unchecked requires the index to be within the slice",
+            "slice::split_at_unchecked requires the index to be within the slice"
         );
 
         // SAFETY: Caller has to check that `0 <= mid <= self.len()`
@@ -2014,7 +2014,7 @@ impl<T> [T] {
 
         debug_assert_nounwind!(
             mid <= len,
-            "slice::split_at_mut_unchecked requires the index to be within the slice",
+            "slice::split_at_mut_unchecked requires the index to be within the slice"
         );
 
         // SAFETY: Caller has to check that `0 <= mid <= self.len()`.
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 777ad0d818b..3b9e9c98127 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -200,7 +200,7 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
             // `str::get_unchecked` without adding a special function
             // to `SliceIndex` just for this.
             self.end >= self.start && self.end <= slice.len(),
-            "str::get_unchecked requires that the range is within the string slice",
+            "str::get_unchecked requires that the range is within the string slice"
         );
 
         // SAFETY: the caller guarantees that `self` is in bounds of `slice`
@@ -215,7 +215,7 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
 
         debug_assert_nounwind!(
             self.end >= self.start && self.end <= slice.len(),
-            "str::get_unchecked_mut requires that the range is within the string slice",
+            "str::get_unchecked_mut requires that the range is within the string slice"
         );
 
         // SAFETY: see comments for `get_unchecked`.
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
index bc7617bb6dd..153505b1bbb 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
@@ -7,89 +7,13 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
     scope 1 (inlined core::slice::<impl [u32]>::get_mut::<usize>) {
         debug self => _1;
         debug index => _2;
-        scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
-            debug self => _2;
-            debug slice => _1;
-            let mut _3: usize;
-            let mut _4: bool;
-            let mut _5: *mut [u32];
-            let mut _7: *mut u32;
-            let mut _8: &mut u32;
-            scope 3 {
-                scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) {
-                    debug self => _2;
-                    debug slice => _5;
-                    let mut _6: *mut u32;
-                    let mut _9: *mut [u32];
-                    let mut _10: &[&str];
-                    scope 5 {
-                        scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
-                            debug self => _5;
-                        }
-                        scope 11 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
-                            debug self => _6;
-                            debug count => _2;
-                            scope 12 {
-                            }
-                        }
-                    }
-                    scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
-                        debug self => _9;
-                        let mut _11: *const [u32];
-                        scope 7 (inlined std::ptr::metadata::<[u32]>) {
-                            debug ptr => _11;
-                            scope 8 {
-                            }
-                        }
-                    }
-                    scope 9 (inlined Arguments::<'_>::new_const) {
-                        debug pieces => _10;
-                    }
-                }
-            }
-        }
     }
 
     bb0: {
-        StorageLive(_7);
-        StorageLive(_4);
-        StorageLive(_3);
-        _3 = Len((*_1));
-        _4 = Lt(_2, move _3);
-        switchInt(move _4) -> [0: bb1, otherwise: bb2];
+        _0 = <usize as SliceIndex<[u32]>>::get_mut(move _2, move _1) -> [return: bb1, unwind unreachable];
     }
 
     bb1: {
-        StorageDead(_3);
-        _0 = const Option::<&mut u32>::None;
-        goto -> bb3;
-    }
-
-    bb2: {
-        StorageDead(_3);
-        StorageLive(_8);
-        StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_9);
-        StorageLive(_10);
-        StorageLive(_11);
-        StorageLive(_6);
-        _6 = _5 as *mut u32 (PtrToPtr);
-        _7 = Offset(_6, _2);
-        StorageDead(_6);
-        StorageDead(_11);
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(move _8);
-        StorageDead(_8);
-        goto -> bb3;
-    }
-
-    bb3: {
-        StorageDead(_4);
-        StorageDead(_7);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
index bc7617bb6dd..d37ee783117 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
@@ -7,89 +7,13 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
     scope 1 (inlined core::slice::<impl [u32]>::get_mut::<usize>) {
         debug self => _1;
         debug index => _2;
-        scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
-            debug self => _2;
-            debug slice => _1;
-            let mut _3: usize;
-            let mut _4: bool;
-            let mut _5: *mut [u32];
-            let mut _7: *mut u32;
-            let mut _8: &mut u32;
-            scope 3 {
-                scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) {
-                    debug self => _2;
-                    debug slice => _5;
-                    let mut _6: *mut u32;
-                    let mut _9: *mut [u32];
-                    let mut _10: &[&str];
-                    scope 5 {
-                        scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
-                            debug self => _5;
-                        }
-                        scope 11 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
-                            debug self => _6;
-                            debug count => _2;
-                            scope 12 {
-                            }
-                        }
-                    }
-                    scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
-                        debug self => _9;
-                        let mut _11: *const [u32];
-                        scope 7 (inlined std::ptr::metadata::<[u32]>) {
-                            debug ptr => _11;
-                            scope 8 {
-                            }
-                        }
-                    }
-                    scope 9 (inlined Arguments::<'_>::new_const) {
-                        debug pieces => _10;
-                    }
-                }
-            }
-        }
     }
 
     bb0: {
-        StorageLive(_7);
-        StorageLive(_4);
-        StorageLive(_3);
-        _3 = Len((*_1));
-        _4 = Lt(_2, move _3);
-        switchInt(move _4) -> [0: bb1, otherwise: bb2];
+        _0 = <usize as SliceIndex<[u32]>>::get_mut(move _2, move _1) -> [return: bb1, unwind continue];
     }
 
     bb1: {
-        StorageDead(_3);
-        _0 = const Option::<&mut u32>::None;
-        goto -> bb3;
-    }
-
-    bb2: {
-        StorageDead(_3);
-        StorageLive(_8);
-        StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_9);
-        StorageLive(_10);
-        StorageLive(_11);
-        StorageLive(_6);
-        _6 = _5 as *mut u32 (PtrToPtr);
-        _7 = Offset(_6, _2);
-        StorageDead(_6);
-        StorageDead(_11);
-        StorageDead(_10);
-        StorageDead(_9);
-        StorageDead(_5);
-        _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(move _8);
-        StorageDead(_8);
-        goto -> bb3;
-    }
-
-    bb3: {
-        StorageDead(_4);
-        StorageDead(_7);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
index 2fdc21d636f..bcc540ae6fc 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
@@ -4,106 +4,24 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     debug slice => _1;
     debug index => _2;
     let mut _0: &mut [u32];
-    let mut _3: usize;
-    let mut _4: usize;
     scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
         debug self => _1;
-        debug ((index: std::ops::Range<usize>).0: usize) => _3;
-        debug ((index: std::ops::Range<usize>).1: usize) => _4;
-        let mut _5: *mut [u32];
-        let mut _13: *mut [u32];
+        debug index => _2;
+        let mut _3: *mut [u32];
+        let mut _4: *mut [u32];
         scope 2 {
-            scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
-                debug ((self: std::ops::Range<usize>).0: usize) => _3;
-                debug ((self: std::ops::Range<usize>).1: usize) => _4;
-                debug slice => _5;
-                let mut _7: *mut u32;
-                let mut _8: *mut u32;
-                let mut _14: *mut [u32];
-                let mut _15: &[&str];
-                scope 4 {
-                    let _6: usize;
-                    scope 5 {
-                        debug new_len => _6;
-                        scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
-                            debug self => _5;
-                        }
-                        scope 11 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
-                            debug self => _7;
-                            debug count => _3;
-                            scope 12 {
-                            }
-                        }
-                        scope 13 (inlined slice_from_raw_parts_mut::<u32>) {
-                            debug data => _8;
-                            debug len => _6;
-                            let mut _9: *mut ();
-                            scope 14 (inlined std::ptr::mut_ptr::<impl *mut u32>::cast::<()>) {
-                                debug self => _8;
-                            }
-                            scope 15 (inlined std::ptr::from_raw_parts_mut::<[u32]>) {
-                                debug data_pointer => _9;
-                                debug metadata => _6;
-                                let mut _10: *const ();
-                                let mut _11: std::ptr::metadata::PtrComponents<[u32]>;
-                                let mut _12: std::ptr::metadata::PtrRepr<[u32]>;
-                                scope 16 {
-                                }
-                            }
-                        }
-                    }
-                }
-                scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
-                    debug self => _14;
-                    let mut _16: *const [u32];
-                    scope 7 (inlined std::ptr::metadata::<[u32]>) {
-                        debug ptr => _16;
-                        scope 8 {
-                        }
-                    }
-                }
-                scope 9 (inlined Arguments::<'_>::new_const) {
-                    debug pieces => _15;
-                }
-            }
         }
     }
 
     bb0: {
-        _3 = move (_2.0: usize);
-        _4 = move (_2.1: usize);
-        StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_14);
-        StorageLive(_15);
-        StorageLive(_6);
-        StorageLive(_16);
-        _6 = SubUnchecked(_4, _3);
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = _5 as *mut u32 (PtrToPtr);
-        _8 = Offset(_7, _3);
-        StorageDead(_7);
-        StorageLive(_9);
-        _9 = _8 as *mut () (PtrToPtr);
-        StorageLive(_12);
-        StorageLive(_11);
-        StorageLive(_10);
-        _10 = _8 as *const () (PtrToPtr);
-        _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_pointer: move _10, metadata: _6 };
-        StorageDead(_10);
-        _12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 };
-        StorageDead(_11);
-        _13 = (_12.1: *mut [u32]);
-        StorageDead(_12);
-        StorageDead(_9);
-        StorageDead(_8);
-        StorageDead(_16);
-        StorageDead(_6);
-        StorageDead(_15);
-        StorageDead(_14);
-        StorageDead(_5);
-        _0 = &mut (*_13);
+        StorageLive(_3);
+        _3 = &raw mut (*_1);
+        _4 = <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut(move _2, move _3) -> [return: bb1, unwind unreachable];
+    }
+
+    bb1: {
+        StorageDead(_3);
+        _0 = &mut (*_4);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
index 2fdc21d636f..1fe7da7d2fd 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
@@ -4,106 +4,24 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     debug slice => _1;
     debug index => _2;
     let mut _0: &mut [u32];
-    let mut _3: usize;
-    let mut _4: usize;
     scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) {
         debug self => _1;
-        debug ((index: std::ops::Range<usize>).0: usize) => _3;
-        debug ((index: std::ops::Range<usize>).1: usize) => _4;
-        let mut _5: *mut [u32];
-        let mut _13: *mut [u32];
+        debug index => _2;
+        let mut _3: *mut [u32];
+        let mut _4: *mut [u32];
         scope 2 {
-            scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
-                debug ((self: std::ops::Range<usize>).0: usize) => _3;
-                debug ((self: std::ops::Range<usize>).1: usize) => _4;
-                debug slice => _5;
-                let mut _7: *mut u32;
-                let mut _8: *mut u32;
-                let mut _14: *mut [u32];
-                let mut _15: &[&str];
-                scope 4 {
-                    let _6: usize;
-                    scope 5 {
-                        debug new_len => _6;
-                        scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
-                            debug self => _5;
-                        }
-                        scope 11 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
-                            debug self => _7;
-                            debug count => _3;
-                            scope 12 {
-                            }
-                        }
-                        scope 13 (inlined slice_from_raw_parts_mut::<u32>) {
-                            debug data => _8;
-                            debug len => _6;
-                            let mut _9: *mut ();
-                            scope 14 (inlined std::ptr::mut_ptr::<impl *mut u32>::cast::<()>) {
-                                debug self => _8;
-                            }
-                            scope 15 (inlined std::ptr::from_raw_parts_mut::<[u32]>) {
-                                debug data_pointer => _9;
-                                debug metadata => _6;
-                                let mut _10: *const ();
-                                let mut _11: std::ptr::metadata::PtrComponents<[u32]>;
-                                let mut _12: std::ptr::metadata::PtrRepr<[u32]>;
-                                scope 16 {
-                                }
-                            }
-                        }
-                    }
-                }
-                scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
-                    debug self => _14;
-                    let mut _16: *const [u32];
-                    scope 7 (inlined std::ptr::metadata::<[u32]>) {
-                        debug ptr => _16;
-                        scope 8 {
-                        }
-                    }
-                }
-                scope 9 (inlined Arguments::<'_>::new_const) {
-                    debug pieces => _15;
-                }
-            }
         }
     }
 
     bb0: {
-        _3 = move (_2.0: usize);
-        _4 = move (_2.1: usize);
-        StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_14);
-        StorageLive(_15);
-        StorageLive(_6);
-        StorageLive(_16);
-        _6 = SubUnchecked(_4, _3);
-        StorageLive(_8);
-        StorageLive(_7);
-        _7 = _5 as *mut u32 (PtrToPtr);
-        _8 = Offset(_7, _3);
-        StorageDead(_7);
-        StorageLive(_9);
-        _9 = _8 as *mut () (PtrToPtr);
-        StorageLive(_12);
-        StorageLive(_11);
-        StorageLive(_10);
-        _10 = _8 as *const () (PtrToPtr);
-        _11 = std::ptr::metadata::PtrComponents::<[u32]> { data_pointer: move _10, metadata: _6 };
-        StorageDead(_10);
-        _12 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _11 };
-        StorageDead(_11);
-        _13 = (_12.1: *mut [u32]);
-        StorageDead(_12);
-        StorageDead(_9);
-        StorageDead(_8);
-        StorageDead(_16);
-        StorageDead(_6);
-        StorageDead(_15);
-        StorageDead(_14);
-        StorageDead(_5);
-        _0 = &mut (*_13);
+        StorageLive(_3);
+        _3 = &raw mut (*_1);
+        _4 = <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut(move _2, move _3) -> [return: bb1, unwind continue];
+    }
+
+    bb1: {
+        StorageDead(_3);
+        _0 = &mut (*_4);
         return;
     }
 }
diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
index 7956d5e8743..77bec6aab7f 100644
--- a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
+++ b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
@@ -1,6 +1,6 @@
 //@ run-fail
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes
-//@ error-pattern: unsafe precondition(s) violated: hint::assert_unchecked
+//@ error-pattern: slice::get_unchecked requires
 //@ ignore-debug
 //@ ignore-wasm32-bare no panic messages