11// ignore-tidy-filelength
2- // ignore-tidy-undocumented-unsafe
32
43//! Slice management and manipulation.
54//!
@@ -70,6 +69,8 @@ impl<T> [T] {
7069 #[ allow( unused_attributes) ]
7170 #[ allow_internal_unstable( const_fn_union) ]
7271 pub const fn len ( & self ) -> usize {
72+ // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
73+ // Only `std` can make this guarantee.
7374 unsafe { crate :: ptr:: Repr { rust : self } . raw . len }
7475 }
7576
@@ -437,7 +438,8 @@ impl<T> [T] {
437438 #[ unstable( feature = "slice_ptr_range" , issue = "65807" ) ]
438439 #[ inline]
439440 pub fn as_ptr_range ( & self ) -> Range < * const T > {
440- // The `add` here is safe, because:
441+ let start = self . as_ptr ( ) ;
442+ // SAFETY: The `add` here is safe, because:
441443 //
442444 // - Both pointers are part of the same object, as pointing directly
443445 // past the object also counts.
@@ -454,7 +456,6 @@ impl<T> [T] {
454456 // the end of the address space.
455457 //
456458 // See the documentation of pointer::add.
457- let start = self . as_ptr ( ) ;
458459 let end = unsafe { start. add ( self . len ( ) ) } ;
459460 start..end
460461 }
@@ -478,8 +479,8 @@ impl<T> [T] {
478479 #[ unstable( feature = "slice_ptr_range" , issue = "65807" ) ]
479480 #[ inline]
480481 pub fn as_mut_ptr_range ( & mut self ) -> Range < * mut T > {
481- // See as_ptr_range() above for why `add` here is safe.
482482 let start = self . as_mut_ptr ( ) ;
483+ // SAFETY: See as_ptr_range() above for why `add` here is safe.
483484 let end = unsafe { start. add ( self . len ( ) ) } ;
484485 start..end
485486 }
@@ -505,6 +506,8 @@ impl<T> [T] {
505506 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
506507 #[ inline]
507508 pub fn swap ( & mut self , a : usize , b : usize ) {
509+ // SAFETY: `pa` and `pb` have been created from safe mutable references and refer
510+ // to elements in the slice and therefore are guaranteed to be valid and aligned.
508511 unsafe {
509512 // Can't take two mutable loans from one vector, so instead just cast
510513 // them to their raw pointers to do the swap
@@ -548,6 +551,10 @@ impl<T> [T] {
548551 // Use the llvm.bswap intrinsic to reverse u8s in a usize
549552 let chunk = mem:: size_of :: < usize > ( ) ;
550553 while i + chunk - 1 < ln / 2 {
554+ // SAFETY: the condition of the `while` guarantees that
555+ // `i` and `ln - i - chunk` are inside the slice.
556+ // The resulting pointers `pa` and `pb` are therefore valid,
557+ // and can be read from and written to.
551558 unsafe {
552559 let pa: * mut T = self . get_unchecked_mut ( i) ;
553560 let pb: * mut T = self . get_unchecked_mut ( ln - i - chunk) ;
@@ -564,6 +571,10 @@ impl<T> [T] {
564571 // Use rotate-by-16 to reverse u16s in a u32
565572 let chunk = mem:: size_of :: < u32 > ( ) / 2 ;
566573 while i + chunk - 1 < ln / 2 {
574+ // SAFETY: the condition of the `while` guarantees that
575+ // `i` and `ln - i - chunk` are inside the slice.
576+ // The resulting pointers `pa` and `pb` are therefore valid,
577+ // and can be read from and written to.
567578 unsafe {
568579 let pa: * mut T = self . get_unchecked_mut ( i) ;
569580 let pb: * mut T = self . get_unchecked_mut ( ln - i - chunk) ;
@@ -577,8 +588,12 @@ impl<T> [T] {
577588 }
578589
579590 while i < ln / 2 {
580- // Unsafe swap to avoid the bounds check in safe swap.
591+ // SAFETY: the condition of the `while` guarantees that `i` and `ln - i - 1`
592+ // are inside the slice and refer to an element inside the slice.
593+ // The resulting pointers `pa` and `pb` are therefore valid and aligned,
594+ // and can be read from and written to.
581595 unsafe {
596+ // Unsafe swap to avoid the bounds check in safe swap.
582597 let pa: * mut T = self . get_unchecked_mut ( i) ;
583598 let pb: * mut T = self . get_unchecked_mut ( ln - i - 1 ) ;
584599 ptr:: swap ( pa, pb) ;
@@ -603,6 +618,9 @@ impl<T> [T] {
603618 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
604619 #[ inline]
605620 pub fn iter ( & self ) -> Iter < ' _ , T > {
621+ // SAFETY: adding `self.len()` to the starting pointer gives a pointer
622+ // at the end of `self`, which fulfills the expectations of `ptr.add()`
623+ // and `NonNull::new_unchecked()`.
606624 unsafe {
607625 let ptr = self . as_ptr ( ) ;
608626 assume ( !ptr. is_null ( ) ) ;
@@ -631,6 +649,9 @@ impl<T> [T] {
631649 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
632650 #[ inline]
633651 pub fn iter_mut ( & mut self ) -> IterMut < ' _ , T > {
652+ // SAFETY: adding `self.len()` to the starting pointer gives a pointer
653+ // at the end of `self`, which fulfills the expectations of `ptr.add()`
654+ // and `NonNull::new_unchecked()`.
634655 unsafe {
635656 let ptr = self . as_mut_ptr ( ) ;
636657 assume ( !ptr. is_null ( ) ) ;
@@ -1062,6 +1083,8 @@ impl<T> [T] {
10621083 let len = self . len ( ) ;
10631084 let ptr = self . as_mut_ptr ( ) ;
10641085
1086+ // SAFETY: `[ptr;mid]` and `[mid;len]` are inside `self`, which fulfills the
1087+ // requirements of `from_raw_parts_mut`.
10651088 unsafe {
10661089 assert ! ( mid <= len) ;
10671090
@@ -1548,14 +1571,14 @@ impl<T> [T] {
15481571 while size > 1 {
15491572 let half = size / 2 ;
15501573 let mid = base + half;
1551- // mid is always in [0, size), that means mid is >= 0 and < size.
1574+ // SAFETY: mid is always in [0, size), that means mid is >= 0 and < size.
15521575 // mid >= 0: by definition
15531576 // mid < size: mid = size / 2 + size / 4 + size / 8 ...
15541577 let cmp = f ( unsafe { s. get_unchecked ( mid) } ) ;
15551578 base = if cmp == Greater { base } else { mid } ;
15561579 size -= half;
15571580 }
1558- // base is always in [0, size) because base <= mid.
1581+ // SAFETY: base is always in [0, size) because base <= mid.
15591582 let cmp = f ( unsafe { s. get_unchecked ( base) } ) ;
15601583 if cmp == Equal { Ok ( base) } else { Err ( base + ( cmp == Less ) as usize ) }
15611584 }
@@ -2013,6 +2036,13 @@ impl<T> [T] {
20132036 let mut next_read: usize = 1 ;
20142037 let mut next_write: usize = 1 ;
20152038
2039+ // SAFETY: the `while` condition guarantees `next_read` and `next_write`
2040+ // are less than `len`, thus are inside `self`. `prev_ptr_write` points to
2041+ // one element before `ptr_write`, but `next_write` starts at 1, so
2042+ // `prev_ptr_write` is never less than 0 and is inside the slice.
2043+ // This fulfils the requirements for dereferencing `ptr_read`, `prev_ptr_write`
2044+ // and `ptr_write`, and for using `ptr.add(next_read)`, `ptr.add(next_write - 1)`
2045+ // and `prev_ptr_write.offset(1)`.
20162046 unsafe {
20172047 // Avoid bounds checks by using raw pointers.
20182048 while next_read < len {
@@ -2097,6 +2127,8 @@ impl<T> [T] {
20972127 assert ! ( mid <= self . len( ) ) ;
20982128 let k = self . len ( ) - mid;
20992129
2130+ // SAFETY: `[mid - mid;mid+k]` corresponds to the entire
2131+ // `self` slice, thus is valid for reads and writes.
21002132 unsafe {
21012133 let p = self . as_mut_ptr ( ) ;
21022134 rotate:: ptr_rotate ( mid, p. add ( mid) , k) ;
@@ -2138,6 +2170,8 @@ impl<T> [T] {
21382170 assert ! ( k <= self . len( ) ) ;
21392171 let mid = self . len ( ) - k;
21402172
2173+ // SAFETY: `[mid - mid;mid+k]` corresponds to the entire
2174+ // `self` slice, thus is valid for reads and writes.
21412175 unsafe {
21422176 let p = self . as_mut_ptr ( ) ;
21432177 rotate:: ptr_rotate ( mid, p. add ( mid) , k) ;
@@ -2300,6 +2334,9 @@ impl<T> [T] {
23002334 T : Copy ,
23012335 {
23022336 assert_eq ! ( self . len( ) , src. len( ) , "destination and source slices have different lengths" ) ;
2337+ // SAFETY: `self` is valid for `self.len()` bytes by definition, and `src` was
2338+ // checked to have the same length. Both slices cannot be overlapping because
2339+ // Rust's mutable references are exclusive.
23032340 unsafe {
23042341 ptr:: copy_nonoverlapping ( src. as_ptr ( ) , self . as_mut_ptr ( ) , self . len ( ) ) ;
23052342 }
@@ -2353,6 +2390,7 @@ impl<T> [T] {
23532390 assert ! ( src_end <= self . len( ) , "src is out of bounds" ) ;
23542391 let count = src_end - src_start;
23552392 assert ! ( dest <= self . len( ) - count, "dest is out of bounds" ) ;
2393+ // SAFETY: the conditions for `ptr::copy` have been checked above.
23562394 unsafe {
23572395 ptr:: copy ( self . as_ptr ( ) . add ( src_start) , self . as_mut_ptr ( ) . add ( dest) , count) ;
23582396 }
@@ -2408,6 +2446,9 @@ impl<T> [T] {
24082446 #[ stable( feature = "swap_with_slice" , since = "1.27.0" ) ]
24092447 pub fn swap_with_slice ( & mut self , other : & mut [ T ] ) {
24102448 assert ! ( self . len( ) == other. len( ) , "destination and source slices have different lengths" ) ;
2449+ // SAFETY: `self` is valid for `self.len()` bytes by definition, and `src` was
2450+ // checked to have the same length. Both slices cannot be overlapping because
2451+ // Rust's mutable references are exclusive.
24112452 unsafe {
24122453 ptr:: swap_nonoverlapping ( self . as_mut_ptr ( ) , other. as_mut_ptr ( ) , self . len ( ) ) ;
24132454 }
@@ -2439,6 +2480,8 @@ impl<T> [T] {
24392480 // iterative stein’s algorithm
24402481 // We should still make this `const fn` (and revert to recursive algorithm if we do)
24412482 // because relying on llvm to consteval all this is… well, it makes me uncomfortable.
2483+
2484+ // SAFETY: `a` and `b` are checked to be non-zero values.
24422485 let ( ctz_a, mut ctz_b) = unsafe {
24432486 if a == 0 {
24442487 return b;
@@ -2458,6 +2501,7 @@ impl<T> [T] {
24582501 mem:: swap ( & mut a, & mut b) ;
24592502 }
24602503 b = b - a;
2504+ // SAFETY: `b` is checked to be non-zero.
24612505 unsafe {
24622506 if b == 0 {
24632507 break ;
@@ -2848,11 +2892,13 @@ impl<T> SliceIndex<[T]> for usize {
28482892
28492893 #[ inline]
28502894 fn get ( self , slice : & [ T ] ) -> Option < & T > {
2895+ // SAFETY: `self` is checked to be in bounds.
28512896 if self < slice. len ( ) { unsafe { Some ( self . get_unchecked ( slice) ) } } else { None }
28522897 }
28532898
28542899 #[ inline]
28552900 fn get_mut ( self , slice : & mut [ T ] ) -> Option < & mut T > {
2901+ // SAFETY: `self` is checked to be in bounds.
28562902 if self < slice. len ( ) { unsafe { Some ( self . get_unchecked_mut ( slice) ) } } else { None }
28572903 }
28582904
@@ -2888,6 +2934,7 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> {
28882934 if self . start > self . end || self . end > slice. len ( ) {
28892935 None
28902936 } else {
2937+ // SAFETY: `self` is checked to be valid and in bounds above.
28912938 unsafe { Some ( self . get_unchecked ( slice) ) }
28922939 }
28932940 }
@@ -2897,6 +2944,7 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> {
28972944 if self . start > self . end || self . end > slice. len ( ) {
28982945 None
28992946 } else {
2947+ // SAFETY: `self` is checked to be valid and in bounds above.
29002948 unsafe { Some ( self . get_unchecked_mut ( slice) ) }
29012949 }
29022950 }
@@ -2918,6 +2966,7 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> {
29182966 } else if self . end > slice. len ( ) {
29192967 slice_index_len_fail ( self . end , slice. len ( ) ) ;
29202968 }
2969+ // SAFETY: `self` is checked to be valid and in bounds above.
29212970 unsafe { self . get_unchecked ( slice) }
29222971 }
29232972
@@ -2928,6 +2977,7 @@ impl<T> SliceIndex<[T]> for ops::Range<usize> {
29282977 } else if self . end > slice. len ( ) {
29292978 slice_index_len_fail ( self . end , slice. len ( ) ) ;
29302979 }
2980+ // SAFETY: `self` is checked to be valid and in bounds above.
29312981 unsafe { self . get_unchecked_mut ( slice) }
29322982 }
29332983}
@@ -3239,6 +3289,8 @@ macro_rules! iterator {
32393289 // Helper function for creating a slice from the iterator.
32403290 #[ inline( always) ]
32413291 fn make_slice( & self ) -> & ' a [ T ] {
3292+ // SAFETY: the iterator was created from a slice with pointer `self.ptr` and length `len!(self)`.
3293+ // This guarantees that all the prerequisites for `from_raw_parts` are fulfilled.
32423294 unsafe { from_raw_parts( self . ptr. as_ptr( ) , len!( self ) ) }
32433295 }
32443296
@@ -3292,6 +3344,10 @@ macro_rules! iterator {
32923344 #[ inline]
32933345 fn next( & mut self ) -> Option <$elem> {
32943346 // could be implemented with slices, but this avoids bounds checks
3347+
3348+ // SAFETY: `assume` calls are safe since a slice's start pointer must be non-null,
3349+ // and slices over non-ZSTs must also have a non-null end pointer.
3350+ // The call to `next_unchecked!` is safe since we check if the iterator is empty first.
32953351 unsafe {
32963352 assume( !self . ptr. as_ptr( ) . is_null( ) ) ;
32973353 if mem:: size_of:: <T >( ) != 0 {
@@ -3325,14 +3381,14 @@ macro_rules! iterator {
33253381 // could be (due to wrapping).
33263382 self . end = self . ptr. as_ptr( ) ;
33273383 } else {
3384+ // SAFETY: end can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr
33283385 unsafe {
3329- // End can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr
33303386 self . ptr = NonNull :: new_unchecked( self . end as * mut T ) ;
33313387 }
33323388 }
33333389 return None ;
33343390 }
3335- // We are in bounds. `post_inc_start` does the right thing even for ZSTs.
3391+ // SAFETY: we are in bounds. `post_inc_start` does the right thing even for ZSTs.
33363392 unsafe {
33373393 self . post_inc_start( n as isize ) ;
33383394 Some ( next_unchecked!( self ) )
@@ -3439,6 +3495,8 @@ macro_rules! iterator {
34393495 let mut i = 0 ;
34403496 while let Some ( x) = self . next( ) {
34413497 if predicate( x) {
3498+ // SAFETY: we are guaranteed to be in bounds by the loop invariant:
3499+ // when `i >= n`, `self.next()` returns `None` and the loop breaks.
34423500 unsafe { assume( i < n) } ;
34433501 return Some ( i) ;
34443502 }
@@ -3460,6 +3518,8 @@ macro_rules! iterator {
34603518 while let Some ( x) = self . next_back( ) {
34613519 i -= 1 ;
34623520 if predicate( x) {
3521+ // SAFETY: `i` must be lower than `n` since it starts at `n`
3522+ // and is only decreasing.
34633523 unsafe { assume( i < n) } ;
34643524 return Some ( i) ;
34653525 }
@@ -3475,6 +3535,10 @@ macro_rules! iterator {
34753535 #[ inline]
34763536 fn next_back( & mut self ) -> Option <$elem> {
34773537 // could be implemented with slices, but this avoids bounds checks
3538+
3539+ // SAFETY: `assume` calls are safe since a slice's start pointer must be non-null,
3540+ // and slices over non-ZSTs must also have a non-null end pointer.
3541+ // The call to `next_back_unchecked!` is safe since we check if the iterator is empty first.
34783542 unsafe {
34793543 assume( !self . ptr. as_ptr( ) . is_null( ) ) ;
34803544 if mem:: size_of:: <T >( ) != 0 {
@@ -3495,7 +3559,7 @@ macro_rules! iterator {
34953559 self . end = self . ptr. as_ptr( ) ;
34963560 return None ;
34973561 }
3498- // We are in bounds. `pre_dec_end` does the right thing even for ZSTs.
3562+ // SAFETY: we are in bounds. `pre_dec_end` does the right thing even for ZSTs.
34993563 unsafe {
35003564 self . pre_dec_end( n as isize ) ;
35013565 Some ( next_back_unchecked!( self ) )
@@ -3690,6 +3754,8 @@ impl<'a, T> IterMut<'a, T> {
36903754 /// ```
36913755 #[ stable( feature = "iter_to_slice" , since = "1.4.0" ) ]
36923756 pub fn into_slice ( self ) -> & ' a mut [ T ] {
3757+ // SAFETY: the iterator was created from a mutable slice with pointer `self.ptr` and length `len!(self)`.
3758+ // This guarantees that all the prerequisites for `from_raw_parts_mut` are fulfilled.
36933759 unsafe { from_raw_parts_mut ( self . ptr . as_ptr ( ) , len ! ( self ) ) }
36943760 }
36953761
@@ -5855,12 +5921,20 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T]
58555921/// Converts a reference to T into a slice of length 1 (without copying).
58565922#[ stable( feature = "from_ref" , since = "1.28.0" ) ]
58575923pub fn from_ref < T > ( s : & T ) -> & [ T ] {
5924+ // SAFETY: a reference is guaranteed to be valid for reads. The returned
5925+ // reference cannot be mutated as it is an immutable reference.
5926+ // `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
5927+ // Thus the call to `from_raw_parts` is safe.
58585928 unsafe { from_raw_parts ( s, 1 ) }
58595929}
58605930
58615931/// Converts a reference to T into a slice of length 1 (without copying).
58625932#[ stable( feature = "from_ref" , since = "1.28.0" ) ]
58635933pub fn from_mut < T > ( s : & mut T ) -> & mut [ T ] {
5934+ // SAFETY: a mutable reference is guaranteed to be valid for writes.
5935+ // The reference cannot be accessed by another pointer as it is an mutable reference.
5936+ // `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
5937+ // Thus the call to `from_raw_parts_mut` is safe.
58645938 unsafe { from_raw_parts_mut ( s, 1 ) }
58655939}
58665940
@@ -5993,6 +6067,9 @@ where
59936067 if self . as_ptr ( ) . guaranteed_eq ( other. as_ptr ( ) ) {
59946068 return true ;
59956069 }
6070+
6071+ // SAFETY: `self` and `other` are references and are thus guaranteed to be valid.
6072+ // The two slices have been checked to have the same size above.
59966073 unsafe {
59976074 let size = mem:: size_of_val ( self ) ;
59986075 memcmp ( self . as_ptr ( ) as * const u8 , other. as_ptr ( ) as * const u8 , size) == 0
@@ -6095,6 +6172,9 @@ impl SliceOrd for u8 {
60956172 #[ inline]
60966173 fn compare ( left : & [ Self ] , right : & [ Self ] ) -> Ordering {
60976174 let order =
6175+ // SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
6176+ // We use the minimum of both lengths which guarantees that both regions are
6177+ // valid for reads in that interval.
60986178 unsafe { memcmp ( left. as_ptr ( ) , right. as_ptr ( ) , cmp:: min ( left. len ( ) , right. len ( ) ) ) } ;
60996179 if order == 0 {
61006180 left. len ( ) . cmp ( & right. len ( ) )
@@ -6164,6 +6244,10 @@ impl SliceContains for u8 {
61646244impl SliceContains for i8 {
61656245 fn slice_contains ( & self , x : & [ Self ] ) -> bool {
61666246 let byte = * self as u8 ;
6247+ // SAFETY: `i8` and `u8` have the same memory layout, thus casting `x.as_ptr()`
6248+ // as `*const u8` is safe. The `x.as_ptr()` comes from a reference and is thus guaranteed
6249+ // to be valid for reads for the length of the slice `x.len()`, which cannot be larger
6250+ // than `isize::MAX`. The returned slice is never mutated.
61676251 let bytes: & [ u8 ] = unsafe { from_raw_parts ( x. as_ptr ( ) as * const u8 , x. len ( ) ) } ;
61686252 memchr:: memchr ( byte, bytes) . is_some ( )
61696253 }
0 commit comments