about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2024-09-11 18:04:40 -0400
committerBen Kimock <kimockb@gmail.com>2024-10-07 11:12:58 -0400
commit6d246e47fb55e089589681a41db6dedb20ccdaa3 (patch)
treec4e1e3d4b9aad8f0a4d89d5d3b13b554ac22a7df
parent7caad6925314911eefe54b040d4bc5be940e8f92 (diff)
downloadrust-6d246e47fb55e089589681a41db6dedb20ccdaa3.tar.gz
rust-6d246e47fb55e089589681a41db6dedb20ccdaa3.zip
Add precondition checks to ptr::offset, ptr::add, ptr::sub
-rw-r--r--library/core/src/ptr/const_ptr.rs88
-rw-r--r--library/core/src/ptr/mut_ptr.rs88
-rw-r--r--tests/codegen/option-as-slice.rs8
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir12
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir12
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir12
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir12
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir32
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir12
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir8
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir8
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir14
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir14
13 files changed, 277 insertions, 43 deletions
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 332c5e904d7..4727dc77d18 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -395,6 +395,36 @@ impl<T: ?Sized> *const T {
     where
         T: Sized,
     {
+        #[inline]
+        const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
+            #[inline]
+            fn runtime(this: *const (), count: isize, size: usize) -> bool {
+                // We know `size <= isize::MAX` so the `as` cast here is not lossy.
+                let Some(byte_offset) = count.checked_mul(size as isize) else {
+                    return false;
+                };
+                let (_, overflow) = this.addr().overflowing_add_signed(byte_offset);
+                !overflow
+            }
+
+            const fn comptime(_: *const (), _: isize, _: usize) -> bool {
+                true
+            }
+
+            // We can use const_eval_select here because this is only for UB checks.
+            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+        }
+
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::offset requires the address calculation to not overflow",
+            (
+                this: *const () = self as *const (),
+                count: isize = count,
+                size: usize = size_of::<T>(),
+            ) => runtime_offset_nowrap(this, count, size)
+        );
+
         // SAFETY: the caller must uphold the safety contract for `offset`.
         unsafe { intrinsics::offset(self, count) }
     }
@@ -726,7 +756,6 @@ impl<T: ?Sized> *const T {
                 true
             }
 
-            #[allow(unused_unsafe)]
             intrinsics::const_eval_select((this, origin), comptime, runtime)
         }
 
@@ -858,6 +887,34 @@ impl<T: ?Sized> *const T {
     where
         T: Sized,
     {
+        #[inline]
+        const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
+            #[inline]
+            fn runtime(this: *const (), count: usize, size: usize) -> bool {
+                let Some(byte_offset) = count.checked_mul(size) else {
+                    return false;
+                };
+                let (_, overflow) = this.addr().overflowing_add(byte_offset);
+                byte_offset <= (isize::MAX as usize) && !overflow
+            }
+
+            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
+                true
+            }
+
+            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+        }
+
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::add requires that the address calculation does not overflow",
+            (
+                this: *const () = self as *const (),
+                count: usize = count,
+                size: usize = size_of::<T>(),
+            ) => runtime_add_nowrap(this, count, size)
+        );
+
         // SAFETY: the caller must uphold the safety contract for `offset`.
         unsafe { intrinsics::offset(self, count) }
     }
@@ -936,6 +993,33 @@ impl<T: ?Sized> *const T {
     where
         T: Sized,
     {
+        #[inline]
+        const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
+            #[inline]
+            fn runtime(this: *const (), count: usize, size: usize) -> bool {
+                let Some(byte_offset) = count.checked_mul(size) else {
+                    return false;
+                };
+                byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset
+            }
+
+            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
+                true
+            }
+
+            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+        }
+
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::sub requires that the address calculation does not overflow",
+            (
+                this: *const () = self as *const (),
+                count: usize = count,
+                size: usize = size_of::<T>(),
+            ) => runtime_sub_nowrap(this, count, size)
+        );
+
         if T::IS_ZST {
             // Pointer arithmetic does nothing when the pointee is a ZST.
             self
@@ -943,7 +1027,7 @@ impl<T: ?Sized> *const T {
             // SAFETY: the caller must uphold the safety contract for `offset`.
             // Because the pointee is *not* a ZST, that means that `count` is
             // at most `isize::MAX`, and thus the negation cannot overflow.
-            unsafe { self.offset((count as isize).unchecked_neg()) }
+            unsafe { intrinsics::offset(self, intrinsics::unchecked_sub(0, count as isize)) }
         }
     }
 
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 287073497f8..8dbce1fdb98 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -393,6 +393,37 @@ impl<T: ?Sized> *mut T {
     where
         T: Sized,
     {
+        #[inline]
+        const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
+            #[inline]
+            fn runtime(this: *const (), count: isize, size: usize) -> bool {
+                // `size` is the size of a Rust type, so we know that
+                // `size <= isize::MAX` and thus `as` cast here is not lossy.
+                let Some(byte_offset) = count.checked_mul(size as isize) else {
+                    return false;
+                };
+                let (_, overflow) = this.addr().overflowing_add_signed(byte_offset);
+                !overflow
+            }
+
+            const fn comptime(_: *const (), _: isize, _: usize) -> bool {
+                true
+            }
+
+            // We can use const_eval_select here because this is only for UB checks.
+            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+        }
+
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::offset requires the address calculation to not overflow",
+            (
+                this: *const () = self as *const (),
+                count: isize = count,
+                size: usize = size_of::<T>(),
+            ) => runtime_offset_nowrap(this, count, size)
+        );
+
         // SAFETY: the caller must uphold the safety contract for `offset`.
         // The obtained pointer is valid for writes since the caller must
         // guarantee that it points to the same allocated object as `self`.
@@ -940,6 +971,34 @@ impl<T: ?Sized> *mut T {
     where
         T: Sized,
     {
+        #[inline]
+        const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
+            #[inline]
+            fn runtime(this: *const (), count: usize, size: usize) -> bool {
+                let Some(byte_offset) = count.checked_mul(size) else {
+                    return false;
+                };
+                let (_, overflow) = this.addr().overflowing_add(byte_offset);
+                byte_offset <= (isize::MAX as usize) && !overflow
+            }
+
+            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
+                true
+            }
+
+            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+        }
+
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::add requires that the address calculation does not overflow",
+            (
+                this: *const () = self as *const (),
+                count: usize = count,
+                size: usize = size_of::<T>(),
+            ) => runtime_add_nowrap(this, count, size)
+        );
+
         // SAFETY: the caller must uphold the safety contract for `offset`.
         unsafe { intrinsics::offset(self, count) }
     }
@@ -1018,6 +1077,33 @@ impl<T: ?Sized> *mut T {
     where
         T: Sized,
     {
+        #[inline]
+        const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
+            #[inline]
+            fn runtime(this: *const (), count: usize, size: usize) -> bool {
+                let Some(byte_offset) = count.checked_mul(size) else {
+                    return false;
+                };
+                byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset
+            }
+
+            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
+                true
+            }
+
+            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+        }
+
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::sub requires that the address calculation does not overflow",
+            (
+                this: *const () = self as *const (),
+                count: usize = count,
+                size: usize = size_of::<T>(),
+            ) => runtime_sub_nowrap(this, count, size)
+        );
+
         if T::IS_ZST {
             // Pointer arithmetic does nothing when the pointee is a ZST.
             self
@@ -1025,7 +1111,7 @@ impl<T: ?Sized> *mut T {
             // SAFETY: the caller must uphold the safety contract for `offset`.
             // Because the pointee is *not* a ZST, that means that `count` is
             // at most `isize::MAX`, and thus the negation cannot overflow.
-            unsafe { self.offset((count as isize).unchecked_neg()) }
+            unsafe { intrinsics::offset(self, intrinsics::unchecked_sub(0, count as isize)) }
         }
     }
 
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
index cfa479aa4b2..0edbbac1176 100644
--- a/tests/codegen/option-as-slice.rs
+++ b/tests/codegen/option-as-slice.rs
@@ -14,7 +14,9 @@ pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
     // CHECK-NOT: br
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
-    // CHECK: %[[LEN:.+]] = load i64,{{.+}} !range ![[META_U64:.+]], !noundef
+    // CHECK: %[[LEN:.+]] = load i64
+    // CHECK-SAME: !range ![[META_U64:[0-9]+]],
+    // CHECK-SAME: !noundef
     // CHECK-NOT: select
     // CHECK-NOT: br
     // CHECK-NOT: switch
@@ -51,7 +53,9 @@ pub fn u8_opt_as_slice(o: &Option<u8>) -> &[u8] {
     // CHECK-NOT: br
     // CHECK-NOT: switch
     // CHECK-NOT: icmp
-    // CHECK: %[[TAG:.+]] = load i8,{{.+}} !range ![[META_U8:.+]], !noundef
+    // CHECK: %[[TAG:.+]] = load i8
+    // CHECK-SAME: !range ![[META_U8:[0-9]+]],
+    // CHECK-SAME: !noundef
     // CHECK: %[[LEN:.+]] = zext{{.*}} i8 %[[TAG]] to i64
     // CHECK-NOT: select
     // CHECK-NOT: br
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
index 5faa1e210cf..c99c6f7de88 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
@@ -10,12 +10,18 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         scope 2 (inlined std::ptr::const_ptr::<impl *const [u32]>::cast::<u8>) {
         }
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+            scope 4 (inlined core::ub_checks::check_language_ub) {
+                scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
+                }
+            }
+            scope 6 (inlined std::mem::size_of::<u8>) {
+            }
         }
-        scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
+        scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
             let mut _5: usize;
-            scope 5 (inlined std::ptr::metadata::<[u32]>) {
+            scope 8 (inlined std::ptr::metadata::<[u32]>) {
             }
-            scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
+            scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
             }
         }
     }
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
index 5faa1e210cf..c99c6f7de88 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
@@ -10,12 +10,18 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         scope 2 (inlined std::ptr::const_ptr::<impl *const [u32]>::cast::<u8>) {
         }
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+            scope 4 (inlined core::ub_checks::check_language_ub) {
+                scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
+                }
+            }
+            scope 6 (inlined std::mem::size_of::<u8>) {
+            }
         }
-        scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
+        scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
             let mut _5: usize;
-            scope 5 (inlined std::ptr::metadata::<[u32]>) {
+            scope 8 (inlined std::ptr::metadata::<[u32]>) {
             }
-            scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
+            scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
             }
         }
     }
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
index 9429785045a..07665b2adc8 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
@@ -10,11 +10,17 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
         scope 2 (inlined std::ptr::const_ptr::<impl *const u32>::cast::<u8>) {
         }
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+            scope 4 (inlined core::ub_checks::check_language_ub) {
+                scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
+                }
+            }
+            scope 6 (inlined std::mem::size_of::<u8>) {
+            }
         }
-        scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
-            scope 5 (inlined std::ptr::metadata::<u32>) {
+        scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
+            scope 8 (inlined std::ptr::metadata::<u32>) {
             }
-            scope 6 (inlined std::ptr::from_raw_parts::<u32, ()>) {
+            scope 9 (inlined std::ptr::from_raw_parts::<u32, ()>) {
             }
         }
     }
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
index 9429785045a..07665b2adc8 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
@@ -10,11 +10,17 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
         scope 2 (inlined std::ptr::const_ptr::<impl *const u32>::cast::<u8>) {
         }
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
+            scope 4 (inlined core::ub_checks::check_language_ub) {
+                scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
+                }
+            }
+            scope 6 (inlined std::mem::size_of::<u8>) {
+            }
         }
-        scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
-            scope 5 (inlined std::ptr::metadata::<u32>) {
+        scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
+            scope 8 (inlined std::ptr::metadata::<u32>) {
             }
-            scope 6 (inlined std::ptr::from_raw_parts::<u32, ()>) {
+            scope 9 (inlined std::ptr::from_raw_parts::<u32, ()>) {
             }
         }
     }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index 3aa483ed1ae..da3295bf8c9 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -19,30 +19,30 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
             debug i => _22;
             debug x => _23;
         }
-        scope 17 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
+        scope 20 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
             let mut _14: &mut std::slice::Iter<'_, T>;
             let mut _15: std::option::Option<&T>;
             let mut _19: (usize, bool);
             let mut _20: (usize, &T);
-            scope 18 {
+            scope 21 {
                 let _18: usize;
-                scope 23 {
+                scope 26 {
                 }
             }
-            scope 19 {
-                scope 20 {
-                    scope 26 (inlined <Option<(usize, &T)> as FromResidual<Option<Infallible>>>::from_residual) {
+            scope 22 {
+                scope 23 {
+                    scope 29 (inlined <Option<(usize, &T)> as FromResidual<Option<Infallible>>>::from_residual) {
                     }
                 }
             }
-            scope 21 {
-                scope 22 {
+            scope 24 {
+                scope 25 {
                 }
             }
-            scope 24 (inlined <Option<&T> as Try>::branch) {
+            scope 27 (inlined <Option<&T> as Try>::branch) {
                 let mut _16: isize;
                 let _17: &T;
-                scope 25 {
+                scope 28 {
                 }
             }
         }
@@ -64,6 +64,12 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     scope 12 (inlined NonNull::<T>::as_ptr) {
                     }
                     scope 13 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                        scope 14 (inlined core::ub_checks::check_language_ub) {
+                            scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                        scope 16 (inlined std::mem::size_of::<T>) {
+                        }
                     }
                 }
                 scope 8 (inlined <NonNull<[T]> as From<&[T]>>::from) {
@@ -77,11 +83,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
             }
         }
     }
-    scope 14 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
-        scope 15 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
+    scope 17 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
+        scope 18 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
         }
     }
-    scope 16 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+    scope 19 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
     }
 
     bb0: {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index 4cc0aa0ed78..46c868ba8a1 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -39,6 +39,12 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
                     scope 12 (inlined NonNull::<T>::as_ptr) {
                     }
                     scope 13 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                        scope 14 (inlined core::ub_checks::check_language_ub) {
+                            scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                        scope 16 (inlined std::mem::size_of::<T>) {
+                        }
                     }
                 }
                 scope 8 (inlined <NonNull<[T]> as From<&[T]>>::from) {
@@ -52,11 +58,11 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
             }
         }
     }
-    scope 14 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
-        scope 15 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
+    scope 17 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
+        scope 18 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
         }
     }
-    scope 16 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+    scope 19 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
     }
 
     bb0: {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index 507afa63c68..cedda097c38 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -36,6 +36,12 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     scope 12 (inlined NonNull::<T>::as_ptr) {
                     }
                     scope 13 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                        scope 14 (inlined core::ub_checks::check_language_ub) {
+                            scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                        scope 16 (inlined std::mem::size_of::<T>) {
+                        }
                     }
                 }
                 scope 8 (inlined <NonNull<[T]> as From<&[T]>>::from) {
@@ -49,7 +55,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             }
         }
     }
-    scope 14 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
+    scope 17 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
     }
 
     bb0: {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index a25f12edc28..e299760d982 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -36,6 +36,12 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     scope 12 (inlined NonNull::<T>::as_ptr) {
                     }
                     scope 13 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                        scope 14 (inlined core::ub_checks::check_language_ub) {
+                            scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                        scope 16 (inlined std::mem::size_of::<T>) {
+                        }
                     }
                 }
                 scope 8 (inlined <NonNull<[T]> as From<&[T]>>::from) {
@@ -49,7 +55,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             }
         }
     }
-    scope 14 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
+    scope 17 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
     }
 
     bb0: {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index 1b397a4e4cd..d01bd4a9a4a 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         scope 2 {
             debug x => _17;
         }
-        scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
+        scope 20 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
             let mut _14: &mut std::slice::Iter<'_, T>;
         }
     }
@@ -39,6 +39,12 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     scope 12 (inlined NonNull::<T>::as_ptr) {
                     }
                     scope 13 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                        scope 14 (inlined core::ub_checks::check_language_ub) {
+                            scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                        scope 16 (inlined std::mem::size_of::<T>) {
+                        }
                     }
                 }
                 scope 8 (inlined <NonNull<[T]> as From<&[T]>>::from) {
@@ -52,11 +58,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             }
         }
     }
-    scope 14 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
-        scope 15 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
+    scope 17 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
+        scope 18 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
         }
     }
-    scope 16 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+    scope 19 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
     }
 
     bb0: {
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index 77689dd9b51..d2d0492add4 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -18,7 +18,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         scope 2 {
             debug x => _17;
         }
-        scope 17 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
+        scope 20 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
             let mut _14: &mut std::slice::Iter<'_, T>;
         }
     }
@@ -39,6 +39,12 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                     scope 12 (inlined NonNull::<T>::as_ptr) {
                     }
                     scope 13 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                        scope 14 (inlined core::ub_checks::check_language_ub) {
+                            scope 15 (inlined core::ub_checks::check_language_ub::runtime) {
+                            }
+                        }
+                        scope 16 (inlined std::mem::size_of::<T>) {
+                        }
                     }
                 }
                 scope 8 (inlined <NonNull<[T]> as From<&[T]>>::from) {
@@ -52,11 +58,11 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             }
         }
     }
-    scope 14 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
-        scope 15 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
+    scope 17 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
+        scope 18 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
         }
     }
-    scope 16 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+    scope 19 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
     }
 
     bb0: {