Add precondition checks to ptr::offset, ptr::add, ptr::sub
This commit is contained in:
parent
7caad69253
commit
6d246e47fb
@ -395,6 +395,36 @@ pub const fn to_raw_parts(self) -> (*const (), <T as super::Pointee>::Metadata)
|
||||
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 @@ const fn comptime(_: *const (), _: *const ()) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[allow(unused_unsafe)]
|
||||
intrinsics::const_eval_select((this, origin), comptime, runtime)
|
||||
}
|
||||
|
||||
@ -858,6 +887,34 @@ pub const fn guaranteed_ne(self, other: *const T) -> Option<bool>
|
||||
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 @@ pub const fn guaranteed_ne(self, other: *const T) -> Option<bool>
|
||||
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 @@ pub const fn guaranteed_ne(self, other: *const T) -> Option<bool>
|
||||
// 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)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,6 +393,37 @@ pub const fn to_raw_parts(self) -> (*mut (), <T as super::Pointee>::Metadata) {
|
||||
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 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
|
||||
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 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
|
||||
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 @@ pub const fn guaranteed_ne(self, other: *mut T) -> Option<bool>
|
||||
// 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)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
||||
let mut _5: usize;
|
||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||
scope 4 (inlined core::ub_checks::check_language_ub) {
|
||||
scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
|
||||
}
|
||||
}
|
||||
scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
|
||||
scope 6 (inlined std::mem::size_of::<u8>) {
|
||||
}
|
||||
}
|
||||
scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
||||
let mut _5: usize;
|
||||
scope 8 (inlined std::ptr::metadata::<[u32]>) {
|
||||
}
|
||||
scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
||||
let mut _5: usize;
|
||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||
scope 4 (inlined core::ub_checks::check_language_ub) {
|
||||
scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
|
||||
}
|
||||
}
|
||||
scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
|
||||
scope 6 (inlined std::mem::size_of::<u8>) {
|
||||
}
|
||||
}
|
||||
scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
|
||||
let mut _5: usize;
|
||||
scope 8 (inlined std::ptr::metadata::<[u32]>) {
|
||||
}
|
||||
scope 9 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
|
||||
scope 5 (inlined std::ptr::metadata::<u32>) {
|
||||
scope 4 (inlined core::ub_checks::check_language_ub) {
|
||||
scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
|
||||
}
|
||||
}
|
||||
scope 6 (inlined std::ptr::from_raw_parts::<u32, ()>) {
|
||||
scope 6 (inlined std::mem::size_of::<u8>) {
|
||||
}
|
||||
}
|
||||
scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
|
||||
scope 8 (inlined std::ptr::metadata::<u32>) {
|
||||
}
|
||||
scope 9 (inlined std::ptr::from_raw_parts::<u32, ()>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
|
||||
scope 5 (inlined std::ptr::metadata::<u32>) {
|
||||
scope 4 (inlined core::ub_checks::check_language_ub) {
|
||||
scope 5 (inlined core::ub_checks::check_language_ub::runtime) {
|
||||
}
|
||||
}
|
||||
scope 6 (inlined std::ptr::from_raw_parts::<u32, ()>) {
|
||||
scope 6 (inlined std::mem::size_of::<u8>) {
|
||||
}
|
||||
}
|
||||
scope 7 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<u32>) {
|
||||
scope 8 (inlined std::ptr::metadata::<u32>) {
|
||||
}
|
||||
scope 9 (inlined std::ptr::from_raw_parts::<u32, ()>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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: {
|
||||
|
@ -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: {
|
||||
|
@ -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: {
|
||||
|
@ -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: {
|
||||
|
@ -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: {
|
||||
|
@ -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: {
|
||||
|
Loading…
Reference in New Issue
Block a user