diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index e7e5e30b4eff5..bcdadcada9a30 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -1,4 +1,5 @@ use super::TrustedLen; +use crate::marker::Destruct; /// Conversion from an [`Iterator`]. /// @@ -131,7 +132,8 @@ use super::TrustedLen; label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" )] #[rustc_diagnostic_item = "FromIterator"] -pub trait FromIterator: Sized { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +pub const trait FromIterator: Sized { /// Creates a value from an iterator. /// /// See the [module-level documentation] for more. @@ -288,7 +290,7 @@ pub const 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. /// @@ -393,8 +395,9 @@ const impl IntoIterator for I { /// // we've added these elements onto the end /// assert_eq!("MyCollection([5, 6, 7, 1, 2, 3])", format!("{c:?}")); /// ``` +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] #[stable(feature = "rust1", since = "1.0.0")] -pub trait Extend { +pub const trait Extend { /// Extends a collection with the contents of an iterator. /// /// As this is the only required method for this trait, the [trait-level] docs @@ -413,11 +416,16 @@ 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) + where + T::IntoIter: [const] Destruct; /// Extends a collection with exactly one element. #[unstable(feature = "extend_one", issue = "72631")] - fn extend_one(&mut self, item: A) { + fn extend_one(&mut self, item: A) + where + A: [const] Destruct, + { self.extend(Some(item)); } @@ -445,6 +453,7 @@ pub trait Extend { unsafe fn extend_one_unchecked(&mut self, item: A) where Self: Sized, + A: [const] Destruct, { self.extend_one(item); } @@ -540,41 +549,54 @@ where /// An implementation of [`extend`](Extend::extend) that calls `extend_one` or /// `extend_one_unchecked` for each element of the iterator. -fn default_extend(collection: &mut ExtendT, iter: I) + +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +const fn default_extend(collection: &mut ExtendT, iter: I) where - ExtendT: Extend, - I: IntoIterator, + ExtendT: [const] Extend, + T: [const] Destruct, + I: [const] IntoIterator, + I::IntoIter: [const] Destruct, { // Specialize on `TrustedLen` and call `extend_one_unchecked` where // applicable. - trait SpecExtend { + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const trait SpecExtend { fn extend(&mut self, iter: I); } // Extracting these to separate functions avoid monomorphising the closures // for every iterator type. - fn extender(collection: &mut ExtendT) -> impl FnMut(T) + use<'_, ExtendT, T> + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const fn extender( + collection: &mut ExtendT, + ) -> impl [const] FnMut(T) + use<'_, ExtendT, T> + [const] Destruct where - ExtendT: Extend, + ExtendT: [const] Extend, + T: [const] Destruct, { - move |item| collection.extend_one(item) + const move |item| collection.extend_one(item) } - unsafe fn unchecked_extender( + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const unsafe fn unchecked_extender( collection: &mut ExtendT, - ) -> impl FnMut(T) + use<'_, ExtendT, T> + ) -> impl [const] FnMut(T) + [const] Destruct + use<'_, ExtendT, T> where - ExtendT: Extend, + ExtendT: [const] Extend, + T: [const] Destruct, { // SAFETY: we make sure that there is enough space at the callsite of // this function. - move |item| unsafe { collection.extend_one_unchecked(item) } + const move |item| unsafe { collection.extend_one_unchecked(item) } } - impl SpecExtend for ExtendT + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const impl SpecExtend for ExtendT where - ExtendT: Extend, - I: Iterator, + ExtendT: [const] Extend, + T: [const] Destruct, + I: [const] Iterator + [const] Destruct, { default fn extend(&mut self, iter: I) { let (lower_bound, _) = iter.size_hint(); @@ -586,10 +608,12 @@ where } } - impl SpecExtend for ExtendT + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const impl SpecExtend for ExtendT where - ExtendT: Extend, - I: TrustedLen, + ExtendT: [const] Extend, + T: [const] Destruct, + I: [const] TrustedLen + [const] Destruct, { fn extend(&mut self, iter: I) { let (lower_bound, upper_bound) = iter.size_hint(); @@ -616,11 +640,14 @@ macro_rules! impl_extend_tuple { ($(($ty:tt, $extend_ty:tt, $index:tt)),+) => { #[doc(hidden)] #[stable(feature = "extend_for_tuple", since = "1.56.0")] - impl<$($ty,)+ $($extend_ty,)+> Extend<($($ty,)+)> for ($($extend_ty,)+) + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const impl<$($ty,)+ $($extend_ty,)+> Extend<($($ty,)+)> for ($($extend_ty,)+) where - $($extend_ty: Extend<$ty>,)+ + $($ty: [const] Destruct,)+ + $($extend_ty: [const] Extend<$ty>,)+ { - fn extend>(&mut self, iter: T) { + fn extend>(&mut self, iter: T) + where T::IntoIter: [const] Destruct{ default_extend(self, iter) } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 120c6de3c621d..cbf836e871a36 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -873,15 +873,17 @@ pub const trait Iterator { /// ``` #[inline] #[stable(feature = "iterator_for_each", since = "1.21.0")] - #[rustc_non_const_trait_method] fn for_each(self, f: F) where - Self: Sized, - F: FnMut(Self::Item), + Self: Sized + [const] Destruct, + F: [const] FnMut(Self::Item) + [const] Destruct, { #[inline] - fn call(mut f: impl FnMut(T)) -> impl FnMut((), T) { - move |(), item| f(item) + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const fn call( + mut f: impl [const] FnMut(T) + [const] Destruct, + ) -> impl [const] FnMut((), T) + [const] Destruct { + const move |(), item| f(item) } self.fold((), call(f));