Specialize implementations
Implementations in stdlib are now optimized as they were before.
This commit is contained in:
parent
a875876027
commit
bc2f0fb5a9
@ -17,6 +17,8 @@
|
|||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(label_break_value)]
|
#![feature(label_break_value)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
|
#![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(fn_traits)]
|
#![feature(fn_traits)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
|
|
||||||
pub mod bit_set;
|
pub mod bit_set;
|
||||||
pub mod vec;
|
pub mod vec;
|
||||||
|
@ -204,6 +204,9 @@ fn backward_checked(start: Self, u: usize) -> Option<Self> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety: The implementation of `Step` upholds all invariants.
|
||||||
|
unsafe impl ::std::iter::TrustedStep for $type {}
|
||||||
|
|
||||||
impl From<$type> for u32 {
|
impl From<$type> for u32 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(v: $type) -> u32 {
|
fn from(v: $type) -> u32 {
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
#![recursion_limit = "512"] // For rustdoc
|
#![recursion_limit = "512"] // For rustdoc
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(thread_local_const_init)]
|
#![feature(thread_local_const_init)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
#![recursion_limit = "512"]
|
#![recursion_limit = "512"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#![feature(option_get_or_insert_default)]
|
#![feature(option_get_or_insert_default)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
#![feature(control_flow_enum)]
|
#![feature(control_flow_enum)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#![feature(iter_zip)]
|
#![feature(iter_zip)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate tracing;
|
extern crate tracing;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(thread_local_const_init)]
|
#![feature(thread_local_const_init)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc_macros;
|
extern crate rustc_macros;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(exhaustive_patterns)]
|
#![feature(exhaustive_patterns)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
#![feature(min_specialization)]
|
||||||
|
#![feature(trusted_step)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
@ -384,6 +384,8 @@
|
|||||||
pub use self::traits::InPlaceIterable;
|
pub use self::traits::InPlaceIterable;
|
||||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||||
pub use self::traits::TrustedLen;
|
pub use self::traits::TrustedLen;
|
||||||
|
#[unstable(feature = "trusted_step", issue = "85731")]
|
||||||
|
pub use self::traits::TrustedStep;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::traits::{
|
pub use self::traits::{
|
||||||
DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
|
DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum,
|
||||||
|
@ -3,7 +3,16 @@
|
|||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::ops::{self, Try};
|
use crate::ops::{self, Try};
|
||||||
|
|
||||||
use super::{FusedIterator, TrustedLen, TrustedRandomAccess};
|
use super::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedStep};
|
||||||
|
|
||||||
|
// Safety: All invariants are upheld.
|
||||||
|
macro_rules! unsafe_impl_trusted_step {
|
||||||
|
($($type:ty)*) => {$(
|
||||||
|
#[unstable(feature = "trusted_step", issue = "85731")]
|
||||||
|
unsafe impl TrustedStep for $type {}
|
||||||
|
)*};
|
||||||
|
}
|
||||||
|
unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
|
||||||
|
|
||||||
/// Objects that have a notion of *successor* and *predecessor* operations.
|
/// Objects that have a notion of *successor* and *predecessor* operations.
|
||||||
///
|
///
|
||||||
@ -505,12 +514,24 @@ impl ExactSizeIterator for ops::RangeInclusive<$t> { }
|
|||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
/// Specialization implementations for `Range`.
|
||||||
impl<A: Step> Iterator for ops::Range<A> {
|
trait RangeIteratorImpl {
|
||||||
|
type Item;
|
||||||
|
|
||||||
|
// Iterator
|
||||||
|
fn spec_next(&mut self) -> Option<Self::Item>;
|
||||||
|
fn spec_nth(&mut self, n: usize) -> Option<Self::Item>;
|
||||||
|
|
||||||
|
// DoubleEndedIterator
|
||||||
|
fn spec_next_back(&mut self) -> Option<Self::Item>;
|
||||||
|
fn spec_nth_back(&mut self, n: usize) -> Option<Self::Item>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Step> RangeIteratorImpl for ops::Range<A> {
|
||||||
type Item = A;
|
type Item = A;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<A> {
|
default fn spec_next(&mut self) -> Option<A> {
|
||||||
if self.start < self.end {
|
if self.start < self.end {
|
||||||
let n =
|
let n =
|
||||||
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
|
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
|
||||||
@ -520,6 +541,107 @@ fn next(&mut self) -> Option<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn spec_nth(&mut self, n: usize) -> Option<A> {
|
||||||
|
if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
|
||||||
|
if plus_n < self.end {
|
||||||
|
self.start =
|
||||||
|
Step::forward_checked(plus_n.clone(), 1).expect("`Step` invariants not upheld");
|
||||||
|
return Some(plus_n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.start = self.end.clone();
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn spec_next_back(&mut self) -> Option<A> {
|
||||||
|
if self.start < self.end {
|
||||||
|
self.end =
|
||||||
|
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
|
||||||
|
Some(self.end.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn spec_nth_back(&mut self, n: usize) -> Option<A> {
|
||||||
|
if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
|
||||||
|
if minus_n > self.start {
|
||||||
|
self.end =
|
||||||
|
Step::backward_checked(minus_n, 1).expect("`Step` invariants not upheld");
|
||||||
|
return Some(self.end.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.end = self.start.clone();
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
|
||||||
|
#[inline]
|
||||||
|
fn spec_next(&mut self) -> Option<T> {
|
||||||
|
if self.start < self.end {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
|
||||||
|
Some(mem::replace(&mut self.start, n))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn spec_nth(&mut self, n: usize) -> Option<T> {
|
||||||
|
if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
|
||||||
|
if plus_n < self.end {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
self.start = unsafe { Step::forward_unchecked(plus_n.clone(), 1) };
|
||||||
|
return Some(plus_n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.start = self.end.clone();
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn spec_next_back(&mut self) -> Option<T> {
|
||||||
|
if self.start < self.end {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
self.end = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
|
||||||
|
Some(self.end.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn spec_nth_back(&mut self, n: usize) -> Option<T> {
|
||||||
|
if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
|
||||||
|
if minus_n > self.start {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
self.end = unsafe { Step::backward_unchecked(minus_n, 1) };
|
||||||
|
return Some(self.end.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.end = self.start.clone();
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<A: Step> Iterator for ops::Range<A> {
|
||||||
|
type Item = A;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<A> {
|
||||||
|
self.spec_next()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
if self.start < self.end {
|
if self.start < self.end {
|
||||||
@ -532,16 +654,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn nth(&mut self, n: usize) -> Option<A> {
|
fn nth(&mut self, n: usize) -> Option<A> {
|
||||||
if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
|
self.spec_nth(n)
|
||||||
if plus_n < self.end {
|
|
||||||
self.start =
|
|
||||||
Step::forward_checked(plus_n.clone(), 1).expect("`Step` invariants not upheld");
|
|
||||||
return Some(plus_n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.start = self.end.clone();
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -624,37 +737,36 @@ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
|
|||||||
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
|
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next_back(&mut self) -> Option<A> {
|
fn next_back(&mut self) -> Option<A> {
|
||||||
if self.start < self.end {
|
self.spec_next_back()
|
||||||
self.end =
|
|
||||||
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
|
|
||||||
Some(self.end.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn nth_back(&mut self, n: usize) -> Option<A> {
|
fn nth_back(&mut self, n: usize) -> Option<A> {
|
||||||
if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
|
self.spec_nth_back(n)
|
||||||
if minus_n > self.start {
|
|
||||||
self.end =
|
|
||||||
Step::backward_checked(minus_n, 1).expect("`Step` invariants not upheld");
|
|
||||||
return Some(self.end.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.end = self.start.clone();
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_trusted_len_for_range {
|
// Safety:
|
||||||
($($type:ty)*) => {$(
|
// The following invariants for `Step::steps_between` exist:
|
||||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
//
|
||||||
unsafe impl TrustedLen for ops::Range<$type> {}
|
// > * `steps_between(&a, &b) == Some(n)` only if `a <= b`
|
||||||
)*}
|
// > * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
|
||||||
}
|
// > this is the case when it would require more than `usize::MAX` steps to
|
||||||
impl_trusted_len_for_range![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
|
// > get to `b`
|
||||||
|
// > * `steps_between(&a, &b) == None` if `a > b`
|
||||||
|
//
|
||||||
|
// The first invariant is what is generally required for `TrustedLen` to be
|
||||||
|
// sound. The note addendum satisfies an additional `TrustedLen` invariant.
|
||||||
|
//
|
||||||
|
// > The upper bound must only be `None` if the actual iterator length is larger
|
||||||
|
// > than `usize::MAX`
|
||||||
|
//
|
||||||
|
// The second invariant logically follows the first so long as the `PartialOrd`
|
||||||
|
// implementation is correct; regardless it is explicitly stated. If `a < b`
|
||||||
|
// then `(0, Some(0))` is returned by `ops::Range<A: Step>::size_hint`. As such
|
||||||
|
// the second invariant is upheld.
|
||||||
|
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||||
|
unsafe impl<A: TrustedStep> TrustedLen for ops::Range<A> {}
|
||||||
|
|
||||||
#[stable(feature = "fused", since = "1.26.0")]
|
#[stable(feature = "fused", since = "1.26.0")]
|
||||||
impl<A: Step> FusedIterator for ops::Range<A> {}
|
impl<A: Step> FusedIterator for ops::Range<A> {}
|
||||||
@ -682,23 +794,38 @@ fn nth(&mut self, n: usize) -> Option<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safety: See above implementation for `ops::Range<A>`
|
||||||
|
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||||
|
unsafe impl<A: TrustedStep> TrustedLen for ops::RangeFrom<A> {}
|
||||||
|
|
||||||
#[stable(feature = "fused", since = "1.26.0")]
|
#[stable(feature = "fused", since = "1.26.0")]
|
||||||
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
|
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
|
||||||
|
|
||||||
macro_rules! impl_trusted_len_for_range_from {
|
trait RangeInclusiveIteratorImpl {
|
||||||
($($type:ty)*) => {$(
|
type Item;
|
||||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
|
||||||
unsafe impl TrustedLen for ops::RangeFrom<$type> {}
|
|
||||||
)*}
|
|
||||||
}
|
|
||||||
impl_trusted_len_for_range_from![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
|
|
||||||
|
|
||||||
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
// Iterator
|
||||||
impl<A: Step> Iterator for ops::RangeInclusive<A> {
|
fn spec_next(&mut self) -> Option<Self::Item>;
|
||||||
|
fn spec_try_fold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(B, Self::Item) -> R,
|
||||||
|
R: Try<Output = B>;
|
||||||
|
|
||||||
|
// DoubleEndedIterator
|
||||||
|
fn spec_next_back(&mut self) -> Option<Self::Item>;
|
||||||
|
fn spec_try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(B, Self::Item) -> R,
|
||||||
|
R: Try<Output = B>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Step> RangeInclusiveIteratorImpl for ops::RangeInclusive<A> {
|
||||||
type Item = A;
|
type Item = A;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<A> {
|
default fn spec_next(&mut self) -> Option<A> {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@ -713,6 +840,182 @@ fn next(&mut self) -> Option<A> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn spec_try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(B, A) -> R,
|
||||||
|
R: Try<Output = B>,
|
||||||
|
{
|
||||||
|
if self.is_empty() {
|
||||||
|
return try { init };
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut accum = init;
|
||||||
|
|
||||||
|
while self.start < self.end {
|
||||||
|
let n =
|
||||||
|
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
|
||||||
|
let n = mem::replace(&mut self.start, n);
|
||||||
|
accum = f(accum, n)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.exhausted = true;
|
||||||
|
|
||||||
|
if self.start == self.end {
|
||||||
|
accum = f(accum, self.start.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { accum }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn spec_next_back(&mut self) -> Option<A> {
|
||||||
|
if self.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let is_iterating = self.start < self.end;
|
||||||
|
Some(if is_iterating {
|
||||||
|
let n =
|
||||||
|
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
|
||||||
|
mem::replace(&mut self.end, n)
|
||||||
|
} else {
|
||||||
|
self.exhausted = true;
|
||||||
|
self.end.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn spec_try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(B, A) -> R,
|
||||||
|
R: Try<Output = B>,
|
||||||
|
{
|
||||||
|
if self.is_empty() {
|
||||||
|
return try { init };
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut accum = init;
|
||||||
|
|
||||||
|
while self.start < self.end {
|
||||||
|
let n =
|
||||||
|
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
|
||||||
|
let n = mem::replace(&mut self.end, n);
|
||||||
|
accum = f(accum, n)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.exhausted = true;
|
||||||
|
|
||||||
|
if self.start == self.end {
|
||||||
|
accum = f(accum, self.start.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { accum }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: TrustedStep> RangeInclusiveIteratorImpl for ops::RangeInclusive<T> {
|
||||||
|
#[inline]
|
||||||
|
fn spec_next(&mut self) -> Option<T> {
|
||||||
|
if self.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let is_iterating = self.start < self.end;
|
||||||
|
Some(if is_iterating {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
|
||||||
|
mem::replace(&mut self.start, n)
|
||||||
|
} else {
|
||||||
|
self.exhausted = true;
|
||||||
|
self.start.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn spec_try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(B, T) -> R,
|
||||||
|
R: Try<Output = B>,
|
||||||
|
{
|
||||||
|
if self.is_empty() {
|
||||||
|
return try { init };
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut accum = init;
|
||||||
|
|
||||||
|
while self.start < self.end {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
|
||||||
|
let n = mem::replace(&mut self.start, n);
|
||||||
|
accum = f(accum, n)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.exhausted = true;
|
||||||
|
|
||||||
|
if self.start == self.end {
|
||||||
|
accum = f(accum, self.start.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { accum }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn spec_next_back(&mut self) -> Option<T> {
|
||||||
|
if self.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let is_iterating = self.start < self.end;
|
||||||
|
Some(if is_iterating {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
|
||||||
|
mem::replace(&mut self.end, n)
|
||||||
|
} else {
|
||||||
|
self.exhausted = true;
|
||||||
|
self.end.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn spec_try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: FnMut(B, T) -> R,
|
||||||
|
R: Try<Output = B>,
|
||||||
|
{
|
||||||
|
if self.is_empty() {
|
||||||
|
return try { init };
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut accum = init;
|
||||||
|
|
||||||
|
while self.start < self.end {
|
||||||
|
// SAFETY: just checked precondition
|
||||||
|
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
|
||||||
|
let n = mem::replace(&mut self.end, n);
|
||||||
|
accum = f(accum, n)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.exhausted = true;
|
||||||
|
|
||||||
|
if self.start == self.end {
|
||||||
|
accum = f(accum, self.start.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
try { accum }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
||||||
|
impl<A: Step> Iterator for ops::RangeInclusive<A> {
|
||||||
|
type Item = A;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn next(&mut self) -> Option<A> {
|
||||||
|
self.spec_next()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
@ -754,32 +1057,13 @@ fn nth(&mut self, n: usize) -> Option<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(B, Self::Item) -> R,
|
F: FnMut(B, Self::Item) -> R,
|
||||||
R: Try<Output = B>,
|
R: Try<Output = B>,
|
||||||
{
|
{
|
||||||
if self.is_empty() {
|
self.spec_try_fold(init, f)
|
||||||
return try { init };
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut accum = init;
|
|
||||||
|
|
||||||
while self.start < self.end {
|
|
||||||
let n =
|
|
||||||
Step::forward_checked(self.start.clone(), 1).expect("`Step` invariants not upheld");
|
|
||||||
let n = mem::replace(&mut self.start, n);
|
|
||||||
accum = f(accum, n)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.exhausted = true;
|
|
||||||
|
|
||||||
if self.start == self.end {
|
|
||||||
accum = f(accum, self.start.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
try { accum }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -816,18 +1100,7 @@ fn max(mut self) -> Option<A> {
|
|||||||
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
|
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next_back(&mut self) -> Option<A> {
|
fn next_back(&mut self) -> Option<A> {
|
||||||
if self.is_empty() {
|
self.spec_next_back()
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let is_iterating = self.start < self.end;
|
|
||||||
Some(if is_iterating {
|
|
||||||
let n =
|
|
||||||
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
|
|
||||||
mem::replace(&mut self.end, n)
|
|
||||||
} else {
|
|
||||||
self.exhausted = true;
|
|
||||||
self.end.clone()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -859,32 +1132,13 @@ fn nth_back(&mut self, n: usize) -> Option<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
F: FnMut(B, Self::Item) -> R,
|
F: FnMut(B, Self::Item) -> R,
|
||||||
R: Try<Output = B>,
|
R: Try<Output = B>,
|
||||||
{
|
{
|
||||||
if self.is_empty() {
|
self.spec_try_rfold(init, f)
|
||||||
return try { init };
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut accum = init;
|
|
||||||
|
|
||||||
while self.start < self.end {
|
|
||||||
let n =
|
|
||||||
Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
|
|
||||||
let n = mem::replace(&mut self.end, n);
|
|
||||||
accum = f(accum, n)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.exhausted = true;
|
|
||||||
|
|
||||||
if self.start == self.end {
|
|
||||||
accum = f(accum, self.start.clone())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
try { accum }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -902,13 +1156,9 @@ fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_trusted_len_for_range_inclusive {
|
// Safety: See above implementation for `ops::Range<A>`
|
||||||
($($type:ty)*) => {$(
|
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
unsafe impl<A: TrustedStep> TrustedLen for ops::RangeInclusive<A> {}
|
||||||
unsafe impl TrustedLen for ops::RangeInclusive<$type> {}
|
|
||||||
)*}
|
|
||||||
}
|
|
||||||
impl_trusted_len_for_range_inclusive![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
|
|
||||||
|
|
||||||
#[stable(feature = "fused", since = "1.26.0")]
|
#[stable(feature = "fused", since = "1.26.0")]
|
||||||
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}
|
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::iter::Step;
|
||||||
|
|
||||||
/// An iterator that always continues to yield `None` when exhausted.
|
/// An iterator that always continues to yield `None` when exhausted.
|
||||||
///
|
///
|
||||||
/// Calling next on a fused iterator that has returned `None` once is guaranteed
|
/// Calling next on a fused iterator that has returned `None` once is guaranteed
|
||||||
@ -55,3 +57,18 @@ unsafe impl<I: TrustedLen + ?Sized> TrustedLen for &mut I {}
|
|||||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub unsafe trait InPlaceIterable: Iterator {}
|
pub unsafe trait InPlaceIterable: Iterator {}
|
||||||
|
|
||||||
|
/// A type that upholds all invariants of [`Step`].
|
||||||
|
///
|
||||||
|
/// The invariants of [`Step::steps_between()`] are a superset of the invariants
|
||||||
|
/// of [`TrustedLen`]. As such, [`TrustedLen`] is implemented for all range
|
||||||
|
/// types with the same generic type argument.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The implementation of [`Step`] for the given type must guarantee all
|
||||||
|
/// invariants of all methods are upheld. See the [`Step`] trait's documentation
|
||||||
|
/// for details. Consumers are free to rely on the invariants in unsafe code.
|
||||||
|
#[unstable(feature = "trusted_step", issue = "85731")]
|
||||||
|
#[rustc_specialization_trait]
|
||||||
|
pub unsafe trait TrustedStep: Step {}
|
||||||
|
@ -13,5 +13,7 @@
|
|||||||
pub use self::iterator::Iterator;
|
pub use self::iterator::Iterator;
|
||||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||||
pub use self::marker::InPlaceIterable;
|
pub use self::marker::InPlaceIterable;
|
||||||
|
#[unstable(feature = "trusted_step", issue = "85731")]
|
||||||
|
pub use self::marker::TrustedStep;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub use self::marker::{FusedIterator, TrustedLen};
|
pub use self::marker::{FusedIterator, TrustedLen};
|
||||||
|
Loading…
Reference in New Issue
Block a user