diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-04-03 07:39:05 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-03 07:39:05 +0200 |
| commit | e332aa89a73f90259aafa69d57e74dc07ce4c466 (patch) | |
| tree | 1ec77d03747933716546035c7f8b1decd8c3acc8 /tests/codegen | |
| parent | dbd7f52c83edcf5710f08a063cbe1016b5f6d621 (diff) | |
| parent | 59ca7679c7db634465b5f021060f143567824ac4 (diff) | |
| download | rust-e332aa89a73f90259aafa69d57e74dc07ce4c466.tar.gz rust-e332aa89a73f90259aafa69d57e74dc07ce4c466.zip | |
Rollup merge of #139145 - okaneco:safe_splits, r=Amanieu
slice: Remove some uses of unsafe in first/last chunk methods
Remove unsafe `split_at_unchecked` and `split_at_mut_unchecked` in some slice `split_first_chunk`/`split_last_chunk` methods.
Replace those calls with the safe `split_at` and `split_at_checked` where applicable.
Add codegen tests to check for no panics when calculating the last chunk index using `checked_sub` and `split_at`.
Better viewed with whitespace disabled in diff view
---
The unchecked calls are mostly manual implementations of the safe methods, but with the safety condition negated from `mid <= len` to `len < mid`.
```rust
if self.len() < N {
None
} else {
// SAFETY: We manually verified the bounds of the split.
let (first, tail) = unsafe { self.split_at_unchecked(N) };
// Or for the last_chunk methods
let (init, last) = unsafe { self.split_at_unchecked(self.len() - N) };
```
Unsafe is still needed for the pointer array casts. Their safety comments are unmodified.
Diffstat (limited to 'tests/codegen')
| -rw-r--r-- | tests/codegen/slice-split-at.rs | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/tests/codegen/slice-split-at.rs b/tests/codegen/slice-split-at.rs new file mode 100644 index 00000000000..07018cf9c91 --- /dev/null +++ b/tests/codegen/slice-split-at.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -Copt-level=3 +#![crate_type = "lib"] + +// Check that no panic is generated in `split_at` when calculating the index for +// the tail chunk using `checked_sub`. +// +// Tests written for refactored implementations of: +// `<[T]>::{split_last_chunk, split_last_chunk_mut, last_chunk, last_chunk_mut}` + +// CHECK-LABEL: @split_at_last_chunk +#[no_mangle] +pub fn split_at_last_chunk(s: &[u8], chunk_size: usize) -> Option<(&[u8], &[u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at(index)) +} + +// CHECK-LABEL: @split_at_mut_last_chunk +#[no_mangle] +pub fn split_at_mut_last_chunk(s: &mut [u8], chunk_size: usize) -> Option<(&mut [u8], &mut [u8])> { + // CHECK-NOT: panic + let Some(index) = s.len().checked_sub(chunk_size) else { return None }; + Some(s.split_at_mut(index)) +} |
