Skip to content

Commit 4b5844f

Browse files
committed
Document all unsafe blocks
There were several unsafe blocks in the existing implementation that were not documented with a SAFETY comment.
1 parent 1ec59cd commit 4b5844f

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

library/core/src/slice/sort.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,7 @@ where
940940
F: FnMut(&T, &T) -> bool,
941941
{
942942
if v.len() >= 2 && is_less(&v[1], &v[0]) {
943+
// SAFETY: Copy tmp back even if panic, and ensure unique observation.
943944
unsafe {
944945
// There are three ways to implement insertion here:
945946
//
@@ -992,6 +993,7 @@ where
992993

993994
impl<T> Drop for InsertionHole<T> {
994995
fn drop(&mut self) {
996+
// SAFETY: The caller must ensure that src and dest are correctly set.
995997
unsafe {
996998
ptr::copy_nonoverlapping(self.src, self.dest, 1);
997999
}
@@ -1012,6 +1014,8 @@ where
10121014
{
10131015
let len = v.len();
10141016
let v = v.as_mut_ptr();
1017+
1018+
// SAFETY: mid and len must be in-bounds of v.
10151019
let (v_mid, v_end) = unsafe { (v.add(mid), v.add(len)) };
10161020

10171021
// The merge process first copies the shorter run into `buf`. Then it traces the newly copied
@@ -1035,6 +1039,8 @@ where
10351039

10361040
if mid <= len - mid {
10371041
// The left run is shorter.
1042+
1043+
// SAFETY: buf must have enough capacity for `v[..mid]`.
10381044
unsafe {
10391045
ptr::copy_nonoverlapping(v, buf, mid);
10401046
hole = MergeHole { start: buf, end: buf.add(mid), dest: v };
@@ -1048,6 +1054,8 @@ where
10481054
while *left < hole.end && right < v_end {
10491055
// Consume the lesser side.
10501056
// If equal, prefer the left run to maintain stability.
1057+
1058+
// SAFETY: left and right must be valid and part of v same for out.
10511059
unsafe {
10521060
let to_copy = if is_less(&*right, &**left) {
10531061
get_and_increment(&mut right)
@@ -1059,6 +1067,8 @@ where
10591067
}
10601068
} else {
10611069
// The right run is shorter.
1070+
1071+
// SAFETY: buf must have enough capacity for `v[mid..]`.
10621072
unsafe {
10631073
ptr::copy_nonoverlapping(v_mid, buf, len - mid);
10641074
hole = MergeHole { start: buf, end: buf.add(len - mid), dest: v_mid };
@@ -1072,6 +1082,8 @@ where
10721082
while v < *left && buf < *right {
10731083
// Consume the greater side.
10741084
// If equal, prefer the right run to maintain stability.
1085+
1086+
// SAFETY: left and right must be valid and part of v same for out.
10751087
unsafe {
10761088
let to_copy = if is_less(&*right.sub(1), &*left.sub(1)) {
10771089
decrement_and_get(left)
@@ -1087,11 +1099,14 @@ where
10871099

10881100
unsafe fn get_and_increment<T>(ptr: &mut *mut T) -> *mut T {
10891101
let old = *ptr;
1102+
1103+
// SAFETY: ptr.add(1) must still be a valid pointer and part of `v`.
10901104
*ptr = unsafe { ptr.add(1) };
10911105
old
10921106
}
10931107

10941108
unsafe fn decrement_and_get<T>(ptr: &mut *mut T) -> *mut T {
1109+
// SAFETY: ptr.sub(1) must still be a valid pointer and part of `v`.
10951110
*ptr = unsafe { ptr.sub(1) };
10961111
*ptr
10971112
}
@@ -1105,7 +1120,7 @@ where
11051120

11061121
impl<T> Drop for MergeHole<T> {
11071122
fn drop(&mut self) {
1108-
// `T` is not a zero-sized type, and these are pointers into a slice's elements.
1123+
// SAFETY: `T` is not a zero-sized type, and these are pointers into a slice's elements.
11091124
unsafe {
11101125
let len = self.end.sub_ptr(self.start);
11111126
ptr::copy_nonoverlapping(self.start, self.dest, len);
@@ -1180,6 +1195,8 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
11801195
let mut start = end - 1;
11811196
if start > 0 {
11821197
start -= 1;
1198+
1199+
// SAFETY: The v.get_unchecked must be fed with correct inbound indicies.
11831200
unsafe {
11841201
if is_less(v.get_unchecked(start + 1), v.get_unchecked(start)) {
11851202
while start > 0 && is_less(v.get_unchecked(start), v.get_unchecked(start - 1)) {
@@ -1210,6 +1227,8 @@ pub fn merge_sort<T, CmpF, ElemAllocF, ElemDeallocF, RunAllocF, RunDeallocF>(
12101227
while let Some(r) = collapse(runs.as_slice()) {
12111228
let left = runs[r + 1];
12121229
let right = runs[r];
1230+
// SAFETY: `buf_ptr` must hold enough capacity for the shorter of the two sides, and
1231+
// neither side may be on length 0.
12131232
unsafe {
12141233
merge(&mut v[left.start..right.start + right.len], left.len, buf_ptr, is_less);
12151234
}

0 commit comments

Comments
 (0)