diff options
| author | bors <bors@rust-lang.org> | 2024-04-07 12:49:15 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-04-07 12:49:15 +0000 |
| commit | 4e431fad67b46c480f1833119cd368fa33df95f7 (patch) | |
| tree | 9d793a570f5ce2b0c6aedd34c2d5aeaac4df2a16 | |
| parent | fc1a4c5cc9308c4b5980c64a73fd344a59c10601 (diff) | |
| parent | 712aab72df2a9c511e49a51974294d3d2712056e (diff) | |
| download | rust-4e431fad67b46c480f1833119cd368fa33df95f7.tar.gz rust-4e431fad67b46c480f1833119cd368fa33df95f7.zip | |
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
| -rw-r--r-- | library/core/src/str/traits.rs | 15 | ||||
| -rw-r--r-- | tests/codegen/slice-indexing.rs | 28 |
2 files changed, 37 insertions, 6 deletions
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 672af752149..ba2d6f64496 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -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 impl SliceIndex<str> for ops::Range<usize> { // 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 impl SliceIndex<str> for ops::Range<usize> { ); // 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 { diff --git a/tests/codegen/slice-indexing.rs b/tests/codegen/slice-indexing.rs index ecce9201071..3d284148db2 100644 --- a/tests/codegen/slice-indexing.rs +++ b/tests/codegen/slice-indexing.rs @@ -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) +} |
