Skip to content

Commit 99f95e5

Browse files
committed
Improve documentation of TrustedRandomAccess
Include new details regarding coercions to a subtype. These conditions also explain why the previously removed implementations for {array, vec, vec_deque}::IntoIter<T> were unsound, because they introduced an extra `T: Clone` for the TrustedRandomAccess impl, even though their parameter T is covariant.
1 parent a1f68b5 commit 99f95e5

File tree

1 file changed

+30
-14
lines changed
  • library/core/src/iter/adapters

1 file changed

+30
-14
lines changed

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

+30-14
Original file line numberDiff line numberDiff line change
@@ -433,28 +433,44 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
433433
///
434434
/// `size` may not be overridden.
435435
///
436-
/// `<Self as Iterator>::__iterator_get_unchecked` must be safe to call
437-
/// provided the following conditions are met.
436+
/// All subtypes and all supertypes of `Self` must also implement `TrustedRandomAccess`.
437+
/// In particular, this means that types with non-invariant parameters usually can not have
438+
/// an impl for `TrustedRandomAccess` that depends on any trait bounds on such parameters, except
439+
/// for bounds that come from the respective struct/enum definition itself, or bounds involving
440+
/// traits that themselves come with a guarantee similar to this one.
441+
///
442+
/// If `Self: Iterator`, then `<Self as Iterator>::__iterator_get_unchecked(&mut self, idx)`
443+
/// must be safe to call provided the following conditions are met.
438444
///
439445
/// 1. `0 <= idx` and `idx < self.size()`.
440-
/// 2. If `self: !Clone`, then `get_unchecked` is never called with the same
446+
/// 2. If `Self: !Clone`, then `self.__iterator_get_unchecked(idx)` is never called with the same
441447
/// index on `self` more than once.
442-
/// 3. After `self.get_unchecked(idx)` has been called then `next_back` will
443-
/// only be called at most `self.size() - idx - 1` times.
444-
/// 4. After `get_unchecked` is called, then only the following methods will be
445-
/// called on `self`:
446-
/// * `std::clone::Clone::clone()`
447-
/// * `std::iter::Iterator::size_hint()`
448-
/// * `std::iter::DoubleEndedIterator::next_back()`
449-
/// * `std::iter::Iterator::__iterator_get_unchecked()`
450-
/// * `std::iter::TrustedRandomAccess::size()`
448+
/// 3. After `self.__iterator_get_unchecked(idx)` has been called, then `self.next_back()` will
449+
/// only be called at most `self.size() - idx - 1` times. If `Self: Clone` and `self` is cloned,
450+
/// then this number is calculated for `self` and its clone individually,
451+
/// but `self.next_back()` calls that happened before the cloning count for both `self` and the clone.
452+
/// 4. After `self.__iterator_get_unchecked(idx)` has been called, then only the following methods
453+
/// will be called on `self` or on any new clones of `self`:
454+
/// * `std::clone::Clone::clone`
455+
/// * `std::iter::Iterator::size_hint`
456+
/// * `std::iter::DoubleEndedIterator::next_back`
457+
/// * `std::iter::Iterator::__iterator_get_unchecked`
458+
/// * `std::iter::TrustedRandomAccess::size`
459+
/// 5. If `T` is a subtype of `Self`, then `self` is allowed to be coerced
460+
/// to `T`. If `self` is coerced to `T` after `self.__iterator_get_unchecked(idx)` has already
461+
/// been called, then no methods except for the ones listed under 4. are allowed to be called
462+
/// on the resulting value of type `T`, either. Multiple such coercion steps are allowed.
463+
/// Regarding 2. and 3., the number of times `__iterator_get_unchecked(idx)` or `next_back()` is
464+
/// called on `self` and the resulting value of type `T` (and on further coercion results with
465+
/// sub-subtypes) are added together and their sums must not exceed the specified bounds.
451466
///
452467
/// Further, given that these conditions are met, it must guarantee that:
453468
///
454469
/// * It does not change the value returned from `size_hint`
455470
/// * It must be safe to call the methods listed above on `self` after calling
456-
/// `get_unchecked`, assuming that the required traits are implemented.
457-
/// * It must also be safe to drop `self` after calling `get_unchecked`.
471+
/// `self.__iterator_get_unchecked(idx)`, assuming that the required traits are implemented.
472+
/// * It must also be safe to drop `self` after calling `self.__iterator_get_unchecked(idx)`.
473+
/// * If `T` is a subtype of `Self`, then it must be safe to coerce `self` to `T`.
458474
#[doc(hidden)]
459475
#[unstable(feature = "trusted_random_access", issue = "none")]
460476
#[rustc_specialization_trait]

0 commit comments

Comments
 (0)