Skip to content

Commit

Permalink
Clarify safety comments
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Jul 27, 2022
1 parent e2e3a88 commit 746afe8
Showing 1 changed file with 47 additions and 59 deletions.
106 changes: 47 additions & 59 deletions library/core/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1629,11 +1629,12 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for Chunks<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ChunksMut<'a, T: 'a> {
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
/// # Safety
/// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally,
/// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot
/// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing
/// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw
/// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap.
v: *mut [T],
chunk_size: usize,
_marker: PhantomData<&'a mut T>,
Expand All @@ -1656,7 +1657,7 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
None
} else {
let sz = cmp::min(self.v.len(), self.chunk_size);
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (head, tail) = unsafe { self.v.split_at_mut(sz) };
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand Down Expand Up @@ -1692,9 +1693,9 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
Some(sum) => cmp::min(self.v.len(), sum),
None => self.v.len(),
};
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (head, tail) = unsafe { self.v.split_at_mut(end) };
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (_, nth) = unsafe { head.split_at_mut(start) };
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand All @@ -1715,7 +1716,7 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {

unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
// SAFETY: see comments for `Chunks::__iterator_get_unchecked`.
// SAFETY: see comments for `Chunks::__iterator_get_unchecked` and `self.v`.
//
// Also note that the caller also guarantees that we're never called
// with the same index again, and that no other methods that will
Expand Down Expand Up @@ -1758,9 +1759,9 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
Some(res) => cmp::min(self.v.len(), res),
None => self.v.len(),
};
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (temp, _tail) = unsafe { self.v.split_at_mut(end) };
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (head, nth_back) = unsafe { temp.split_at_mut(start) };
self.v = head;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand Down Expand Up @@ -1970,11 +1971,12 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for ChunksExact<'a, T> {
#[stable(feature = "chunks_exact", since = "1.31.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ChunksExactMut<'a, T: 'a> {
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
/// # Safety
/// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally,
/// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot
/// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing
/// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw
/// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap.
v: *mut [T],
rem: &'a mut [T], // The iterator never yields from here, so this can be unique
chunk_size: usize,
Expand Down Expand Up @@ -2036,7 +2038,7 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {
self.v = &mut [];
None
} else {
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (_, snd) = unsafe { self.v.split_at_mut(start) };
self.v = snd;
self.next()
Expand All @@ -2050,7 +2052,7 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {

unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let start = idx * self.chunk_size;
// SAFETY: see comments for `ChunksMut::__iterator_get_unchecked`.
// SAFETY: see comments for `Chunks::__iterator_get_unchecked` and `self.v`.
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
}
}
Expand Down Expand Up @@ -2079,9 +2081,9 @@ impl<'a, T> DoubleEndedIterator for ChunksExactMut<'a, T> {
} else {
let start = (len - 1 - n) * self.chunk_size;
let end = start + self.chunk_size;
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (temp, _tail) = unsafe { mem::replace(&mut self.v, &mut []).split_at_mut(end) };
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (head, nth_back) = unsafe { temp.split_at_mut(start) };
self.v = head;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand Down Expand Up @@ -2669,11 +2671,12 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunks<'a, T> {
#[stable(feature = "rchunks", since = "1.31.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct RChunksMut<'a, T: 'a> {
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
/// # Safety
/// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally,
/// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot
/// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing
/// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw
/// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap.
v: *mut [T],
chunk_size: usize,
_marker: PhantomData<&'a mut T>,
Expand Down Expand Up @@ -2770,7 +2773,7 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
Some(start) => start,
};
// SAFETY: see comments for `RChunks::__iterator_get_unchecked` and
// `ChunksMut::__iterator_get_unchecked`
// `ChunksMut::__iterator_get_unchecked`, `self.v`.
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
}
}
Expand Down Expand Up @@ -2803,9 +2806,9 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
let offset_from_end = (len - 1 - n) * self.chunk_size;
let end = self.v.len() - offset_from_end;
let start = end.saturating_sub(self.chunk_size);
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (tmp, tail) = unsafe { self.v.split_at_mut(end) };
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (_, nth_back) = unsafe { tmp.split_at_mut(start) };
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand Down Expand Up @@ -3018,11 +3021,12 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for RChunksExact<'a, T> {
#[stable(feature = "rchunks", since = "1.31.0")]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct RChunksExactMut<'a, T: 'a> {
// This slice pointer must point at a valid region of T with at least length v.len(). Normally,
// those requirements would mean that we could instead use a &mut [T] here, but we cannot
// because __iterator_get_unchecked needs to return &mut [T], which guarantees certain aliasing
// properties that we cannot uphold if we hold on to the full original &mut [T]. Wrapping a raw
// slice instead lets us hand out non-overlapping &mut [T] subslices of the slice we wrap.
/// # Safety
/// This slice pointer must point at a valid region of `T` with at least length `v.len()`. Normally,
/// those requirements would mean that we could instead use a `&mut [T]` here, but we cannot
/// because `__iterator_get_unchecked` needs to return `&mut [T]`, which guarantees certain aliasing
/// properties that we cannot uphold if we hold on to the full original `&mut [T]`. Wrapping a raw
/// slice instead lets us hand out non-overlapping `&mut [T]` subslices of the slice we wrap.
v: *mut [T],
rem: &'a mut [T],
chunk_size: usize,
Expand Down Expand Up @@ -3057,7 +3061,7 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
None
} else {
let len = self.v.len();
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (head, tail) = unsafe { self.v.split_at_mut(len - self.chunk_size) };
self.v = head;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand All @@ -3084,7 +3088,7 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
None
} else {
let len = self.v.len();
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (fst, _) = unsafe { self.v.split_at_mut(len - end) };
self.v = fst;
self.next()
Expand All @@ -3099,7 +3103,7 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
let end = self.v.len() - idx * self.chunk_size;
let start = end - self.chunk_size;
// SAFETY: see comments for `RChunksMut::__iterator_get_unchecked`.
// SAFETY: see comments for `RChunksMut::__iterator_get_unchecked` and `self.v`.
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
}
}
Expand All @@ -3111,7 +3115,7 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
if self.v.len() < self.chunk_size {
None
} else {
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (head, tail) = unsafe { self.v.split_at_mut(self.chunk_size) };
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand All @@ -3131,9 +3135,9 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
let offset = (len - n) * self.chunk_size;
let start = self.v.len() - offset;
let end = start + self.chunk_size;
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (tmp, tail) = unsafe { self.v.split_at_mut(end) };
// SAFETY: This type ensures that any split_at_mut on self.v is valid.
// SAFETY: The self.v contract ensures that any split_at_mut is valid.
let (_, nth_back) = unsafe { tmp.split_at_mut(start) };
self.v = tail;
// SAFETY: Nothing else points to or will point to the contents of this slice.
Expand Down Expand Up @@ -3220,11 +3224,7 @@ where
let mut len = 1;
let mut iter = self.slice.windows(2);
while let Some([l, r]) = iter.next() {
if (self.predicate)(l, r) {
len += 1
} else {
break;
}
if (self.predicate)(l, r) { len += 1 } else { break }
}
let (head, tail) = self.slice.split_at(len);
self.slice = tail;
Expand Down Expand Up @@ -3256,11 +3256,7 @@ where
let mut len = 1;
let mut iter = self.slice.windows(2);
while let Some([l, r]) = iter.next_back() {
if (self.predicate)(l, r) {
len += 1
} else {
break;
}
if (self.predicate)(l, r) { len += 1 } else { break }
}
let (head, tail) = self.slice.split_at(self.slice.len() - len);
self.slice = head;
Expand Down Expand Up @@ -3315,11 +3311,7 @@ where
let mut len = 1;
let mut iter = self.slice.windows(2);
while let Some([l, r]) = iter.next() {
if (self.predicate)(l, r) {
len += 1
} else {
break;
}
if (self.predicate)(l, r) { len += 1 } else { break }
}
let slice = mem::take(&mut self.slice);
let (head, tail) = slice.split_at_mut(len);
Expand Down Expand Up @@ -3352,11 +3344,7 @@ where
let mut len = 1;
let mut iter = self.slice.windows(2);
while let Some([l, r]) = iter.next_back() {
if (self.predicate)(l, r) {
len += 1
} else {
break;
}
if (self.predicate)(l, r) { len += 1 } else { break }
}
let slice = mem::take(&mut self.slice);
let (head, tail) = slice.split_at_mut(slice.len() - len);
Expand Down

0 comments on commit 746afe8

Please sign in to comment.