Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 52 additions & 25 deletions library/core/src/iter/traits/collect.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::TrustedLen;
use crate::marker::Destruct;

/// Conversion from an [`Iterator`].
///
Expand Down Expand Up @@ -131,7 +132,8 @@ use super::TrustedLen;
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
)]
#[rustc_diagnostic_item = "FromIterator"]
pub trait FromIterator<A>: Sized {
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
pub const trait FromIterator<A>: Sized {
/// Creates a value from an iterator.
///
/// See the [module-level documentation] for more.
Expand Down Expand Up @@ -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<Item = Self::Item>;
type IntoIter: [const] Iterator<Item = Self::Item>;

/// Creates an iterator from a value.
///
Expand Down Expand Up @@ -393,8 +395,9 @@ const impl<I: [const] Iterator> 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<A> {
pub const trait Extend<A> {
/// Extends a collection with the contents of an iterator.
///
/// As this is the only required method for this trait, the [trait-level] docs
Expand All @@ -413,11 +416,16 @@ pub trait Extend<A> {
/// assert_eq!("abcdef", &message);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T);
fn extend<T: [const] IntoIterator<Item = A>>(&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));
}

Expand Down Expand Up @@ -445,6 +453,7 @@ pub trait Extend<A> {
unsafe fn extend_one_unchecked(&mut self, item: A)
where
Self: Sized,
A: [const] Destruct,
{
self.extend_one(item);
}
Expand Down Expand Up @@ -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<ExtendT, I, T>(collection: &mut ExtendT, iter: I)

#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const fn default_extend<ExtendT, I, T>(collection: &mut ExtendT, iter: I)
where
ExtendT: Extend<T>,
I: IntoIterator<Item = T>,
ExtendT: [const] Extend<T>,
T: [const] Destruct,
I: [const] IntoIterator<Item = T>,
I::IntoIter: [const] Destruct,
{
// Specialize on `TrustedLen` and call `extend_one_unchecked` where
// applicable.
trait SpecExtend<I> {
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const trait SpecExtend<I> {
fn extend(&mut self, iter: I);
}

// Extracting these to separate functions avoid monomorphising the closures
// for every iterator type.
fn extender<ExtendT, T>(collection: &mut ExtendT) -> impl FnMut(T) + use<'_, ExtendT, T>
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const fn extender<ExtendT, T>(
collection: &mut ExtendT,
) -> impl [const] FnMut(T) + use<'_, ExtendT, T> + [const] Destruct
where
ExtendT: Extend<T>,
ExtendT: [const] Extend<T>,
T: [const] Destruct,
{
move |item| collection.extend_one(item)
const move |item| collection.extend_one(item)
}

unsafe fn unchecked_extender<ExtendT, T>(
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const unsafe fn unchecked_extender<ExtendT, T>(
collection: &mut ExtendT,
) -> impl FnMut(T) + use<'_, ExtendT, T>
) -> impl [const] FnMut(T) + [const] Destruct + use<'_, ExtendT, T>
where
ExtendT: Extend<T>,
ExtendT: [const] Extend<T>,
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<ExtendT, I, T> SpecExtend<I> for ExtendT
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const impl<ExtendT, I, T> SpecExtend<I> for ExtendT
where
ExtendT: Extend<T>,
I: Iterator<Item = T>,
ExtendT: [const] Extend<T>,
T: [const] Destruct,
I: [const] Iterator<Item = T> + [const] Destruct,
{
default fn extend(&mut self, iter: I) {
let (lower_bound, _) = iter.size_hint();
Expand All @@ -586,10 +608,12 @@ where
}
}

impl<ExtendT, I, T> SpecExtend<I> for ExtendT
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const impl<ExtendT, I, T> SpecExtend<I> for ExtendT
where
ExtendT: Extend<T>,
I: TrustedLen<Item = T>,
ExtendT: [const] Extend<T>,
T: [const] Destruct,
I: [const] TrustedLen<Item = T> + [const] Destruct,
{
fn extend(&mut self, iter: I) {
let (lower_bound, upper_bound) = iter.size_hint();
Expand All @@ -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<T: IntoIterator<Item = ($($ty,)+)>>(&mut self, iter: T) {
fn extend<T: [const] IntoIterator<Item = ($($ty,)+)>>(&mut self, iter: T)
where T::IntoIter: [const] Destruct{
default_extend(self, iter)
}

Expand Down
12 changes: 7 additions & 5 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F>(self, f: F)
where
Self: Sized,
F: FnMut(Self::Item),
Self: Sized + [const] Destruct,
F: [const] FnMut(Self::Item) + [const] Destruct,
{
#[inline]
fn call<T>(mut f: impl FnMut(T)) -> impl FnMut((), T) {
move |(), item| f(item)
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const fn call<T>(
mut f: impl [const] FnMut(T) + [const] Destruct,
) -> impl [const] FnMut((), T) + [const] Destruct {
const move |(), item| f(item)
}

self.fold((), call(f));
Expand Down
Loading