From b67c5af1d115e723e62ddb80a195112d7d07a374 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 24 Sep 2022 06:24:37 +0000 Subject: [PATCH 1/3] Allow const iterator implementations --- library/core/src/array/mod.rs | 140 ++-- library/core/src/cmp.rs | 23 +- .../core/src/iter/adapters/array_chunks.rs | 2 +- .../core/src/iter/adapters/by_ref_sized.rs | 25 +- library/core/src/iter/adapters/chain.rs | 2 +- library/core/src/iter/adapters/cloned.rs | 2 +- library/core/src/iter/adapters/copied.rs | 2 +- library/core/src/iter/adapters/cycle.rs | 5 +- library/core/src/iter/adapters/enumerate.rs | 2 +- library/core/src/iter/adapters/filter.rs | 2 +- library/core/src/iter/adapters/filter_map.rs | 2 +- library/core/src/iter/adapters/flatten.rs | 37 +- library/core/src/iter/adapters/fuse.rs | 2 +- library/core/src/iter/adapters/inspect.rs | 2 +- library/core/src/iter/adapters/intersperse.rs | 13 +- library/core/src/iter/adapters/map.rs | 56 +- library/core/src/iter/adapters/map_while.rs | 2 +- library/core/src/iter/adapters/mod.rs | 88 ++- library/core/src/iter/adapters/peekable.rs | 2 +- library/core/src/iter/adapters/rev.rs | 2 +- library/core/src/iter/adapters/scan.rs | 2 +- library/core/src/iter/adapters/skip.rs | 2 +- library/core/src/iter/adapters/skip_while.rs | 2 +- library/core/src/iter/adapters/step_by.rs | 2 +- library/core/src/iter/adapters/take.rs | 2 +- library/core/src/iter/adapters/take_while.rs | 2 +- library/core/src/iter/adapters/zip.rs | 312 ++++++++- library/core/src/iter/traits/collect.rs | 85 ++- library/core/src/iter/traits/exact_size.rs | 24 +- library/core/src/iter/traits/iterator.rs | 603 +++++++++++------- library/core/src/iter/traits/marker.rs | 3 +- library/core/src/lib.rs | 11 +- library/core/src/ops/control_flow.rs | 19 +- library/core/src/option.rs | 9 +- library/core/src/ptr/mod.rs | 3 +- src/test/ui/issues/issue-23966.stderr | 4 +- src/test/ui/issues/issue-34334.stderr | 4 +- ...e-66923-show-error-for-correct-call.stderr | 8 +- .../ui/iterators/collect-into-array.stderr | 4 +- .../ui/iterators/collect-into-slice.stderr | 6 +- .../branches.stderr | 4 +- .../recursion4.stderr | 8 +- .../ui/suggestions/derive-clone-for-eq.stderr | 4 +- src/test/ui/traits/alias/object-fail.stderr | 4 +- 44 files changed, 1130 insertions(+), 408 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 2090756d7a3ec..e1c1a40a956bf 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -11,6 +11,7 @@ use crate::error::Error; use crate::fmt; use crate::hash::{self, Hash}; use crate::iter::TrustedLen; +use crate::marker::Destruct; use crate::mem::{self, MaybeUninit}; use crate::ops::{ ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try, @@ -841,6 +842,54 @@ where } } +/// Panic guard for incremental initialization of arrays. +/// +/// Disarm the guard with `mem::forget` once the array has been initialized. +/// +/// # Safety +/// +/// All write accesses to this structure are unsafe and must maintain a correct +/// count of `initialized` elements. +/// +/// To minimize indirection fields are still pub but callers should at least use +/// `push_unchecked` to signal that something unsafe is going on. +pub(crate) struct Guard<'a, T: Destruct, const N: usize> { + /// The array to be initialized. + pub array_mut: &'a mut [MaybeUninit; N], + /// The number of items that have been initialized so far. + pub initialized: usize, +} + +impl Guard<'_, T, N> { + /// Adds an item to the array and updates the initialized item counter. + /// + /// # Safety + /// + /// No more than N elements must be initialized. + #[inline] + pub unsafe fn push_unchecked(&mut self, item: T) { + // SAFETY: If `initialized` was correct before and the caller does not + // invoke this method more than N times then writes will be in-bounds + // and slots will not be initialized more than once. + unsafe { + self.array_mut.get_unchecked_mut(self.initialized).write(item); + self.initialized = self.initialized.unchecked_add(1); + } + } +} + +impl const Drop for Guard<'_, T, N> { + fn drop(&mut self) { + debug_assert!(self.initialized <= N); + + // SAFETY: this slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( + &mut self.array_mut.get_unchecked_mut(..self.initialized), + )); + } + } +} /// Pulls `N` items from `iter` and returns them as an array. If the iterator /// yields fewer than `N` items, `Err` is returned containing an iterator over /// the already yielded items. @@ -852,23 +901,27 @@ where /// If `iter.next()` panicks, all items already yielded by the iterator are /// dropped. #[inline] -fn try_collect_into_array( +const fn try_collect_into_array( iter: &mut I, ) -> Result> where - I: Iterator, - I::Item: Try, - R: Residual<[T; N]>, + I: ~const Iterator, + I::Item: ~const Try, + R: ~const Residual<[T; N]>, + T: ~const Destruct, + R::TryType: ~const Try, // #[cfg(bootstrap)] { if N == 0 { // SAFETY: An empty array is always inhabited and has no validity invariants. - return Ok(Try::from_output(unsafe { mem::zeroed() })); + return Ok(Try::from_output(unsafe { MaybeUninit::zeroed().assume_init() })); } let mut array = MaybeUninit::uninit_array::(); let mut guard = Guard { array_mut: &mut array, initialized: 0 }; - for _ in 0..N { + let mut i = 0; + // FIXME(const_trait_impl): replace with `for` loop + while i < N { match iter.next() { Some(item_rslt) => { let item = match item_rslt.branch() { @@ -878,11 +931,13 @@ where ControlFlow::Continue(elem) => elem, }; - // SAFETY: `guard.initialized` starts at 0, which means push can be called - // at most N times, which this loop does. + // SAFETY: `guard.initialized` starts at 0, is increased by one in the + // loop and the loop is aborted once it reaches N (which is + // `array.len()`). unsafe { - guard.push_unchecked(item); + guard.array_mut.get_unchecked_mut(guard.initialized).write(item); } + guard.initialized += 1; } None => { let alive = 0..guard.initialized; @@ -892,66 +947,35 @@ where return Err(unsafe { IntoIter::new_unchecked(array, alive) }); } } + i += 1; } mem::forget(guard); // SAFETY: All elements of the array were populated in the loop above. - let output = unsafe { array.transpose().assume_init() }; + let output = unsafe { MaybeUninit::array_assume_init(array) }; Ok(Try::from_output(output)) } -/// Panic guard for incremental initialization of arrays. -/// -/// Disarm the guard with `mem::forget` once the array has been initialized. -/// -/// # Safety -/// -/// All write accesses to this structure are unsafe and must maintain a correct -/// count of `initialized` elements. -/// -/// To minimize indirection fields are still pub but callers should at least use -/// `push_unchecked` to signal that something unsafe is going on. -pub(crate) struct Guard<'a, T, const N: usize> { - /// The array to be initialized. - pub array_mut: &'a mut [MaybeUninit; N], - /// The number of items that have been initialized so far. - pub initialized: usize, -} - -impl Guard<'_, T, N> { - /// Adds an item to the array and updates the initialized item counter. - /// - /// # Safety - /// - /// No more than N elements must be initialized. - #[inline] - pub unsafe fn push_unchecked(&mut self, item: T) { - // SAFETY: If `initialized` was correct before and the caller does not - // invoke this method more than N times then writes will be in-bounds - // and slots will not be initialized more than once. - unsafe { - self.array_mut.get_unchecked_mut(self.initialized).write(item); - self.initialized = self.initialized.unchecked_add(1); - } - } -} - -impl Drop for Guard<'_, T, N> { - fn drop(&mut self) { - debug_assert!(self.initialized <= N); +/// Returns the next chunk of `N` items from the iterator or errors with an +/// iterator over the remainder. Used for `Iterator::next_chunk`. +#[inline] +#[cfg(not(bootstrap))] +pub(crate) const fn iter_next_chunk( + iter: &mut I, +) -> Result<[I::Item; N], IntoIter> +where + I: ~const Iterator, + I::Item: ~const Destruct, +{ + let mut map = iter.map(NeverShortCircuit); - // SAFETY: this slice will contain only initialized objects. - unsafe { - crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut( - &mut self.array_mut.get_unchecked_mut(..self.initialized), - )); - } + match try_collect_into_array(&mut map) { + Ok(NeverShortCircuit(x)) => Ok(x), + Err(e) => Err(e), } } -/// Returns the next chunk of `N` items from the iterator or errors with an -/// iterator over the remainder. Used for `Iterator::next_chunk`. -#[inline] +#[cfg(bootstrap)] pub(crate) fn iter_next_chunk( iter: &mut I, ) -> Result<[I::Item; N], IntoIter> diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index f0fa2e1d2c190..eb8f441291dbc 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -24,6 +24,7 @@ use crate::const_closure::ConstFnMutClosure; use crate::marker::Destruct; +use crate::marker::StructuralEq; use crate::marker::StructuralPartialEq; use self::Ordering::*; @@ -280,7 +281,8 @@ pub macro PartialEq($item:item) { #[doc(alias = "!=")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Eq"] -pub trait Eq: PartialEq { +#[const_trait] +pub trait Eq: ~const PartialEq { // this method is used solely by #[deriving] to assert // that every component of a type implements #[deriving] // itself, the current deriving infrastructure means doing this @@ -330,7 +332,7 @@ pub struct AssertParamIsEq { /// let result = 2.cmp(&1); /// assert_eq!(Ordering::Greater, result); /// ``` -#[derive(Clone, Copy, Eq, Debug, Hash)] +#[derive(Clone, Copy, Debug, Hash)] #[stable(feature = "rust1", since = "1.0.0")] #[repr(i8)] pub enum Ordering { @@ -578,6 +580,9 @@ impl Ordering { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl StructuralEq for Ordering {} + /// A helper struct for reverse ordering. /// /// This struct is a helper to be used with functions like [`Vec::sort_by_key`] and @@ -760,7 +765,7 @@ impl Clone for Reverse { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "Ord"] #[const_trait] -pub trait Ord: Eq + PartialOrd { +pub trait Ord: ~const Eq + ~const PartialOrd { /// This method returns an [`Ordering`] between `self` and `other`. /// /// By convention, `self.cmp(&other)` returns the ordering matching the expression @@ -888,6 +893,10 @@ impl const PartialEq for Ordering { } } +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_cmp", issue = "92391")] +impl const Eq for Ordering {} + #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] impl const Ord for Ordering { @@ -1227,7 +1236,6 @@ pub const fn min(v1: T, v2: T) -> T { pub const fn min_by Ordering>(v1: T, v2: T, compare: F) -> T where T: ~const Destruct, - F: ~const Destruct, { match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v1, @@ -1312,7 +1320,6 @@ pub const fn max(v1: T, v2: T) -> T { pub const fn max_by Ordering>(v1: T, v2: T, compare: F) -> T where T: ~const Destruct, - F: ~const Destruct, { match compare(&v1, &v2) { Ordering::Less | Ordering::Equal => v2, @@ -1393,7 +1400,8 @@ mod impls { macro_rules! eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Eq for $t {} + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const Eq for $t {} )*) } @@ -1517,7 +1525,8 @@ mod impls { } #[unstable(feature = "never_type", issue = "35121")] - impl Eq for ! {} + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const Eq for ! {} #[unstable(feature = "never_type", issue = "35121")] #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs index 5e4211058aa6f..1f431f7ce0005 100644 --- a/library/core/src/iter/adapters/array_chunks.rs +++ b/library/core/src/iter/adapters/array_chunks.rs @@ -24,7 +24,7 @@ where I: Iterator, { #[track_caller] - pub(in crate::iter) fn new(iter: I) -> Self { + pub(in crate::iter) const fn new(iter: I) -> Self { assert!(N != 0, "chunk size must be non-zero"); Self { iter, remainder: None } } diff --git a/library/core/src/iter/adapters/by_ref_sized.rs b/library/core/src/iter/adapters/by_ref_sized.rs index 1945e402ff50e..f9efa970ed93c 100644 --- a/library/core/src/iter/adapters/by_ref_sized.rs +++ b/library/core/src/iter/adapters/by_ref_sized.rs @@ -1,7 +1,6 @@ -use crate::{ - const_closure::ConstFnMutClosure, - ops::{NeverShortCircuit, Try}, -}; +use crate::const_closure::ConstFnMutClosure; +use crate::marker::Destruct; +use crate::ops::{NeverShortCircuit, Try}; /// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics. /// @@ -15,7 +14,7 @@ pub struct ByRefSized<'a, I>(pub &'a mut I); // to avoid accidentally calling the `&mut Iterator` implementations. #[unstable(feature = "std_internals", issue = "none")] -impl Iterator for ByRefSized<'_, I> { +impl const Iterator for ByRefSized<'_, I> { type Item = I::Item; #[inline] @@ -29,19 +28,25 @@ impl Iterator for ByRefSized<'_, I> { } #[inline] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), usize> + where + I::Item: ~const Destruct, + { I::advance_by(self.0, n) } #[inline] - fn nth(&mut self, n: usize) -> Option { + fn nth(&mut self, n: usize) -> Option + where + I::Item: ~const Destruct, + { I::nth(self.0, n) } #[inline] fn fold(self, init: B, mut f: F) -> B where - F: FnMut(B, Self::Item) -> B, + F: ~const FnMut(B, Self::Item) -> B + ~const Destruct, { // `fold` needs ownership, so this can't forward directly. I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp)) @@ -51,8 +56,8 @@ impl Iterator for ByRefSized<'_, I> { #[inline] fn try_fold(&mut self, init: B, f: F) -> R where - F: FnMut(B, Self::Item) -> R, - R: Try, + F: ~const FnMut(B, Self::Item) -> R + ~const Destruct, + R: ~const Try, { I::try_fold(self.0, init, f) } diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 60eb3a6da3a4b..f5fcf49bb2da5 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -32,7 +32,7 @@ pub struct Chain { b: Option, } impl Chain { - pub(in super::super) fn new(a: A, b: B) -> Chain { + pub(in super::super) const fn new(a: A, b: B) -> Chain { Chain { a: Some(a), b: Some(b) } } } diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index aba24a79dcf79..8d79729b6c975 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -19,7 +19,7 @@ pub struct Cloned { } impl Cloned { - pub(in crate::iter) fn new(it: I) -> Cloned { + pub(in crate::iter) const fn new(it: I) -> Cloned { Cloned { it } } } diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 62d3afb81603d..ea6dd32529fde 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -22,7 +22,7 @@ pub struct Copied { } impl Copied { - pub(in crate::iter) fn new(it: I) -> Copied { + pub(in crate::iter) const fn new(it: I) -> Copied { Copied { it } } } diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs index 02b5939072ef0..a4ede289572e8 100644 --- a/library/core/src/iter/adapters/cycle.rs +++ b/library/core/src/iter/adapters/cycle.rs @@ -16,7 +16,10 @@ pub struct Cycle { } impl Cycle { - pub(in crate::iter) fn new(iter: I) -> Cycle { + pub(in crate::iter) const fn new(iter: I) -> Cycle + where + I: ~const Clone, + { Cycle { orig: iter.clone(), iter } } } diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index 14a126951115c..f696fd808be1e 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -19,7 +19,7 @@ pub struct Enumerate { count: usize, } impl Enumerate { - pub(in crate::iter) fn new(iter: I) -> Enumerate { + pub(in crate::iter) const fn new(iter: I) -> Enumerate { Enumerate { iter, count: 0 } } } diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index a0afaa326ad63..c46893250c087 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -18,7 +18,7 @@ pub struct Filter { predicate: P, } impl Filter { - pub(in crate::iter) fn new(iter: I, predicate: P) -> Filter { + pub(in crate::iter) const fn new(iter: I, predicate: P) -> Filter { Filter { iter, predicate } } } diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index e0d665c9e12ba..bbe5e8b5c1a0f 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -17,7 +17,7 @@ pub struct FilterMap { f: F, } impl FilterMap { - pub(in crate::iter) fn new(iter: I, f: F) -> FilterMap { + pub(in crate::iter) const fn new(iter: I, f: F) -> FilterMap { FilterMap { iter, f } } } diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 307016c269099..632b7967df1ee 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,5 +1,7 @@ use crate::fmt; use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen}; +#[cfg(not(bootstrap))] +use crate::marker::Destruct; use crate::ops::{ControlFlow, Try}; /// An iterator that maps each element to an iterator, and yields the elements @@ -13,8 +15,21 @@ pub struct FlatMap { inner: FlattenCompat, ::IntoIter>, } -impl U> FlatMap { - pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap { +impl FlatMap { + #[cfg(bootstrap)] + pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap + where + I: Iterator, + F: FnMut(I::Item) -> U, + { + FlatMap { inner: FlattenCompat::new(iter.map(f)) } + } + #[cfg(not(bootstrap))] + pub(in crate::iter) const fn new(iter: I, f: F) -> FlatMap + where + I: ~const Iterator + ~const Destruct, + F: ~const FnMut(I::Item) -> U + ~const Destruct, + { FlatMap { inner: FlattenCompat::new(iter.map(f)) } } } @@ -172,9 +187,17 @@ pub struct Flatten> { } impl> Flatten { + #[cfg(bootstrap)] pub(in super::super) fn new(iter: I) -> Flatten { Flatten { inner: FlattenCompat::new(iter) } } + #[cfg(not(bootstrap))] + pub(in super::super) const fn new(iter: I) -> Flatten + where + I: ~const Iterator, + { + Flatten { inner: FlattenCompat::new(iter) } + } } #[stable(feature = "iterator_flatten", since = "1.29.0")] @@ -310,12 +333,12 @@ struct FlattenCompat { frontiter: Option, backiter: Option, } -impl FlattenCompat -where - I: Iterator, -{ +impl FlattenCompat { /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`. - fn new(iter: I) -> FlattenCompat { + const fn new(iter: I) -> FlattenCompat + where + I: ~const Iterator, + { FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None } } } diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs index c931445420342..e779eead02e57 100644 --- a/library/core/src/iter/adapters/fuse.rs +++ b/library/core/src/iter/adapters/fuse.rs @@ -21,7 +21,7 @@ pub struct Fuse { iter: Option, } impl Fuse { - pub(in crate::iter) fn new(iter: I) -> Fuse { + pub(in crate::iter) const fn new(iter: I) -> Fuse { Fuse { iter: Some(iter) } } } diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 19839fdfe5bc3..4ed0ce2e2d4d7 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -18,7 +18,7 @@ pub struct Inspect { f: F, } impl Inspect { - pub(in crate::iter) fn new(iter: I, f: F) -> Inspect { + pub(in crate::iter) const fn new(iter: I, f: F) -> Inspect { Inspect { iter, f } } } diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index d8bbd424cf258..7915b67341a78 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -19,7 +19,10 @@ impl Intersperse where I::Item: Clone, { - pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { + pub(in crate::iter) const fn new(iter: I, separator: I::Item) -> Self + where + I: ~const Iterator, + { Self { iter: iter.peekable(), separator, needs_sep: false } } } @@ -103,12 +106,14 @@ where } } -impl IntersperseWith +impl IntersperseWith where - I: Iterator, G: FnMut() -> I::Item, { - pub(in crate::iter) fn new(iter: I, separator: G) -> Self { + pub(in crate::iter) const fn new(iter: I, separator: G) -> Self + where + I: ~const Iterator, + { Self { iter: iter.peekable(), separator, needs_sep: false } } } diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 9e25dbe462c91..8e06d332cdef1 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -1,8 +1,10 @@ +use crate::const_closure::ConstFnMutClosure; use crate::fmt; use crate::iter::adapters::{ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; +use crate::marker::Destruct; use crate::ops::Try; /// An iterator that maps the values of `iter` with `f`. @@ -65,7 +67,7 @@ pub struct Map { } impl Map { - pub(in crate::iter) fn new(iter: I, f: F) -> Map { + pub(in crate::iter) const fn new(iter: I, f: F) -> Map { Map { iter, f } } } @@ -77,24 +79,29 @@ impl fmt::Debug for Map { } } -fn map_fold( - mut f: impl FnMut(T) -> B, - mut g: impl FnMut(Acc, B) -> Acc, -) -> impl FnMut(Acc, T) -> Acc { - move |acc, elt| g(acc, f(elt)) +const fn map_fold(x: &mut (F, G), (acc, elt): (Acc, T)) -> Acc +where + F: ~const FnMut(T) -> B, + G: ~const FnMut(Acc, B) -> Acc, +{ + x.1(acc, x.0(elt)) } -fn map_try_fold<'a, T, B, Acc, R>( - f: &'a mut impl FnMut(T) -> B, - mut g: impl FnMut(Acc, B) -> R + 'a, -) -> impl FnMut(Acc, T) -> R + 'a { - move |acc, elt| g(acc, f(elt)) +const fn map_try_fold(x: &mut (F, G), (acc, elt): (Acc, T)) -> R +where + F: ~const FnMut(T) -> B, + G: ~const FnMut(Acc, B) -> R, +{ + x.1(acc, x.0(elt)) } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Map +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for Map where - F: FnMut(I::Item) -> B, + F: ~const FnMut(I::Item) -> B, + F: ~const Destruct, + I: ~const Destruct, { type Item = B; @@ -111,17 +118,20 @@ where fn try_fold(&mut self, init: Acc, g: G) -> R where Self: Sized, - G: FnMut(Acc, Self::Item) -> R, - R: Try, + G: ~const FnMut(Acc, Self::Item) -> R + ~const Destruct, + R: ~const Try, { - self.iter.try_fold(init, map_try_fold(&mut self.f, g)) + let mut tup = (&mut self.f, g); + self.iter.try_fold(init, ConstFnMutClosure::new(&mut tup, map_try_fold)) } - fn fold(self, init: Acc, g: G) -> Acc + fn fold(mut self, init: Acc, g: G) -> Acc where - G: FnMut(Acc, Self::Item) -> Acc, + G: ~const FnMut(Acc, Self::Item) -> Acc + ~const Destruct, + Self: ~const Destruct, { - self.iter.fold(init, map_fold(self.f, g)) + let mut tup = (&mut self.f, g); + self.iter.fold(init, ConstFnMutClosure::new(&mut tup, map_fold)) } #[inline] @@ -151,14 +161,16 @@ where G: FnMut(Acc, Self::Item) -> R, R: Try, { - self.iter.try_rfold(init, map_try_fold(&mut self.f, g)) + let mut tup = (&mut self.f, g); + self.iter.try_rfold(init, ConstFnMutClosure::new(&mut tup, map_try_fold)) } - fn rfold(self, init: Acc, g: G) -> Acc + fn rfold(mut self, init: Acc, g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc, { - self.iter.rfold(init, map_fold(self.f, g)) + let mut tup = (&mut self.f, g); + self.iter.rfold(init, ConstFnMutClosure::new(&mut tup, map_fold)) } } diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index fbdeca4d4ee4f..31eb84b570e6f 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -18,7 +18,7 @@ pub struct MapWhile { } impl MapWhile { - pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile { + pub(in crate::iter) const fn new(iter: I, predicate: P) -> MapWhile { MapWhile { iter, predicate } } } diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 8cc2b7cec4165..bf1f40d5219fd 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,4 +1,6 @@ use crate::iter::{InPlaceIterable, Iterator}; +#[cfg(not(bootstrap))] +use crate::marker::Destruct; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; mod array_chunks; @@ -150,9 +152,7 @@ pub(crate) struct GenericShunt<'a, I, R> { residual: &'a mut Option, } -/// Process the given iterator as if it yielded a the item's `Try::Output` -/// type instead. Any `Try::Residual`s encountered will stop the inner iterator -/// and be propagated back to the overall result. +#[cfg(bootstrap)] pub(crate) fn try_process(iter: I, mut f: F) -> ChangeOutputType where I: Iterator>, @@ -168,6 +168,29 @@ where } } +/// Process the given iterator as if it yielded a the item's `Try::Output` +/// type instead. Any `Try::Residual`s encountered will stop the inner iterator +/// and be propagated back to the overall result. +#[cfg(not(bootstrap))] +pub(crate) const fn try_process(iter: I, mut f: F) -> ChangeOutputType +where + I: ~const Iterator, + I::Item: ~const Try, + for<'a> F: ~const FnMut(GenericShunt<'a, I, R>) -> U, + F: ~const Destruct, + R: ~const Residual, + U: ~const Destruct, +{ + let mut residual = None; + let shunt = GenericShunt { iter, residual: &mut residual }; + let value = f(shunt); + match residual { + Some(r) => FromResidual::from_residual(r), + None => Try::from_output(value), + } +} + +#[cfg(bootstrap)] impl Iterator for GenericShunt<'_, I, R> where I: Iterator>, @@ -206,6 +229,65 @@ where impl_fold_via_try_fold! { fold -> try_fold } } +#[cfg(not(bootstrap))] +impl const Iterator for GenericShunt<'_, I, R> +where + I: ~const Iterator, + I::Item: ~const Try, + R: ~const Destruct, +{ + type Item = ::Output; + + fn next(&mut self) -> Option { + self.try_for_each(ControlFlow::Break).break_value() + } + + fn size_hint(&self) -> (usize, Option) { + if self.residual.is_some() { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } + + fn try_fold(&mut self, init: B, f: F) -> T + where + F: ~const FnMut(B, Self::Item) -> T + ~const Destruct, + T: ~const Try, + { + const fn try_fold_impl( + (f, residual): &mut (F, &mut Option), + (acc, x): (B, Item), + ) -> ControlFlow + where + F: ~const FnMut(B, Item::Output) -> T, + Item: ~const Try, + T: ~const Try, + Item::Residual: ~const Destruct, + { + match Try::branch(x) { + ControlFlow::Continue(x) => ControlFlow::from_try(f(acc, x)), + ControlFlow::Break(r) => { + **residual = Some(r); + ControlFlow::Break(try { acc }) + } + } + } + let mut tuple = (f, &mut *self.residual); + self.iter.try_fold(init, ConstFnMutClosure::new(&mut tuple, try_fold_impl)).into_try() + } + + fn fold(mut self, init: B, mut fold: F) -> B + where + Self: Sized, + F: ~const FnMut(B, Self::Item) -> B + ~const Destruct, + Self: ~const Destruct, + { + self.try_fold(init, ConstFnMutClosure::new(&mut fold, NeverShortCircuit::wrap_mut_2_imp)).0 + } +} + #[unstable(issue = "none", feature = "inplace_iteration")] unsafe impl SourceIter for GenericShunt<'_, I, R> where diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 20aca323bab79..a3e957efbb73d 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -19,7 +19,7 @@ pub struct Peekable { } impl Peekable { - pub(in crate::iter) fn new(iter: I) -> Peekable { + pub(in crate::iter) const fn new(iter: I) -> Peekable { Peekable { iter, peeked: None } } } diff --git a/library/core/src/iter/adapters/rev.rs b/library/core/src/iter/adapters/rev.rs index 139fb7bbdd996..b048d8246777b 100644 --- a/library/core/src/iter/adapters/rev.rs +++ b/library/core/src/iter/adapters/rev.rs @@ -16,7 +16,7 @@ pub struct Rev { } impl Rev { - pub(in crate::iter) fn new(iter: T) -> Rev { + pub(in crate::iter) const fn new(iter: T) -> Rev { Rev { iter } } } diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs index 62470512cc747..631da4894231a 100644 --- a/library/core/src/iter/adapters/scan.rs +++ b/library/core/src/iter/adapters/scan.rs @@ -19,7 +19,7 @@ pub struct Scan { } impl Scan { - pub(in crate::iter) fn new(iter: I, state: St, f: F) -> Scan { + pub(in crate::iter) const fn new(iter: I, state: St, f: F) -> Scan { Scan { iter, state, f } } } diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index c6334880db57c..c62ba7b9be946 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -18,7 +18,7 @@ pub struct Skip { } impl Skip { - pub(in crate::iter) fn new(iter: I, n: usize) -> Skip { + pub(in crate::iter) const fn new(iter: I, n: usize) -> Skip { Skip { iter, n } } } diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index f29661779c056..0103123be7d2c 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -19,7 +19,7 @@ pub struct SkipWhile { } impl SkipWhile { - pub(in crate::iter) fn new(iter: I, predicate: P) -> SkipWhile { + pub(in crate::iter) const fn new(iter: I, predicate: P) -> SkipWhile { SkipWhile { iter, flag: false, predicate } } } diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index 4252c34a0e0fc..9ce84343efcbb 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -17,7 +17,7 @@ pub struct StepBy { } impl StepBy { - pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy { + pub(in crate::iter) const fn new(iter: I, step: usize) -> StepBy { assert!(step != 0); StepBy { iter, step: step - 1, first_take: true } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 58a0b9d7bbe99..36244e3dfcf79 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -18,7 +18,7 @@ pub struct Take { } impl Take { - pub(in crate::iter) fn new(iter: I, n: usize) -> Take { + pub(in crate::iter) const fn new(iter: I, n: usize) -> Take { Take { iter, n } } } diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index ec66dc3aec360..fdef2dc44ae02 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -19,7 +19,7 @@ pub struct TakeWhile { } impl TakeWhile { - pub(in crate::iter) fn new(iter: I, predicate: P) -> TakeWhile { + pub(in crate::iter) const fn new(iter: I, predicate: P) -> TakeWhile { TakeWhile { iter, flag: false, predicate } } } diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 8153c8cfef133..a4aad675b124d 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -1,7 +1,11 @@ use crate::cmp; use crate::fmt::{self, Debug}; +#[cfg(not(bootstrap))] +use crate::intrinsics::const_eval_select; use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator}; use crate::iter::{InPlaceIterable, SourceIter, TrustedLen}; +#[cfg(not(bootstrap))] +use crate::marker::Destruct; /// An iterator that iterates two other iterators simultaneously. /// @@ -19,9 +23,21 @@ pub struct Zip { a_len: usize, } impl Zip { + #[cfg(bootstrap)] pub(in crate::iter) fn new(a: A, b: B) -> Zip { ZipImpl::new(a, b) } + #[cfg(not(bootstrap))] + pub(in crate::iter) const fn new(a: A, b: B) -> Zip + where + A: ~const Iterator, + B: ~const Iterator, + A::Item: ~const Destruct, + B::Item: ~const Destruct, + { + ZipImpl::new(a, b) + } + #[cfg(bootstrap)] fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> { while let Some(x) = Iterator::next(self) { if n == 0 { @@ -31,6 +47,22 @@ impl Zip { } None } + #[cfg(not(bootstrap))] + const fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> + where + A: ~const Iterator, + B: ~const Iterator, + A::Item: ~const Destruct, + B::Item: ~const Destruct, + { + while let Some(x) = Iterator::next(self) { + if n == 0 { + return Some(x); + } + n -= 1; + } + None + } } /// Converts the arguments to iterators and zips them. @@ -72,10 +104,45 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Zip +#[cfg(bootstrap)] +impl Iterator for Zip { + type Item = (A::Item, B::Item); + + #[inline] + fn next(&mut self) -> Option { + ZipImpl::next(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + ZipImpl::size_hint(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + ZipImpl::nth(self, n) + } + + #[inline] + unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item + where + Self: TrustedRandomAccessNoCoerce, + { + // SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety + // requirements as `Iterator::__iterator_get_unchecked`. + unsafe { ZipImpl::get_unchecked(self, idx) } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +#[cfg(not(bootstrap))] +impl const Iterator for Zip where - A: Iterator, - B: Iterator, + A: ~const Iterator, + B: ~const Iterator, + A::Item: ~const Destruct, + B::Item: ~const Destruct, { type Item = (A::Item, B::Item); @@ -119,6 +186,7 @@ where // Zip specialization trait #[doc(hidden)] +#[const_trait] trait ZipImpl { type Item; fn new(a: A, b: B) -> Self; @@ -150,6 +218,7 @@ macro_rules! zip_impl_general_defaults { } #[inline] + #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_try, const_for))] default fn next(&mut self) -> Option<(A::Item, B::Item)> { let x = self.a.next()?; let y = self.b.next()?; @@ -164,8 +233,8 @@ macro_rules! zip_impl_general_defaults { #[inline] default fn next_back(&mut self) -> Option<(A::Item, B::Item)> where - A: DoubleEndedIterator + ExactSizeIterator, - B: DoubleEndedIterator + ExactSizeIterator, + A: ~const DoubleEndedIterator + ~const ExactSizeIterator, + B: ~const DoubleEndedIterator + ~const ExactSizeIterator, { // The function body below only uses `self.a/b.len()` and `self.a/b.next_back()` // and doesn’t call `next_back` too often, so this implementation is safe in @@ -176,12 +245,17 @@ macro_rules! zip_impl_general_defaults { if a_sz != b_sz { // Adjust a, b to equal length if a_sz > b_sz { - for _ in 0..a_sz - b_sz { + // FIXME(const_trait_impl): replace with `for` + let mut i = 0; + while i < a_sz - b_sz { self.a.next_back(); + i += 1; } } else { - for _ in 0..b_sz - a_sz { + let mut i = 0; + while i < b_sz - a_sz { self.b.next_back(); + i += 1; } } } @@ -196,6 +270,7 @@ macro_rules! zip_impl_general_defaults { // General Zip impl #[doc(hidden)] +#[cfg(bootstrap)] impl ZipImpl for Zip where A: Iterator, @@ -231,6 +306,45 @@ where } #[doc(hidden)] +#[cfg(not(bootstrap))] +impl const ZipImpl for Zip +where + A: ~const Iterator, + B: ~const Iterator, + A::Item: ~const Destruct, + B::Item: ~const Destruct, +{ + type Item = (A::Item, B::Item); + + zip_impl_general_defaults! {} + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = cmp::min(a_lower, b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => Some(cmp::min(x, y)), + (Some(x), None) => Some(x), + (None, Some(y)) => Some(y), + (None, None) => None, + }; + + (lower, upper) + } + + default unsafe fn get_unchecked(&mut self, _idx: usize) -> ::Item + where + Self: TrustedRandomAccessNoCoerce, + { + panic!("internal error: entered unreachable code: Always specialized"); + } +} + +#[doc(hidden)] +#[cfg(bootstrap)] impl ZipImpl for Zip where A: TrustedRandomAccessNoCoerce + Iterator, @@ -254,6 +368,33 @@ where } #[doc(hidden)] +#[cfg(not(bootstrap))] +impl const ZipImpl for Zip +where + A: ~const TrustedRandomAccessNoCoerce + ~const Iterator, + B: ~const TrustedRandomAccessNoCoerce + ~const Iterator, + A::Item: ~const Destruct, + B::Item: ~const Destruct, +{ + zip_impl_general_defaults! {} + + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let size = cmp::min(self.a.size(), self.b.size()); + (size, Some(size)) + } + + #[inline] + unsafe fn get_unchecked(&mut self, idx: usize) -> ::Item { + let idx = self.index + idx; + // SAFETY: the caller must uphold the contract for + // `Iterator::__iterator_get_unchecked`. + unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) } + } +} + +#[doc(hidden)] +#[cfg(bootstrap)] impl ZipImpl for Zip where A: TrustedRandomAccess + Iterator, @@ -374,6 +515,149 @@ where } } +#[doc(hidden)] +#[cfg(not(bootstrap))] +impl const ZipImpl for Zip +where + A: ~const TrustedRandomAccess + ~const Iterator, + B: ~const TrustedRandomAccess + ~const Iterator, + A::Item: ~const Destruct, + B::Item: ~const Destruct, +{ + fn new(a: A, b: B) -> Self { + let a_len = a.size(); + let len = cmp::min(a_len, b.size()); + Zip { a, b, index: 0, len, a_len } + } + + #[inline] + fn next(&mut self) -> Option<(A::Item, B::Item)> { + if self.index < self.len { + let i = self.index; + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess + self.index += 1; + // SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()` + unsafe { + Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i))) + } + } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len { + let i = self.index; + // as above, increment before executing code that may panic + self.index += 1; + self.len += 1; + // match the base implementation's potential side effects + // SAFETY: we just checked that `i` < `self.a.len()` + unsafe { + self.a.__iterator_get_unchecked(i); + } + None + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len - self.index; + (len, Some(len)) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + let delta = cmp::min(n, self.len - self.index); + let end = self.index + delta; + while self.index < end { + let i = self.index; + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess + self.index += 1; + if A::MAY_HAVE_SIDE_EFFECT { + // SAFETY: the usage of `cmp::min` to calculate `delta` + // ensures that `end` is smaller than or equal to `self.len`, + // so `i` is also smaller than `self.len`. + unsafe { + self.a.__iterator_get_unchecked(i); + } + } + if B::MAY_HAVE_SIDE_EFFECT { + // SAFETY: same as above. + unsafe { + self.b.__iterator_get_unchecked(i); + } + } + } + + self.super_nth(n - delta) + } + + #[inline] + fn next_back(&mut self) -> Option<(A::Item, B::Item)> + where + A: ~const DoubleEndedIterator + ~const ExactSizeIterator, + B: ~const DoubleEndedIterator + ~const ExactSizeIterator, + { + if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_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::MAY_HAVE_SIDE_EFFECT && sz_a > self.len { + // FIXME(const_trait_impl): replace with `for` + let mut i = 0; + while i < sz_a - self.len { + // since next_back() may panic we increment the counters beforehand + // to keep Zip's state in sync with the underlying iterator source + self.a_len -= 1; + self.a.next_back(); + i += 1; + } + #[track_caller] + fn assert_rt(a: usize, b: usize) { + debug_assert_eq!(a, b); + } + const fn assert_ct(a: usize, b: usize) { + if a == b { + return; + } + panic!("assertion failed") + } + // SAFETY: only panicking + unsafe { + const_eval_select((self.a_len, self.len), assert_ct, assert_rt); + } + } + let sz_b = self.b.size(); + if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len { + // FIXME(const_trait_impl): replace with `for` + let mut i = 0; + while i < sz_a - self.len { + self.b.next_back(); + i += 1; + } + } + } + } + if self.index < self.len { + // since get_unchecked executes code which can panic we increment the counters beforehand + // so that the same index won't be accessed twice, as required by TrustedRandomAccess + self.len -= 1; + self.a_len -= 1; + let i = self.len; + // SAFETY: `i` is smaller than the previous value of `self.len`, + // which is also smaller than or equal to `self.a.len()` and `self.b.len()` + unsafe { + Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i))) + } + } else { + None + } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Zip where @@ -520,7 +804,7 @@ impl(it: &mut I, idx: usize) -> I::Item +pub(in crate::iter::adapters) const unsafe fn try_get_unchecked( + it: &mut I, + idx: usize, +) -> I::Item where - I: Iterator, + I: ~const Iterator, { // SAFETY: the caller must uphold the contract for // `Iterator::__iterator_get_unchecked`. unsafe { it.try_get_unchecked(idx) } } +#[const_trait] unsafe trait SpecTrustedRandomAccess: Iterator { /// If `Self: TrustedRandomAccess`, it must be safe to call /// `Iterator::__iterator_get_unchecked(self, index)`. unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item; } -unsafe impl SpecTrustedRandomAccess for I { +unsafe impl const SpecTrustedRandomAccess for I { default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item { panic!("Should only be called on TrustedRandomAccess iterators"); } } -unsafe impl SpecTrustedRandomAccess for I { +unsafe impl const SpecTrustedRandomAccess for I { #[inline] unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item { // SAFETY: the caller must uphold the contract for diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index e099700e3e7c8..14ab23f236ed9 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -1,3 +1,6 @@ +#[cfg(not(bootstrap))] +use crate::marker::Destruct; + /// Conversion from an [`Iterator`]. /// /// By implementing `FromIterator` for a type, you define how it will be @@ -236,7 +239,7 @@ pub trait IntoIterator { /// Which kind of iterator are we turning this into? #[stable(feature = "rust1", since = "1.0.0")] - type IntoIter: Iterator; + type IntoIter: ~const Iterator; /// Creates an iterator from a value. /// @@ -264,7 +267,7 @@ pub trait IntoIterator { #[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")] #[stable(feature = "rust1", since = "1.0.0")] -impl const IntoIterator for I { +impl const IntoIterator for I { type Item = I::Item; type IntoIter = I; @@ -344,6 +347,7 @@ impl const IntoIterator for I { /// assert_eq!("MyCollection([5, 6, 7, 1, 2, 3])", format!("{c:?}")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(bootstrap), const_trait)] pub trait Extend { /// Extends a collection with the contents of an iterator. /// @@ -365,7 +369,7 @@ pub trait Extend { /// assert_eq!("abcdef", &message); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn extend>(&mut self, iter: T); + fn extend>(&mut self, iter: T); /// Extends a collection with exactly one element. #[unstable(feature = "extend_one", issue = "72631")] @@ -391,10 +395,51 @@ impl Extend<()> for () { } #[stable(feature = "extend_for_tuple", since = "1.56.0")] +#[cfg(bootstrap)] impl Extend<(A, B)> for (ExtendA, ExtendB) where ExtendA: Extend, ExtendB: Extend, +{ + fn extend>(&mut self, into_iter: T) { + let (a, b) = self; + let iter = into_iter.into_iter(); + + fn extend<'a, A, B>( + a: &'a mut impl Extend, + b: &'a mut impl Extend, + ) -> impl FnMut((), (A, B)) + 'a { + move |(), (t, u)| { + a.extend_one(t); + b.extend_one(u); + } + } + let (lower_bound, _) = iter.size_hint(); + if lower_bound > 0 { + a.extend_reserve(lower_bound); + b.extend_reserve(lower_bound); + } + iter.fold((), extend(a, b)); + } + + fn extend_one(&mut self, item: (A, B)) { + self.0.extend_one(item.0); + self.1.extend_one(item.1); + } + + fn extend_reserve(&mut self, additional: usize) { + self.0.extend_reserve(additional); + self.1.extend_reserve(additional); + } +} + +#[stable(feature = "extend_for_tuple", since = "1.56.0")] +#[rustc_const_unstable(feature = "const_extend", issue = "none")] +#[cfg(not(bootstrap))] +impl const Extend<(A, B)> for (ExtendA, ExtendB) +where + ExtendA: ~const Extend, + ExtendB: ~const Extend, { /// Allows to `extend` a tuple of collections that also implement `Extend`. /// @@ -416,17 +461,32 @@ where /// assert_eq!(b, [2, 5, 8]); /// assert_eq!(c, [3, 6, 9]); /// ``` - fn extend>(&mut self, into_iter: T) { + fn extend>(&mut self, into_iter: T) + where + T::IntoIter: ~const Destruct, + { let (a, b) = self; let iter = into_iter.into_iter(); - fn extend<'a, A, B>( - a: &'a mut impl Extend, - b: &'a mut impl Extend, - ) -> impl FnMut((), (A, B)) + 'a { - move |(), (t, u)| { - a.extend_one(t); - b.extend_one(u); + pub struct ExtendFold<'a, EA, EB>(&'a mut EA, &'a mut EB); + impl<'a, A, B, EA, EB> const FnOnce<((), (A, B))> for ExtendFold<'a, EA, EB> + where + EA: ~const Extend, + EB: ~const Extend, + { + type Output = (); + extern "rust-call" fn call_once(mut self, args: ((), (A, B))) { + self.call_mut(args) + } + } + impl<'a, A, B, EA, EB> const FnMut<((), (A, B))> for ExtendFold<'a, EA, EB> + where + EA: ~const Extend, + EB: ~const Extend, + { + extern "rust-call" fn call_mut(&mut self, ((), (t, u)): ((), (A, B))) { + self.0.extend_one(t); + self.1.extend_one(u); } } @@ -435,8 +495,7 @@ where a.extend_reserve(lower_bound); b.extend_reserve(lower_bound); } - - iter.fold((), extend(a, b)); + iter.fold((), ExtendFold(a, b)); } fn extend_one(&mut self, item: (A, B)) { diff --git a/library/core/src/iter/traits/exact_size.rs b/library/core/src/iter/traits/exact_size.rs index 1757e37ec0e2f..195965e8ee806 100644 --- a/library/core/src/iter/traits/exact_size.rs +++ b/library/core/src/iter/traits/exact_size.rs @@ -1,3 +1,5 @@ +use crate::intrinsics::const_eval_select; + /// An iterator that knows its exact length. /// /// Many [`Iterator`]s don't know how many times they will iterate, but some do. @@ -73,7 +75,8 @@ /// assert_eq!(4, counter.len()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub trait ExactSizeIterator: Iterator { +#[const_trait] +pub trait ExactSizeIterator: ~const Iterator { /// Returns the exact remaining length of the iterator. /// /// The implementation ensures that the iterator will return exactly `len()` @@ -105,11 +108,25 @@ pub trait ExactSizeIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn len(&self) -> usize { let (lower, upper) = self.size_hint(); + #[track_caller] + #[inline] + fn assert_rt(lower: usize, upper: Option) { + assert_eq!(upper, Some(lower)); + } + const fn assert_ct(lower: usize, upper: Option) { + match upper { + Some(upper) if upper == lower => {} + _ => panic!("expected `upper` to be equal to `Some(lower)`"), + } + } // Note: This assertion is overly defensive, but it checks the invariant // guaranteed by the trait. If this trait were rust-internal, // we could use debug_assert!; assert_eq! will check all Rust user // implementations too. - assert_eq!(upper, Some(lower)); + // SAFETY: only using because compile time functions do not get formatted panic messages + unsafe { + const_eval_select((lower, upper), assert_ct, assert_rt); + } lower } @@ -141,7 +158,8 @@ pub trait ExactSizeIterator: Iterator { } #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for &mut I { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const ExactSizeIterator for &mut I { fn len(&self) -> usize { (**self).len() } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 83c7e8977e9f3..8afbc6b4461fb 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,5 +1,8 @@ use crate::array; use crate::cmp::{self, Ordering}; +use crate::const_closure::ConstFnMutClosure; +use crate::iter::adapters::GenericShunt; +use crate::marker::Destruct; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; use super::super::try_process; @@ -64,6 +67,7 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} #[doc(notable_trait)] #[rustc_diagnostic_item = "Iterator"] #[must_use = "iterators are lazy and do nothing unless consumed"] +#[cfg_attr(not(bootstrap), const_trait)] pub trait Iterator { /// The type of the elements being iterated over. #[stable(feature = "rust1", since = "1.0.0")] @@ -140,6 +144,7 @@ pub trait Iterator { ) -> Result<[Self::Item; N], array::IntoIter> where Self: Sized, + Self::Item: ~const Destruct, { array::iter_next_chunk(self) } @@ -252,12 +257,14 @@ pub trait Iterator { fn count(self) -> usize where Self: Sized, + Self: ~const Destruct, + Self::Item: ~const Destruct, { - self.fold( - 0, - #[rustc_inherit_overflow_checks] - |count, _| count + 1, - ) + #[rustc_inherit_overflow_checks] + const fn fold(count: usize, _: T) -> usize { + count + 1 + } + self.fold(0, fold) } /// Consumes the iterator, returning the last element. @@ -282,9 +289,11 @@ pub trait Iterator { fn last(self) -> Option where Self: Sized, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] - fn some(_: Option, x: T) -> Option { + const fn some(_: Option, x: T) -> Option { Some(x) } @@ -325,9 +334,15 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { - for i in 0..n { + fn advance_by(&mut self, n: usize) -> Result<(), usize> + where + Self::Item: ~const Destruct, + { + let mut i = 0; + // FIXME(const_trait_impl) use a for loop once `Range` can implement iterator. + while i < n { self.next().ok_or(i)?; + i += 1; } Ok(()) } @@ -373,7 +388,10 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn nth(&mut self, n: usize) -> Option { + fn nth(&mut self, n: usize) -> Option + where + Self::Item: ~const Destruct, + { self.advance_by(n).ok()?; self.next() } @@ -499,7 +517,7 @@ pub trait Iterator { fn chain(self, other: U) -> Chain where Self: Sized, - U: IntoIterator, + U: ~const IntoIterator, { Chain::new(self, other.into_iter()) } @@ -617,7 +635,9 @@ pub trait Iterator { fn zip(self, other: U) -> Zip where Self: Sized, - U: IntoIterator, + U: ~const IntoIterator, + U::Item: ~const Destruct, + Self::Item: ~const Destruct, { Zip::new(self, other.into_iter()) } @@ -818,17 +838,18 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] - fn for_each(self, f: F) + fn for_each(self, mut f: F) where Self: Sized, - F: FnMut(Self::Item), + F: ~const FnMut(Self::Item) + ~const Destruct, + Self: ~const Destruct, { #[inline] - fn call(mut f: impl FnMut(T)) -> impl FnMut((), T) { - move |(), item| f(item) + const fn call(f: &mut F, ((), item): ((), T)) { + f(item) } - self.fold((), call(f)); + self.fold((), ConstFnMutClosure::new(&mut f, call)); } /// Creates an iterator which uses a closure to determine if an element @@ -1461,7 +1482,8 @@ pub trait Iterator { where Self: Sized, U: IntoIterator, - F: FnMut(Self::Item) -> U, + F: ~const FnMut(Self::Item) -> U + ~const Destruct, + Self: ~const Destruct, { FlatMap::new(self, f) } @@ -1829,7 +1851,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] - fn collect>(self) -> B + fn collect>(self) -> B where Self: Sized, { @@ -1910,11 +1932,28 @@ pub trait Iterator { fn try_collect(&mut self) -> ChangeOutputType where Self: Sized, - ::Item: Try, - <::Item as Try>::Residual: Residual, - B: FromIterator<::Output>, - { - try_process(ByRefSized(self), |i| i.collect()) + ::Item: ~const Try, + <::Item as Try>::Residual: ~const Residual + ~const Destruct, + B: ~const FromIterator<::Output> + ~const Destruct, + { + #[cfg(bootstrap)] + let collect = |x: GenericShunt<'_, _, _>| x.collect(); + #[cfg(not(bootstrap))] + const fn collect< + 'a, + T: ~const Iterator, + R, + O: ~const FromIterator<<::Item as Try>::Output>, + >( + x: GenericShunt<'a, T, R>, + ) -> O + where + T::Item: ~const Try, + R: ~const Destruct, + { + x.collect() + } + try_process(ByRefSized(self), collect) } /// Collects all the items from an iterator into a collection. @@ -1980,7 +2019,7 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_collect_into", reason = "new API", issue = "94780")] - fn collect_into>(self, collection: &mut E) -> &mut E + fn collect_into>(self, collection: &mut E) -> &mut E where Self: Sized, { @@ -2017,30 +2056,29 @@ pub trait Iterator { fn partition(self, f: F) -> (B, B) where Self: Sized, - B: Default + Extend, - F: FnMut(&Self::Item) -> bool, + B: ~const Default + ~const Extend + ~const Destruct, + F: ~const FnMut(&Self::Item) -> bool + ~const Destruct, + Self: ~const Destruct, { #[inline] - fn extend<'a, T, B: Extend>( - mut f: impl FnMut(&T) -> bool + 'a, - left: &'a mut B, - right: &'a mut B, - ) -> impl FnMut((), T) + 'a { - move |(), x| { - if f(&x) { - left.extend_one(x); - } else { - right.extend_one(x); - } + const fn extend bool, T, B: ~const Extend>( + (f, left, right): &mut (F, B, B), + ((), x): ((), T), + ) { + if f(&x) { + left.extend_one(x); + } else { + right.extend_one(x); } } - let mut left: B = Default::default(); - let mut right: B = Default::default(); + let left: B = Default::default(); + let right: B = Default::default(); + let mut tuple = (f, left, right); - self.fold((), extend(f, &mut left, &mut right)); + self.fold((), ConstFnMutClosure::new(&mut tuple, extend)); - (left, right) + (tuple.1, tuple.2) } /// Reorders the elements of this iterator *in-place* according to the given predicate, @@ -2078,8 +2116,9 @@ pub trait Iterator { #[unstable(feature = "iter_partition_in_place", reason = "new API", issue = "62543")] fn partition_in_place<'a, T: 'a, P>(mut self, ref mut predicate: P) -> usize where - Self: Sized + DoubleEndedIterator, - P: FnMut(&T) -> bool, + Self: Sized + ~const DoubleEndedIterator, + P: ~const FnMut(&T) -> bool + ~const Destruct, + Self: ~const Destruct, { // FIXME: should we worry about the count overflowing? The only way to have more than // `usize::MAX` mutable references is with ZSTs, which aren't useful to partition... @@ -2087,33 +2126,35 @@ pub trait Iterator { // These closure "factory" functions exist to avoid genericity in `Self`. #[inline] - fn is_false<'a, T>( - predicate: &'a mut impl FnMut(&T) -> bool, - true_count: &'a mut usize, - ) -> impl FnMut(&&mut T) -> bool + 'a { - move |x| { - let p = predicate(&**x); - *true_count += p as usize; - !p - } + const fn is_false bool, T>( + (predicate, true_count): &mut (F, usize), + (x,): (&&mut T,), + ) -> bool { + let p = predicate(&**x); + *true_count += p as usize; + !p } #[inline] - fn is_true(predicate: &mut impl FnMut(&T) -> bool) -> impl FnMut(&&mut T) -> bool + '_ { - move |x| predicate(&**x) + const fn is_true bool, T>( + predicate: &mut F, + (x,): (&&mut T,), + ) -> bool { + predicate(&**x) } // Repeatedly find the first `false` and swap it with the last `true`. - let mut true_count = 0; - while let Some(head) = self.find(is_false(predicate, &mut true_count)) { - if let Some(tail) = self.rfind(is_true(predicate)) { + let mut tuple = (predicate, 0); + let mut f = ConstFnMutClosure::new(&mut tuple, is_false); + while let Some(head) = self.find(&mut f) { + if let Some(tail) = self.rfind(ConstFnMutClosure::new(&mut f.data.0, is_true)) { crate::mem::swap(head, tail); - true_count += 1; + f.data.1 += 1; } else { break; } } - true_count + tuple.1 } /// Checks if the elements of this iterator are partitioned according to the given predicate, @@ -2136,7 +2177,9 @@ pub trait Iterator { fn is_partitioned

(mut self, mut predicate: P) -> bool where Self: Sized, - P: FnMut(Self::Item) -> bool, + P: ~const FnMut(Self::Item) -> bool + ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { // Either all items test `true`, or the first clause stops at `false` // and we check that there are no more `true` items after that. @@ -2230,12 +2273,15 @@ pub trait Iterator { fn try_fold(&mut self, init: B, mut f: F) -> R where Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try, + F: ~const FnMut(B, Self::Item) -> R + ~const Destruct, + R: ~const Try, { let mut accum = init; - while let Some(x) = self.next() { - accum = f(accum, x)?; + loop { + match self.next() { + Some(x) => accum = f(accum, x)?, + None => break, + } } try { accum } } @@ -2285,18 +2331,21 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] - fn try_for_each(&mut self, f: F) -> R + fn try_for_each(&mut self, mut f: F) -> R where Self: Sized, - F: FnMut(Self::Item) -> R, - R: Try, + F: ~const FnMut(Self::Item) -> R + ~const Destruct, + R: ~const Try, { #[inline] - fn call(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R { - move |(), x| f(x) + const fn call(f: &mut F, ((), x): ((), T)) -> R + where + F: ~const FnMut(T) -> R, + { + f(x) } - self.try_fold((), call(f)) + self.try_fold((), ConstFnMutClosure::new(&mut f, call)) } /// Folds every element into an accumulator by applying an operation, @@ -2407,11 +2456,15 @@ pub trait Iterator { fn fold(mut self, init: B, mut f: F) -> B where Self: Sized, - F: FnMut(B, Self::Item) -> B, + F: ~const FnMut(B, Self::Item) -> B + ~const Destruct, + Self: ~const Destruct, { let mut accum = init; - while let Some(x) = self.next() { - accum = f(accum, x); + loop { + match self.next() { + Some(x) => accum = f(accum, x), + None => break, + } } accum } @@ -2444,7 +2497,8 @@ pub trait Iterator { fn reduce(mut self, f: F) -> Option where Self: Sized, - F: FnMut(Self::Item, Self::Item) -> Self::Item, + F: ~const FnMut(Self::Item, Self::Item) -> Self::Item + ~const Destruct, + Self: ~const Destruct, { let first = self.next()?; Some(self.fold(first, f)) @@ -2515,9 +2569,9 @@ pub trait Iterator { fn try_reduce(&mut self, f: F) -> ChangeOutputType> where Self: Sized, - F: FnMut(Self::Item, Self::Item) -> R, - R: Try, - R::Residual: Residual>, + F: ~const FnMut(Self::Item, Self::Item) -> R + ~const Destruct, + R: ~const Try, + R::Residual: ~const Residual>, { let first = match self.next() { Some(i) => i, @@ -2569,18 +2623,19 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn all(&mut self, f: F) -> bool + fn all(&mut self, mut f: F) -> bool where Self: Sized, - F: FnMut(Self::Item) -> bool, + F: ~const FnMut(Self::Item) -> bool + ~const Destruct, { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> { - move |(), x| { - if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } - } + const fn check bool, T>( + f: &mut F, + ((), x): ((), T), + ) -> ControlFlow<()> { + if f(x) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } } - self.try_fold((), check(f)) == ControlFlow::CONTINUE + matches!(self.try_fold((), ConstFnMutClosure::new(&mut f, check)), ControlFlow::CONTINUE) } /// Tests if any element of the iterator matches a predicate. @@ -2622,19 +2677,20 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn any(&mut self, f: F) -> bool + fn any(&mut self, mut f: F) -> bool where Self: Sized, - F: FnMut(Self::Item) -> bool, + F: ~const FnMut(Self::Item) -> bool + ~const Destruct, { #[inline] - fn check(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> { - move |(), x| { - if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE } - } + const fn check bool, T>( + f: &mut F, + ((), x): ((), T), + ) -> ControlFlow<()> { + if f(x) { ControlFlow::BREAK } else { ControlFlow::CONTINUE } } - self.try_fold((), check(f)) == ControlFlow::BREAK + matches!(self.try_fold((), ConstFnMutClosure::new(&mut f, check)), ControlFlow::BREAK) } /// Searches for an element of an iterator that satisfies a predicate. @@ -2682,19 +2738,22 @@ pub trait Iterator { /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn find

(&mut self, predicate: P) -> Option + fn find

(&mut self, mut predicate: P) -> Option where Self: Sized, - P: FnMut(&Self::Item) -> bool, + P: ~const FnMut(&Self::Item) -> bool + ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] - fn check(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow { - move |(), x| { - if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } - } + const fn check bool, T: ~const Destruct>( + predicate: &mut F, + ((), x): ((), T), + ) -> ControlFlow { + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } } - self.try_fold((), check(predicate)).break_value() + self.try_fold((), ConstFnMutClosure::new(&mut predicate, check)).break_value() } /// Applies function to the elements of iterator and returns @@ -2713,20 +2772,23 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_find_map", since = "1.30.0")] - fn find_map(&mut self, f: F) -> Option + fn find_map(&mut self, mut f: F) -> Option where Self: Sized, - F: FnMut(Self::Item) -> Option, + F: ~const FnMut(Self::Item) -> Option + ~const Destruct, { #[inline] - fn check(mut f: impl FnMut(T) -> Option) -> impl FnMut((), T) -> ControlFlow { - move |(), x| match f(x) { + const fn check(f: &mut F, ((), x): ((), T)) -> ControlFlow + where + F: ~const FnMut(T) -> Option, + { + match f(x) { Some(x) => ControlFlow::Break(x), None => ControlFlow::CONTINUE, } } - self.try_fold((), check(f)).break_value() + self.try_fold((), ConstFnMutClosure::new(&mut f, check)).break_value() } /// Applies function to the elements of iterator and returns @@ -2769,29 +2831,45 @@ pub trait Iterator { /// ``` #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] - fn try_find(&mut self, f: F) -> ChangeOutputType> + fn try_find(&mut self, mut f: F) -> ChangeOutputType> where Self: Sized, - F: FnMut(&Self::Item) -> R, - R: Try, - R::Residual: Residual>, + F: ~const FnMut(&Self::Item) -> R + ~const Destruct, + R: ~const Try, + R::Residual: ~const Residual>, + Self::Item: ~const Destruct, { #[inline] - fn check( - mut f: impl FnMut(&I) -> V, - ) -> impl FnMut((), I) -> ControlFlow + #[cfg(not(bootstrap))] + const fn check(f: &mut F, ((), x): ((), I)) -> ControlFlow where + F: ~const FnMut(&I) -> V, + V: ~const Try, + R: ~const Residual>, + I: ~const Destruct, + { + match f(&x).branch() { + ControlFlow::Continue(false) => ControlFlow::CONTINUE, + ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))), + ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)), + } + } + + #[cfg(bootstrap)] + fn check(f: &mut F, ((), x): ((), I)) -> ControlFlow + where + F: FnMut(&I) -> V, V: Try, R: Residual>, { - move |(), x| match f(&x).branch() { + match f(&x).branch() { ControlFlow::Continue(false) => ControlFlow::CONTINUE, ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))), ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)), } } - match self.try_fold((), check(f)) { + match self.try_fold((), ConstFnMutClosure::new(&mut f, check)) { ControlFlow::Break(x) => x, ControlFlow::Continue(()) => Try::from_output(None), } @@ -2851,22 +2929,22 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn position

(&mut self, predicate: P) -> Option + fn position

(&mut self, mut predicate: P) -> Option where Self: Sized, - P: FnMut(Self::Item) -> bool, + P: ~const FnMut(Self::Item) -> bool + ~const Destruct, + Self::Item: ~const Destruct, { #[inline] - fn check( - mut predicate: impl FnMut(T) -> bool, - ) -> impl FnMut(usize, T) -> ControlFlow { - #[rustc_inherit_overflow_checks] - move |i, x| { - if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i + 1) } - } + #[rustc_inherit_overflow_checks] + const fn check bool, T>( + predicate: &mut F, + (i, x): (usize, T), + ) -> ControlFlow { + if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i + 1) } } - self.try_fold(0, check(predicate)).break_value() + self.try_fold(0, ConstFnMutClosure::new(&mut predicate, check)).break_value() } /// Searches for an element in an iterator from the right, returning its @@ -2908,25 +2986,25 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn rposition

(&mut self, predicate: P) -> Option + fn rposition

(self) -> P where Self: Sized, - P: Product, + P: ~const Product, { Product::product(self) } @@ -3425,11 +3528,18 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn cmp(self, other: I) -> Ordering where - I: IntoIterator, - Self::Item: Ord, + I: ~const IntoIterator, + Self::Item: ~const Ord + ~const Destruct, + I::IntoIter: ~const Destruct, + I::Item: ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, Self: Sized, { - self.cmp_by(other, |x, y| x.cmp(&y)) + const fn cmp(x: T, y: T) -> Ordering { + x.cmp(&y) + } + self.cmp_by(other, cmp) } /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those @@ -3455,8 +3565,12 @@ pub trait Iterator { fn cmp_by(self, other: I, cmp: F) -> Ordering where Self: Sized, - I: IntoIterator, - F: FnMut(Self::Item, I::Item) -> Ordering, + I: ~const IntoIterator, + F: ~const FnMut(Self::Item, I::Item) -> Ordering + ~const Destruct, + I::IntoIter: ~const Destruct, + I::Item: ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] fn compare(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow @@ -3492,11 +3606,19 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn partial_cmp(self, other: I) -> Option where - I: IntoIterator, - Self::Item: PartialOrd, - Self: Sized, - { - self.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) + I: ~const IntoIterator, + Self::Item: ~const PartialOrd + ~const Destruct, + I::Item: ~const Destruct, + I::IntoIter: ~const Destruct, + Self: ~const Destruct + Sized, + { + const fn partial_cmp + ~const Destruct, B: ~const Destruct>( + a: A, + b: B, + ) -> Option { + a.partial_cmp(&b) + } + self.partial_cmp_by(other, partial_cmp) } /// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those @@ -3531,8 +3653,12 @@ pub trait Iterator { fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option where Self: Sized, - I: IntoIterator, - F: FnMut(Self::Item, I::Item) -> Option, + I: ~const IntoIterator, + F: ~const FnMut(Self::Item, I::Item) -> Option + ~const Destruct, + I::IntoIter: ~const Destruct, + I::Item: ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] fn compare(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow> @@ -3563,11 +3689,21 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn eq(self, other: I) -> bool where - I: IntoIterator, - Self::Item: PartialEq, + I: ~const IntoIterator, + Self::Item: ~const PartialEq + ~const Destruct, + I::IntoIter: ~const Destruct, + I::Item: ~const Destruct, + Self: ~const Destruct, Self: Sized, { - self.eq_by(other, |x, y| x == y) + const fn eq + ~const Destruct, B: ~const Destruct>( + a: A, + b: B, + ) -> bool { + a == b + } + + self.eq_by(other, eq) } /// Determines if the elements of this [`Iterator`] are equal to those of @@ -3589,8 +3725,12 @@ pub trait Iterator { fn eq_by(self, other: I, eq: F) -> bool where Self: Sized, - I: IntoIterator, - F: FnMut(Self::Item, I::Item) -> bool, + I: ~const IntoIterator, + I::IntoIter: ~const Destruct, + F: ~const FnMut(Self::Item, I::Item) -> bool + ~const Destruct, + Self::Item: ~const Destruct, + I::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] fn compare(mut eq: F) -> impl FnMut(X, Y) -> ControlFlow<()> @@ -3620,8 +3760,11 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn ne(self, other: I) -> bool where - I: IntoIterator, - Self::Item: PartialEq, + I: ~const IntoIterator, + Self::Item: ~const PartialEq + ~const Destruct, + I::Item: ~const Destruct, + I::IntoIter: ~const Destruct, + Self: ~const Destruct, Self: Sized, { !self.eq(other) @@ -3641,11 +3784,14 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn lt(self, other: I) -> bool where - I: IntoIterator, - Self::Item: PartialOrd, + I: ~const IntoIterator, + Self::Item: ~const PartialOrd + ~const Destruct, + I::Item: ~const Destruct, + I::IntoIter: ~const Destruct, + Self: ~const Destruct, Self: Sized, { - self.partial_cmp(other) == Some(Ordering::Less) + matches!(self.partial_cmp(other), Some(Ordering::Less)) } /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison) @@ -3662,8 +3808,11 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn le(self, other: I) -> bool where - I: IntoIterator, - Self::Item: PartialOrd, + I: ~const IntoIterator, + Self::Item: ~const PartialOrd + ~const Destruct, + I::Item: ~const Destruct, + I::IntoIter: ~const Destruct, + Self: ~const Destruct, Self: Sized, { matches!(self.partial_cmp(other), Some(Ordering::Less | Ordering::Equal)) @@ -3683,11 +3832,14 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn gt(self, other: I) -> bool where - I: IntoIterator, - Self::Item: PartialOrd, + I: ~const IntoIterator, + Self::Item: ~const PartialOrd + ~const Destruct, + I::Item: ~const Destruct, + I::IntoIter: ~const Destruct, + Self: ~const Destruct, Self: Sized, { - self.partial_cmp(other) == Some(Ordering::Greater) + matches!(self.partial_cmp(other), Some(Ordering::Greater)) } /// Determines if the elements of this [`Iterator`] are [lexicographically](Ord#lexicographical-comparison) @@ -3704,9 +3856,11 @@ pub trait Iterator { #[stable(feature = "iter_order", since = "1.5.0")] fn ge(self, other: I) -> bool where - I: IntoIterator, - Self::Item: PartialOrd, - Self: Sized, + I: ~const IntoIterator, + Self::Item: ~const PartialOrd + ~const Destruct, + I::Item: ~const Destruct, + I::IntoIter: ~const Destruct, + Self: ~const Destruct + Sized, { matches!(self.partial_cmp(other), Some(Ordering::Greater | Ordering::Equal)) } @@ -3736,9 +3890,13 @@ pub trait Iterator { fn is_sorted(self) -> bool where Self: Sized, - Self::Item: PartialOrd, + Self::Item: ~const PartialOrd + ~const Destruct, + Self: ~const Destruct, { - self.is_sorted_by(PartialOrd::partial_cmp) + const fn partial_cmp(x: &T, y: &T) -> Option { + x.partial_cmp(y) + } + self.is_sorted_by(partial_cmp) } /// Checks if the elements of this iterator are sorted using the given comparator function. @@ -3764,28 +3922,30 @@ pub trait Iterator { fn is_sorted_by(mut self, compare: F) -> bool where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Option, + F: ~const FnMut(&Self::Item, &Self::Item) -> Option + ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] - fn check<'a, T>( - last: &'a mut T, - mut compare: impl FnMut(&T, &T) -> Option + 'a, - ) -> impl FnMut(T) -> bool + 'a { - move |curr| { - if let Some(Ordering::Greater) | None = compare(&last, &curr) { - return false; - } - *last = curr; - true + const fn check Option>( + (last, compare): &mut (T, F), + (curr,): (T,), + ) -> bool { + if let Some(Ordering::Greater) | None = compare(&last, &curr) { + return false; } + *last = curr; + true } - let mut last = match self.next() { + let last = match self.next() { Some(e) => e, None => return true, }; - self.all(check(&mut last, compare)) + let mut tupled = (last, compare); + + self.all(ConstFnMutClosure::new(&mut tupled, check)) } /// Checks if the elements of this iterator are sorted using the given key extraction @@ -3810,8 +3970,9 @@ pub trait Iterator { fn is_sorted_by_key(self, f: F) -> bool where Self: Sized, - F: FnMut(Self::Item) -> K, - K: PartialOrd, + F: ~const FnMut(Self::Item) -> K + ~const Destruct, + K: ~const PartialOrd + ~const Destruct, + Self: ~const Destruct, { self.map(f).is_sorted() } @@ -3826,7 +3987,8 @@ pub trait Iterator { where Self: TrustedRandomAccessNoCoerce, { - unreachable!("Always specialized"); + // FIXME(const_trait_impl): replace with unreachable when formatting is const + panic!("internal error: entered unreachable code: Always specialized"); } } @@ -3871,7 +4033,8 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for &mut I { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for &mut I { type Item = I::Item; #[inline] fn next(&mut self) -> Option { @@ -3880,10 +4043,16 @@ impl Iterator for &mut I { fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), usize> + where + I::Item: ~const Destruct, + { (**self).advance_by(n) } - fn nth(&mut self, n: usize) -> Option { + fn nth(&mut self, n: usize) -> Option + where + I::Item: ~const Destruct, + { (**self).nth(n) } } diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs index da753745740d7..dd25794039733 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -75,4 +75,5 @@ pub unsafe trait InPlaceIterable: Iterator {} /// 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 {} +#[const_trait] +pub unsafe trait TrustedStep: ~const Step {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5dc7427bee003..5411e90a6541d 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -107,22 +107,29 @@ #![feature(const_char_convert)] #![feature(const_clone)] #![feature(const_cmp)] +#![feature(const_control_flow)] #![feature(const_discriminant)] +#![cfg_attr(not(bootstrap), feature(const_extend))] #![feature(const_eval_select)] +#![feature(const_for)] #![feature(const_float_bits_conv)] #![feature(const_float_classify)] #![feature(const_fmt_arguments_new)] #![feature(const_hash)] #![feature(const_heap)] #![feature(const_convert)] +#![feature(const_iter)] #![feature(const_index_range_slice_index)] #![feature(const_inherent_unchecked_arith)] #![feature(const_int_unchecked_arith)] #![feature(const_intrinsic_forget)] #![feature(const_likely)] -#![feature(const_maybe_uninit_uninit_array)] +#![feature(const_maybe_uninit_array_assume_init)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init)] +#![feature(const_maybe_uninit_uninit_array)] +#![feature(const_maybe_uninit_write)] +#![feature(const_maybe_uninit_zeroed)] #![feature(const_nonnull_new)] #![feature(const_num_from_num)] #![feature(const_ops)] @@ -132,10 +139,12 @@ #![feature(const_ptr_sub_ptr)] #![feature(const_replace)] #![feature(const_ptr_as_ref)] +#![feature(const_ptr_drop_in_place)] #![feature(const_ptr_is_null)] #![feature(const_ptr_read)] #![feature(const_ptr_write)] #![feature(const_raw_ptr_comparison)] +#![feature(const_result_drop)] #![feature(const_size_of_val)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_ptr_len)] diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index cd183540cd5e9..d4b835ee2d216 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -1,3 +1,4 @@ +use crate::marker::Destruct; use crate::{convert, ops}; /// Used to tell an operation whether it should exit early or go on as usual. @@ -180,9 +181,13 @@ impl ControlFlow { /// ``` #[inline] #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] - pub fn break_value(self) -> Option { + #[rustc_const_unstable(feature = "const_control_flow", issue = "none")] + pub const fn break_value(self) -> Option + where + C: ~const Destruct, + { match self { - ControlFlow::Continue(..) => None, + ControlFlow::Continue(_x) => None, ControlFlow::Break(x) => Some(x), } } @@ -243,7 +248,10 @@ impl ControlFlow { impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[inline] - pub(crate) fn from_try(r: R) -> Self { + pub(crate) const fn from_try(r: R) -> Self + where + R: ~const ops::Try, + { match R::branch(r) { ControlFlow::Continue(v) => ControlFlow::Continue(v), ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)), @@ -252,7 +260,10 @@ impl ControlFlow { /// Convert a `ControlFlow` into any type implementing `Try`; #[inline] - pub(crate) fn into_try(self) -> R { + pub(crate) const fn into_try(self) -> R + where + R: ~const ops::Try, + { match self { ControlFlow::Continue(v) => R::from_output(v), ControlFlow::Break(v) => v, diff --git a/library/core/src/option.rs b/library/core/src/option.rs index a81dbc6924fb7..2c3620c34c3ca 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1924,7 +1924,8 @@ impl const Default for Option { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for Option { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const IntoIterator for Option { type Item = T; type IntoIter = IntoIter; @@ -2044,7 +2045,8 @@ struct Item { opt: Option, } -impl Iterator for Item { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for Item { type Item = A; #[inline] @@ -2175,7 +2177,8 @@ pub struct IntoIter { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for IntoIter { type Item = A; #[inline] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 565c38d222a2c..097844c0304b7 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -487,7 +487,8 @@ mod mut_ptr; #[stable(feature = "drop_in_place", since = "1.8.0")] #[lang = "drop_in_place"] #[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { +#[rustc_const_unstable(feature = "const_ptr_drop_in_place", issue = "none")] +pub const unsafe fn drop_in_place(to_drop: *mut T) { // Code here does not matter - this is replaced by the // real drop glue by the compiler. diff --git a/src/test/ui/issues/issue-23966.stderr b/src/test/ui/issues/issue-23966.stderr index ae8233d5c76e6..3f48c93603ee9 100644 --- a/src/test/ui/issues/issue-23966.stderr +++ b/src/test/ui/issues/issue-23966.stderr @@ -10,8 +10,8 @@ LL | "".chars().fold(|_, _| (), ()); note: required by a bound in `fold` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | F: FnMut(B, Self::Item) -> B, - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fold` +LL | F: ~const FnMut(B, Self::Item) -> B + ~const Destruct, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fold` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr index 72082f0cd1728..9bbe55c814a5a 100644 --- a/src/test/ui/issues/issue-34334.stderr +++ b/src/test/ui/issues/issue-34334.stderr @@ -25,8 +25,8 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr index 2de1503765082..b769b50787538 100644 --- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -11,8 +11,8 @@ LL | let x2: Vec = x1.into_iter().collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error[E0277]: a value of type `Vec` cannot be built from an iterator over elements of type `&f64` --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14 @@ -27,8 +27,8 @@ LL | let x3 = x1.into_iter().collect::>(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to 2 previous errors diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr index 7fe9707e6d232..4c0f8cbd0ba16 100644 --- a/src/test/ui/iterators/collect-into-array.stderr +++ b/src/test/ui/iterators/collect-into-array.stderr @@ -10,8 +10,8 @@ LL | let whatever: [u32; 10] = (0..10).collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to previous error diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr index bce40118bdfa0..45ff1cbda60e3 100644 --- a/src/test/ui/iterators/collect-into-slice.stderr +++ b/src/test/ui/iterators/collect-into-slice.stderr @@ -18,7 +18,7 @@ LL | let some_generated_vec = (0..10).collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B +LL | fn collect>(self) -> B | ^ required by this bound in `collect` error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size @@ -33,8 +33,8 @@ LL | let some_generated_vec = (0..10).collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to 3 previous errors diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr index 33f82448dd2ac..acc73d149b7df 100644 --- a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr +++ b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr @@ -10,8 +10,8 @@ LL | std::iter::empty().collect() note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to previous error diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr index 57978edf2bf05..b8f6582a7b2b6 100644 --- a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr +++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr @@ -10,8 +10,8 @@ LL | x = std::iter::empty().collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_` --> $DIR/recursion4.rs:19:9 @@ -25,8 +25,8 @@ LL | x = std::iter::empty().collect(); note: required by a bound in `collect` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL | -LL | fn collect>(self) -> B - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/derive-clone-for-eq.stderr b/src/test/ui/suggestions/derive-clone-for-eq.stderr index 0645f0cdde7c0..e5c244692bb28 100644 --- a/src/test/ui/suggestions/derive-clone-for-eq.stderr +++ b/src/test/ui/suggestions/derive-clone-for-eq.stderr @@ -12,8 +12,8 @@ LL | impl PartialEq for Struct note: required by a bound in `Eq` --> $SRC_DIR/core/src/cmp.rs:LL:COL | -LL | pub trait Eq: PartialEq { - | ^^^^^^^^^^^^^^^ required by this bound in `Eq` +LL | pub trait Eq: ~const PartialEq { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Eq` = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | diff --git a/src/test/ui/traits/alias/object-fail.stderr b/src/test/ui/traits/alias/object-fail.stderr index 325bc6d280859..a2ed0948b6862 100644 --- a/src/test/ui/traits/alias/object-fail.stderr +++ b/src/test/ui/traits/alias/object-fail.stderr @@ -7,8 +7,8 @@ LL | let _: &dyn EqAlias = &123; note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit --> $SRC_DIR/core/src/cmp.rs:LL:COL | -LL | pub trait Eq: PartialEq { - | ^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter +LL | pub trait Eq: ~const PartialEq { + | ^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter error[E0191]: the value of the associated type `Item` (from trait `Iterator`) must be specified --> $DIR/object-fail.rs:9:17 From 0634b1c21eb74429fba975409ef0441fc179f629 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 24 Sep 2022 06:48:17 +0000 Subject: [PATCH 2/3] Add libcore test --- library/core/src/iter/adapters/zip.rs | 5 +++-- library/core/tests/iter/mod.rs | 14 ++++++++++++++ library/core/tests/lib.rs | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index a4aad675b124d..903bd6659b433 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -608,7 +608,8 @@ where if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len { // FIXME(const_trait_impl): replace with `for` let mut i = 0; - while i < sz_a - self.len { + let upper_bound = sz_a - self.len; + while i < upper_bound { // since next_back() may panic we increment the counters beforehand // to keep Zip's state in sync with the underlying iterator source self.a_len -= 1; @@ -634,7 +635,7 @@ where if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len { // FIXME(const_trait_impl): replace with `for` let mut i = 0; - while i < sz_a - self.len { + while i < sz_b - self.len { self.b.next_back(); i += 1; } diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 770b6f7601fa2..ed9b00458b190 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -100,3 +100,17 @@ pub fn extend_for_unit() { } assert_eq!(x, 5); } + +#[test] +fn test_const_iter() { + const X: usize = { + let mut n = 0; + for a in Some(1) { + n = a; + } + n + }; + + const _: () = assert!(X == 1); + assert_eq!(1, X); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 61d31b3448734..2aea5f964ea62 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -12,7 +12,9 @@ #![feature(const_cell_into_inner)] #![feature(const_convert)] #![feature(const_hash)] +#![feature(const_for)] #![feature(const_heap)] +#![feature(const_iter)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init_read)] #![feature(const_nonnull_new)] From bd189bd6feb88fb7b2b1cdbf6b51e4bfbfa3be3c Mon Sep 17 00:00:00 2001 From: onestacked Date: Wed, 9 Nov 2022 11:08:27 +0100 Subject: [PATCH 3/3] rebased --- library/core/src/array/mod.rs | 8 ++ library/core/src/iter/adapters/mod.rs | 4 + library/core/src/iter/adapters/zip.rs | 27 ++--- library/core/src/iter/range.rs | 1 + library/core/src/iter/traits/accum.rs | 2 + library/core/src/iter/traits/collect.rs | 1 + library/core/src/iter/traits/double_ended.rs | 54 +++++++--- library/core/src/iter/traits/iterator.rs | 75 ++++++++------ library/core/tests/iter/mod.rs | 1 + ...place.Test.SimplifyCfg-make_shim.after.mir | 14 +-- ...[String].AddMovesForPackedDrops.before.mir | 98 +++++++++---------- ...Vec_i32_.AddMovesForPackedDrops.before.mir | 22 ++--- src/test/ui/consts/const-fn-error.stderr | 4 +- src/test/ui/consts/const-for.stderr | 4 +- .../consts/miri_unleashed/assoc_const.stderr | 4 +- src/test/ui/consts/miri_unleashed/drop.stderr | 4 +- src/test/ui/never_type/issue-52443.stderr | 4 +- 17 files changed, 191 insertions(+), 136 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index e1c1a40a956bf..f3fac33c5cbc3 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -853,6 +853,14 @@ where /// /// To minimize indirection fields are still pub but callers should at least use /// `push_unchecked` to signal that something unsafe is going on. +#[cfg(not(bootstrap))] +pub(crate) struct Guard<'a, T: ~const Destruct, const N: usize> { + /// The array to be initialized. + pub array_mut: &'a mut [MaybeUninit; N], + /// The number of items that have been initialized so far. + pub initialized: usize, +} +#[cfg(bootstrap)] pub(crate) struct Guard<'a, T: Destruct, const N: usize> { /// The array to be initialized. pub array_mut: &'a mut [MaybeUninit; N], diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index bf1f40d5219fd..8016486933e14 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,6 +1,10 @@ +#[cfg(not(bootstrap))] +use crate::const_closure::ConstFnMutClosure; use crate::iter::{InPlaceIterable, Iterator}; #[cfg(not(bootstrap))] use crate::marker::Destruct; +#[cfg(not(bootstrap))] +use crate::ops::NeverShortCircuit; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; mod array_chunks; diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 903bd6659b433..db605b9c0485e 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -371,8 +371,8 @@ where #[cfg(not(bootstrap))] impl const ZipImpl for Zip where - A: ~const TrustedRandomAccessNoCoerce + ~const Iterator, - B: ~const TrustedRandomAccessNoCoerce + ~const Iterator, + A: TrustedRandomAccessNoCoerce + ~const Iterator, + B: TrustedRandomAccessNoCoerce + ~const Iterator, A::Item: ~const Destruct, B::Item: ~const Destruct, { @@ -380,7 +380,7 @@ where #[inline] default fn size_hint(&self) -> (usize, Option) { - let size = cmp::min(self.a.size(), self.b.size()); + let size = cmp::min(self.a.size_hint().0, self.b.size_hint().0); (size, Some(size)) } @@ -519,14 +519,14 @@ where #[cfg(not(bootstrap))] impl const ZipImpl for Zip where - A: ~const TrustedRandomAccess + ~const Iterator, - B: ~const TrustedRandomAccess + ~const Iterator, + A: TrustedRandomAccess + ~const Iterator, + B: TrustedRandomAccess + ~const Iterator, A::Item: ~const Destruct, B::Item: ~const Destruct, { fn new(a: A, b: B) -> Self { - let a_len = a.size(); - let len = cmp::min(a_len, b.size()); + let a_len = a.size_hint().0; + let len = cmp::min(a_len, b.size_hint().0); Zip { a, b, index: 0, len, a_len } } @@ -598,13 +598,13 @@ where B: ~const DoubleEndedIterator + ~const ExactSizeIterator, { if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT { - let sz_a = self.a.size(); - let sz_b = self.b.size(); + let sz_a = self.a.size_hint().0; + let sz_b = self.b.size_hint().0; // 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(); + let sz_a = self.a.size_hint().0; if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len { // FIXME(const_trait_impl): replace with `for` let mut i = 0; @@ -631,7 +631,7 @@ where const_eval_select((self.a_len, self.len), assert_ct, assert_rt); } } - let sz_b = self.b.size(); + let sz_b = self.b.size_hint().0; if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len { // FIXME(const_trait_impl): replace with `for` let mut i = 0; @@ -805,7 +805,8 @@ impl usize where - Self: Iterator, + Self: ~const Iterator, { self.size_hint().0 } diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index ac7b389b15b4d..a52753f5753eb 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -21,6 +21,7 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi /// The *successor* operation moves towards values that compare greater. /// The *predecessor* operation moves towards values that compare lesser. #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] +#[const_trait] pub trait Step: Clone + PartialOrd + Sized { /// Returns the number of *successor* steps required to get from `start` to `end`. /// diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 84d83ee39699f..9d71ae02837fc 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -10,6 +10,7 @@ use crate::num::Wrapping; /// [`sum()`]: Iterator::sum /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] +#[const_trait] pub trait Sum: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// "summing up" the items. @@ -27,6 +28,7 @@ pub trait Sum: Sized { /// [`product()`]: Iterator::product /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] +#[const_trait] pub trait Product: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// multiplying the items. diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 14ab23f236ed9..fd1260ba1ba2f 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -122,6 +122,7 @@ use crate::marker::Destruct; label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" )] #[rustc_diagnostic_item = "FromIterator"] +#[const_trait] pub trait FromIterator: Sized { /// Creates a value from an iterator. /// diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index bdf94c792c27c..c097b60a446ed 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,4 +1,8 @@ -use crate::ops::{ControlFlow, Try}; +use crate::{ + const_closure::ConstFnMutClosure, + marker::Destruct, + ops::{ControlFlow, Try}, +}; /// An iterator able to yield elements from both ends. /// @@ -37,7 +41,8 @@ use crate::ops::{ControlFlow, Try}; /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")] -pub trait DoubleEndedIterator: Iterator { +#[const_trait] +pub trait DoubleEndedIterator: ~const Iterator { /// Removes and returns an element from the end of the iterator. /// /// Returns `None` when there are no more elements. @@ -131,10 +136,20 @@ pub trait DoubleEndedIterator: Iterator { /// [`Err(k)`]: Err #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - for i in 0..n { + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> + where + Self::Item: ~const Destruct, + { + //for i in 0..n { + // self.next_back().ok_or(i)?; + //} + + let mut i = 0; + while i < n { self.next_back().ok_or(i)?; + i += 1; } + Ok(()) } @@ -181,7 +196,10 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_nth_back", since = "1.37.0")] - fn nth_back(&mut self, n: usize) -> Option { + fn nth_back(&mut self, n: usize) -> Option + where + Self::Item: ~const Destruct, + { self.advance_back_by(n).ok()?; self.next_back() } @@ -221,8 +239,9 @@ pub trait DoubleEndedIterator: Iterator { fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, - F: FnMut(B, Self::Item) -> R, - R: Try, + Self::Item: ~const Destruct, + F: ~const FnMut(B, Self::Item) -> R + ~const Destruct, + R: ~const Try, { let mut accum = init; while let Some(x) = self.next_back() { @@ -291,8 +310,9 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "iter_rfold", since = "1.27.0")] fn rfold(mut self, init: B, mut f: F) -> B where - Self: Sized, - F: FnMut(B, Self::Item) -> B, + Self: Sized + ~const Destruct, + Self::Item: ~const Destruct, + F: ~const FnMut(B, Self::Item) -> B + ~const Destruct, { let mut accum = init; while let Some(x) = self.next_back() { @@ -344,19 +364,21 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] - fn rfind

(&mut self, predicate: P) -> Option + fn rfind

(&mut self, mut predicate: P) -> Option where Self: Sized, - P: FnMut(&Self::Item) -> bool, + Self::Item: ~const Destruct, + P: ~const FnMut(&Self::Item) -> bool + ~const Destruct, { #[inline] - fn check(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow { - move |(), x| { - if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } - } + const fn check bool>( + predicate: &mut P, + ((), x): ((), T), + ) -> ControlFlow { + if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE } } - self.try_rfold((), check(predicate)).break_value() + self.try_rfold((), ConstFnMutClosure::new(&mut predicate, check)).break_value() } } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 8afbc6b4461fb..25acc428ef4e3 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3562,7 +3562,7 @@ pub trait Iterator { /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn cmp_by(self, other: I, cmp: F) -> Ordering + fn cmp_by(self, other: I, mut cmp: F) -> Ordering where Self: Sized, I: ~const IntoIterator, @@ -3573,17 +3573,17 @@ pub trait Iterator { Self: ~const Destruct, { #[inline] - fn compare(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow + const fn compare(cmp: &mut F, (x, y): (X, Y)) -> ControlFlow where - F: FnMut(X, Y) -> Ordering, + F: ~const FnMut(X, Y) -> Ordering, { - move |x, y| match cmp(x, y) { + match cmp(x, y) { Ordering::Equal => ControlFlow::CONTINUE, non_eq => ControlFlow::Break(non_eq), } } - match iter_compare(self, other.into_iter(), compare(cmp)) { + match iter_compare(self, other.into_iter(), ConstFnMutClosure::new(&mut cmp, compare)) { ControlFlow::Continue(ord) => ord, ControlFlow::Break(ord) => ord, } @@ -3650,7 +3650,7 @@ pub trait Iterator { /// ); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn partial_cmp_by(self, other: I, partial_cmp: F) -> Option + fn partial_cmp_by(self, other: I, mut partial_cmp: F) -> Option where Self: Sized, I: ~const IntoIterator, @@ -3661,17 +3661,24 @@ pub trait Iterator { Self: ~const Destruct, { #[inline] - fn compare(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow> + const fn compare( + partial_cmp: &mut F, + (x, y): (X, Y), + ) -> ControlFlow> where - F: FnMut(X, Y) -> Option, + F: ~const FnMut(X, Y) -> Option, { - move |x, y| match partial_cmp(x, y) { + match partial_cmp(x, y) { Some(Ordering::Equal) => ControlFlow::CONTINUE, non_eq => ControlFlow::Break(non_eq), } } - match iter_compare(self, other.into_iter(), compare(partial_cmp)) { + match iter_compare( + self, + other.into_iter(), + ConstFnMutClosure::new(&mut partial_cmp, compare), + ) { ControlFlow::Continue(ord) => Some(ord), ControlFlow::Break(ord) => ord, } @@ -3722,7 +3729,7 @@ pub trait Iterator { /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); /// ``` #[unstable(feature = "iter_order_by", issue = "64295")] - fn eq_by(self, other: I, eq: F) -> bool + fn eq_by(self, other: I, mut eq: F) -> bool where Self: Sized, I: ~const IntoIterator, @@ -3733,16 +3740,14 @@ pub trait Iterator { Self: ~const Destruct, { #[inline] - fn compare(mut eq: F) -> impl FnMut(X, Y) -> ControlFlow<()> + const fn compare(eq: &mut F, (x, y): (X, Y)) -> ControlFlow<()> where - F: FnMut(X, Y) -> bool, + F: ~const FnMut(X, Y) -> bool, { - move |x, y| { - if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } - } + if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK } } - match iter_compare(self, other.into_iter(), compare(eq)) { + match iter_compare(self, other.into_iter(), ConstFnMutClosure::new(&mut eq, compare)) { ControlFlow::Continue(ord) => ord == Ordering::Equal, ControlFlow::Break(()) => false, } @@ -4003,28 +4008,38 @@ pub trait Iterator { /// Isolates the logic shared by ['cmp_by'](Iterator::cmp_by), /// ['partial_cmp_by'](Iterator::partial_cmp_by), and ['eq_by'](Iterator::eq_by). #[inline] -fn iter_compare(mut a: A, mut b: B, f: F) -> ControlFlow +const fn iter_compare(mut a: A, b: B, f: F) -> ControlFlow where - A: Iterator, - B: Iterator, - F: FnMut(A::Item, B::Item) -> ControlFlow, + A: ~const Iterator + ~const Destruct, + B: ~const Iterator + ~const Destruct, + A::Item: ~const Destruct, + B::Item: ~const Destruct, + F: ~const FnMut(A::Item, B::Item) -> ControlFlow + ~const Destruct, { #[inline] - fn compare<'a, B, X, T>( - b: &'a mut B, - mut f: impl FnMut(X, B::Item) -> ControlFlow + 'a, - ) -> impl FnMut(X) -> ControlFlow> + 'a + const fn compare<'a, B, F, X, T>( + (b, f): &'a mut (B, F), + (x,): (X,), + ) -> ControlFlow> where - B: Iterator, + B: ~const Iterator, + F: ~const FnMut(X, B::Item) -> ControlFlow, + X: ~const Destruct, { - move |x| match b.next() { + match b.next() { None => ControlFlow::Break(ControlFlow::Continue(Ordering::Greater)), - Some(y) => f(x, y).map_break(ControlFlow::Break), + Some(y) => match f(x, y) { + ControlFlow::Break(x) => ControlFlow::Break(ControlFlow::Break(x)), + ControlFlow::Continue(x) => ControlFlow::Continue(x), + }, } } - match a.try_for_each(compare(&mut b, f)) { - ControlFlow::Continue(()) => ControlFlow::Continue(match b.next() { + let mut tuple = (b, f); + let mut f = ConstFnMutClosure::new(&mut tuple, compare); + + match a.try_for_each(&mut f) { + ControlFlow::Continue(()) => ControlFlow::Continue(match f.data.0.next() { None => Ordering::Equal, Some(_) => Ordering::Less, }), diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index ed9b00458b190..6d79b4cb89e14 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -105,6 +105,7 @@ pub fn extend_for_unit() { fn test_const_iter() { const X: usize = { let mut n = 0; + #[cfg_attr(not(bootstrap), allow(for_loops_over_fallibles))] for a in Some(1) { n = a; } diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir index cdc413c568f18..e96c72398816c 100644 --- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir @@ -1,20 +1,20 @@ // MIR for `std::ptr::drop_in_place` after SimplifyCfg-make_shim fn std::ptr::drop_in_place(_1: *mut Test) -> () { - let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _2: &mut Test; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _2: &mut Test; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 bb0: { - Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _3 = ::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _3 = ::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 // mir::Constant // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL // + literal: Const { ty: for<'a> fn(&'a mut Test) {::drop}, val: Value() } } bb1: { - return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } } diff --git a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir index 31ccf14549ca2..3c57d14dea391 100644 --- a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir +++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir @@ -1,101 +1,101 @@ // MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops fn std::ptr::drop_in_place(_1: *mut [String]) -> () { - let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _3: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _4: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _5: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _6: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _7: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _8: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _9: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _10: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _11: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _13: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _14: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _15: *mut [std::string::String]; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _2: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _3: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _4: usize; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _5: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _6: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _7: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _8: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _9: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _10: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _11: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _13: *mut std::string::String; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _14: bool; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _15: *mut [std::string::String]; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 bb0: { - goto -> bb15; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + goto -> bb15; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb1: { - return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb2 (cleanup): { - resume; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + resume; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb3 (cleanup): { - _5 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_5)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _5 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + drop((*_5)) -> bb4; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb4 (cleanup): { - _6 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _6) -> [false: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _6 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + switchInt(move _6) -> [false: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb5: { - _7 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_7)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _7 = &raw mut (*_1)[_4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _4 = Add(move _4, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + drop((*_7)) -> [return: bb6, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb6: { - _8 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _8) -> [false: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _8 = Eq(_4, _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + switchInt(move _8) -> [false: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb7: { - _4 = const 0_usize; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _4 = const 0_usize; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb8: { - goto -> bb7; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + goto -> bb7; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb9 (cleanup): { - _11 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_11)) -> bb10; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _11 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + drop((*_11)) -> bb10; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb10 (cleanup): { - _12 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _12) -> [false: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _12 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + switchInt(move _12) -> [false: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb11: { - _13 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - drop((*_13)) -> [return: bb12, unwind: bb10]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _13 = _9; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _9 = Offset(move _9, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + drop((*_13)) -> [return: bb12, unwind: bb10]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb12: { - _14 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _14) -> [false: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _14 = Eq(_9, _10); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + switchInt(move _14) -> [false: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb13: { - _15 = &raw mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _9 = move _15 as *mut std::string::String (PtrToPtr); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _10 = Offset(_9, move _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - goto -> bb12; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _15 = &raw mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _9 = move _15 as *mut std::string::String (PtrToPtr); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _10 = Offset(_9, move _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + goto -> bb12; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb14: { - goto -> bb13; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + goto -> bb13; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb15: { - _2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _3 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - switchInt(move _2) -> [0_usize: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _3 = Len((*_1)); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + switchInt(move _2) -> [0_usize: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } } diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir index ed9f3bdbdf4d6..ee5b4467c8bf8 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir @@ -1,37 +1,37 @@ // MIR for `std::ptr::drop_in_place` before AddMovesForPackedDrops fn std::ptr::drop_in_place(_1: *mut Vec) -> () { - let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _2: &mut std::vec::Vec; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + let mut _0: (); // return place in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _2: &mut std::vec::Vec; // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + let mut _3: (); // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 bb0: { - goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + goto -> bb6; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb1: { - return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + return; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb2 (cleanup): { - resume; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + resume; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb3: { - goto -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + goto -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb4 (cleanup): { - drop(((*_1).0: alloc::raw_vec::RawVec)) -> bb2; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + drop(((*_1).0: alloc::raw_vec::RawVec)) -> bb2; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb5: { - drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb3, unwind: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb3, unwind: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 } bb6: { - _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 - _3 = as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56 + _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 + _3 = as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:62 // mir::Constant // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL // + literal: Const { ty: for<'a> fn(&'a mut Vec) { as Drop>::drop}, val: Value() } diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr index 02960b363e78f..e36324f0b3eea 100644 --- a/src/test/ui/consts/const-fn-error.stderr +++ b/src/test/ui/consts/const-fn-error.stderr @@ -22,8 +22,8 @@ LL | for i in 0..x { note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL | -LL | impl const IntoIterator for I { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl const IntoIterator for I { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error[E0658]: mutable references are not allowed in constant functions diff --git a/src/test/ui/consts/const-for.stderr b/src/test/ui/consts/const-for.stderr index 11e4ae309c01f..f2e1c8a4991a3 100644 --- a/src/test/ui/consts/const-for.stderr +++ b/src/test/ui/consts/const-for.stderr @@ -7,8 +7,8 @@ LL | for _ in 0..5 {} note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL | -LL | impl const IntoIterator for I { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl const IntoIterator for I { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr index 519bd0748e2b7..ca52a8f58c1ba 100644 --- a/src/test/ui/consts/miri_unleashed/assoc_const.stderr +++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of `, std::string::String>>::F` failed --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | -LL | pub unsafe fn drop_in_place(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub const unsafe fn drop_in_place(to_drop: *mut T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | calling non-const function ` as Drop>::drop` | inside `std::ptr::drop_in_place::> - shim(Some(Vec))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr index a3a502723d223..18417ca487a38 100644 --- a/src/test/ui/consts/miri_unleashed/drop.stderr +++ b/src/test/ui/consts/miri_unleashed/drop.stderr @@ -1,8 +1,8 @@ error[E0080]: could not evaluate static initializer --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL | -LL | pub unsafe fn drop_in_place(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub const unsafe fn drop_in_place(to_drop: *mut T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | calling non-const function ` as Drop>::drop` | inside `std::ptr::drop_in_place::> - shim(Some(Vec))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr index 0910e9ad77a84..3c0daa4c55f01 100644 --- a/src/test/ui/never_type/issue-52443.stderr +++ b/src/test/ui/never_type/issue-52443.stderr @@ -47,8 +47,8 @@ LL | [(); { for _ in 0usize.. {}; 0}]; note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL | -LL | impl const IntoIterator for I { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl const IntoIterator for I { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0658]: mutable references are not allowed in constants

(&mut self, mut predicate: P) -> Option where - P: FnMut(Self::Item) -> bool, - Self: Sized + ExactSizeIterator + DoubleEndedIterator, + P: ~const FnMut(Self::Item) -> bool + ~const Destruct, + Self::Item: ~const Destruct, + Self: Sized + ~const ExactSizeIterator + ~const DoubleEndedIterator, { // No need for an overflow check here, because `ExactSizeIterator` // implies that the number of elements fits into a `usize`. #[inline] - fn check( - mut predicate: impl FnMut(T) -> bool, - ) -> impl FnMut(usize, T) -> ControlFlow { - move |i, x| { - let i = i - 1; - if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i) } - } + const fn check(predicate: &mut F, (i, x): (usize, T)) -> ControlFlow + where + F: ~const FnMut(T) -> bool, + { + let i = i - 1; + if predicate(x) { ControlFlow::Break(i) } else { ControlFlow::Continue(i) } } let n = self.len(); - self.try_rfold(n, check(predicate)).break_value() + self.try_rfold(n, ConstFnMutClosure::new(&mut predicate, check)).break_value() } /// Returns the maximum element of an iterator. @@ -2962,9 +3040,13 @@ pub trait Iterator { fn max(self) -> Option where Self: Sized, - Self::Item: Ord, + Self::Item: ~const Ord + ~const Destruct, + Self: ~const Destruct, { - self.max_by(Ord::cmp) + const fn cmp(x: &T, y: &T) -> Ordering { + x.cmp(y) + } + self.max_by(cmp) } /// Returns the minimum element of an iterator. @@ -3000,9 +3082,14 @@ pub trait Iterator { fn min(self) -> Option where Self: Sized, - Self::Item: Ord, + Self::Item: ~const Ord, + Self::Item: ~const Destruct, + Self: ~const Destruct, { - self.min_by(Ord::cmp) + const fn cmp(x: &T, y: &T) -> Ordering { + x.cmp(y) + } + self.min_by(cmp) } /// Returns the element that gives the maximum value from the @@ -3019,22 +3106,25 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn max_by_key(self, f: F) -> Option + fn max_by_key(self, mut f: F) -> Option where Self: Sized, - F: FnMut(&Self::Item) -> B, + F: ~const FnMut(&Self::Item) -> B + ~const Destruct, + B: ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] - fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { - move |x| (f(&x), x) + const fn key B, T, B>(f: &mut F, (x,): (T,)) -> (B, T) { + (f(&x), x) } #[inline] - fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { + const fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { x_p.cmp(y_p) } - let (_, x) = self.map(key(f)).max_by(compare)?; + let (_, x) = self.map(ConstFnMutClosure::new(&mut f, key)).max_by(compare)?; Some(x) } @@ -3052,17 +3142,22 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_max_by", since = "1.15.0")] - fn max_by(self, compare: F) -> Option + fn max_by(self, mut compare: F) -> Option where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, + F: ~const FnMut(&Self::Item, &Self::Item) -> Ordering + ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] - fn fold(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T { - move |x, y| cmp::max_by(x, y, &mut compare) + const fn fold Ordering, T: ~const Destruct>( + compare: &mut F, + (x, y): (T, T), + ) -> T { + cmp::max_by(x, y, compare) } - self.reduce(fold(compare)) + self.reduce(ConstFnMutClosure::new(&mut compare, fold)) } /// Returns the element that gives the minimum value from the @@ -3079,22 +3174,25 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_cmp_by_key", since = "1.6.0")] - fn min_by_key(self, f: F) -> Option + fn min_by_key(self, mut f: F) -> Option where Self: Sized, - F: FnMut(&Self::Item) -> B, + F: ~const FnMut(&Self::Item) -> B + ~const Destruct, + B: ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] - fn key(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) { - move |x| (f(&x), x) + const fn key B, T, B>(f: &mut F, (x,): (T,)) -> (B, T) { + (f(&x), x) } #[inline] - fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { + const fn compare((x_p, _): &(B, T), (y_p, _): &(B, T)) -> Ordering { x_p.cmp(y_p) } - let (_, x) = self.map(key(f)).min_by(compare)?; + let (_, x) = self.map(ConstFnMutClosure::new(&mut f, key)).min_by(compare)?; Some(x) } @@ -3112,17 +3210,22 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "iter_min_by", since = "1.15.0")] - fn min_by(self, compare: F) -> Option + fn min_by(self, mut compare: F) -> Option where Self: Sized, - F: FnMut(&Self::Item, &Self::Item) -> Ordering, + F: ~const FnMut(&Self::Item, &Self::Item) -> Ordering + ~const Destruct, + Self::Item: ~const Destruct, + Self: ~const Destruct, { #[inline] - fn fold(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T { - move |x, y| cmp::min_by(x, y, &mut compare) + const fn fold Ordering, T: ~const Destruct>( + compare: &mut F, + (x, y): (T, T), + ) -> T { + cmp::min_by(x, y, compare) } - self.reduce(fold(compare)) + self.reduce(ConstFnMutClosure::new(&mut compare, fold)) } /// Reverses an iterator's direction. @@ -3189,9 +3292,9 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn unzip(self) -> (FromA, FromB) where - FromA: Default + Extend, - FromB: Default + Extend, - Self: Sized + Iterator, + FromA: ~const Default + ~const Extend, + FromB: ~const Default + ~const Extend, + Self: Sized + ~const Iterator, { let mut unzipped: (FromA, FromB) = Default::default(); unzipped.extend(self); @@ -3221,7 +3324,7 @@ pub trait Iterator { #[stable(feature = "iter_copied", since = "1.36.0")] fn copied<'a, T: 'a>(self) -> Copied where - Self: Sized + Iterator, + Self: Sized + ~const Iterator, T: Copy, { Copied::new(self) @@ -3302,7 +3405,7 @@ pub trait Iterator { #[inline] fn cycle(self) -> Cycle where - Self: Sized + Clone, + Self: Sized + ~const Clone, { Cycle::new(self) } @@ -3376,7 +3479,7 @@ pub trait Iterator { fn sum(self) -> S where Self: Sized, - S: Sum, + S: ~const Sum, { Sum::sum(self) } @@ -3405,7 +3508,7 @@ pub trait Iterator { fn product