Skip to content

Commit 29a53e6

Browse files
authored
Rollup merge of #81607 - the8472:trustedrandomaccess-all-the-things, r=m-ou-se
Implement TrustedLen and TrustedRandomAccess for Range<integer>, array::IntoIter, VecDequeue's iterators This should make some `FromIterator` and `.zip()` specializations applicable in a few more cases. ``@rustbot`` label libs-impl
2 parents ad8aa18 + 08a1dd2 commit 29a53e6

File tree

6 files changed

+144
-6
lines changed

6 files changed

+144
-6
lines changed

library/alloc/src/collections/vec_deque/into_iter.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::fmt;
2-
use core::iter::FusedIterator;
2+
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
33

44
use super::VecDeque;
55

@@ -36,6 +36,22 @@ impl<T> Iterator for IntoIter<T> {
3636
let len = self.inner.len();
3737
(len, Some(len))
3838
}
39+
40+
#[inline]
41+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
42+
where
43+
Self: TrustedRandomAccess,
44+
{
45+
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
46+
// that is in bounds.
47+
// Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
48+
// multiple repeated reads of the same index would be safe and the
49+
// values are !Drop, thus won't suffer from double drops.
50+
unsafe {
51+
let idx = self.inner.wrap_add(self.inner.tail, idx);
52+
self.inner.buffer_read(idx)
53+
}
54+
}
3955
}
4056

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

5672
#[stable(feature = "fused", since = "1.26.0")]
5773
impl<T> FusedIterator for IntoIter<T> {}
74+
75+
#[unstable(feature = "trusted_len", issue = "37572")]
76+
unsafe impl<T> TrustedLen for IntoIter<T> {}
77+
78+
#[doc(hidden)]
79+
#[unstable(feature = "trusted_random_access", issue = "none")]
80+
// T: Copy as approximation for !Drop since get_unchecked does not update the pointers
81+
// and thus we can't implement drop-handling
82+
unsafe impl<T> TrustedRandomAccess for IntoIter<T>
83+
where
84+
T: Copy,
85+
{
86+
const MAY_HAVE_SIDE_EFFECT: bool = false;
87+
}

library/alloc/src/collections/vec_deque/iter.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::fmt;
2-
use core::iter::FusedIterator;
2+
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
33
use core::ops::Try;
44

55
use super::{count, wrap_index, RingSlices};
@@ -101,6 +101,19 @@ impl<'a, T> Iterator for Iter<'a, T> {
101101
fn last(mut self) -> Option<&'a T> {
102102
self.next_back()
103103
}
104+
105+
#[inline]
106+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
107+
where
108+
Self: TrustedRandomAccess,
109+
{
110+
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
111+
// that is in bounds.
112+
unsafe {
113+
let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
114+
self.ring.get_unchecked(idx)
115+
}
116+
}
104117
}
105118

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

158171
#[stable(feature = "fused", since = "1.26.0")]
159172
impl<T> FusedIterator for Iter<'_, T> {}
173+
174+
#[unstable(feature = "trusted_len", issue = "37572")]
175+
unsafe impl<T> TrustedLen for Iter<'_, T> {}
176+
177+
#[doc(hidden)]
178+
#[unstable(feature = "trusted_random_access", issue = "none")]
179+
unsafe impl<T> TrustedRandomAccess for Iter<'_, T> {
180+
const MAY_HAVE_SIDE_EFFECT: bool = false;
181+
}

library/alloc/src/collections/vec_deque/iter_mut.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::fmt;
2-
use core::iter::FusedIterator;
2+
use core::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
33
use core::marker::PhantomData;
44

55
use super::{count, wrap_index, RingSlices};
@@ -87,6 +87,19 @@ impl<'a, T> Iterator for IterMut<'a, T> {
8787
fn last(mut self) -> Option<&'a mut T> {
8888
self.next_back()
8989
}
90+
91+
#[inline]
92+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
93+
where
94+
Self: TrustedRandomAccess,
95+
{
96+
// Safety: The TrustedRandomAccess contract requires that callers only pass an index
97+
// that is in bounds.
98+
unsafe {
99+
let idx = wrap_index(self.tail.wrapping_add(idx), self.ring.len());
100+
&mut *self.ring.get_unchecked_mut(idx)
101+
}
102+
}
90103
}
91104

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

127140
#[stable(feature = "fused", since = "1.26.0")]
128141
impl<T> FusedIterator for IterMut<'_, T> {}
142+
143+
#[unstable(feature = "trusted_len", issue = "37572")]
144+
unsafe impl<T> TrustedLen for IterMut<'_, T> {}
145+
146+
#[doc(hidden)]
147+
#[unstable(feature = "trusted_random_access", issue = "none")]
148+
unsafe impl<T> TrustedRandomAccess for IterMut<'_, T> {
149+
const MAY_HAVE_SIDE_EFFECT: bool = false;
150+
}

library/alloc/src/collections/vec_deque/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ mod tests;
5858
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
5959
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
6060

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

6363
/// A double-ended queue implemented with a growable ring buffer.
6464
///

library/core/src/array/iter.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
fmt,
5-
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
5+
iter::{ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess},
66
mem::{self, MaybeUninit},
77
ops::Range,
88
ptr,
@@ -130,6 +130,18 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
130130
fn last(mut self) -> Option<Self::Item> {
131131
self.next_back()
132132
}
133+
134+
#[inline]
135+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
136+
where
137+
Self: TrustedRandomAccess,
138+
{
139+
// SAFETY: Callers are only allowed to pass an index that is in bounds
140+
// Additionally Self: TrustedRandomAccess is only implemented for T: Copy which means even
141+
// multiple repeated reads of the same index would be safe and the
142+
// values aree !Drop, thus won't suffer from double drops.
143+
unsafe { self.data.get_unchecked(self.alive.start + idx).assume_init_read() }
144+
}
133145
}
134146

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

199+
#[doc(hidden)]
200+
#[unstable(feature = "trusted_random_access", issue = "none")]
201+
// T: Copy as approximation for !Drop since get_unchecked does not update the pointers
202+
// and thus we can't implement drop-handling
203+
unsafe impl<T, const N: usize> TrustedRandomAccess for IntoIter<T, N>
204+
where
205+
T: Copy,
206+
{
207+
const MAY_HAVE_SIDE_EFFECT: bool = false;
208+
}
209+
187210
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
188211
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
189212
fn clone(&self) -> Self {

library/core/src/iter/range.rs

+42-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::convert::TryFrom;
33
use crate::mem;
44
use crate::ops::{self, Try};
55

6-
use super::{FusedIterator, TrustedLen};
6+
use super::{FusedIterator, TrustedLen, TrustedRandomAccess};
77

88
/// Objects that have a notion of *successor* and *predecessor* operations.
99
///
@@ -493,6 +493,18 @@ macro_rules! range_exact_iter_impl {
493493
)*)
494494
}
495495

496+
/// Safety: This macro must only be used on types that are `Copy` and result in ranges
497+
/// which have an exact `size_hint()` where the upper bound must not be `None`.
498+
macro_rules! unsafe_range_trusted_random_access_impl {
499+
($($t:ty)*) => ($(
500+
#[doc(hidden)]
501+
#[unstable(feature = "trusted_random_access", issue = "none")]
502+
unsafe impl TrustedRandomAccess for ops::Range<$t> {
503+
const MAY_HAVE_SIDE_EFFECT: bool = false;
504+
}
505+
)*)
506+
}
507+
496508
macro_rules! range_incl_exact_iter_impl {
497509
($($t:ty)*) => ($(
498510
#[stable(feature = "inclusive_range", since = "1.26.0")]
@@ -553,6 +565,18 @@ impl<A: Step> Iterator for ops::Range<A> {
553565
fn max(mut self) -> Option<A> {
554566
self.next_back()
555567
}
568+
569+
#[inline]
570+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
571+
where
572+
Self: TrustedRandomAccess,
573+
{
574+
// SAFETY: The TrustedRandomAccess contract requires that callers only pass an index
575+
// that is in bounds.
576+
// Additionally Self: TrustedRandomAccess is only implemented for Copy types
577+
// which means even repeated reads of the same index would be safe.
578+
unsafe { Step::forward_unchecked(self.start.clone(), idx) }
579+
}
556580
}
557581

558582
// These macros generate `ExactSizeIterator` impls for various range types.
@@ -574,6 +598,23 @@ range_exact_iter_impl! {
574598
u32
575599
i32
576600
}
601+
602+
unsafe_range_trusted_random_access_impl! {
603+
usize u8 u16
604+
isize i8 i16
605+
}
606+
607+
#[cfg(target_pointer_width = "32")]
608+
unsafe_range_trusted_random_access_impl! {
609+
u32 i32
610+
}
611+
612+
#[cfg(target_pointer_width = "64")]
613+
unsafe_range_trusted_random_access_impl! {
614+
u32 i32
615+
u64 i64
616+
}
617+
577618
range_incl_exact_iter_impl! {
578619
u8
579620
i8

0 commit comments

Comments
 (0)