Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit b812f16

Browse files
committed
Use slice_index in SliceIndex<[T]> for usize
1 parent 2d383ad commit b812f16

File tree

7 files changed

+74
-129
lines changed

7 files changed

+74
-129
lines changed

library/core/src/slice/index.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
33
use crate::intrinsics::assert_unsafe_precondition;
44
use crate::intrinsics::const_eval_select;
5+
#[cfg(not(bootstrap))]
6+
use crate::intrinsics::slice_index;
57
use crate::intrinsics::unchecked_sub;
68
use crate::ops;
79
use crate::ptr;
@@ -213,14 +215,38 @@ unsafe impl<T> SliceIndex<[T]> for usize {
213215

214216
#[inline]
215217
fn get(self, slice: &[T]) -> Option<&T> {
216-
// SAFETY: `self` is checked to be in bounds.
217-
if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None }
218+
if self < slice.len() {
219+
#[cfg(bootstrap)]
220+
// SAFETY: `self` is checked to be in bounds.
221+
unsafe {
222+
Some(&*self.get_unchecked(slice))
223+
}
224+
#[cfg(not(bootstrap))]
225+
// SAFETY: `self` is checked to be in bounds.
226+
unsafe {
227+
Some(slice_index(slice, self))
228+
}
229+
} else {
230+
None
231+
}
218232
}
219233

220234
#[inline]
221235
fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
222-
// SAFETY: `self` is checked to be in bounds.
223-
if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None }
236+
if self < slice.len() {
237+
#[cfg(bootstrap)]
238+
// SAFETY: `self` is checked to be in bounds.
239+
unsafe {
240+
Some(&mut *self.get_unchecked_mut(slice))
241+
}
242+
#[cfg(not(bootstrap))]
243+
// SAFETY: `self` is checked to be in bounds.
244+
unsafe {
245+
Some(slice_index(slice, self))
246+
}
247+
} else {
248+
None
249+
}
224250
}
225251

226252
#[inline]
@@ -231,11 +257,18 @@ unsafe impl<T> SliceIndex<[T]> for usize {
231257
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
232258
// so the call to `add` is safe.
233259
unsafe {
234-
assert_unsafe_precondition!(
235-
"slice::get_unchecked requires that the index is within the slice",
236-
[T](this: usize, slice: *const [T]) => this < slice.len()
237-
);
238-
slice.as_ptr().add(self)
260+
#[cfg(bootstrap)]
261+
{
262+
assert_unsafe_precondition!(
263+
"slice::get_unchecked requires that the index is within the slice",
264+
[T](this: usize, slice: *const [T]) => this < slice.len()
265+
);
266+
slice.as_ptr().add(self)
267+
}
268+
#[cfg(not(bootstrap))]
269+
{
270+
slice_index(slice, this)
271+
}
239272
}
240273
}
241274

@@ -244,11 +277,18 @@ unsafe impl<T> SliceIndex<[T]> for usize {
244277
let this = self;
245278
// SAFETY: see comments for `get_unchecked` above.
246279
unsafe {
247-
assert_unsafe_precondition!(
248-
"slice::get_unchecked_mut requires that the index is within the slice",
249-
[T](this: usize, slice: *mut [T]) => this < slice.len()
250-
);
251-
slice.as_mut_ptr().add(self)
280+
#[cfg(bootstrap)]
281+
{
282+
assert_unsafe_precondition!(
283+
"slice::get_unchecked_mut requires that the index is within the slice",
284+
[T](this: usize, slice: *mut [T]) => this < slice.len()
285+
);
286+
slice.as_mut_ptr().add(self)
287+
}
288+
#[cfg(not(bootstrap))]
289+
{
290+
slice_index(slice, this)
291+
}
252292
}
253293
}
254294

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
//@compile-flags: -Zmiri-strict-provenance
2-
//@error-in-other-file: /retag .* tag does not exist in the borrow stack/
32

43
fn main() {
54
unsafe {
65
let a = [1, 2, 3];
76
let s = &a[0..0];
87
assert_eq!(s.len(), 0);
9-
assert_eq!(*s.get_unchecked(1), 2);
8+
assert_eq!(*s.as_ptr().add(1), 2); //~ ERROR: /retag .* tag does not exist in the borrow stack/
109
}
1110
}

src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
error: Undefined Behavior: trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
2-
--> RUSTLIB/core/src/slice/mod.rs:LL:CC
2+
--> $DIR/zst_slice.rs:LL:CC
33
|
4-
LL | unsafe { &*index.get_unchecked(self) }
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
| |
7-
| trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
8-
| this error occurs as part of retag at ALLOC[0x4..0x8]
4+
LL | assert_eq!(*s.as_ptr().add(1), 2);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| trying to retag from <TAG> for SharedReadOnly permission at ALLOC[0x4], but that tag does not exist in the borrow stack for this location
8+
| this error occurs as part of retag at ALLOC[0x4..0x8]
99
|
1010
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
1111
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
1212
help: <TAG> would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere
1313
--> $DIR/zst_slice.rs:LL:CC
1414
|
15-
LL | assert_eq!(*s.get_unchecked(1), 2);
16-
| ^^^^^^^^^^^^^^^^^^
15+
LL | assert_eq!(*s.as_ptr().add(1), 2);
16+
| ^^^^^^^^^^
1717
= note: BACKTRACE (of the first span):
18-
= note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
19-
note: inside `main`
20-
--> $DIR/zst_slice.rs:LL:CC
21-
|
22-
LL | assert_eq!(*s.get_unchecked(1), 2);
23-
| ^^^^^^^^^^^^^^^^^^
18+
= note: inside `main` at RUSTLIB/core/src/macros/mod.rs:LL:CC
19+
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
2420

2521
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
2622

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@compile-flags: -Zmiri-disable-stacked-borrows
22
fn main() {
33
let v: Vec<u8> = Vec::with_capacity(10);
4-
let undef = unsafe { *v.get_unchecked(5) }; //~ ERROR: uninitialized
4+
let undef = unsafe { *v.as_ptr().add(5) }; //~ ERROR: uninitialized
55
let x = undef + 1;
66
panic!("this should never print: {}", x);
77
}

src/tools/miri/tests/fail/uninit_byte_read.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
22
--> $DIR/uninit_byte_read.rs:LL:CC
33
|
4-
LL | let undef = unsafe { *v.get_unchecked(5) };
5-
| ^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
4+
LL | let undef = unsafe { *v.as_ptr().add(5) };
5+
| ^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

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

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,13 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
1212
debug slice => _1;
1313
let mut _3: usize;
1414
let mut _4: bool;
15-
let mut _5: *mut [u32];
16-
let mut _7: *mut u32;
17-
let mut _8: &mut u32;
15+
let mut _5: &mut u32;
1816
scope 3 {
19-
scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) {
20-
debug self => _2;
21-
debug slice => _5;
22-
let mut _6: *mut u32;
23-
scope 5 {
24-
debug this => _2;
25-
scope 6 {
26-
scope 7 (inlined <usize as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) {
27-
debug this => _2;
28-
debug slice => _5;
29-
scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) {
30-
debug self => _5;
31-
let mut _9: *const [u32];
32-
scope 9 (inlined std::ptr::metadata::<[u32]>) {
33-
debug ptr => _9;
34-
scope 10 {
35-
}
36-
}
37-
}
38-
}
39-
scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
40-
debug self => _5;
41-
}
42-
scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) {
43-
debug self => _6;
44-
debug count => _2;
45-
scope 13 {
46-
}
47-
}
48-
}
49-
}
50-
}
5117
}
5218
}
5319
}
5420

5521
bb0: {
56-
StorageLive(_7);
5722
StorageLive(_4);
5823
StorageLive(_3);
5924
_3 = Len((*_1));
@@ -69,25 +34,15 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
6934

7035
bb2: {
7136
StorageDead(_3);
72-
StorageLive(_8);
7337
StorageLive(_5);
74-
_5 = &raw mut (*_1);
75-
StorageLive(_9);
76-
StorageLive(_6);
77-
_6 = _5 as *mut u32 (PtrToPtr);
78-
_7 = Offset(_6, _2);
79-
StorageDead(_6);
80-
StorageDead(_9);
38+
_5 = &mut (*_1)[_2];
39+
_0 = Option::<&mut u32>::Some(move _5);
8140
StorageDead(_5);
82-
_8 = &mut (*_7);
83-
_0 = Option::<&mut u32>::Some(move _8);
84-
StorageDead(_8);
8541
goto -> bb3;
8642
}
8743

8844
bb3: {
8945
StorageDead(_4);
90-
StorageDead(_7);
9146
return;
9247
}
9348
}

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

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,13 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
1212
debug slice => _1;
1313
let mut _3: usize;
1414
let mut _4: bool;
15-
let mut _5: *mut [u32];
16-
let mut _7: *mut u32;
17-
let mut _8: &mut u32;
15+
let mut _5: &mut u32;
1816
scope 3 {
19-
scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) {
20-
debug self => _2;
21-
debug slice => _5;
22-
let mut _6: *mut u32;
23-
scope 5 {
24-
debug this => _2;
25-
scope 6 {
26-
scope 7 (inlined <usize as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) {
27-
debug this => _2;
28-
debug slice => _5;
29-
scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) {
30-
debug self => _5;
31-
let mut _9: *const [u32];
32-
scope 9 (inlined std::ptr::metadata::<[u32]>) {
33-
debug ptr => _9;
34-
scope 10 {
35-
}
36-
}
37-
}
38-
}
39-
scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) {
40-
debug self => _5;
41-
}
42-
scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) {
43-
debug self => _6;
44-
debug count => _2;
45-
scope 13 {
46-
}
47-
}
48-
}
49-
}
50-
}
5117
}
5218
}
5319
}
5420

5521
bb0: {
56-
StorageLive(_7);
5722
StorageLive(_4);
5823
StorageLive(_3);
5924
_3 = Len((*_1));
@@ -69,25 +34,15 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
6934

7035
bb2: {
7136
StorageDead(_3);
72-
StorageLive(_8);
7337
StorageLive(_5);
74-
_5 = &raw mut (*_1);
75-
StorageLive(_9);
76-
StorageLive(_6);
77-
_6 = _5 as *mut u32 (PtrToPtr);
78-
_7 = Offset(_6, _2);
79-
StorageDead(_6);
80-
StorageDead(_9);
38+
_5 = &mut (*_1)[_2];
39+
_0 = Option::<&mut u32>::Some(move _5);
8140
StorageDead(_5);
82-
_8 = &mut (*_7);
83-
_0 = Option::<&mut u32>::Some(move _8);
84-
StorageDead(_8);
8541
goto -> bb3;
8642
}
8743

8844
bb3: {
8945
StorageDead(_4);
90-
StorageDead(_7);
9146
return;
9247
}
9348
}

0 commit comments

Comments
 (0)