Redo SliceIndex implementations
This commit is contained in:
parent
17a9d3498b
commit
33c4817d98
@ -2,7 +2,6 @@
|
||||
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::ops;
|
||||
use crate::ptr;
|
||||
use crate::ub_checks::assert_unsafe_precondition;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -106,6 +105,47 @@ const fn slice_end_index_overflow_fail() -> ! {
|
||||
panic!("attempted to index slice up to maximum usize");
|
||||
}
|
||||
|
||||
// The UbChecks are great for catching bugs in the unsafe methods, but including
|
||||
// them in safe indexing is unnecessary and hurts inlining and debug runtime perf.
|
||||
// Both the safe and unsafe public methods share these helpers,
|
||||
// which use intrinsics directly to get *no* extra checks.
|
||||
|
||||
#[inline(always)]
|
||||
const unsafe fn get_noubcheck<T>(ptr: *const [T], index: usize) -> *const T {
|
||||
let ptr = ptr as *const T;
|
||||
// SAFETY: The caller already checked these preconditions
|
||||
unsafe { crate::intrinsics::offset(ptr, index) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
const unsafe fn get_mut_noubcheck<T>(ptr: *mut [T], index: usize) -> *mut T {
|
||||
let ptr = ptr as *mut T;
|
||||
// SAFETY: The caller already checked these preconditions
|
||||
unsafe { crate::intrinsics::offset(ptr, index) }
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
const unsafe fn get_offset_len_noubcheck<T>(
|
||||
ptr: *const [T],
|
||||
offset: usize,
|
||||
len: usize,
|
||||
) -> *const [T] {
|
||||
// SAFETY: The caller already checked these preconditions
|
||||
let ptr = unsafe { get_noubcheck(ptr, offset) };
|
||||
crate::intrinsics::aggregate_raw_ptr(ptr, len)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
const unsafe fn get_offset_len_mut_noubcheck<T>(
|
||||
ptr: *mut [T],
|
||||
offset: usize,
|
||||
len: usize,
|
||||
) -> *mut [T] {
|
||||
// SAFETY: The caller already checked these preconditions
|
||||
let ptr = unsafe { get_mut_noubcheck(ptr, offset) };
|
||||
crate::intrinsics::aggregate_raw_ptr(ptr, len)
|
||||
}
|
||||
|
||||
mod private_slice_index {
|
||||
use super::ops;
|
||||
#[stable(feature = "slice_get_slice", since = "1.28.0")]
|
||||
@ -203,13 +243,17 @@ unsafe impl<T> SliceIndex<[T]> for usize {
|
||||
#[inline]
|
||||
fn get(self, slice: &[T]) -> Option<&T> {
|
||||
// SAFETY: `self` is checked to be in bounds.
|
||||
if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None }
|
||||
if self < slice.len() { unsafe { Some(&*get_noubcheck(slice, self)) } } else { None }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
|
||||
// SAFETY: `self` is checked to be in bounds.
|
||||
if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None }
|
||||
if self < slice.len() {
|
||||
// SAFETY: `self` is checked to be in bounds.
|
||||
unsafe { Some(&mut *get_mut_noubcheck(slice, self)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -227,7 +271,7 @@ unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
|
||||
// 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)
|
||||
get_noubcheck(slice, self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +283,7 @@ unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
|
||||
(this: usize = self, len: usize = slice.len()) => this < len
|
||||
);
|
||||
// SAFETY: see comments for `get_unchecked` above.
|
||||
unsafe { slice.as_mut_ptr().add(self) }
|
||||
unsafe { get_mut_noubcheck(slice, self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -265,7 +309,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
|
||||
fn get(self, slice: &[T]) -> Option<&[T]> {
|
||||
if self.end() <= slice.len() {
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { Some(&*self.get_unchecked(slice)) }
|
||||
unsafe { Some(&*get_offset_len_noubcheck(slice, self.start(), self.len())) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -275,7 +319,7 @@ fn get(self, slice: &[T]) -> Option<&[T]> {
|
||||
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
|
||||
if self.end() <= slice.len() {
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
|
||||
unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len())) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -292,7 +336,7 @@ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
|
||||
// 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 { ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len()) }
|
||||
unsafe { get_offset_len_noubcheck(slice, self.start(), self.len()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -304,14 +348,14 @@ unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
|
||||
);
|
||||
|
||||
// SAFETY: see comments for `get_unchecked` above.
|
||||
unsafe { ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len()) }
|
||||
unsafe { get_offset_len_mut_noubcheck(slice, self.start(), self.len()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index(self, slice: &[T]) -> &[T] {
|
||||
if self.end() <= slice.len() {
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { &*self.get_unchecked(slice) }
|
||||
unsafe { &*get_offset_len_noubcheck(slice, self.start(), self.len()) }
|
||||
} else {
|
||||
slice_end_index_len_fail(self.end(), slice.len())
|
||||
}
|
||||
@ -321,7 +365,7 @@ fn index(self, slice: &[T]) -> &[T] {
|
||||
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
||||
if self.end() <= slice.len() {
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { &mut *self.get_unchecked_mut(slice) }
|
||||
unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len()) }
|
||||
} else {
|
||||
slice_end_index_len_fail(self.end(), slice.len())
|
||||
}
|
||||
@ -338,21 +382,26 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
|
||||
|
||||
#[inline]
|
||||
fn get(self, slice: &[T]) -> Option<&[T]> {
|
||||
if self.start > self.end || self.end > slice.len() {
|
||||
None
|
||||
} else {
|
||||
// Using checked_sub is a safe way to get `SubUnchecked` in MIR
|
||||
if let Some(new_len) = usize::checked_sub(self.end, self.start)
|
||||
&& self.end <= slice.len()
|
||||
{
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { Some(&*self.get_unchecked(slice)) }
|
||||
unsafe { Some(&*get_offset_len_noubcheck(slice, self.start, new_len)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
|
||||
if self.start > self.end || self.end > slice.len() {
|
||||
None
|
||||
} else {
|
||||
if let Some(new_len) = usize::checked_sub(self.end, self.start)
|
||||
&& self.end <= slice.len()
|
||||
{
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
|
||||
unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start, new_len)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -373,8 +422,10 @@ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
|
||||
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
|
||||
// so the call to `add` is safe and the length calculation cannot overflow.
|
||||
unsafe {
|
||||
let new_len = self.end.unchecked_sub(self.start);
|
||||
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len)
|
||||
// Using the intrinsic avoids a superfluous UB check,
|
||||
// since the one on this method already checked `end >= start`.
|
||||
let new_len = crate::intrinsics::unchecked_sub(self.end, self.start);
|
||||
get_offset_len_noubcheck(slice, self.start, new_len)
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,31 +442,34 @@ unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
|
||||
);
|
||||
// SAFETY: see comments for `get_unchecked` above.
|
||||
unsafe {
|
||||
let new_len = self.end.unchecked_sub(self.start);
|
||||
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len)
|
||||
let new_len = crate::intrinsics::unchecked_sub(self.end, self.start);
|
||||
get_offset_len_mut_noubcheck(slice, self.start, new_len)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn index(self, slice: &[T]) -> &[T] {
|
||||
if self.start > self.end {
|
||||
slice_index_order_fail(self.start, self.end);
|
||||
} else if self.end > slice.len() {
|
||||
// Using checked_sub is a safe way to get `SubUnchecked` in MIR
|
||||
let Some(new_len) = usize::checked_sub(self.end, self.start) else {
|
||||
slice_index_order_fail(self.start, self.end)
|
||||
};
|
||||
if self.end > slice.len() {
|
||||
slice_end_index_len_fail(self.end, slice.len());
|
||||
}
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { &*self.get_unchecked(slice) }
|
||||
unsafe { &*get_offset_len_noubcheck(slice, self.start, new_len) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
||||
if self.start > self.end {
|
||||
slice_index_order_fail(self.start, self.end);
|
||||
} else if self.end > slice.len() {
|
||||
let Some(new_len) = usize::checked_sub(self.end, self.start) else {
|
||||
slice_index_order_fail(self.start, self.end)
|
||||
};
|
||||
if self.end > slice.len() {
|
||||
slice_end_index_len_fail(self.end, slice.len());
|
||||
}
|
||||
// SAFETY: `self` is checked to be valid and in bounds above.
|
||||
unsafe { &mut *self.get_unchecked_mut(slice) }
|
||||
unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start, new_len) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// skip-filecheck
|
||||
//@ compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Z ub-checks=yes
|
||||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
|
||||
@ -9,21 +8,39 @@
|
||||
|
||||
// EMIT_MIR slice_index.slice_index_usize.PreCodegen.after.mir
|
||||
pub fn slice_index_usize(slice: &[u32], index: usize) -> u32 {
|
||||
// CHECK-LABEL: slice_index_usize
|
||||
// CHECK: [[LEN:_[0-9]+]] = Len((*_1))
|
||||
// CHECK: Lt(_2, [[LEN]])
|
||||
// CHECK-NOT: precondition_check
|
||||
// CHECK: _0 = (*_1)[_2];
|
||||
slice[index]
|
||||
}
|
||||
|
||||
// EMIT_MIR slice_index.slice_get_mut_usize.PreCodegen.after.mir
|
||||
pub fn slice_get_mut_usize(slice: &mut [u32], index: usize) -> Option<&mut u32> {
|
||||
// CHECK-LABEL: slice_get_mut_usize
|
||||
// CHECK: [[LEN:_[0-9]+]] = Len((*_1))
|
||||
// CHECK: Lt(_2, move [[LEN]])
|
||||
// CHECK-NOT: precondition_check
|
||||
slice.get_mut(index)
|
||||
}
|
||||
|
||||
// EMIT_MIR slice_index.slice_index_range.PreCodegen.after.mir
|
||||
pub fn slice_index_range(slice: &[u32], index: Range<usize>) -> &[u32] {
|
||||
// CHECK-LABEL: slice_index_range
|
||||
&slice[index]
|
||||
}
|
||||
|
||||
// EMIT_MIR slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
|
||||
pub unsafe fn slice_get_unchecked_mut_range(slice: &mut [u32], index: Range<usize>) -> &mut [u32] {
|
||||
// CHECK-LABEL: slice_get_unchecked_mut_range
|
||||
// CHECK: [[START:_[0-9]+]] = move (_2.0: usize);
|
||||
// CHECK: [[END:_[0-9]+]] = move (_2.1: usize);
|
||||
// CHECK: precondition_check
|
||||
// CHECK: [[LEN:_[0-9]+]] = SubUnchecked([[END]], [[START]]);
|
||||
// CHECK: [[PTR:_[0-9]+]] = Offset({{_[0-9]+}}, [[START]]);
|
||||
// CHECK: [[SLICE:_[0-9]+]] = *mut [u32] from ([[PTR]], [[LEN]])
|
||||
// CHECK: _0 = &mut (*[[SLICE]]);
|
||||
slice.get_unchecked_mut(index)
|
||||
}
|
||||
|
||||
@ -32,5 +49,12 @@ pub unsafe fn slice_ptr_get_unchecked_range(
|
||||
slice: *const [u32],
|
||||
index: Range<usize>,
|
||||
) -> *const [u32] {
|
||||
// CHECK-LABEL: slice_ptr_get_unchecked_range
|
||||
// CHECK: [[START:_[0-9]+]] = move (_2.0: usize);
|
||||
// CHECK: [[END:_[0-9]+]] = move (_2.1: usize);
|
||||
// CHECK: precondition_check
|
||||
// CHECK: [[LEN:_[0-9]+]] = SubUnchecked([[END]], [[START]]);
|
||||
// CHECK: [[PTR:_[0-9]+]] = Offset({{_[0-9]+}}, [[START]]);
|
||||
// CHECK: _0 = *const [u32] from ([[PTR]], [[LEN]])
|
||||
slice.get_unchecked(index)
|
||||
}
|
||||
|
@ -5,13 +5,54 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
|
||||
debug index => _2;
|
||||
let mut _0: std::option::Option<&mut u32>;
|
||||
scope 1 (inlined core::slice::<impl [u32]>::get_mut::<usize>) {
|
||||
scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
|
||||
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 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
|
||||
let _6: *mut u32;
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_0 = <usize as SliceIndex<[u32]>>::get_mut(move _2, move _1) -> [return: bb1, unwind unreachable];
|
||||
StorageLive(_7);
|
||||
StorageLive(_4);
|
||||
StorageLive(_3);
|
||||
_3 = Len((*_1));
|
||||
_4 = Lt(_2, move _3);
|
||||
switchInt(move _4) -> [0: bb1, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
_0 = const Option::<&mut u32>::None;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_3);
|
||||
StorageLive(_8);
|
||||
StorageLive(_5);
|
||||
_5 = &raw mut (*_1);
|
||||
StorageLive(_6);
|
||||
_6 = _5 as *mut u32 (PtrToPtr);
|
||||
_7 = Offset(_6, _2);
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
_8 = &mut (*_7);
|
||||
_0 = Option::<&mut u32>::Some(move _8);
|
||||
StorageDead(_8);
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_4);
|
||||
StorageDead(_7);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -5,13 +5,54 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
|
||||
debug index => _2;
|
||||
let mut _0: std::option::Option<&mut u32>;
|
||||
scope 1 (inlined core::slice::<impl [u32]>::get_mut::<usize>) {
|
||||
scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
|
||||
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 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
|
||||
let _6: *mut u32;
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_0 = <usize as SliceIndex<[u32]>>::get_mut(move _2, move _1) -> [return: bb1, unwind continue];
|
||||
StorageLive(_7);
|
||||
StorageLive(_4);
|
||||
StorageLive(_3);
|
||||
_3 = Len((*_1));
|
||||
_4 = Lt(_2, move _3);
|
||||
switchInt(move _4) -> [0: bb1, otherwise: bb2];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
_0 = const Option::<&mut u32>::None;
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageDead(_3);
|
||||
StorageLive(_8);
|
||||
StorageLive(_5);
|
||||
_5 = &raw mut (*_1);
|
||||
StorageLive(_6);
|
||||
_6 = _5 as *mut u32 (PtrToPtr);
|
||||
_7 = Offset(_6, _2);
|
||||
StorageDead(_6);
|
||||
StorageDead(_5);
|
||||
_8 = &mut (*_7);
|
||||
_0 = Option::<&mut u32>::Some(move _8);
|
||||
StorageDead(_8);
|
||||
goto -> bb3;
|
||||
}
|
||||
|
||||
bb3: {
|
||||
StorageDead(_4);
|
||||
StorageDead(_7);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4,20 +4,62 @@ 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>>) {
|
||||
let mut _3: *mut [u32];
|
||||
let mut _4: *mut [u32];
|
||||
let mut _5: *mut [u32];
|
||||
let mut _12: *mut [u32];
|
||||
scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
|
||||
let mut _7: usize;
|
||||
let _8: ();
|
||||
let _9: usize;
|
||||
scope 3 {
|
||||
scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
|
||||
let _11: *mut u32;
|
||||
scope 7 {
|
||||
}
|
||||
scope 8 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
|
||||
let _10: *mut u32;
|
||||
scope 9 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 4 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
|
||||
let mut _6: *const [u32];
|
||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
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];
|
||||
_3 = move (_2.0: usize);
|
||||
_4 = move (_2.1: usize);
|
||||
StorageLive(_5);
|
||||
_5 = &raw mut (*_1);
|
||||
StorageLive(_9);
|
||||
StorageLive(_7);
|
||||
StorageLive(_6);
|
||||
_6 = _5 as *const [u32] (PointerCoercion(MutToConstPointer));
|
||||
_7 = PtrMetadata(_6);
|
||||
StorageDead(_6);
|
||||
_8 = <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(_3, _4, move _7) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
_0 = &mut (*_4);
|
||||
StorageDead(_7);
|
||||
_9 = SubUnchecked(_4, _3);
|
||||
StorageLive(_11);
|
||||
StorageLive(_10);
|
||||
_10 = _5 as *mut u32 (PtrToPtr);
|
||||
_11 = Offset(_10, _3);
|
||||
StorageDead(_10);
|
||||
_12 = *mut [u32] from (_11, _9);
|
||||
StorageDead(_11);
|
||||
StorageDead(_9);
|
||||
StorageDead(_5);
|
||||
_0 = &mut (*_12);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4,20 +4,62 @@ 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>>) {
|
||||
let mut _3: *mut [u32];
|
||||
let mut _4: *mut [u32];
|
||||
let mut _5: *mut [u32];
|
||||
let mut _12: *mut [u32];
|
||||
scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) {
|
||||
let mut _7: usize;
|
||||
let _8: ();
|
||||
let _9: usize;
|
||||
scope 3 {
|
||||
scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
|
||||
let _11: *mut u32;
|
||||
scope 7 {
|
||||
}
|
||||
scope 8 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
|
||||
let _10: *mut u32;
|
||||
scope 9 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 4 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
|
||||
let mut _6: *const [u32];
|
||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
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];
|
||||
_3 = move (_2.0: usize);
|
||||
_4 = move (_2.1: usize);
|
||||
StorageLive(_5);
|
||||
_5 = &raw mut (*_1);
|
||||
StorageLive(_9);
|
||||
StorageLive(_7);
|
||||
StorageLive(_6);
|
||||
_6 = _5 as *const [u32] (PointerCoercion(MutToConstPointer));
|
||||
_7 = PtrMetadata(_6);
|
||||
StorageDead(_6);
|
||||
_8 = <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::precondition_check(_3, _4, move _7) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_3);
|
||||
_0 = &mut (*_4);
|
||||
StorageDead(_7);
|
||||
_9 = SubUnchecked(_4, _3);
|
||||
StorageLive(_11);
|
||||
StorageLive(_10);
|
||||
_10 = _5 as *mut u32 (PtrToPtr);
|
||||
_11 = Offset(_10, _3);
|
||||
StorageDead(_10);
|
||||
_12 = *mut [u32] from (_11, _9);
|
||||
StorageDead(_11);
|
||||
StorageDead(_9);
|
||||
StorageDead(_5);
|
||||
_0 = &mut (*_12);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,52 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
|
||||
debug slice => _1;
|
||||
debug index => _2;
|
||||
let mut _0: *const [u32];
|
||||
let mut _3: usize;
|
||||
let mut _4: usize;
|
||||
scope 1 (inlined std::ptr::const_ptr::<impl *const [u32]>::get_unchecked::<std::ops::Range<usize>>) {
|
||||
scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked) {
|
||||
let mut _5: usize;
|
||||
let _6: ();
|
||||
let _7: usize;
|
||||
scope 3 {
|
||||
scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
|
||||
let _9: *const u32;
|
||||
scope 7 {
|
||||
}
|
||||
scope 8 (inlined core::slice::index::get_noubcheck::<u32>) {
|
||||
let _8: *const u32;
|
||||
scope 9 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 4 (inlined std::ptr::const_ptr::<impl *const [u32]>::len) {
|
||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_0 = <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked(move _2, move _1) -> [return: bb1, unwind unreachable];
|
||||
_3 = move (_2.0: usize);
|
||||
_4 = move (_2.1: usize);
|
||||
StorageLive(_7);
|
||||
StorageLive(_5);
|
||||
_5 = PtrMetadata(_1);
|
||||
_6 = <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked::precondition_check(_3, _4, move _5) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_5);
|
||||
_7 = SubUnchecked(_4, _3);
|
||||
StorageLive(_9);
|
||||
StorageLive(_8);
|
||||
_8 = _1 as *const u32 (PtrToPtr);
|
||||
_9 = Offset(_8, _3);
|
||||
StorageDead(_8);
|
||||
_0 = *const [u32] from (_9, _7);
|
||||
StorageDead(_9);
|
||||
StorageDead(_7);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,52 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
|
||||
debug slice => _1;
|
||||
debug index => _2;
|
||||
let mut _0: *const [u32];
|
||||
let mut _3: usize;
|
||||
let mut _4: usize;
|
||||
scope 1 (inlined std::ptr::const_ptr::<impl *const [u32]>::get_unchecked::<std::ops::Range<usize>>) {
|
||||
scope 2 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked) {
|
||||
let mut _5: usize;
|
||||
let _6: ();
|
||||
let _7: usize;
|
||||
scope 3 {
|
||||
scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
|
||||
let _9: *const u32;
|
||||
scope 7 {
|
||||
}
|
||||
scope 8 (inlined core::slice::index::get_noubcheck::<u32>) {
|
||||
let _8: *const u32;
|
||||
scope 9 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
scope 4 (inlined std::ptr::const_ptr::<impl *const [u32]>::len) {
|
||||
scope 5 (inlined std::ptr::metadata::<[u32]>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_0 = <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked(move _2, move _1) -> [return: bb1, unwind continue];
|
||||
_3 = move (_2.0: usize);
|
||||
_4 = move (_2.1: usize);
|
||||
StorageLive(_7);
|
||||
StorageLive(_5);
|
||||
_5 = PtrMetadata(_1);
|
||||
_6 = <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked::precondition_check(_3, _4, move _5) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
StorageDead(_5);
|
||||
_7 = SubUnchecked(_4, _3);
|
||||
StorageLive(_9);
|
||||
StorageLive(_8);
|
||||
_8 = _1 as *const u32 (PtrToPtr);
|
||||
_9 = Offset(_8, _3);
|
||||
StorageDead(_8);
|
||||
_0 = *const [u32] from (_9, _7);
|
||||
StorageDead(_9);
|
||||
StorageDead(_7);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user