mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Auto merge of #73565 - matthewjasper:core-min-spec, r=nagisa
Use min_specialization in libcore Getting `TrustedRandomAccess` to work is the main interesting thing here. - `get_unchecked` is now an unstable, hidden method on `Iterator` - The contract for `TrustedRandomAccess` is made clearer in documentation - Fixed a bug where `Debug` would create aliasing references when using the specialized zip impl - Added tests for the side effects of `next_back` and `nth`. closes #68536
This commit is contained in:
commit
d9d4d39612
@ -1,7 +1,7 @@
|
||||
use crate::intrinsics;
|
||||
use crate::iter::{
|
||||
DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess,
|
||||
};
|
||||
use crate::iter::adapters::zip::try_get_unchecked;
|
||||
use crate::iter::TrustedRandomAccess;
|
||||
use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that yields `None` forever after the underlying iterator
|
||||
@ -114,6 +114,19 @@ where
|
||||
{
|
||||
FuseImpl::find(self, predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
match self.iter {
|
||||
// SAFETY: the caller must uphold the contract for `Iterator::get_unchecked`.
|
||||
Some(ref mut iter) => unsafe { try_get_unchecked(iter, idx) },
|
||||
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
|
||||
None => unsafe { intrinsics::unreachable() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -172,19 +185,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Fuse<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
|
||||
match self.iter {
|
||||
// SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`.
|
||||
Some(ref mut iter) => unsafe { iter.get_unchecked(i) },
|
||||
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
|
||||
None => unsafe { intrinsics::unreachable() },
|
||||
}
|
||||
}
|
||||
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ pub use self::chain::Chain;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::flatten::{FlatMap, Flatten};
|
||||
pub use self::fuse::Fuse;
|
||||
use self::zip::try_get_unchecked;
|
||||
pub(crate) use self::zip::TrustedRandomAccess;
|
||||
pub use self::zip::Zip;
|
||||
|
||||
@ -213,6 +214,15 @@ where
|
||||
fn count(self) -> usize {
|
||||
self.it.count()
|
||||
}
|
||||
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> T
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::get_unchecked`.
|
||||
*unsafe { try_get_unchecked(&mut self.it, idx) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
@ -266,16 +276,11 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Copied<I>
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Copied<I>
|
||||
where
|
||||
I: TrustedRandomAccess<Item = &'a T>,
|
||||
T: Copy,
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
|
||||
// SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`.
|
||||
unsafe { *self.it.get_unchecked(i) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
@ -344,6 +349,15 @@ where
|
||||
{
|
||||
self.it.map(T::clone).fold(init, f)
|
||||
}
|
||||
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> T
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::get_unchecked`.
|
||||
unsafe { try_get_unchecked(&mut self.it, idx).clone() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
@ -397,36 +411,14 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Cloned<I>
|
||||
where
|
||||
I: TrustedRandomAccess<Item = &'a T>,
|
||||
T: Clone,
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
default unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
|
||||
// SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`.
|
||||
unsafe { self.it.get_unchecked(i) }.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn may_have_side_effect() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
|
||||
where
|
||||
I: TrustedRandomAccess<Item = &'a T>,
|
||||
T: Copy,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
|
||||
// SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`.
|
||||
unsafe { *self.it.get_unchecked(i) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@ -872,6 +864,15 @@ where
|
||||
{
|
||||
self.iter.fold(init, map_fold(self.f, g))
|
||||
}
|
||||
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> B
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::get_unchecked`.
|
||||
unsafe { (self.f)(try_get_unchecked(&mut self.iter, idx)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -927,15 +928,11 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe impl<B, I, F> TrustedRandomAccess for Map<I, F>
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I, F> TrustedRandomAccess for Map<I, F>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
F: FnMut(I::Item) -> B,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
|
||||
// SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`.
|
||||
(self.f)(unsafe { self.iter.get_unchecked(i) })
|
||||
}
|
||||
#[inline]
|
||||
fn may_have_side_effect() -> bool {
|
||||
true
|
||||
@ -1306,6 +1303,16 @@ where
|
||||
|
||||
self.iter.fold(init, enumerate(self.count, fold))
|
||||
}
|
||||
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::get_unchecked`.
|
||||
let value = unsafe { try_get_unchecked(&mut self.iter, idx) };
|
||||
(Add::add(self.count, idx), value)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -1391,15 +1398,11 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Enumerate<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> (usize, I::Item) {
|
||||
// SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`.
|
||||
(self.count + i, unsafe { self.iter.get_unchecked(i) })
|
||||
}
|
||||
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::cmp;
|
||||
use crate::fmt::{self, Debug};
|
||||
|
||||
use super::super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedLen};
|
||||
|
||||
@ -9,7 +10,7 @@ use super::super::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterat
|
||||
///
|
||||
/// [`zip`]: trait.Iterator.html#method.zip
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Zip<A, B> {
|
||||
@ -56,6 +57,16 @@ where
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
ZipImpl::nth(self, n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: `ZipImpl::get_unchecked` has same safety requirements as
|
||||
// `Iterator::get_unchecked`.
|
||||
unsafe { ZipImpl::get_unchecked(self, idx) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -82,6 +93,10 @@ trait ZipImpl<A, B> {
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator;
|
||||
// This has the same safety requirements as `Iterator::get_unchecked`
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
|
||||
where
|
||||
Self: Iterator + TrustedRandomAccess;
|
||||
}
|
||||
|
||||
// General Zip impl
|
||||
@ -156,16 +171,23 @@ where
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
|
||||
default unsafe fn get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
unreachable!("Always specialized");
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
||||
where
|
||||
A: TrustedRandomAccess,
|
||||
B: TrustedRandomAccess,
|
||||
A: TrustedRandomAccess + Iterator,
|
||||
B: TrustedRandomAccess + Iterator,
|
||||
{
|
||||
fn new(a: A, b: B) -> Self {
|
||||
let len = cmp::min(a.len(), b.len());
|
||||
let len = cmp::min(a.size(), b.size());
|
||||
Zip { a, b, index: 0, len }
|
||||
}
|
||||
|
||||
@ -176,7 +198,7 @@ where
|
||||
self.index += 1;
|
||||
// SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
|
||||
unsafe { Some((self.a.get_unchecked(i), self.b.get_unchecked(i))) }
|
||||
} else if A::may_have_side_effect() && self.index < self.a.len() {
|
||||
} else if A::may_have_side_effect() && self.index < self.a.size() {
|
||||
// match the base implementation's potential side effects
|
||||
// SAFETY: we just checked that `self.index` < `self.a.len()`
|
||||
unsafe {
|
||||
@ -227,20 +249,26 @@ where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
// Adjust a, b to equal length
|
||||
if A::may_have_side_effect() {
|
||||
let sz = self.a.len();
|
||||
if sz > self.len {
|
||||
for _ in 0..sz - cmp::max(self.len, self.index) {
|
||||
self.a.next_back();
|
||||
let a_side_effect = A::may_have_side_effect();
|
||||
let b_side_effect = B::may_have_side_effect();
|
||||
if a_side_effect || b_side_effect {
|
||||
let sz_a = self.a.size();
|
||||
let sz_b = self.b.size();
|
||||
// Adjust a, b to equal length, make sure that only the first call
|
||||
// of `next_back` does this, otherwise we will break the restriction
|
||||
// on calls to `self.next_back()` after calling `get_unchecked()`.
|
||||
if sz_a != sz_b {
|
||||
let sz_a = self.a.size();
|
||||
if a_side_effect && sz_a > self.len {
|
||||
for _ in 0..sz_a - cmp::max(self.len, self.index) {
|
||||
self.a.next_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if B::may_have_side_effect() {
|
||||
let sz = self.b.len();
|
||||
if sz > self.len {
|
||||
for _ in 0..sz - self.len {
|
||||
self.b.next_back();
|
||||
let sz_b = self.b.size();
|
||||
if b_side_effect && sz_b > self.len {
|
||||
for _ in 0..sz_b - self.len {
|
||||
self.b.next_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -254,6 +282,13 @@ where
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::get_unchecked`.
|
||||
unsafe { (self.a.get_unchecked(idx), self.b.get_unchecked(idx)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -265,16 +300,12 @@ where
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
|
||||
where
|
||||
A: TrustedRandomAccess,
|
||||
B: TrustedRandomAccess,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> (A::Item, B::Item) {
|
||||
// SAFETY: the caller must uphold the contract for `TrustedRandomAccess::get_unchecked`.
|
||||
unsafe { (self.a.get_unchecked(i), self.b.get_unchecked(i)) }
|
||||
}
|
||||
|
||||
fn may_have_side_effect() -> bool {
|
||||
A::may_have_side_effect() || B::may_have_side_effect()
|
||||
}
|
||||
@ -296,19 +327,109 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Debug, B: Debug> Debug for Zip<A, B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ZipFmt::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
trait ZipFmt<A, B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
}
|
||||
|
||||
impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
|
||||
default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Zip").field("a", &self.a).field("b", &self.b).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B> for Zip<A, B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// It's *not safe* to call fmt on the contained iterators, since once
|
||||
// we start iterating they're in strange, potentially unsafe, states.
|
||||
f.debug_struct("Zip").finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator whose items are random-accessible efficiently
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The iterator's .len() and size_hint() must be exact.
|
||||
/// `.len()` must be cheap to call.
|
||||
/// The iterator's `size_hint` must be exact and cheap to call.
|
||||
///
|
||||
/// .get_unchecked() must return distinct mutable references for distinct
|
||||
/// indices (if applicable), and must return a valid reference if index is in
|
||||
/// 0..self.len().
|
||||
pub(crate) unsafe trait TrustedRandomAccess: ExactSizeIterator {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item;
|
||||
/// `size` may not be overridden.
|
||||
///
|
||||
/// `<Self as Iterator>::get_unchecked` must be safe to call provided the
|
||||
/// following conditions are met.
|
||||
///
|
||||
/// 1. `0 <= idx` and `idx < self.size()`.
|
||||
/// 2. If `self: !Clone`, then `get_unchecked` is never called with the same
|
||||
/// index on `self` more than once.
|
||||
/// 3. After `self.get_unchecked(idx)` has been called then `next_back` will
|
||||
/// only be called at most `self.size() - idx - 1` times.
|
||||
/// 4. After `get_unchecked` is called, then only the following methods will be
|
||||
/// called on `self`:
|
||||
/// * `std::clone::Clone::clone`
|
||||
/// * `std::iter::Iterator::size_hint()`
|
||||
/// * `std::iter::Iterator::next_back()`
|
||||
/// * `std::iter::Iterator::get_unchecked()`
|
||||
/// * `std::iter::TrustedRandomAccess::size()`
|
||||
///
|
||||
/// Further, given that these conditions are met, it must guarantee that:
|
||||
///
|
||||
/// * It does not change the value returned from `size_hint`
|
||||
/// * It must be safe to call the methods listed above on `self` after calling
|
||||
/// `get_unchecked`, assuming that the required traits are implemented.
|
||||
/// * It must also be safe to drop `self` after calling `get_unchecked`.
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
#[rustc_specialization_trait]
|
||||
pub unsafe trait TrustedRandomAccess: Sized {
|
||||
// Convenience method.
|
||||
fn size(&self) -> usize
|
||||
where
|
||||
Self: Iterator,
|
||||
{
|
||||
self.size_hint().0
|
||||
}
|
||||
/// Returns `true` if getting an iterator element may have
|
||||
/// side effects. Remember to take inner iterators into account.
|
||||
fn may_have_side_effect() -> bool;
|
||||
}
|
||||
|
||||
/// Like `Iterator::get_unchecked`, but doesn't require the compiler to
|
||||
/// know that `U: TrustedRandomAccess`.
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// Same requirements calling `get_unchecked` directly.
|
||||
#[doc(hidden)]
|
||||
pub(in crate::iter::adapters) unsafe fn try_get_unchecked<I>(it: &mut I, idx: usize) -> I::Item
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::get_unchecked`.
|
||||
unsafe { it.try_get_unchecked(idx) }
|
||||
}
|
||||
|
||||
unsafe trait SpecTrustedRandomAccess: Iterator {
|
||||
/// If `Self: TrustedRandomAccess`, it must be safe to call a
|
||||
/// `Iterator::get_unchecked(self, index)`.
|
||||
unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item;
|
||||
}
|
||||
|
||||
unsafe impl<I: Iterator> SpecTrustedRandomAccess for I {
|
||||
default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item {
|
||||
panic!("Should only be called on TrustedRandomAccess iterators");
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<I: Iterator + TrustedRandomAccess> SpecTrustedRandomAccess for I {
|
||||
unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item {
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::get_unchecked`.
|
||||
unsafe { self.get_unchecked(index) }
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use crate::cmp::{self, Ordering};
|
||||
use crate::ops::{Add, Try};
|
||||
|
||||
use super::super::LoopState;
|
||||
use super::super::TrustedRandomAccess;
|
||||
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
|
||||
use super::super::{FlatMap, Flatten};
|
||||
use super::super::{FromIterator, Product, Sum, Zip};
|
||||
@ -3245,6 +3246,17 @@ pub trait Iterator {
|
||||
{
|
||||
self.map(f).is_sorted()
|
||||
}
|
||||
|
||||
/// See [TrustedRandomAccess]
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe fn get_unchecked(&mut self, _idx: usize) -> Self::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
unreachable!("Always specialized");
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -118,7 +118,7 @@
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(simd_ffi)]
|
||||
#![feature(specialization)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
|
@ -3647,21 +3647,21 @@ macro_rules! iterator {
|
||||
struct $name:ident -> $ptr:ty,
|
||||
$elem:ty,
|
||||
$raw_mut:tt,
|
||||
{$( $mut_:tt )*},
|
||||
{$( $mut_:tt )?},
|
||||
{$($extra:tt)*}
|
||||
) => {
|
||||
// Returns the first element and moves the start of the iterator forwards by 1.
|
||||
// Greatly improves performance compared to an inlined function. The iterator
|
||||
// must not be empty.
|
||||
macro_rules! next_unchecked {
|
||||
($self: ident) => {& $( $mut_ )* *$self.post_inc_start(1)}
|
||||
($self: ident) => {& $( $mut_ )? *$self.post_inc_start(1)}
|
||||
}
|
||||
|
||||
// Returns the last element and moves the end of the iterator backwards by 1.
|
||||
// Greatly improves performance compared to an inlined function. The iterator
|
||||
// must not be empty.
|
||||
macro_rules! next_back_unchecked {
|
||||
($self: ident) => {& $( $mut_ )* *$self.pre_dec_end(1)}
|
||||
($self: ident) => {& $( $mut_ )? *$self.pre_dec_end(1)}
|
||||
}
|
||||
|
||||
// Shrinks the iterator when T is a ZST, by moving the end of the iterator
|
||||
@ -3921,6 +3921,21 @@ macro_rules! iterator {
|
||||
None
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
// SAFETY: the caller must guarantee that `i` is in bounds of
|
||||
// the underlying slice, so `i` cannot overflow an `isize`, and
|
||||
// the returned references is guaranteed to refer to an element
|
||||
// of the slice and thus guaranteed to be valid.
|
||||
//
|
||||
// Also note that the caller also guarantees that we're never
|
||||
// called with the same index again, and that no other methods
|
||||
// that will access this subslice are called, so it is valid
|
||||
// for the returned reference to be mutable in the case of
|
||||
// `IterMut`
|
||||
unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) }
|
||||
}
|
||||
|
||||
$($extra)*
|
||||
}
|
||||
|
||||
@ -5005,6 +5020,15 @@ impl<'a, T> Iterator for Windows<'a, T> {
|
||||
Some(&self.v[start..])
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
// SAFETY: since the caller guarantees that `i` is in bounds,
|
||||
// which means that `i` cannot overflow an `isize`, and the
|
||||
// slice created by `from_raw_parts` is a subslice of `self.v`
|
||||
// thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -5044,14 +5068,8 @@ unsafe impl<T> TrustedLen for Windows<'_, T> {}
|
||||
impl<T> FusedIterator for Windows<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for Windows<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
|
||||
// SAFETY: since the caller guarantees that `i` is in bounds,
|
||||
// which means that `i` cannot overflow an `isize`, and the
|
||||
// slice created by `from_raw_parts` is a subslice of `self.v`
|
||||
// thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(i), self.size) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -5141,6 +5159,23 @@ impl<'a, T> Iterator for Chunks<'a, T> {
|
||||
Some(&self.v[start..])
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let start = idx * self.chunk_size;
|
||||
let end = match start.checked_add(self.chunk_size) {
|
||||
None => self.v.len(),
|
||||
Some(end) => cmp::min(end, self.v.len()),
|
||||
};
|
||||
// SAFETY: the caller guarantees that `i` is in bounds,
|
||||
// which means that `start` must be in bounds of the
|
||||
// underlying `self.v` slice, and we made sure that `end`
|
||||
// is also in bounds of `self.v`. Thus, `start` cannot overflow
|
||||
// an `isize`, and the slice constructed by `from_raw_parts`
|
||||
// is a subslice of `self.v` which is guaranteed to be valid
|
||||
// for the lifetime `'a` of `self.v`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -5187,22 +5222,8 @@ unsafe impl<T> TrustedLen for Chunks<'_, T> {}
|
||||
impl<T> FusedIterator for Chunks<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for Chunks<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
|
||||
let start = i * self.chunk_size;
|
||||
let end = match start.checked_add(self.chunk_size) {
|
||||
None => self.v.len(),
|
||||
Some(end) => cmp::min(end, self.v.len()),
|
||||
};
|
||||
// SAFETY: the caller guarantees that `i` is in bounds,
|
||||
// which means that `start` must be in bounds of the
|
||||
// underlying `self.v` slice, and we made sure that `end`
|
||||
// is also in bounds of `self.v`. Thus, `start` cannot overflow
|
||||
// an `isize`, and the slice constructed by `from_raw_parts`
|
||||
// is a subslice of `self.v` which is guaranteed to be valid
|
||||
// for the lifetime `'a` of `self.v`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -5287,6 +5308,22 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
|
||||
Some(&mut self.v[start..])
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let start = idx * self.chunk_size;
|
||||
let end = match start.checked_add(self.chunk_size) {
|
||||
None => self.v.len(),
|
||||
Some(end) => cmp::min(end, self.v.len()),
|
||||
};
|
||||
// SAFETY: see comments for `Chunks::get_unchecked`.
|
||||
//
|
||||
// Also note that the caller also guarantees that we're never called
|
||||
// with the same index again, and that no other methods that will
|
||||
// access this subslice are called, so it is valid for the returned
|
||||
// slice to be mutable.
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -5336,16 +5373,8 @@ unsafe impl<T> TrustedLen for ChunksMut<'_, T> {}
|
||||
impl<T> FusedIterator for ChunksMut<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for ChunksMut<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
|
||||
let start = i * self.chunk_size;
|
||||
let end = match start.checked_add(self.chunk_size) {
|
||||
None => self.v.len(),
|
||||
Some(end) => cmp::min(end, self.v.len()),
|
||||
};
|
||||
// SAFETY: see comments for `Chunks::get_unchecked`.
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -5432,6 +5461,13 @@ impl<'a, T> Iterator for ChunksExact<'a, T> {
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let start = idx * self.chunk_size;
|
||||
// SAFETY: mostly identical to `Chunks::get_unchecked`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "chunks_exact", since = "1.31.0")]
|
||||
@ -5477,13 +5513,8 @@ unsafe impl<T> TrustedLen for ChunksExact<'_, T> {}
|
||||
impl<T> FusedIterator for ChunksExact<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[stable(feature = "chunks_exact", since = "1.31.0")]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for ChunksExact<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
|
||||
let start = i * self.chunk_size;
|
||||
// SAFETY: mostly identical to `Chunks::get_unchecked`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -5564,6 +5595,13 @@ impl<'a, T> Iterator for ChunksExactMut<'a, T> {
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let start = idx * self.chunk_size;
|
||||
// SAFETY: see comments for `ChunksMut::get_unchecked`.
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "chunks_exact", since = "1.31.0")]
|
||||
@ -5612,13 +5650,8 @@ unsafe impl<T> TrustedLen for ChunksExactMut<'_, T> {}
|
||||
impl<T> FusedIterator for ChunksExactMut<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[stable(feature = "chunks_exact", since = "1.31.0")]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for ChunksExactMut<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
|
||||
let start = i * self.chunk_size;
|
||||
// SAFETY: see comments for `ChunksExactMut::get_unchecked`.
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -5689,6 +5722,12 @@ impl<'a, T, const N: usize> Iterator for ArrayChunks<'a, T, N> {
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
self.iter.last()
|
||||
}
|
||||
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T; N] {
|
||||
// SAFETY: The safety guarantees of `get_unchecked` are transferred to
|
||||
// the caller.
|
||||
unsafe { self.iter.get_unchecked(i) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "array_chunks", issue = "74985")]
|
||||
@ -5720,11 +5759,6 @@ impl<T, const N: usize> FusedIterator for ArrayChunks<'_, T, N> {}
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "array_chunks", issue = "74985")]
|
||||
unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T; N] {
|
||||
// SAFETY: The safety guarantees of `get_unchecked` are transferred to
|
||||
// the caller.
|
||||
unsafe { self.iter.get_unchecked(i) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -5817,6 +5851,17 @@ impl<'a, T> Iterator for RChunks<'a, T> {
|
||||
Some(&self.v[0..end])
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let end = self.v.len() - idx * self.chunk_size;
|
||||
let start = match end.checked_sub(self.chunk_size) {
|
||||
None => 0,
|
||||
Some(start) => start,
|
||||
};
|
||||
// SAFETY: mostly identical to `Chunks::get_unchecked`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
@ -5862,17 +5907,8 @@ unsafe impl<T> TrustedLen for RChunks<'_, T> {}
|
||||
impl<T> FusedIterator for RChunks<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for RChunks<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
|
||||
let end = self.v.len() - i * self.chunk_size;
|
||||
let start = match end.checked_sub(self.chunk_size) {
|
||||
None => 0,
|
||||
Some(start) => start,
|
||||
};
|
||||
// SAFETY: mostly identical to `Chunks::get_unchecked`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), end - start) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -5961,6 +5997,17 @@ impl<'a, T> Iterator for RChunksMut<'a, T> {
|
||||
Some(&mut self.v[0..end])
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let end = self.v.len() - idx * self.chunk_size;
|
||||
let start = match end.checked_sub(self.chunk_size) {
|
||||
None => 0,
|
||||
Some(start) => start,
|
||||
};
|
||||
// SAFETY: see comments for `RChunks::get_unchecked` and `ChunksMut::get_unchecked`
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
@ -6008,17 +6055,8 @@ unsafe impl<T> TrustedLen for RChunksMut<'_, T> {}
|
||||
impl<T> FusedIterator for RChunksMut<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for RChunksMut<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
|
||||
let end = self.v.len() - i * self.chunk_size;
|
||||
let start = match end.checked_sub(self.chunk_size) {
|
||||
None => 0,
|
||||
Some(start) => start,
|
||||
};
|
||||
// SAFETY: see comments for `RChunks::get_unchecked`.
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), end - start) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -6105,6 +6143,15 @@ impl<'a, T> Iterator for RChunksExact<'a, T> {
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let end = self.v.len() - idx * self.chunk_size;
|
||||
let start = end - self.chunk_size;
|
||||
// SAFETY:
|
||||
// SAFETY: mostmy identical to `Chunks::get_unchecked`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
@ -6153,14 +6200,8 @@ unsafe impl<T> TrustedLen for RChunksExact<'_, T> {}
|
||||
impl<T> FusedIterator for RChunksExact<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for RChunksExact<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T] {
|
||||
let end = self.v.len() - i * self.chunk_size;
|
||||
let start = end - self.chunk_size;
|
||||
// SAFETY: mostmy identical to `Chunks::get_unchecked`.
|
||||
unsafe { from_raw_parts(self.v.as_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -6243,6 +6284,14 @@ impl<'a, T> Iterator for RChunksExactMut<'a, T> {
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> Self::Item {
|
||||
let end = self.v.len() - idx * self.chunk_size;
|
||||
let start = end - self.chunk_size;
|
||||
// SAFETY: see comments for `RChunksMut::get_unchecked`.
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
@ -6293,14 +6342,8 @@ unsafe impl<T> TrustedLen for RChunksExactMut<'_, T> {}
|
||||
impl<T> FusedIterator for RChunksExactMut<'_, T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[stable(feature = "rchunks", since = "1.31.0")]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for RChunksExactMut<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut [T] {
|
||||
let end = self.v.len() - i * self.chunk_size;
|
||||
let start = end - self.chunk_size;
|
||||
// SAFETY: see comments for `RChunksExact::get_unchecked`.
|
||||
unsafe { from_raw_parts_mut(self.v.as_mut_ptr().add(start), self.chunk_size) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
@ -6543,18 +6586,20 @@ where
|
||||
}
|
||||
|
||||
// Use an equal-pointer optimization when types are `Eq`
|
||||
impl<A> SlicePartialEq<A> for [A]
|
||||
// We can't make `A` and `B` the same type because `min_specialization` won't
|
||||
// allow it.
|
||||
impl<A, B> SlicePartialEq<B> for [A]
|
||||
where
|
||||
A: PartialEq<A> + Eq,
|
||||
A: MarkerEq<B>,
|
||||
{
|
||||
default fn equal(&self, other: &[A]) -> bool {
|
||||
default fn equal(&self, other: &[B]) -> bool {
|
||||
if self.len() != other.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// While performance would suffer if `guaranteed_eq` just returned `false`
|
||||
// for all arguments, correctness and return value of this function are not affected.
|
||||
if self.as_ptr().guaranteed_eq(other.as_ptr()) {
|
||||
if self.as_ptr().guaranteed_eq(other.as_ptr() as *const A) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -6563,18 +6608,18 @@ where
|
||||
}
|
||||
|
||||
// Use memcmp for bytewise equality when the types allow
|
||||
impl<A> SlicePartialEq<A> for [A]
|
||||
impl<A, B> SlicePartialEq<B> for [A]
|
||||
where
|
||||
A: PartialEq<A> + BytewiseEquality,
|
||||
A: BytewiseEquality<B>,
|
||||
{
|
||||
fn equal(&self, other: &[A]) -> bool {
|
||||
fn equal(&self, other: &[B]) -> bool {
|
||||
if self.len() != other.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// While performance would suffer if `guaranteed_eq` just returned `false`
|
||||
// for all arguments, correctness and return value of this function are not affected.
|
||||
if self.as_ptr().guaranteed_eq(other.as_ptr()) {
|
||||
if self.as_ptr().guaranteed_eq(other.as_ptr() as *const A) {
|
||||
return true;
|
||||
}
|
||||
// SAFETY: `self` and `other` are references and are thus guaranteed to be valid.
|
||||
@ -6631,6 +6676,7 @@ impl<A: AlwaysApplicableOrd> SlicePartialOrd for A {
|
||||
}
|
||||
}
|
||||
|
||||
#[rustc_specialization_trait]
|
||||
trait AlwaysApplicableOrd: SliceOrd + Ord {}
|
||||
|
||||
macro_rules! always_applicable_ord {
|
||||
@ -6695,15 +6741,22 @@ impl SliceOrd for u8 {
|
||||
}
|
||||
}
|
||||
|
||||
// Hack to allow specializing on `Eq` even though `Eq` has a method.
|
||||
#[rustc_unsafe_specialization_marker]
|
||||
trait MarkerEq<T>: PartialEq<T> {}
|
||||
|
||||
impl<T: Eq> MarkerEq<T> for T {}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Trait implemented for types that can be compared for equality using
|
||||
/// their bytewise representation
|
||||
trait BytewiseEquality: Eq + Copy {}
|
||||
#[rustc_specialization_trait]
|
||||
trait BytewiseEquality<T>: MarkerEq<T> + Copy {}
|
||||
|
||||
macro_rules! impl_marker_for {
|
||||
($traitname:ident, $($ty:ty)*) => {
|
||||
$(
|
||||
impl $traitname for $ty { }
|
||||
impl $traitname<$ty> for $ty { }
|
||||
)*
|
||||
}
|
||||
}
|
||||
@ -6712,25 +6765,16 @@ impl_marker_for!(BytewiseEquality,
|
||||
u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize char bool);
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a T {
|
||||
// SAFETY: the caller must guarantee that `i` is in bounds
|
||||
// of the underlying slice, so `i` cannot overflow an `isize`,
|
||||
// and the returned references is guaranteed to refer to an element
|
||||
// of the slice and thus guaranteed to be valid.
|
||||
unsafe { &*self.ptr.as_ptr().add(i) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<'a, T> TrustedRandomAccess for IterMut<'a, T> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> &'a mut T {
|
||||
// SAFETY: see comments for `Iter::get_unchecked`.
|
||||
unsafe { &mut *self.ptr.as_ptr().add(i) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
|
@ -13,8 +13,9 @@ use self::pattern::{DoubleEndedSearcher, ReverseSearcher, Searcher};
|
||||
|
||||
use crate::char;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::iter::TrustedRandomAccess;
|
||||
use crate::iter::{Chain, FlatMap, Flatten};
|
||||
use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen, TrustedRandomAccess};
|
||||
use crate::iter::{Copied, Filter, FusedIterator, Map, TrustedLen};
|
||||
use crate::mem;
|
||||
use crate::ops::Try;
|
||||
use crate::option;
|
||||
@ -819,6 +820,13 @@ impl Iterator for Bytes<'_> {
|
||||
{
|
||||
self.0.rposition(predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> u8 {
|
||||
// SAFETY: the caller must uphold the safety contract
|
||||
// for `Iterator::get_unchecked`.
|
||||
unsafe { self.0.get_unchecked(idx) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -862,12 +870,8 @@ impl FusedIterator for Bytes<'_> {}
|
||||
unsafe impl TrustedLen for Bytes<'_> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl TrustedRandomAccess for Bytes<'_> {
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> u8 {
|
||||
// SAFETY: the caller must uphold the safety contract
|
||||
// for `TrustedRandomAccess::get_unchecked`.
|
||||
unsafe { self.0.get_unchecked(i) }
|
||||
}
|
||||
fn may_have_side_effect() -> bool {
|
||||
false
|
||||
}
|
||||
|
@ -304,6 +304,103 @@ fn test_zip_nth_side_effects() {
|
||||
assert_eq!(b, vec![200, 300, 400, 500, 600]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zip_next_back_side_effects() {
|
||||
let mut a = Vec::new();
|
||||
let mut b = Vec::new();
|
||||
let mut iter = [1, 2, 3, 4, 5, 6]
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|n| {
|
||||
a.push(n);
|
||||
n * 10
|
||||
})
|
||||
.zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
|
||||
b.push(n * 100);
|
||||
n * 1000
|
||||
}));
|
||||
|
||||
// The second iterator is one item longer, so `next_back` is called on it
|
||||
// one more time.
|
||||
assert_eq!(iter.next_back(), Some((60, 7000)));
|
||||
assert_eq!(iter.next_back(), Some((50, 6000)));
|
||||
assert_eq!(iter.next_back(), Some((40, 5000)));
|
||||
assert_eq!(iter.next_back(), Some((30, 4000)));
|
||||
assert_eq!(a, vec![6, 5, 4, 3]);
|
||||
assert_eq!(b, vec![800, 700, 600, 500, 400]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zip_nth_back_side_effects() {
|
||||
let mut a = Vec::new();
|
||||
let mut b = Vec::new();
|
||||
let value = [1, 2, 3, 4, 5, 6]
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|n| {
|
||||
a.push(n);
|
||||
n * 10
|
||||
})
|
||||
.zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
|
||||
b.push(n * 100);
|
||||
n * 1000
|
||||
}))
|
||||
.nth_back(3);
|
||||
assert_eq!(value, Some((30, 4000)));
|
||||
assert_eq!(a, vec![6, 5, 4, 3]);
|
||||
assert_eq!(b, vec![800, 700, 600, 500, 400]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zip_next_back_side_effects_exhausted() {
|
||||
let mut a = Vec::new();
|
||||
let mut b = Vec::new();
|
||||
let mut iter = [1, 2, 3, 4, 5, 6]
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|n| {
|
||||
a.push(n);
|
||||
n * 10
|
||||
})
|
||||
.zip([2, 3, 4].iter().cloned().map(|n| {
|
||||
b.push(n * 100);
|
||||
n * 1000
|
||||
}));
|
||||
|
||||
iter.next();
|
||||
iter.next();
|
||||
iter.next();
|
||||
iter.next();
|
||||
assert_eq!(iter.next_back(), None);
|
||||
assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
|
||||
assert_eq!(b, vec![200, 300, 400]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zip_nth_back_side_effects_exhausted() {
|
||||
let mut a = Vec::new();
|
||||
let mut b = Vec::new();
|
||||
let mut iter = [1, 2, 3, 4, 5, 6]
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|n| {
|
||||
a.push(n);
|
||||
n * 10
|
||||
})
|
||||
.zip([2, 3, 4].iter().cloned().map(|n| {
|
||||
b.push(n * 100);
|
||||
n * 1000
|
||||
}));
|
||||
|
||||
iter.next();
|
||||
iter.next();
|
||||
iter.next();
|
||||
iter.next();
|
||||
assert_eq!(iter.nth_back(0), None);
|
||||
assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
|
||||
assert_eq!(b, vec![200, 300, 400]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_step_by() {
|
||||
// Identity
|
||||
|
Loading…
Reference in New Issue
Block a user