Auto merge of #123561 - saethlin:str-unchecked-sub-index, r=scottmcm

Use unchecked_sub in str indexing

https://github.com/rust-lang/rust/pull/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
This commit is contained in:
bors 2024-04-07 12:49:15 +00:00
commit 4e431fad67
2 changed files with 37 additions and 6 deletions

View file

@ -1,6 +1,7 @@
//! Trait implementations for `str`.
use crate::cmp::Ordering;
use crate::intrinsics::unchecked_sub;
use crate::ops;
use crate::ptr;
use crate::slice::SliceIndex;
@ -210,9 +211,10 @@ unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
// SAFETY: the caller guarantees that `self` is in bounds of `slice`
// which satisfies all the conditions for `add`.
let ptr = unsafe { slice.as_ptr().add(self.start) };
let len = self.end - self.start;
ptr::slice_from_raw_parts(ptr, len) as *const str
unsafe {
let new_len = unchecked_sub(self.end, self.start);
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len) as *const str
}
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
@ -229,9 +231,10 @@ unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
);
// SAFETY: see comments for `get_unchecked`.
let ptr = unsafe { slice.as_mut_ptr().add(self.start) };
let len = self.end - self.start;
ptr::slice_from_raw_parts_mut(ptr, len) as *mut str
unsafe {
let new_len = unchecked_sub(self.end, self.start);
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len) as *mut str
}
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {

View file

@ -32,3 +32,31 @@ pub unsafe fn get_unchecked_mut_by_range(x: &mut [i32], r: Range<usize>) -> &mut
// CHECK: sub nuw i64
x.get_unchecked_mut(r)
}
// CHECK-LABEL: @str_index_by_range(
#[no_mangle]
pub fn str_index_by_range(x: &str, r: Range<usize>) -> &str {
// CHECK: sub nuw i64
&x[r]
}
// CHECK-LABEL: @str_get_unchecked_by_range(
#[no_mangle]
pub unsafe fn str_get_unchecked_by_range(x: &str, r: Range<usize>) -> &str {
// CHECK: sub nuw i64
x.get_unchecked(r)
}
// CHECK-LABEL: @str_index_mut_by_range(
#[no_mangle]
pub fn str_index_mut_by_range(x: &mut str, r: Range<usize>) -> &mut str {
// CHECK: sub nuw i64
&mut x[r]
}
// CHECK-LABEL: @str_get_unchecked_mut_by_range(
#[no_mangle]
pub unsafe fn str_get_unchecked_mut_by_range(x: &mut str, r: Range<usize>) -> &mut str {
// CHECK: sub nuw i64
x.get_unchecked_mut(r)
}