Skip to content

Commit 4e431fa

Browse files
committed
Auto merge of #123561 - saethlin:str-unchecked-sub-index, r=scottmcm
Use unchecked_sub in str indexing #108763 applied this logic to indexing for slices, but of course `str` has its own separate impl. Found this by skimming over the codegen for https://github.com/oxidecomputer/hubris/; their dist builds enable overflow checks so the lack of `unchecked_sub` was producing an impossible-to-hit overflow check and also inhibiting some inlining. r? scottmcm
2 parents fc1a4c5 + 712aab7 commit 4e431fa

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

library/core/src/str/traits.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Trait implementations for `str`.
22
33
use crate::cmp::Ordering;
4+
use crate::intrinsics::unchecked_sub;
45
use crate::ops;
56
use crate::ptr;
67
use crate::slice::SliceIndex;
@@ -210,9 +211,10 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
210211

211212
// SAFETY: the caller guarantees that `self` is in bounds of `slice`
212213
// which satisfies all the conditions for `add`.
213-
let ptr = unsafe { slice.as_ptr().add(self.start) };
214-
let len = self.end - self.start;
215-
ptr::slice_from_raw_parts(ptr, len) as *const str
214+
unsafe {
215+
let new_len = unchecked_sub(self.end, self.start);
216+
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
217+
}
216218
}
217219
#[inline]
218220
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
@@ -229,9 +231,10 @@ unsafe impl SliceIndex<str> for ops::Range<usize> {
229231
);
230232

231233
// SAFETY: see comments for `get_unchecked`.
232-
let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
233-
let len = self.end - self.start;
234-
ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
234+
unsafe {
235+
let new_len = unchecked_sub(self.end, self.start);
236+
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
237+
}
235238
}
236239
#[inline]
237240
fn index(self, slice: &str) -> &Self::Output {

tests/codegen/slice-indexing.rs

+28
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,31 @@ pub unsafe fn get_unchecked_mut_by_range(x: &mut [i32], r: Range<usize>) -> &mut
3232
// CHECK: sub nuw i64
3333
x.get_unchecked_mut(r)
3434
}
35+
36+
// CHECK-LABEL: @str_index_by_range(
37+
#[no_mangle]
38+
pub fn str_index_by_range(x: &str, r: Range<usize>) -> &str {
39+
// CHECK: sub nuw i64
40+
&x[r]
41+
}
42+
43+
// CHECK-LABEL: @str_get_unchecked_by_range(
44+
#[no_mangle]
45+
pub unsafe fn str_get_unchecked_by_range(x: &str, r: Range<usize>) -> &str {
46+
// CHECK: sub nuw i64
47+
x.get_unchecked(r)
48+
}
49+
50+
// CHECK-LABEL: @str_index_mut_by_range(
51+
#[no_mangle]
52+
pub fn str_index_mut_by_range(x: &mut str, r: Range<usize>) -> &mut str {
53+
// CHECK: sub nuw i64
54+
&mut x[r]
55+
}
56+
57+
// CHECK-LABEL: @str_get_unchecked_mut_by_range(
58+
#[no_mangle]
59+
pub unsafe fn str_get_unchecked_mut_by_range(x: &mut str, r: Range<usize>) -> &mut str {
60+
// CHECK: sub nuw i64
61+
x.get_unchecked_mut(r)
62+
}

0 commit comments

Comments
 (0)