@@ -512,15 +512,15 @@ impl<T> [T] {
512
512
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
513
513
#[ inline]
514
514
pub fn swap ( & mut self , a : usize , b : usize ) {
515
+ // Can't take two mutable loans from one vector, so instead just cast
516
+ // them to their raw pointers to do the swap.
517
+ let pa: * mut T = & mut self [ a] ;
518
+ let pb: * mut T = & mut self [ b] ;
515
519
// SAFETY: `pa` and `pb` have been created from safe mutable references and refer
516
520
// to elements in the slice and therefore are guaranteed to be valid and aligned.
517
521
// Note that accessing the elements behind `a` and `b` is checked and will
518
522
// panic when out of bounds.
519
523
unsafe {
520
- // Can't take two mutable loans from one vector, so instead just cast
521
- // them to their raw pointers to do the swap
522
- let pa: * mut T = & mut self [ a] ;
523
- let pb: * mut T = & mut self [ b] ;
524
524
ptr:: swap ( pa, pb) ;
525
525
}
526
526
}
@@ -559,15 +559,21 @@ impl<T> [T] {
559
559
// Use the llvm.bswap intrinsic to reverse u8s in a usize
560
560
let chunk = mem:: size_of :: < usize > ( ) ;
561
561
while i + chunk - 1 < ln / 2 {
562
- // SAFETY: An unaligned u32 can be read from `i` if `i + 1 < ln`
563
- // (and obviously `i < ln`), because each element is 2 bytes and
564
- // we're reading 4.
562
+ // SAFETY: An unaligned usize can be read from `i` if `i + 1 < ln`
563
+ // (and obviously `i < ln`), because each element is 1 byte and
564
+ // we're reading 2.
565
+ //
565
566
// `i + chunk - 1 < ln / 2` # while condition
566
567
// `i + 2 - 1 < ln / 2`
567
568
// `i + 1 < ln / 2`
569
+ //
568
570
// Since it's less than the length divided by 2, then it must be
569
571
// in bounds.
570
572
//
573
+ // This also means that the condition `0 < i + chunk <= ln` is
574
+ // always respected, ensuring the `pb` pointer can be used
575
+ // safely.
576
+ //
571
577
// Note: when updating this comment, update the others in the
572
578
// function too.
573
579
unsafe {
@@ -589,12 +595,18 @@ impl<T> [T] {
589
595
// SAFETY: An unaligned u32 can be read from `i` if `i + 1 < ln`
590
596
// (and obviously `i < ln`), because each element is 2 bytes and
591
597
// we're reading 4.
598
+ //
592
599
// `i + chunk - 1 < ln / 2` # while condition
593
600
// `i + 2 - 1 < ln / 2`
594
601
// `i + 1 < ln / 2`
602
+ //
595
603
// Since it's less than the length divided by 2, then it must be
596
604
// in bounds.
597
605
//
606
+ // This also means that the condition `0 < i + chunk <= ln` is
607
+ // always respected, ensuring the `pb` pointer can be used
608
+ // safely.
609
+ //
598
610
// Note: when updating this comment, update the others in the
599
611
// function too.
600
612
unsafe {
@@ -641,11 +653,23 @@ impl<T> [T] {
641
653
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
642
654
#[ inline]
643
655
pub fn iter ( & self ) -> Iter < ' _ , T > {
644
- // SAFETY: adding `self.len()` to the starting pointer gives a pointer
645
- // at the end of `self`, which fulfills the expectations of `ptr.add()`
646
- // and `NonNull::new_unchecked()`.
656
+ let ptr = self . as_ptr ( ) ;
657
+ // SAFETY: There are several things here:
658
+ //
659
+ // `ptr` has been checked for nullity before being passed to `NonNull` via
660
+ // `new_unchecked`.
661
+ //
662
+ // Adding `self.len()` to the starting pointer gives a pointer
663
+ // at the end of `self`. `end` will never be dereferenced, only checked
664
+ // for direct pointer equality with `ptr` to check if the iterator is
665
+ // done.
666
+ //
667
+ // In the case of a ZST, the end pointer is just the start pointer plus
668
+ // the length, to also allows for the fast `ptr == end` check.
669
+ //
670
+ // See the `next_unchecked!` and `is_empty!` macros as well as the
671
+ // `post_inc_start` method for more informations.
647
672
unsafe {
648
- let ptr = self . as_ptr ( ) ;
649
673
assume ( !ptr. is_null ( ) ) ;
650
674
651
675
let end = if mem:: size_of :: < T > ( ) == 0 {
@@ -672,11 +696,23 @@ impl<T> [T] {
672
696
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
673
697
#[ inline]
674
698
pub fn iter_mut ( & mut self ) -> IterMut < ' _ , T > {
675
- // SAFETY: adding `self.len()` to the starting pointer gives a pointer
676
- // at the end of `self`, which fulfills the expectations of `ptr.add()`
677
- // and `NonNull::new_unchecked()`.
699
+ let ptr = self . as_mut_ptr ( ) ;
700
+ // SAFETY: There are several things here:
701
+ //
702
+ // `ptr` has been checked for nullity before being passed to `NonNull` via
703
+ // `new_unchecked`.
704
+ //
705
+ // Adding `self.len()` to the starting pointer gives a pointer
706
+ // at the end of `self`. `end` will never be dereferenced, only checked
707
+ // for direct pointer equality with `ptr` to check if the iterator is
708
+ // done.
709
+ //
710
+ // In the case of a ZST, the end pointer is just the start pointer plus
711
+ // the length, to also allows for the fast `ptr == end` check.
712
+ //
713
+ // See the `next_unchecked!` and `is_empty!` macros as well as the
714
+ // `post_inc_start` method for more informations.
678
715
unsafe {
679
- let ptr = self . as_mut_ptr ( ) ;
680
716
assume ( !ptr. is_null ( ) ) ;
681
717
682
718
let end = if mem:: size_of :: < T > ( ) == 0 {
@@ -2170,6 +2206,11 @@ impl<T> [T] {
2170
2206
//
2171
2207
// `next_write` is also incremented at most once per loop at most meaning
2172
2208
// no element is skipped when it may need to be swapped.
2209
+ //
2210
+ // `ptr_read` and `prev_ptr_write` never point to the same element. This
2211
+ // is required for `&mut *ptr_read`, `&mut *prev_ptr_write` to be safe.
2212
+ // The explanation is simply that `next_read >= next_write` is always true,
2213
+ // thus `next_read > next_write - 1` is too.
2173
2214
unsafe {
2174
2215
// Avoid bounds checks by using raw pointers.
2175
2216
while next_read < len {
@@ -2253,11 +2294,11 @@ impl<T> [T] {
2253
2294
pub fn rotate_left ( & mut self , mid : usize ) {
2254
2295
assert ! ( mid <= self . len( ) ) ;
2255
2296
let k = self . len ( ) - mid;
2297
+ let p = self . as_mut_ptr ( ) ;
2256
2298
2257
- // SAFETY: `[mid - mid; mid+k]` corresponds to the entire
2299
+ // SAFETY: `[mid; mid+k]` corresponds to the entire
2258
2300
// `self` slice, thus is valid for reads and writes.
2259
2301
unsafe {
2260
- let p = self . as_mut_ptr ( ) ;
2261
2302
rotate:: ptr_rotate ( mid, p. add ( mid) , k) ;
2262
2303
}
2263
2304
}
@@ -2296,11 +2337,11 @@ impl<T> [T] {
2296
2337
pub fn rotate_right ( & mut self , k : usize ) {
2297
2338
assert ! ( k <= self . len( ) ) ;
2298
2339
let mid = self . len ( ) - k;
2340
+ let p = self . as_mut_ptr ( ) ;
2299
2341
2300
- // SAFETY: `[mid - mid; mid+k]` corresponds to the entire
2342
+ // SAFETY: `[mid; mid+k]` corresponds to the entire
2301
2343
// `self` slice, thus is valid for reads and writes.
2302
2344
unsafe {
2303
- let p = self . as_mut_ptr ( ) ;
2304
2345
rotate:: ptr_rotate ( mid, p. add ( mid) , k) ;
2305
2346
}
2306
2347
}
@@ -2517,7 +2558,8 @@ impl<T> [T] {
2517
2558
assert ! ( src_end <= self . len( ) , "src is out of bounds" ) ;
2518
2559
let count = src_end - src_start;
2519
2560
assert ! ( dest <= self . len( ) - count, "dest is out of bounds" ) ;
2520
- // SAFETY: the conditions for `ptr::copy` have all been checked above.
2561
+ // SAFETY: the conditions for `ptr::copy` have all been checked above,
2562
+ // as have those for `ptr::add`.
2521
2563
unsafe {
2522
2564
ptr:: copy ( self . as_ptr ( ) . add ( src_start) , self . as_mut_ptr ( ) . add ( dest) , count) ;
2523
2565
}
0 commit comments