Skip to content

Commit e2e3a88

Browse files
committed
Explain how *mut [T] helps, and how we rely on the check in split_at_mut
1 parent 7919e42 commit e2e3a88

File tree

1 file changed

+55
-20
lines changed

1 file changed

+55
-20
lines changed

library/core/src/slice/iter.rs

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,11 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Chunks<'a, T> {
16291629
#[stable(feature = "rust1", since = "1.0.0")]
16301630
#[must_use = "iterators are lazy and do nothing unless consumed"]
16311631
pub struct ChunksMut<'a, T: 'a> {
1632+
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
1633+
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
1634+
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
1635+
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
1636+
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
16321637
v: *mut [T],
16331638
chunk_size: usize,
16341639
_marker: PhantomData<&'a mut T>,
@@ -1651,10 +1656,10 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
16511656
None
16521657
} else {
16531658
let sz = cmp::min(self.v.len(), self.chunk_size);
1654-
// SAFETY: sz cannot exceed the slice length based on the calculation above
1659+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
16551660
let (head, tail) = unsafe { self.v.split_at_mut(sz) };
16561661
self.v = tail;
1657-
// SAFETY: Nothing points to or will point to the contents of this slice
1662+
// SAFETY: Nothing else points to or will point to the contents of this slice.
16581663
Some(unsafe { &mut *head })
16591664
}
16601665
}
@@ -1687,12 +1692,12 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
16871692
Some(sum) => cmp::min(self.v.len(), sum),
16881693
None => self.v.len(),
16891694
};
1690-
// SAFETY: end is inbounds because we compared above against self.v.len()
1695+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
16911696
let (head, tail) = unsafe { self.v.split_at_mut(end) };
1692-
// SAFETY: start is inbounds because
1697+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
16931698
let (_, nth) = unsafe { head.split_at_mut(start) };
16941699
self.v = tail;
1695-
// SAFETY: Nothing points to or will point to the contents of this slice
1700+
// SAFETY: Nothing else points to or will point to the contents of this slice.
16961701
Some(unsafe { &mut *nth })
16971702
}
16981703
}
@@ -1703,7 +1708,7 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
17031708
None
17041709
} else {
17051710
let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size;
1706-
// SAFETY: Nothing points to or will point to the contents of this slice
1711+
// SAFETY: Nothing else points to or will point to the contents of this slice.
17071712
Some(unsafe { &mut *self.v.get_unchecked_mut(start..) })
17081713
}
17091714
}
@@ -1736,7 +1741,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
17361741
// SAFETY: Similar to `Chunks::next_back`
17371742
let (head, tail) = unsafe { self.v.split_at_mut_unchecked(len - sz) };
17381743
self.v = head;
1739-
// SAFETY: Nothing points to or will point to the contents of this slice
1744+
// SAFETY: Nothing else points to or will point to the contents of this slice.
17401745
Some(unsafe { &mut *tail })
17411746
}
17421747
}
@@ -1753,11 +1758,12 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
17531758
Some(res) => cmp::min(self.v.len(), res),
17541759
None => self.v.len(),
17551760
};
1756-
// SAFETY: end is inbounds because we compared above against self.v.len()
1761+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
17571762
let (temp, _tail) = unsafe { self.v.split_at_mut(end) };
1763+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
17581764
let (head, nth_back) = unsafe { temp.split_at_mut(start) };
17591765
self.v = head;
1760-
// SAFETY: Nothing points to or will point to the contents of this slice
1766+
// SAFETY: Nothing else points to or will point to the contents of this slice.
17611767
Some(unsafe { &mut *nth_back })
17621768
}
17631769
}
@@ -1964,6 +1970,11 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExact<'a, T> {
19641970
#[stable(feature = "chunks_exact", since = "1.31.0")]
19651971
#[must_use = "iterators are lazy and do nothing unless consumed"]
19661972
pub struct ChunksExactMut<'a, T: 'a> {
1973+
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
1974+
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
1975+
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
1976+
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
1977+
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
19671978
v: *mut [T],
19681979
rem: &'a mut [T], // The iterator never yields from here, so this can be unique
19691980
chunk_size: usize,
@@ -2002,7 +2013,7 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {
20022013
// SAFETY: self.chunk_size is inbounds because we compared above against self.v.len()
20032014
let (head, tail) = unsafe { self.v.split_at_mut(self.chunk_size) };
20042015
self.v = tail;
2005-
// SAFETY: Nothing points to or will point to the contents of this slice
2016+
// SAFETY: Nothing else points to or will point to the contents of this slice.
20062017
Some(unsafe { &mut *head })
20072018
}
20082019
}
@@ -2025,6 +2036,7 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {
20252036
self.v = &mut [];
20262037
None
20272038
} else {
2039+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
20282040
let (_, snd) = unsafe { self.v.split_at_mut(start) };
20292041
self.v = snd;
20302042
self.next()
@@ -2053,7 +2065,7 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
20532065
// SAFETY: This subtraction is inbounds because of the check above
20542066
let (head, tail) = unsafe { self.v.split_at_mut(self.v.len() - self.chunk_size) };
20552067
self.v = head;
2056-
// SAFETY: Nothing points to or will point to the contents of this slice
2068+
// SAFETY: Nothing else points to or will point to the contents of this slice.
20572069
Some(unsafe { &mut *tail })
20582070
}
20592071
}
@@ -2067,10 +2079,12 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
20672079
} else {
20682080
let start = (len - 1 - n) * self.chunk_size;
20692081
let end = start + self.chunk_size;
2082+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
20702083
let (temp, _tail) = unsafe { mem::replace(&mut self.v, &mut []).split_at_mut(end) };
2084+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
20712085
let (head, nth_back) = unsafe { temp.split_at_mut(start) };
20722086
self.v = head;
2073-
// SAFETY: Nothing points to or will point to the contents of this slice
2087+
// SAFETY: Nothing else points to or will point to the contents of this slice.
20742088
Some(unsafe { &mut *nth_back })
20752089
}
20762090
}
@@ -2655,6 +2669,11 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunks<'a, T> {
26552669
#[stable(feature = "rchunks", since = "1.31.0")]
26562670
#[must_use = "iterators are lazy and do nothing unless consumed"]
26572671
pub struct RChunksMut<'a, T: 'a> {
2672+
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
2673+
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
2674+
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
2675+
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
2676+
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
26582677
v: *mut [T],
26592678
chunk_size: usize,
26602679
_marker: PhantomData<&'a mut T>,
@@ -2685,7 +2704,7 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
26852704
// `self.v.len()` (e.g. `len`) and `self.chunk_size`.
26862705
let (head, tail) = unsafe { self.v.split_at_mut_unchecked(len - sz) };
26872706
self.v = head;
2688-
// SAFETY: Nothing points to or will point to the contents of this slice
2707+
// SAFETY: Nothing else points to or will point to the contents of this slice.
26892708
Some(unsafe { &mut *tail })
26902709
}
26912710
}
@@ -2720,10 +2739,14 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
27202739
Some(sum) => sum,
27212740
None => 0,
27222741
};
2742+
// SAFETY: This type ensures that self.v is a valid pointer with a correct len.
2743+
// Therefore the bounds check in split_at_mut guarantess the split point is inbounds.
27232744
let (head, tail) = unsafe { self.v.split_at_mut(start) };
2745+
// SAFETY: This type ensures that self.v is a valid pointer with a correct len.
2746+
// Therefore the bounds check in split_at_mut guarantess the split point is inbounds.
27242747
let (nth, _) = unsafe { tail.split_at_mut(end - start) };
27252748
self.v = head;
2726-
// SAFETY: Nothing points to or will point to the contents of this slice
2749+
// SAFETY: Nothing else points to or will point to the contents of this slice.
27272750
Some(unsafe { &mut *nth })
27282751
}
27292752
}
@@ -2735,7 +2758,7 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
27352758
} else {
27362759
let rem = self.v.len() % self.chunk_size;
27372760
let end = if rem == 0 { self.chunk_size } else { rem };
2738-
// SAFETY: Nothing points to or will point to the contents of this slice
2761+
// SAFETY: Nothing else points to or will point to the contents of this slice.
27392762
Some(unsafe { &mut *self.v.get_unchecked_mut(0..end) })
27402763
}
27412764
}
@@ -2764,7 +2787,7 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
27642787
// SAFETY: Similar to `Chunks::next_back`
27652788
let (head, tail) = unsafe { self.v.split_at_mut_unchecked(sz) };
27662789
self.v = tail;
2767-
// SAFETY: Nothing points to or will point to the contents of this slice
2790+
// SAFETY: Nothing else points to or will point to the contents of this slice.
27682791
Some(unsafe { &mut *head })
27692792
}
27702793
}
@@ -2780,10 +2803,12 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
27802803
let offset_from_end = (len - 1 - n) * self.chunk_size;
27812804
let end = self.v.len() - offset_from_end;
27822805
let start = end.saturating_sub(self.chunk_size);
2806+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
27832807
let (tmp, tail) = unsafe { self.v.split_at_mut(end) };
2808+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
27842809
let (_, nth_back) = unsafe { tmp.split_at_mut(start) };
27852810
self.v = tail;
2786-
// SAFETY: Nothing points to or will point to the contents of this slice
2811+
// SAFETY: Nothing else points to or will point to the contents of this slice.
27872812
Some(unsafe { &mut *nth_back })
27882813
}
27892814
}
@@ -2993,6 +3018,11 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExact<'a, T> {
29933018
#[stable(feature = "rchunks", since = "1.31.0")]
29943019
#[must_use = "iterators are lazy and do nothing unless consumed"]
29953020
pub struct RChunksExactMut<'a, T: 'a> {
3021+
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
3022+
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
3023+
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
3024+
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
3025+
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
29963026
v: *mut [T],
29973027
rem: &'a mut [T],
29983028
chunk_size: usize,
@@ -3027,9 +3057,10 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
30273057
None
30283058
} else {
30293059
let len = self.v.len();
3060+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
30303061
let (head, tail) = unsafe { self.v.split_at_mut(len - self.chunk_size) };
30313062
self.v = head;
3032-
// SAFETY: Nothing points to or will point to the contents of this slice
3063+
// SAFETY: Nothing else points to or will point to the contents of this slice.
30333064
Some(unsafe { &mut *tail })
30343065
}
30353066
}
@@ -3053,6 +3084,7 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
30533084
None
30543085
} else {
30553086
let len = self.v.len();
3087+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
30563088
let (fst, _) = unsafe { self.v.split_at_mut(len - end) };
30573089
self.v = fst;
30583090
self.next()
@@ -3079,9 +3111,10 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
30793111
if self.v.len() < self.chunk_size {
30803112
None
30813113
} else {
3114+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
30823115
let (head, tail) = unsafe { self.v.split_at_mut(self.chunk_size) };
30833116
self.v = tail;
3084-
// SAFETY: Nothing points to or will point to the contents of this slice
3117+
// SAFETY: Nothing else points to or will point to the contents of this slice.
30853118
Some(unsafe { &mut *head })
30863119
}
30873120
}
@@ -3098,10 +3131,12 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
30983131
let offset = (len - n) * self.chunk_size;
30993132
let start = self.v.len() - offset;
31003133
let end = start + self.chunk_size;
3134+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
31013135
let (tmp, tail) = unsafe { self.v.split_at_mut(end) };
3136+
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
31023137
let (_, nth_back) = unsafe { tmp.split_at_mut(start) };
31033138
self.v = tail;
3104-
// SAFETY: Nothing points to or will point to the contents of this slice
3139+
// SAFETY: Nothing else points to or will point to the contents of this slice.
31053140
Some(unsafe { &mut *nth_back })
31063141
}
31073142
}

0 commit comments

Comments
 (0)