Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement TrustedLen and TrustedRandomAccess for Range<integer>, array::IntoIter, VecDequeue's iterators #81607

Merged
merged 4 commits into from
Mar 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion library/alloc/src/collections/vec_deque/into_iter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::fmt;
use core::iter::FusedIterator;
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};

use super::VecDeque;

Expand Down Expand Up @@ -36,6 +36,22 @@ impl<T> Iterator for IntoIter<T> {
let len = self.inner.len();
(len, Some(len))
}

#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccess,
{
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
// that is in bounds.
// Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
// multiple repeated reads of the same index would be safe and the
// values are !Drop, thus won't suffer from double drops.
unsafe {
let idx = self.inner.wrap_add(self.inner.tail, idx);
self.inner.buffer_read(idx)
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand All @@ -55,3 +71,17 @@ impl<T> ExactSizeIterator for IntoIter<T> {

#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T> TrustedLen for IntoIter<T> {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
// T: Copy as approximation for !Drop since get_unchecked does not update the pointers
// and thus we can't implement drop-handling
unsafe impl<T> TrustedRandomAccess for IntoIter<T>
where
T: Copy,
the8472 marked this conversation as resolved.
Show resolved Hide resolved
{
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
24 changes: 23 additions & 1 deletion library/alloc/src/collections/vec_deque/iter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::fmt;
use core::iter::FusedIterator;
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
use core::ops::Try;

use super::{count, wrap_index, RingSlices};
Expand Down Expand Up @@ -101,6 +101,19 @@ impl<'a, T> Iterator for Iter<'a, T> {
fn last(mut self) -> Option<&'a T> {
self.next_back()
}

#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccess,
{
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
// that is in bounds.
unsafe {
let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
self.ring.get_unchecked(idx)
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -157,3 +170,12 @@ impl<T> ExactSizeIterator for Iter<'_, T> {

#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for Iter<'_, T> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T> TrustedLen for Iter<'_, T> {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl<T> TrustedRandomAccess for Iter<'_, T> {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
24 changes: 23 additions & 1 deletion library/alloc/src/collections/vec_deque/iter_mut.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use core::fmt;
use core::iter::FusedIterator;
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
use core::marker::PhantomData;

use super::{count, wrap_index, RingSlices};
Expand Down Expand Up @@ -87,6 +87,19 @@ impl<'a, T> Iterator for IterMut<'a, T> {
fn last(mut self) -> Option<&'a mut T> {
self.next_back()
}

#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccess,
{
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
// that is in bounds.
unsafe {
let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
&mut *self.ring.get_unchecked_mut(idx)
}
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -126,3 +139,12 @@ impl<T> ExactSizeIterator for IterMut<'_, T> {

#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IterMut<'_, T> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T> TrustedLen for IterMut<'_, T> {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl<T> TrustedRandomAccess for IterMut<'_, T> {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
2 changes: 1 addition & 1 deletion library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ mod tests;
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
const MINIMUM_CAPACITY: usize = 1; // 2 - 1

const MAXIMUM_ZST_CAPACITY: usize = 1 << (core::mem::size_of::<usize>() * 8 - 1); // Largest possible power of two
const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two

/// A double-ended queue implemented with a growable ring buffer.
///
Expand Down
25 changes: 24 additions & 1 deletion library/core/src/array/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{
fmt,
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
iter::{ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess},
mem::{self, MaybeUninit},
ops::Range,
ptr,
Expand Down Expand Up @@ -130,6 +130,18 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}

#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccess,
{
// SAFETY: Callers are only allowed to pass an index that is in bounds
// Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
// multiple repeated reads of the same index would be safe and the
// values aree !Drop, thus won't suffer from double drops.
unsafe { self.data.get_unchecked(self.alive.start + idx).assume_init_read() }
}
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
Expand Down Expand Up @@ -184,6 +196,17 @@ impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}

#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
// T: Copy as approximation for !Drop since get_unchecked does not update the pointers
// and thus we can't implement drop-handling
unsafe impl<T, const N: usize> TrustedRandomAccess for IntoIter<T, N>
where
T: Copy,
the8472 marked this conversation as resolved.
Show resolved Hide resolved
{
const MAY_HAVE_SIDE_EFFECT: bool = false;
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
fn clone(&self) -> Self {
Expand Down
43 changes: 42 additions & 1 deletion library/core/src/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::convert::TryFrom;
use crate::mem;
use crate::ops::{self, Try};

use super::{FusedIterator, TrustedLen};
use super::{FusedIterator, TrustedLen, TrustedRandomAccess};

/// Objects that have a notion of *successor* and *predecessor* operations.
///
Expand Down Expand Up @@ -493,6 +493,18 @@ macro_rules! range_exact_iter_impl {
)*)
}

/// Safety: This macro must only be used on types that are `Copy` and result in ranges
/// which have an exact `size_hint()` where the upper bound must not be `None`.
macro_rules! unsafe_range_trusted_random_access_impl {
($($t:ty)*) => ($(
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
unsafe impl TrustedRandomAccess for ops::Range<$t> {
const MAY_HAVE_SIDE_EFFECT: bool = false;
}
)*)
}

macro_rules! range_incl_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "inclusive_range", since = "1.26.0")]
Expand Down Expand Up @@ -553,6 +565,18 @@ impl<A: Step> Iterator for ops::Range<A> {
fn max(mut self) -> Option<A> {
self.next_back()
}

#[inline]
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
where
Self: TrustedRandomAccess,
{
// SAFETY: The TrustedRandomAccess contract requires that callers only pass an index
// that is in bounds.
// Additionally Self: TrustedRandomAccess is only implemented for Copy types
// which means even repeated reads of the same index would be safe.
the8472 marked this conversation as resolved.
Show resolved Hide resolved
unsafe { Step::forward_unchecked(self.start.clone(), idx) }
}
}

// These macros generate `ExactSizeIterator` impls for various range types.
Expand All @@ -574,6 +598,23 @@ range_exact_iter_impl! {
u32
i32
}

unsafe_range_trusted_random_access_impl! {
usize u8 u16
isize i8 i16
}

#[cfg(target_pointer_width = "32")]
unsafe_range_trusted_random_access_impl! {
u32 i32
}

#[cfg(target_pointer_width = "64")]
unsafe_range_trusted_random_access_impl! {
u32 i32
u64 i64
}

range_incl_exact_iter_impl! {
u8
i8
Expand Down