@@ -20,6 +20,9 @@ struct CopyOnDrop<T> {
20
20
21
21
impl < T > Drop for CopyOnDrop < T > {
22
22
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`.
23
26
unsafe {
24
27
ptr:: copy_nonoverlapping ( self . src , self . dest , 1 ) ;
25
28
}
43
46
// 1. We are obtaining pointers to references which are guaranteed to be valid.
44
47
// 2. They cannot overlap because we obtain pointers to difference indices of the slice.
45
48
// 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.
47
51
//
48
52
// See comments below for further detail.
49
53
unsafe {
@@ -76,18 +80,19 @@ where
76
80
F : FnMut ( & T , & T ) -> bool ,
77
81
{
78
82
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`)
80
84
// and copying memory (`ptr::copy_nonoverlapping`).
81
85
//
82
86
// 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.
85
89
//
86
90
// b. Memory copying
87
91
// 1. We are obtaining pointers to references which are guaranteed to be valid.
88
92
// 2. They cannot overlap because we obtain pointers to difference indices of the slice.
89
93
// 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.
91
96
//
92
97
// See comments below for further detail.
93
98
unsafe {
@@ -131,8 +136,8 @@ where
131
136
let mut i = 1 ;
132
137
133
138
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`
136
141
unsafe {
137
142
// Find the next pair of adjacent out-of-order elements.
138
143
while i < len && !is_less ( v. get_unchecked ( i) , v. get_unchecked ( i - 1 ) ) {
@@ -299,6 +304,16 @@ where
299
304
let mut elem = l;
300
305
301
306
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.
302
317
unsafe {
303
318
// Branchless comparison.
304
319
* end_l = i as u8 ;
@@ -315,6 +330,17 @@ where
315
330
let mut elem = r;
316
331
317
332
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.
318
344
unsafe {
319
345
// Branchless comparison.
320
346
elem = elem. offset ( -1 ) ;
@@ -437,8 +463,9 @@ where
437
463
let mut r = v. len ( ) ;
438
464
439
465
// 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.
442
469
unsafe {
443
470
// Find the first element greater than or equal to the pivot.
444
471
while l < r && is_less ( v. get_unchecked ( l) , pivot) {
@@ -489,8 +516,9 @@ where
489
516
let mut r = v. len ( ) ;
490
517
loop {
491
518
// 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.
494
522
unsafe {
495
523
// Find the first element greater than the pivot.
496
524
while l < r && !is_less ( pivot, v. get_unchecked ( l) ) {
0 commit comments