@@ -512,15 +512,15 @@ impl<T> [T] {
512512 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
513513 #[ inline]
514514 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] ;
515519 // SAFETY: `pa` and `pb` have been created from safe mutable references and refer
516520 // to elements in the slice and therefore are guaranteed to be valid and aligned.
517521 // Note that accessing the elements behind `a` and `b` is checked and will
518522 // panic when out of bounds.
519523 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] ;
524524 ptr:: swap ( pa, pb) ;
525525 }
526526 }
@@ -559,15 +559,21 @@ impl<T> [T] {
559559 // Use the llvm.bswap intrinsic to reverse u8s in a usize
560560 let chunk = mem:: size_of :: < usize > ( ) ;
561561 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+ //
565566 // `i + chunk - 1 < ln / 2` # while condition
566567 // `i + 2 - 1 < ln / 2`
567568 // `i + 1 < ln / 2`
569+ //
568570 // Since it's less than the length divided by 2, then it must be
569571 // in bounds.
570572 //
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+ //
571577 // Note: when updating this comment, update the others in the
572578 // function too.
573579 unsafe {
@@ -589,12 +595,18 @@ impl<T> [T] {
589595 // SAFETY: An unaligned u32 can be read from `i` if `i + 1 < ln`
590596 // (and obviously `i < ln`), because each element is 2 bytes and
591597 // we're reading 4.
598+ //
592599 // `i + chunk - 1 < ln / 2` # while condition
593600 // `i + 2 - 1 < ln / 2`
594601 // `i + 1 < ln / 2`
602+ //
595603 // Since it's less than the length divided by 2, then it must be
596604 // in bounds.
597605 //
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+ //
598610 // Note: when updating this comment, update the others in the
599611 // function too.
600612 unsafe {
@@ -641,11 +653,23 @@ impl<T> [T] {
641653 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
642654 #[ inline]
643655 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.
647672 unsafe {
648- let ptr = self . as_ptr ( ) ;
649673 assume ( !ptr. is_null ( ) ) ;
650674
651675 let end = if mem:: size_of :: < T > ( ) == 0 {
@@ -672,11 +696,23 @@ impl<T> [T] {
672696 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
673697 #[ inline]
674698 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.
678715 unsafe {
679- let ptr = self . as_mut_ptr ( ) ;
680716 assume ( !ptr. is_null ( ) ) ;
681717
682718 let end = if mem:: size_of :: < T > ( ) == 0 {
@@ -2170,6 +2206,11 @@ impl<T> [T] {
21702206 //
21712207 // `next_write` is also incremented at most once per loop at most meaning
21722208 // 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.
21732214 unsafe {
21742215 // Avoid bounds checks by using raw pointers.
21752216 while next_read < len {
@@ -2253,11 +2294,11 @@ impl<T> [T] {
22532294 pub fn rotate_left ( & mut self , mid : usize ) {
22542295 assert ! ( mid <= self . len( ) ) ;
22552296 let k = self . len ( ) - mid;
2297+ let p = self . as_mut_ptr ( ) ;
22562298
2257- // SAFETY: `[mid - mid; mid+k]` corresponds to the entire
2299+ // SAFETY: `[mid; mid+k]` corresponds to the entire
22582300 // `self` slice, thus is valid for reads and writes.
22592301 unsafe {
2260- let p = self . as_mut_ptr ( ) ;
22612302 rotate:: ptr_rotate ( mid, p. add ( mid) , k) ;
22622303 }
22632304 }
@@ -2296,11 +2337,11 @@ impl<T> [T] {
22962337 pub fn rotate_right ( & mut self , k : usize ) {
22972338 assert ! ( k <= self . len( ) ) ;
22982339 let mid = self . len ( ) - k;
2340+ let p = self . as_mut_ptr ( ) ;
22992341
2300- // SAFETY: `[mid - mid; mid+k]` corresponds to the entire
2342+ // SAFETY: `[mid; mid+k]` corresponds to the entire
23012343 // `self` slice, thus is valid for reads and writes.
23022344 unsafe {
2303- let p = self . as_mut_ptr ( ) ;
23042345 rotate:: ptr_rotate ( mid, p. add ( mid) , k) ;
23052346 }
23062347 }
@@ -2517,7 +2558,8 @@ impl<T> [T] {
25172558 assert ! ( src_end <= self . len( ) , "src is out of bounds" ) ;
25182559 let count = src_end - src_start;
25192560 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`.
25212563 unsafe {
25222564 ptr:: copy ( self . as_ptr ( ) . add ( src_start) , self . as_mut_ptr ( ) . add ( dest) , count) ;
25232565 }
0 commit comments