Skip to content

Commit 5a9df84

Browse files
committed
Added some more documentations to unsafety blocks in slice/sort.rs
1 parent c710461 commit 5a9df84

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

src/libcore/slice/sort.rs

+39-11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ struct CopyOnDrop<T> {
2020

2121
impl<T> Drop for CopyOnDrop<T> {
2222
fn drop(&mut self) {
23+
// SAFETY: This is a helper class.
24+
// Please refer to its usage for correctness.
25+
// Namely, one must be sure that `src` and `dst` does not overlap as required by `ptr::copy_nonoverlapping`.
2326
unsafe {
2427
ptr::copy_nonoverlapping(self.src, self.dest, 1);
2528
}
@@ -43,7 +46,8 @@ where
4346
// 1. We are obtaining pointers to references which are guaranteed to be valid.
4447
// 2. They cannot overlap because we obtain pointers to difference indices of the slice.
4548
// Namely, `i` and `i-1`.
46-
// 3. FIXME: Guarantees that the elements are properly aligned?
49+
// 3. If the slice is properly aligned, the elements are properly aligned.
50+
// It is the caller's responsibility to make sure the slice is properly aligned.
4751
//
4852
// See comments below for further detail.
4953
unsafe {
@@ -76,18 +80,19 @@ where
7680
F: FnMut(&T, &T) -> bool,
7781
{
7882
let len = v.len();
79-
// SAFETY: As with shift_head, the unsafe operations below involves indexing without a bound check (`get_unchecked` and `get_unchecked_mut`)
83+
// SAFETY: The unsafe operations below involves indexing without a bound check (`get_unchecked` and `get_unchecked_mut`)
8084
// and copying memory (`ptr::copy_nonoverlapping`).
8185
//
8286
// a. Indexing:
83-
// 1. We checked the size of the array to >=2.
84-
// 2. All the indexing that we will do is always between {0 <= index < len-1} at most.
87+
// 1. We checked the size of the array to >= 2.
88+
// 2. All the indexing that we will do is always between `0 <= index < len-1` at most.
8589
//
8690
// b. Memory copying
8791
// 1. We are obtaining pointers to references which are guaranteed to be valid.
8892
// 2. They cannot overlap because we obtain pointers to difference indices of the slice.
8993
// Namely, `i` and `i+1`.
90-
// 3. FIXME: Guarantees that the elements are properly aligned?
94+
// 3. If the slice is properly aligned, the elements are properly aligned.
95+
// It is the caller's responsibility to make sure the slice is properly aligned.
9196
//
9297
// See comments below for further detail.
9398
unsafe {
@@ -131,8 +136,8 @@ where
131136
let mut i = 1;
132137

133138
for _ in 0..MAX_STEPS {
134-
// SAFETY: We already explicitly done the bound checking with `i<len`
135-
// All our indexing following that is only in the range {0 <= index < len}
139+
// SAFETY: We already explicitly did the bound checking with `i < len`.
140+
// All our subsequent indexing is only in the range `0 <= index < len`
136141
unsafe {
137142
// Find the next pair of adjacent out-of-order elements.
138143
while i < len && !is_less(v.get_unchecked(i), v.get_unchecked(i - 1)) {
@@ -299,6 +304,16 @@ where
299304
let mut elem = l;
300305

301306
for i in 0..block_l {
307+
// SAFETY: The unsafety operations below involve the usage of the `offset`.
308+
// According to the conditions required by the function, we satisfy them because:
309+
// 1. `offsets_l` is stack-allocated, and thus considered separate allocated object.
310+
// 2. The function `is_less` returns a `bool`.
311+
// Casting a `bool` will never overflow `isize`.
312+
// 3. We have guaranteed that `block_l` will be `<= BLOCK`.
313+
// Plus, `end_l` was initially set to the begin pointer of `offsets_` which was declared on the stack.
314+
// Thus, we know that even in the worst case (all invocations of `is_less` returns false) we will only be at most 1 byte pass the end.
315+
// Another unsafety operation here is dereferencing `elem`.
316+
// However, `elem` was initially the begin pointer to the slice which is always valid.
302317
unsafe {
303318
// Branchless comparison.
304319
*end_l = i as u8;
@@ -315,6 +330,17 @@ where
315330
let mut elem = r;
316331

317332
for i in 0..block_r {
333+
// SAFETY: The unsafety operations below involve the usage of the `offset`.
334+
// According to the conditions required by the function, we satisfy them because:
335+
// 1. `offsets_r` is stack-allocated, and thus considered separate allocated object.
336+
// 2. The function `is_less` returns a `bool`.
337+
// Casting a `bool` will never overflow `isize`.
338+
// 3. We have guaranteed that `block_r` will be `<= BLOCK`.
339+
// Plus, `end_r` was initially set to the begin pointer of `offsets_` which was declared on the stack.
340+
// Thus, we know that even in the worst case (all invocations of `is_less` returns true) we will only be at most 1 byte pass the end.
341+
// Another unsafety operation here is dereferencing `elem`.
342+
// However, `elem` was initially `1 * sizeof(T)` past the end and we decrement it by `1 * sizeof(T)` before accessing it.
343+
// Plus, `block_r` was asserted to be less than `BLOCK` and `elem` will therefore at most be pointing to the beginning of the slice.
318344
unsafe {
319345
// Branchless comparison.
320346
elem = elem.offset(-1);
@@ -437,8 +463,9 @@ where
437463
let mut r = v.len();
438464

439465
// SAFETY: The unsafety below involves indexing an array.
440-
// For the first one: we already do the bound checking here with `l<r`.
441-
// For the secondn one: the minimum value for `l` is 0 and the maximum value for `r` is `v.len().`
466+
// For the first one: We already do the bounds checking here with `l < r`.
467+
// For the second one: We initially have `l == 0` and `r == v.len()` and we checked that `l < r` at every indexing operation.
468+
// From here we know that `r` must be at least `r == l` which was shown to be valid from the first one.
442469
unsafe {
443470
// Find the first element greater than or equal to the pivot.
444471
while l < r && is_less(v.get_unchecked(l), pivot) {
@@ -489,8 +516,9 @@ where
489516
let mut r = v.len();
490517
loop {
491518
// SAFETY: The unsafety below involves indexing an array.
492-
// For the first one: we already do the bound checking here with `l<r`.
493-
// For the second one: the minimum value for `l` is 0 and the maximum value for `r` is `v.len().`
519+
// For the first one: We already do the bounds checking here with `l < r`.
520+
// For the second one: We initially have `l == 0` and `r == v.len()` and we checked that `l < r` at every indexing operation.
521+
// From here we know that `r` must be at least `r == l` which was shown to be valid from the first one.
494522
unsafe {
495523
// Find the first element greater than the pivot.
496524
while l < r && !is_less(pivot, v.get_unchecked(l)) {

0 commit comments

Comments
 (0)