Skip to content

Commit dc2c974

Browse files
Rollup merge of rust-lang#88291 - mdsn:partition-in-blocks-safety, r=Mark-Simulacrum
Add SAFETY comments to core::slice::sort::partition_in_blocks A few more SAFETY comments for rust-lang#66219. There are still a few more in this module. `@rustbot` label T-libs T-compiler C-cleanup
2 parents e6d922b + 09e02a8 commit dc2c974

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

library/core/src/slice/sort.rs

+26
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,22 @@ where
369369
// Instead of swapping one pair at the time, it is more efficient to perform a cyclic
370370
// permutation. This is not strictly equivalent to swapping, but produces a similar
371371
// result using fewer memory operations.
372+
373+
// SAFETY: The use of `ptr::read` is valid because there is at least one element in
374+
// both `offsets_l` and `offsets_r`, so `left!` is a valid pointer to read from.
375+
//
376+
// The uses of `left!` involve calls to `offset` on `l`, which points to the
377+
// beginning of `v`. All the offsets pointed-to by `start_l` are at most `block_l`, so
378+
// these `offset` calls are safe as all reads are within the block. The same argument
379+
// applies for the uses of `right!`.
380+
//
381+
// The calls to `start_l.offset` are valid because there are at most `count-1` of them,
382+
// plus the final one at the end of the unsafe block, where `count` is the minimum number
383+
// of collected offsets in `offsets_l` and `offsets_r`, so there is no risk of there not
384+
// being enough elements. The same reasoning applies to the calls to `start_r.offset`.
385+
//
386+
// The calls to `copy_nonoverlapping` are safe because `left!` and `right!` are guaranteed
387+
// not to overlap, and are valid because of the reasoning above.
372388
unsafe {
373389
let tmp = ptr::read(left!());
374390
ptr::copy_nonoverlapping(right!(), left!(), 1);
@@ -389,11 +405,21 @@ where
389405

390406
if start_l == end_l {
391407
// All out-of-order elements in the left block were moved. Move to the next block.
408+
409+
// block-width-guarantee
410+
// SAFETY: if `!is_done` then the slice width is guaranteed to be at least `2*BLOCK` wide. There
411+
// are at most `BLOCK` elements in `offsets_l` because of its size, so the `offset` operation is
412+
// safe. Otherwise, the debug assertions in the `is_done` case guarantee that
413+
// `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account
414+
// for the smaller number of remaining elements.
392415
l = unsafe { l.offset(block_l as isize) };
393416
}
394417

395418
if start_r == end_r {
396419
// All out-of-order elements in the right block were moved. Move to the previous block.
420+
421+
// SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide,
422+
// or `block_r` has been adjusted for the last handful of elements.
397423
r = unsafe { r.offset(-(block_r as isize)) };
398424
}
399425

0 commit comments

Comments
 (0)