From 505223726c9ea764e273b73e7be1716fea85793e Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Sat, 22 Aug 2026 13:54:47 +0300 Subject: [PATCH 1/4] Constify Extend and FromIterator --- library/core/src/iter/traits/collect.rs | 77 ++++++++++++++++-------- library/core/src/iter/traits/iterator.rs | 12 ++-- 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index cf79ceadf0540..775dd800ee966 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: I); + fn extend>(&mut self, iter: I) + where + I::IntoIter: [const] Destruct; /// Extends a collection with exactly one element. #[unstable(feature = "extend_one", issue = "72631")] - fn extend_one(&mut self, item: T) { + fn extend_one(&mut self, item: T) + where + T: [const] Destruct, + { self.extend(Some(item)); } @@ -445,6 +453,7 @@ pub trait Extend { unsafe fn extend_one_unchecked(&mut self, item: T) 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: Iter) { + fn extend>(&mut self, iter: Iter) + where Iter::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)); From 751b284855d559faecbef97f60895f0d76719e51 Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Mon, 7 Sep 2026 07:39:08 +0300 Subject: [PATCH 2/4] Narrow Destruct bounds --- library/core/src/iter/traits/collect.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 775dd800ee966..27c868cad9a75 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -453,7 +453,7 @@ pub const trait Extend { unsafe fn extend_one_unchecked(&mut self, item: T) where Self: Sized, - A: [const] Destruct, + T: [const] Destruct, { self.extend_one(item); } @@ -562,7 +562,9 @@ where // applicable. #[rustc_const_unstable(feature = "const_iter", issue = "92476")] const trait SpecExtend { - fn extend(&mut self, iter: I); + fn extend(&mut self, iter: I) + where + I: [const] Destruct; } // Extracting these to separate functions avoid monomorphising the closures @@ -595,10 +597,13 @@ where const impl SpecExtend for ExtendT where ExtendT: [const] Extend, + I: [const] Iterator, T: [const] Destruct, - I: [const] Iterator + [const] Destruct, { - default fn extend(&mut self, iter: I) { + default fn extend(&mut self, iter: I) + where + I: [const] Destruct, + { let (lower_bound, _) = iter.size_hint(); if lower_bound > 0 { self.extend_reserve(lower_bound); @@ -612,10 +617,13 @@ where const impl SpecExtend for ExtendT where ExtendT: [const] Extend, + I: [const] TrustedLen, T: [const] Destruct, - I: [const] TrustedLen + [const] Destruct, { - fn extend(&mut self, iter: I) { + fn extend(&mut self, iter: I) + where + I: [const] Destruct, + { let (lower_bound, upper_bound) = iter.size_hint(); if lower_bound > 0 { self.extend_reserve(lower_bound); @@ -647,7 +655,9 @@ macro_rules! impl_extend_tuple { $($extend_ty: [const] Extend<$ty>,)+ { fn extend>(&mut self, iter: Iter) - where Iter::IntoIter: [const] Destruct{ + where + Iter::IntoIter: [const] Destruct + { default_extend(self, iter) } From de9f45c2ca323a73fe2cb25a51b30c042be2378e Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Mon, 7 Sep 2026 16:56:11 +0300 Subject: [PATCH 3/4] Constify FromIterator impl --- library/core/src/iter/traits/collect.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 27c868cad9a75..2d8c51f09b1f2 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -151,7 +151,9 @@ pub const trait FromIterator: Sized { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_diagnostic_item = "from_iter_fn"] - fn from_iter>(iter: I) -> Self; + fn from_iter>(iter: I) -> Self + where + I::IntoIter: [const] Destruct; } /// Conversion into an [`Iterator`]. @@ -678,12 +680,17 @@ macro_rules! impl_extend_tuple { } #[doc(hidden)] + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] #[stable(feature = "from_iterator_for_tuple", since = "1.79.0")] - impl<$($ty,)+ $($extend_ty,)+> FromIterator<($($ty,)+)> for ($($extend_ty,)+) + const impl<$($ty,)+ $($extend_ty,)+> FromIterator<($($ty,)+)> for ($($extend_ty,)+) where - $($extend_ty: Default + Extend<$ty>,)+ + $($ty: [const] Destruct,)+ + $($extend_ty: [const] Default + [const] Extend<$ty>,)+ { - fn from_iter>(iter: Iter) -> Self { + fn from_iter>(iter: Iter) -> Self + where + Iter::IntoIter: [const] Destruct + { let mut res = Self::default(); res.extend(iter); res From 85a0996b8a5bbeb1edc83e9bfb4c5322e5002d12 Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Mon, 7 Sep 2026 17:36:03 +0300 Subject: [PATCH 4/4] Bless tests --- tests/ui/suggestions/missing-assoc-fn.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/suggestions/missing-assoc-fn.stderr b/tests/ui/suggestions/missing-assoc-fn.stderr index ac04f6653866e..1ffbcb6d9527d 100644 --- a/tests/ui/suggestions/missing-assoc-fn.stderr +++ b/tests/ui/suggestions/missing-assoc-fn.stderr @@ -19,7 +19,7 @@ error[E0046]: not all trait items implemented, missing: `from_iter` LL | impl FromIterator<()> for X { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation | - = help: implement the missing item: `fn from_iter>(_: I) -> Self { todo!() }` + = help: implement the missing item: `fn from_iter>(_: I) -> Self where ::IntoIter: Destruct { todo!() }` error: aborting due to 2 previous errors