Skip to content

Commit e4c1a38

Browse files
committed
VecDeque: avoid more aliasing issues by working with raw pointers instead of references
1 parent f251dc4 commit e4c1a38

File tree

1 file changed

+31
-12
lines changed

1 file changed

+31
-12
lines changed

library/alloc/src/collections/vec_deque.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,6 +2500,25 @@ impl<T> RingSlices for &mut [T] {
25002500
}
25012501
}
25022502

2503+
impl<T> RingSlices for *mut [T] {
2504+
fn slice(self, from: usize, to: usize) -> Self {
2505+
assert!(from <= to && to < self.len());
2506+
// Not using `get_unchecked_mut` to keep this a safe operation.
2507+
let len = to - from;
2508+
ptr::slice_from_raw_parts_mut(self.as_mut_ptr().wrapping_add(from), len)
2509+
}
2510+
2511+
fn split_at(self, mid: usize) -> (Self, Self) {
2512+
let len = self.len();
2513+
let ptr = self.as_mut_ptr();
2514+
assert!(mid <= len);
2515+
(
2516+
ptr::slice_from_raw_parts_mut(ptr, mid),
2517+
ptr::slice_from_raw_parts_mut(ptr.wrapping_add(mid), len - mid),
2518+
)
2519+
}
2520+
}
2521+
25032522
/// Calculate the number of elements left to be read in the buffer
25042523
#[inline]
25052524
fn count(tail: usize, head: usize, size: usize) -> usize {
@@ -2678,10 +2697,10 @@ pub struct IterMut<'a, T: 'a> {
26782697
#[stable(feature = "collection_debug", since = "1.17.0")]
26792698
impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
26802699
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2681-
// FIXME: this creates a reference to the full ring, including the part
2682-
// to which we already handed out mutable references via `next()`. This
2683-
// is an aliasing violation.
2684-
let (front, back) = RingSlices::ring_slices(unsafe { &*self.ring }, self.head, self.tail);
2700+
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
2701+
// SAFETY: these are the elements we have not handed out yet, so aliasing is fine.
2702+
// We also ensure everything is dereferencable and in-bounds.
2703+
let (front, back) = unsafe { (&*front, &*back) };
26852704
f.debug_tuple("IterMut").field(&front).field(&back).finish()
26862705
}
26872706
}
@@ -2714,10 +2733,10 @@ impl<'a, T> Iterator for IterMut<'a, T> {
27142733
where
27152734
F: FnMut(Acc, Self::Item) -> Acc,
27162735
{
2717-
// FIXME: this creates a reference to the full ring, including the part
2718-
// to which we already handed out mutable references via `next()`. This
2719-
// is an aliasing violation.
2720-
let (front, back) = RingSlices::ring_slices(unsafe { &mut *self.ring }, self.head, self.tail);
2736+
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
2737+
// SAFETY: these are the elements we have not handed out yet, so aliasing is fine.
2738+
// We also ensure everything is dereferencable and in-bounds.
2739+
let (front, back) = unsafe { (&mut *front, &mut *back) };
27212740
accum = front.iter_mut().fold(accum, &mut f);
27222741
back.iter_mut().fold(accum, &mut f)
27232742
}
@@ -2757,10 +2776,10 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
27572776
where
27582777
F: FnMut(Acc, Self::Item) -> Acc,
27592778
{
2760-
// FIXME: this creates a reference to the full ring, including the part
2761-
// to which we already handed out mutable references via `next()`. This
2762-
// is an aliasing violation.
2763-
let (front, back) = RingSlices::ring_slices(unsafe { &mut *self.ring }, self.head, self.tail);
2779+
let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail);
2780+
// SAFETY: these are the elements we have not handed out yet, so aliasing is fine.
2781+
// We also ensure everything is dereferencable and in-bounds.
2782+
let (front, back) = unsafe { (&mut *front, &mut *back) };
27642783
accum = back.iter_mut().rfold(accum, &mut f);
27652784
front.iter_mut().rfold(accum, &mut f)
27662785
}

0 commit comments

Comments
 (0)