Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a8aa174

Browse files
committedFeb 8, 2024
Auto merge of #120762 - saethlin:assume-in-get-unchecked, r=<try>
Expand assumes to the other unchecked slice ops r? `@ghost`
2 parents 8ace7ea + b9947b3 commit a8aa174

6 files changed

+332
-153
lines changed
 

‎library/core/src/slice/index.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,10 @@ unsafe impl<T> SliceIndex<[T]> for usize {
246246
"slice::get_unchecked_mut requires that the index is within the slice",
247247
);
248248
// SAFETY: see comments for `get_unchecked` above.
249-
unsafe { slice.as_mut_ptr().add(self) }
249+
unsafe {
250+
crate::hint::assert_unchecked(self < slice.len());
251+
slice.as_mut_ptr().add(self)
252+
}
250253
}
251254

252255
#[inline]
@@ -298,7 +301,10 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
298301
// cannot be longer than `isize::MAX`. They also guarantee that
299302
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
300303
// so the call to `add` is safe.
301-
unsafe { ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len()) }
304+
unsafe {
305+
crate::hint::assert_unchecked(self.end() <= slice.len());
306+
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len())
307+
}
302308
}
303309

304310
#[inline]
@@ -308,7 +314,10 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
308314
"slice::get_unchecked_mut requires that the index is within the slice",
309315
);
310316
// SAFETY: see comments for `get_unchecked` above.
311-
unsafe { ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len()) }
317+
unsafe {
318+
crate::hint::assert_unchecked(self.end() <= slice.len());
319+
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len())
320+
}
312321
}
313322

314323
#[inline]
@@ -368,6 +377,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
368377
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
369378
// so the call to `add` is safe and the length calculation cannot overflow.
370379
unsafe {
380+
crate::hint::assert_unchecked(self.end <= slice.len());
371381
let new_len = unchecked_sub(self.end, self.start);
372382
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len)
373383
}
@@ -381,6 +391,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
381391
);
382392
// SAFETY: see comments for `get_unchecked` above.
383393
unsafe {
394+
crate::hint::assert_unchecked(self.end <= slice.len());
384395
let new_len = unchecked_sub(self.end, self.start);
385396
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len)
386397
}

‎tests/codegen/issues/issue-116878.rs

+24
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,27 @@ pub unsafe fn unchecked_slice_no_bounds_check(s: &[u8]) -> u8 {
1010
// CHECK-NOT: panic_bounds_check
1111
a + s[0]
1212
}
13+
14+
// CHECK-LABEL: @unchecked_slice_no_bounds_check_mut
15+
#[no_mangle]
16+
pub unsafe fn unchecked_slice_no_bounds_check_mut(s: &mut [u8]) -> u8 {
17+
let a = *s.get_unchecked_mut(2);
18+
// CHECK-NOT: panic_bounds_check
19+
a + s[1]
20+
}
21+
22+
// CHECK-LABEL: @unchecked_slice_no_bounds_check_range
23+
#[no_mangle]
24+
pub unsafe fn unchecked_slice_no_bounds_check_range(s: &[u8]) -> u8 {
25+
let _a = &s.get_unchecked(..1);
26+
// CHECK-NOT: panic_bounds_check
27+
s[0]
28+
}
29+
30+
// CHECK-LABEL: @unchecked_slice_no_bounds_check_range_mut
31+
#[no_mangle]
32+
pub unsafe fn unchecked_slice_no_bounds_check_range_mut(s: &mut [u8]) -> u8 {
33+
let _a = &mut s.get_unchecked_mut(..2);
34+
// CHECK-NOT: panic_bounds_check
35+
s[1]
36+
}

‎tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir

+61-25
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,66 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
1313
let mut _3: usize;
1414
let mut _4: bool;
1515
let mut _5: *mut [u32];
16-
let mut _7: *mut u32;
17-
let mut _8: &mut u32;
16+
let mut _11: *mut u32;
17+
let mut _12: &mut u32;
1818
scope 3 {
1919
scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) {
2020
debug self => _2;
2121
debug slice => _5;
22-
let mut _6: *mut u32;
23-
let mut _9: *mut [u32];
24-
let mut _10: &[&str];
22+
let mut _8: usize;
23+
let mut _9: bool;
24+
let mut _10: *mut u32;
25+
let mut _13: *mut [u32];
26+
let mut _14: &[&str];
2527
scope 5 {
26-
scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
28+
scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
2729
debug self => _5;
30+
let mut _6: *const [u32];
31+
scope 11 (inlined std::ptr::metadata::<[u32]>) {
32+
debug ptr => _6;
33+
let mut _7: std::ptr::metadata::PtrRepr<[u32]>;
34+
scope 12 {
35+
}
36+
}
37+
}
38+
scope 13 (inlined #[track_caller] assert_unchecked) {
39+
debug cond => _9;
40+
let mut _16: bool;
41+
scope 14 {
42+
scope 15 (inlined assert_unchecked::runtime) {
43+
debug cond => _16;
44+
}
45+
}
2846
}
29-
scope 11 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
30-
debug self => _6;
47+
scope 16 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
48+
debug self => _5;
49+
}
50+
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
51+
debug self => _10;
3152
debug count => _2;
32-
scope 12 {
53+
scope 18 {
3354
}
3455
}
3556
}
3657
scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
37-
debug self => _9;
38-
let mut _11: *const [u32];
58+
debug self => _13;
59+
let mut _15: *const [u32];
3960
scope 7 (inlined std::ptr::metadata::<[u32]>) {
40-
debug ptr => _11;
61+
debug ptr => _15;
4162
scope 8 {
4263
}
4364
}
4465
}
4566
scope 9 (inlined Arguments::<'_>::new_const) {
46-
debug pieces => _10;
67+
debug pieces => _14;
4768
}
4869
}
4970
}
5071
}
5172
}
5273

5374
bb0: {
54-
StorageLive(_7);
75+
StorageLive(_11);
5576
StorageLive(_4);
5677
StorageLive(_3);
5778
_3 = Len((*_1));
@@ -67,29 +88,44 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
6788

6889
bb2: {
6990
StorageDead(_3);
70-
StorageLive(_8);
91+
StorageLive(_12);
7192
StorageLive(_5);
7293
_5 = &raw mut (*_1);
94+
StorageLive(_13);
95+
StorageLive(_14);
96+
StorageLive(_15);
7397
StorageLive(_9);
74-
StorageLive(_10);
75-
StorageLive(_11);
98+
StorageLive(_8);
7699
StorageLive(_6);
77-
_6 = _5 as *mut u32 (PtrToPtr);
78-
_7 = Offset(_6, _2);
100+
_6 = _5 as *const [u32] (PointerCoercion(MutToConstPointer));
101+
StorageLive(_7);
102+
_7 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: _6 };
103+
_8 = ((_7.2: std::ptr::metadata::PtrComponents<[u32]>).1: usize);
104+
StorageDead(_7);
79105
StorageDead(_6);
80-
StorageDead(_11);
81-
StorageDead(_10);
106+
_9 = Lt(_2, move _8);
107+
StorageDead(_8);
108+
StorageLive(_16);
109+
assume(_9);
110+
StorageDead(_16);
82111
StorageDead(_9);
112+
StorageLive(_10);
113+
_10 = _5 as *mut u32 (PtrToPtr);
114+
_11 = Offset(_10, _2);
115+
StorageDead(_10);
116+
StorageDead(_15);
117+
StorageDead(_14);
118+
StorageDead(_13);
83119
StorageDead(_5);
84-
_8 = &mut (*_7);
85-
_0 = Option::<&mut u32>::Some(move _8);
86-
StorageDead(_8);
120+
_12 = &mut (*_11);
121+
_0 = Option::<&mut u32>::Some(move _12);
122+
StorageDead(_12);
87123
goto -> bb3;
88124
}
89125

90126
bb3: {
91127
StorageDead(_4);
92-
StorageDead(_7);
128+
StorageDead(_11);
93129
return;
94130
}
95131
}

‎tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir

+61-25
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,66 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
1313
let mut _3: usize;
1414
let mut _4: bool;
1515
let mut _5: *mut [u32];
16-
let mut _7: *mut u32;
17-
let mut _8: &mut u32;
16+
let mut _11: *mut u32;
17+
let mut _12: &mut u32;
1818
scope 3 {
1919
scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) {
2020
debug self => _2;
2121
debug slice => _5;
22-
let mut _6: *mut u32;
23-
let mut _9: *mut [u32];
24-
let mut _10: &[&str];
22+
let mut _8: usize;
23+
let mut _9: bool;
24+
let mut _10: *mut u32;
25+
let mut _13: *mut [u32];
26+
let mut _14: &[&str];
2527
scope 5 {
26-
scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
28+
scope 10 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
2729
debug self => _5;
30+
let mut _6: *const [u32];
31+
scope 11 (inlined std::ptr::metadata::<[u32]>) {
32+
debug ptr => _6;
33+
let mut _7: std::ptr::metadata::PtrRepr<[u32]>;
34+
scope 12 {
35+
}
36+
}
37+
}
38+
scope 13 (inlined #[track_caller] assert_unchecked) {
39+
debug cond => _9;
40+
let mut _16: bool;
41+
scope 14 {
42+
scope 15 (inlined assert_unchecked::runtime) {
43+
debug cond => _16;
44+
}
45+
}
2846
}
29-
scope 11 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
30-
debug self => _6;
47+
scope 16 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
48+
debug self => _5;
49+
}
50+
scope 17 (inlined std::ptr::mut_ptr::<impl *mut u32>::add) {
51+
debug self => _10;
3152
debug count => _2;
32-
scope 12 {
53+
scope 18 {
3354
}
3455
}
3556
}
3657
scope 6 (inlined std::ptr::mut_ptr::<impl *mut [u32]>::len) {
37-
debug self => _9;
38-
let mut _11: *const [u32];
58+
debug self => _13;
59+
let mut _15: *const [u32];
3960
scope 7 (inlined std::ptr::metadata::<[u32]>) {
40-
debug ptr => _11;
61+
debug ptr => _15;
4162
scope 8 {
4263
}
4364
}
4465
}
4566
scope 9 (inlined Arguments::<'_>::new_const) {
46-
debug pieces => _10;
67+
debug pieces => _14;
4768
}
4869
}
4970
}
5071
}
5172
}
5273

5374
bb0: {
54-
StorageLive(_7);
75+
StorageLive(_11);
5576
StorageLive(_4);
5677
StorageLive(_3);
5778
_3 = Len((*_1));
@@ -67,29 +88,44 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
6788

6889
bb2: {
6990
StorageDead(_3);
70-
StorageLive(_8);
91+
StorageLive(_12);
7192
StorageLive(_5);
7293
_5 = &raw mut (*_1);
94+
StorageLive(_13);
95+
StorageLive(_14);
96+
StorageLive(_15);
7397
StorageLive(_9);
74-
StorageLive(_10);
75-
StorageLive(_11);
98+
StorageLive(_8);
7699
StorageLive(_6);
77-
_6 = _5 as *mut u32 (PtrToPtr);
78-
_7 = Offset(_6, _2);
100+
_6 = _5 as *const [u32] (PointerCoercion(MutToConstPointer));
101+
StorageLive(_7);
102+
_7 = std::ptr::metadata::PtrRepr::<[u32]> { const_ptr: _6 };
103+
_8 = ((_7.2: std::ptr::metadata::PtrComponents<[u32]>).1: usize);
104+
StorageDead(_7);
79105
StorageDead(_6);
80-
StorageDead(_11);
81-
StorageDead(_10);
106+
_9 = Lt(_2, move _8);
107+
StorageDead(_8);
108+
StorageLive(_16);
109+
assume(_9);
110+
StorageDead(_16);
82111
StorageDead(_9);
112+
StorageLive(_10);
113+
_10 = _5 as *mut u32 (PtrToPtr);
114+
_11 = Offset(_10, _2);
115+
StorageDead(_10);
116+
StorageDead(_15);
117+
StorageDead(_14);
118+
StorageDead(_13);
83119
StorageDead(_5);
84-
_8 = &mut (*_7);
85-
_0 = Option::<&mut u32>::Some(move _8);
86-
StorageDead(_8);
120+
_12 = &mut (*_11);
121+
_0 = Option::<&mut u32>::Some(move _12);
122+
StorageDead(_12);
87123
goto -> bb3;
88124
}
89125

90126
bb3: {
91127
StorageDead(_4);
92-
StorageDead(_7);
128+
StorageDead(_11);
93129
return;
94130
}
95131
}
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.