Skip to content

Commit aec6846

Browse files
committed
remove TrustedRandomAccess vs. TrustedRandomAccessNoCoerce distinction
TRA is no longer used for single-step (`next()`) specializations, only loops and after each loop we bring the iterator back into a safe state, meaning coercions are now safe because the user code will not have access to an iterator instance that would be unsafe to coerce.
1 parent a66cd5b commit aec6846

File tree

17 files changed

+61
-202
lines changed

17 files changed

+61
-202
lines changed

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

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

@@ -205,11 +205,7 @@ unsafe impl<T> TrustedLen for Iter<'_, T> {}
205205

206206
#[doc(hidden)]
207207
#[unstable(feature = "trusted_random_access", issue = "none")]
208-
unsafe impl<T> TrustedRandomAccess for Iter<'_, T> {}
209-
210-
#[doc(hidden)]
211-
#[unstable(feature = "trusted_random_access", issue = "none")]
212-
unsafe impl<T> TrustedRandomAccessNoCoerce for Iter<'_, T> {
208+
unsafe impl<T> TrustedRandomAccess for Iter<'_, T> {
213209
const NEEDS_CLEANUP: bool = false;
214210

215211
fn cleanup(&mut self, num: usize, forward: bool) {

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

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

55
use super::{count, wrap_index, RingSlices};
@@ -154,11 +154,7 @@ unsafe impl<T> TrustedLen for IterMut<'_, T> {}
154154

155155
#[doc(hidden)]
156156
#[unstable(feature = "trusted_random_access", issue = "none")]
157-
unsafe impl<T> TrustedRandomAccess for IterMut<'_, T> {}
158-
159-
#[doc(hidden)]
160-
#[unstable(feature = "trusted_random_access", issue = "none")]
161-
unsafe impl<T> TrustedRandomAccessNoCoerce for IterMut<'_, T> {
157+
unsafe impl<T> TrustedRandomAccess for IterMut<'_, T> {
162158
const NEEDS_CLEANUP: bool = false;
163159

164160
fn cleanup(&mut self, num: usize, forward: bool) {

library/alloc/src/vec/in_place_collect.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
//! # O(1) collect
6161
//!
6262
//! The main iteration itself is further specialized when the iterator implements
63-
//! [`TrustedRandomAccessNoCoerce`] to let the optimizer see that it is a counted loop with a single
63+
//! [`TrustedRandomAccess`] to let the optimizer see that it is a counted loop with a single
6464
//! [induction variable]. This can turn some iterators into a noop, i.e. it reduces them from O(n) to
6565
//! O(1). This particular optimization is quite fickle and doesn't always work, see [#79308]
6666
//!
@@ -70,7 +70,7 @@
7070
//! Since unchecked accesses through that trait do not advance the read pointer of `IntoIter`
7171
//! this would interact unsoundly with the requirements about dropping the tail described above.
7272
//! But since the normal `Drop` implementation of `IntoIter` would suffer from the same problem it
73-
//! is only correct for `TrustedRandomAccessNoCoerce` to be implemented when the items don't
73+
//! is only correct for `TrustedRandomAccess` to be implemented when the items don't
7474
//! have a destructor. Thus that implicit requirement also makes the specialization safe to use for
7575
//! in-place collection.
7676
//! Note that this safety concern is about the correctness of `impl Drop for IntoIter`,
@@ -134,7 +134,7 @@
134134
//! }
135135
//! vec.truncate(write_idx);
136136
//! ```
137-
use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce};
137+
use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccess};
138138
use core::mem::{self, ManuallyDrop};
139139
use core::ptr::{self};
140140

@@ -195,7 +195,7 @@ where
195195
// itself once IntoIter goes out of scope.
196196
// If the drop panics then we also leak any elements collected into dst_buf.
197197
//
198-
// Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce
198+
// Note: This access to the source wouldn't be allowed by the TrustedRandomIterator
199199
// contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the
200200
// module documenttation why this is ok anyway.
201201
src.forget_allocation_drop_remaining();
@@ -230,7 +230,7 @@ trait SpecInPlaceCollect<T, I>: Iterator<Item = T> {
230230
/// collected. `end` is the last writable element of the allocation and used for bounds checks.
231231
///
232232
/// This method is specialized and one of its implementations makes use of
233-
/// `Iterator::__iterator_get_unchecked` calls with a `TrustedRandomAccessNoCoerce` bound
233+
/// `Iterator::__iterator_get_unchecked` calls with a `TrustedRandomAccess` bound
234234
/// on `I` which means the caller of this method must take the safety conditions
235235
/// of that trait into consideration.
236236
fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize;
@@ -256,7 +256,7 @@ where
256256

257257
impl<T, I> SpecInPlaceCollect<T, I> for I
258258
where
259-
I: Iterator<Item = T> + TrustedRandomAccessNoCoerce,
259+
I: Iterator<Item = T> + TrustedRandomAccess,
260260
{
261261
#[inline]
262262
fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {

library/alloc/src/vec/into_iter.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ use crate::alloc::{Allocator, Global};
44
use crate::raw_vec::RawVec;
55
use core::fmt;
66
use core::intrinsics::arith_offset;
7-
use core::iter::{
8-
FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce,
9-
};
7+
use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess};
108
use core::marker::PhantomData;
119
use core::mem::{self, ManuallyDrop};
1210
use core::ops::Deref;
@@ -200,7 +198,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
200198
#[doc(hidden)]
201199
unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item
202200
where
203-
Self: TrustedRandomAccessNoCoerce,
201+
Self: TrustedRandomAccess,
204202
{
205203
// SAFETY: the caller must guarantee that `i` is in bounds of the
206204
// `Vec<T>`, so `i` cannot overflow an `isize`, and the `self.ptr.add(i)`
@@ -284,9 +282,7 @@ impl<T: Copy> NonDrop for T {}
284282

285283
#[doc(hidden)]
286284
#[unstable(issue = "none", feature = "std_internals")]
287-
// TrustedRandomAccess (without NoCoerce) must not be implemented because
288-
// subtypes/supertypes of `T` might not be `NonDrop`
289-
unsafe impl<T, A: Allocator> TrustedRandomAccessNoCoerce for IntoIter<T, A>
285+
unsafe impl<T, A: Allocator> TrustedRandomAccess for IntoIter<T, A>
290286
where
291287
T: NonDrop,
292288
{

library/core/src/iter/adapters/cloned.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use crate::iter::adapters::{
2-
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
3-
};
1+
use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess};
42
use crate::iter::{FusedIterator, TrustedLen};
53
use crate::ops::Try;
64

@@ -63,7 +61,7 @@ where
6361
#[doc(hidden)]
6462
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
6563
where
66-
Self: TrustedRandomAccessNoCoerce,
64+
Self: TrustedRandomAccess,
6765
{
6866
// SAFETY: the caller must uphold the contract for
6967
// `Iterator::__iterator_get_unchecked`.
@@ -123,13 +121,9 @@ where
123121

124122
#[doc(hidden)]
125123
#[unstable(feature = "trusted_random_access", issue = "none")]
126-
unsafe impl<I> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess {}
127-
128-
#[doc(hidden)]
129-
#[unstable(feature = "trusted_random_access", issue = "none")]
130-
unsafe impl<I> TrustedRandomAccessNoCoerce for Cloned<I>
124+
unsafe impl<I> TrustedRandomAccess for Cloned<I>
131125
where
132-
I: TrustedRandomAccessNoCoerce,
126+
I: TrustedRandomAccess,
133127
{
134128
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
135129

library/core/src/iter/adapters/copied.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use crate::iter::adapters::{
2-
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
3-
};
1+
use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess};
42
use crate::iter::{FusedIterator, TrustedLen};
53
use crate::ops::Try;
64

@@ -84,7 +82,7 @@ where
8482
#[doc(hidden)]
8583
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
8684
where
87-
Self: TrustedRandomAccessNoCoerce,
85+
Self: TrustedRandomAccess,
8886
{
8987
// SAFETY: the caller must uphold the contract for
9088
// `Iterator::__iterator_get_unchecked`.
@@ -149,13 +147,9 @@ where
149147

150148
#[doc(hidden)]
151149
#[unstable(feature = "trusted_random_access", issue = "none")]
152-
unsafe impl<I> TrustedRandomAccess for Copied<I> where I: TrustedRandomAccess {}
153-
154-
#[doc(hidden)]
155-
#[unstable(feature = "trusted_random_access", issue = "none")]
156-
unsafe impl<I> TrustedRandomAccessNoCoerce for Copied<I>
150+
unsafe impl<I> TrustedRandomAccess for Copied<I>
157151
where
158-
I: TrustedRandomAccessNoCoerce,
152+
I: TrustedRandomAccess,
159153
{
160154
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
161155

library/core/src/iter/adapters/enumerate.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use crate::iter::adapters::{
2-
zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
3-
};
1+
use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
42
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
53
use crate::ops::Try;
64

@@ -132,7 +130,7 @@ where
132130
#[inline]
133131
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
134132
where
135-
Self: TrustedRandomAccessNoCoerce,
133+
Self: TrustedRandomAccess,
136134
{
137135
// SAFETY: the caller must uphold the contract for
138136
// `Iterator::__iterator_get_unchecked`.
@@ -232,13 +230,9 @@ where
232230

233231
#[doc(hidden)]
234232
#[unstable(feature = "trusted_random_access", issue = "none")]
235-
unsafe impl<I> TrustedRandomAccess for Enumerate<I> where I: TrustedRandomAccess {}
236-
237-
#[doc(hidden)]
238-
#[unstable(feature = "trusted_random_access", issue = "none")]
239-
unsafe impl<I> TrustedRandomAccessNoCoerce for Enumerate<I>
233+
unsafe impl<I> TrustedRandomAccess for Enumerate<I>
240234
where
241-
I: TrustedRandomAccessNoCoerce,
235+
I: TrustedRandomAccess,
242236
{
243237
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
244238

library/core/src/iter/adapters/fuse.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::intrinsics;
22
use crate::iter::adapters::zip::try_get_unchecked;
33
use crate::iter::{
44
DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccess,
5-
TrustedRandomAccessNoCoerce,
65
};
76
use crate::ops::Try;
87

@@ -132,7 +131,7 @@ where
132131
#[doc(hidden)]
133132
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
134133
where
135-
Self: TrustedRandomAccessNoCoerce,
134+
Self: TrustedRandomAccess,
136135
{
137136
match self.iter {
138137
// SAFETY: the caller must uphold the contract for
@@ -222,13 +221,9 @@ unsafe impl<I> TrustedLen for Fuse<I> where I: TrustedLen {}
222221
//
223222
// This is safe to implement as `Fuse` is just forwarding these to the wrapped iterator `I`, which
224223
// preserves these properties.
225-
unsafe impl<I> TrustedRandomAccess for Fuse<I> where I: TrustedRandomAccess {}
226-
227-
#[doc(hidden)]
228-
#[unstable(feature = "trusted_random_access", issue = "none")]
229-
unsafe impl<I> TrustedRandomAccessNoCoerce for Fuse<I>
224+
unsafe impl<I> TrustedRandomAccess for Fuse<I>
230225
where
231-
I: TrustedRandomAccessNoCoerce,
226+
I: TrustedRandomAccess,
232227
{
233228
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
234229

library/core/src/iter/adapters/map.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
use crate::fmt;
2-
use crate::iter::adapters::{
3-
zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
4-
};
2+
use crate::iter::adapters::{zip::try_get_unchecked, SourceIter, TrustedRandomAccess};
53
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
64
use crate::ops::Try;
75

@@ -128,7 +126,7 @@ where
128126
#[inline]
129127
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> B
130128
where
131-
Self: TrustedRandomAccessNoCoerce,
129+
Self: TrustedRandomAccess,
132130
{
133131
// SAFETY: the caller must uphold the contract for
134132
// `Iterator::__iterator_get_unchecked`.
@@ -190,13 +188,9 @@ where
190188

191189
#[doc(hidden)]
192190
#[unstable(feature = "trusted_random_access", issue = "none")]
193-
unsafe impl<I, F> TrustedRandomAccess for Map<I, F> where I: TrustedRandomAccess {}
194-
195-
#[doc(hidden)]
196-
#[unstable(feature = "trusted_random_access", issue = "none")]
197-
unsafe impl<I, F> TrustedRandomAccessNoCoerce for Map<I, F>
191+
unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
198192
where
199-
I: TrustedRandomAccessNoCoerce,
193+
I: TrustedRandomAccess,
200194
{
201195
const NEEDS_CLEANUP: bool = I::NEEDS_CLEANUP;
202196

library/core/src/iter/adapters/mod.rs

-3
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ pub use self::map_while::MapWhile;
5555
#[unstable(feature = "trusted_random_access", issue = "none")]
5656
pub use self::zip::TrustedRandomAccess;
5757

58-
#[unstable(feature = "trusted_random_access", issue = "none")]
59-
pub use self::zip::TrustedRandomAccessNoCoerce;
60-
6158
#[stable(feature = "iter_zip", since = "1.59.0")]
6259
pub use self::zip::zip;
6360

library/core/src/iter/adapters/zip.rs

+6-38
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ where
9292
#[doc(hidden)]
9393
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
9494
where
95-
Self: TrustedRandomAccessNoCoerce,
95+
Self: TrustedRandomAccess,
9696
{
9797
// SAFETY: the caller must uphold the contract for
9898
// `Iterator::__iterator_get_unchecked`.
@@ -257,15 +257,6 @@ unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
257257
where
258258
A: TrustedRandomAccess,
259259
B: TrustedRandomAccess,
260-
{
261-
}
262-
263-
#[doc(hidden)]
264-
#[unstable(feature = "trusted_random_access", issue = "none")]
265-
unsafe impl<A, B> TrustedRandomAccessNoCoerce for Zip<A, B>
266-
where
267-
A: TrustedRandomAccessNoCoerce,
268-
B: TrustedRandomAccessNoCoerce,
269260
{
270261
const NEEDS_CLEANUP: bool = A::NEEDS_CLEANUP || B::NEEDS_CLEANUP;
271262

@@ -328,9 +319,7 @@ impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
328319
}
329320
}
330321

331-
impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoerce> ZipFmt<A, B>
332-
for Zip<A, B>
333-
{
322+
impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B> for Zip<A, B> {
334323
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
335324
// It's *not safe* to call fmt on the contained iterators, since once
336325
// we start iterating they're in strange, potentially unsafe, states.
@@ -344,7 +333,7 @@ impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoe
344333
///
345334
/// The iterator's `size_hint` must be exact and cheap to call.
346335
///
347-
/// `TrustedRandomAccessNoCoerce::size` may not be overridden.
336+
/// `TrustedRandomAccess::size` may not be overridden.
348337
///
349338
/// All subtypes and all supertypes of `Self` must also implement `TrustedRandomAccess`.
350339
/// In particular, this means that types with non-invariant parameters usually can not have
@@ -372,42 +361,21 @@ impl<A: Debug + TrustedRandomAccessNoCoerce, B: Debug + TrustedRandomAccessNoCoe
372361
/// * `std::iter::DoubleEndedIterator::next_back`
373362
/// * `std::iter::ExactSizeIterator::len`
374363
/// * `std::iter::Iterator::__iterator_get_unchecked`
375-
/// * `std::iter::TrustedRandomAccessNoCoerce::size`
376-
/// 5. If `T` is a subtype of `Self`, then `self` is allowed to be coerced
377-
/// to `T`. If `self` is coerced to `T` after `self.__iterator_get_unchecked(idx)` has already
378-
/// been called, then no methods except for the ones listed under 4. are allowed to be called
379-
/// on the resulting value of type `T`, either. Multiple such coercion steps are allowed.
380-
/// Regarding 2. and 3., the number of times `__iterator_get_unchecked(idx)` or `next_back()` is
381-
/// called on `self` and the resulting value of type `T` (and on further coercion results with
382-
/// sub-subtypes) are added together and their sums must not exceed the specified bounds.
364+
/// * `std::iter::TrustedRandomAccess::size`
383365
///
384366
/// Further, given that these conditions are met, it must guarantee that:
385367
///
386368
/// * It does not change the value returned from `size_hint`
387369
/// * It must be safe to call the methods listed above on `self` after calling
388370
/// `self.__iterator_get_unchecked(idx)`, assuming that the required traits are implemented.
389371
/// * It must also be safe to drop `self` after calling `self.__iterator_get_unchecked(idx)`.
390-
/// * If `T` is a subtype of `Self`, then it must be safe to coerce `self` to `T`.
391372
//
392373
// FIXME: Clarify interaction with SourceIter/InPlaceIterable. Calling `SourceIter::as_inner`
393374
// after `__iterator_get_unchecked` is supposed to be allowed.
394375
#[doc(hidden)]
395376
#[unstable(feature = "trusted_random_access", issue = "none")]
396377
#[rustc_specialization_trait]
397-
pub unsafe trait TrustedRandomAccess: TrustedRandomAccessNoCoerce {}
398-
399-
/// Like [`TrustedRandomAccess`] but without any of the requirements / guarantees around
400-
/// coercions to subtypes after `__iterator_get_unchecked` (they aren’t allowed here!), and
401-
/// without the requirement that subtypes / supertypes implement `TrustedRandomAccessNoCoerce`.
402-
///
403-
/// This trait was created in PR #85874 to fix soundness issue #85873 without performance regressions.
404-
/// It is subject to change as we might want to build a more generally useful (for performance
405-
/// optimizations) and more sophisticated trait or trait hierarchy that replaces or extends
406-
/// [`TrustedRandomAccess`] and `TrustedRandomAccessNoCoerce`.
407-
#[doc(hidden)]
408-
#[unstable(feature = "trusted_random_access", issue = "none")]
409-
#[rustc_specialization_trait]
410-
pub unsafe trait TrustedRandomAccessNoCoerce: Sized {
378+
pub unsafe trait TrustedRandomAccess: Sized {
411379
// Convenience method.
412380
fn size(&self) -> usize
413381
where
@@ -450,7 +418,7 @@ unsafe impl<I: Iterator> SpecTrustedRandomAccess for I {
450418
}
451419
}
452420

453-
unsafe impl<I: Iterator + TrustedRandomAccessNoCoerce> SpecTrustedRandomAccess for I {
421+
unsafe impl<I: Iterator + TrustedRandomAccess> SpecTrustedRandomAccess for I {
454422
#[inline]
455423
unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item {
456424
// SAFETY: the caller must uphold the contract for

0 commit comments

Comments
 (0)