Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it possible to have const impls for Iterator #92433

Closed
wants to merge 5 commits into from
Closed
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
16 changes: 14 additions & 2 deletions library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,7 +1192,13 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
pub const fn min_by<T, F>(v1: T, v2: T, compare: F) -> T
where
F: ~const FnOnce(&T, &T) -> Ordering,
F: ~const Drop,
T: ~const Drop,
{
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
Ordering::Greater => v2,
Expand Down Expand Up @@ -1255,7 +1261,13 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
#[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
pub const fn max_by<T, F>(v1: T, v2: T, compare: F) -> T
where
F: ~const FnOnce(&T, &T) -> Ordering,
F: ~const Drop,
T: ~const Drop,
{
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
Ordering::Greater => v1,
Expand Down
49 changes: 49 additions & 0 deletions library/core/src/internal_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,52 @@ macro_rules! impl_fn_for_zst {
)+
}
}

macro_rules! impl_const_closure {
(
impl$(<$( $tt : tt ),*>)?
const FnOnce for $Name: path $(where $($WhereTy:ty : $(~ $const:ident)? $Trait:path),+ $(,)?)? =
$(#[$meta:meta])*
|$mutorself:ident $($self:ident)?, $( $arg: tt: $ArgTy: ty ),*| $(-> $ReturnTy: ty)?
$body: block;
) => {
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
impl $( < $( $tt ),* > )? const FnOnce<($( $ArgTy, )*)> for $Name
$(where $($WhereTy: $(~$const)? $Trait),+)?
{
#[allow(unused_parens)]
type Output = ( $( $ReturnTy )? );

#[allow(unused_mut)]
$(#[$meta])*
extern "rust-call" fn call_once($mutorself $($self)?, ($( $arg, )*): ($( $ArgTy, )*)) -> Self::Output {
$body
}
}
};
(
impl$(< $( $tt: tt ),* >)?
const FnMut for $Name: path $(where $($WhereTy:ty : $(~ $const:ident)? $Trait:path),+ $(,)?)? =
$(#[$meta:meta])*
|&mut $self:ident, $( $arg: tt: $ArgTy: ty ),*| $(-> $ReturnTy: ty)?
$body: block;
) => {
impl_const_closure! {
impl$(< $( $tt ),* >)?
const FnOnce for $Name $(where $($WhereTy: $(~$const)? $Trait),+)? =
$(#[$meta])*
|mut $self, $( $arg: $ArgTy),*| $(-> $ReturnTy)?
$body;
}
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
impl $( < $( $tt ),* > )? const FnMut<($( $ArgTy, )*)> for $Name
$(where $($WhereTy: $(~$const)? $Trait),+)?
{
$(#[$meta])*
#[allow(unused_parens)]
extern "rust-call" fn call_mut(&mut $self, ($( $arg, )*): ($( $ArgTy, )*)) -> ( $($ReturnTy)? ) {
$body
}
}
}
}
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct Chain<A, B> {
b: Option<B>,
}
impl<A, B> Chain<A, B> {
pub(in super::super) fn new(a: A, b: B) -> Chain<A, B> {
pub(in super::super) const fn new(a: A, b: B) -> Chain<A, B> {
Chain { a: Some(a), b: Some(b) }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/cloned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct Cloned<I> {
}

impl<I> Cloned<I> {
pub(in crate::iter) fn new(it: I) -> Cloned<I> {
pub(in crate::iter) const fn new(it: I) -> Cloned<I> {
Cloned { it }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/copied.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct Copied<I> {
}

impl<I> Copied<I> {
pub(in crate::iter) fn new(it: I) -> Copied<I> {
pub(in crate::iter) const fn new(it: I) -> Copied<I> {
Copied { it }
}
}
Expand Down
8 changes: 6 additions & 2 deletions library/core/src/iter/adapters/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ pub struct Cycle<I> {
iter: I,
}

impl<I: Clone> Cycle<I> {
pub(in crate::iter) fn new(iter: I) -> Cycle<I> {
impl<I> Cycle<I> {
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
pub(in crate::iter) const fn new(iter: I) -> Cycle<I>
where
I: ~const Clone,
{
Cycle { orig: iter.clone(), iter }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/enumerate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct Enumerate<I> {
count: usize,
}
impl<I> Enumerate<I> {
pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
pub(in crate::iter) const fn new(iter: I) -> Enumerate<I> {
Enumerate { iter, count: 0 }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct Filter<I, P> {
predicate: P,
}
impl<I, P> Filter<I, P> {
pub(in crate::iter) fn new(iter: I, predicate: P) -> Filter<I, P> {
pub(in crate::iter) const fn new(iter: I, predicate: P) -> Filter<I, P> {
Filter { iter, predicate }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/filter_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct FilterMap<I, F> {
f: F,
}
impl<I, F> FilterMap<I, F> {
pub(in crate::iter) fn new(iter: I, f: F) -> FilterMap<I, F> {
pub(in crate::iter) const fn new(iter: I, f: F) -> FilterMap<I, F> {
FilterMap { iter, f }
}
}
Expand Down
17 changes: 8 additions & 9 deletions library/core/src/iter/adapters/flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ pub struct FlatMap<I, U: IntoIterator, F> {
}

impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
pub(in crate::iter) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
FlatMap { inner: FlattenCompat::new(iter.map(f)) }
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
pub(in crate::iter) const fn new(iter: I, f: F) -> FlatMap<I, U, F> {
FlatMap { inner: FlattenCompat::new(Map::new(iter, f)) }
}
}

Expand Down Expand Up @@ -152,7 +153,8 @@ pub struct Flatten<I: Iterator<Item: IntoIterator>> {
}

impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
pub(in super::super) fn new(iter: I) -> Flatten<I> {
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
pub(in super::super) const fn new(iter: I) -> Flatten<I> {
Flatten { inner: FlattenCompat::new(iter) }
}
}
Expand Down Expand Up @@ -270,13 +272,10 @@ struct FlattenCompat<I, U> {
frontiter: Option<U>,
backiter: Option<U>,
}
impl<I, U> FlattenCompat<I, U>
where
I: Iterator,
{
impl<I, U> FlattenCompat<I, U> {
/// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
fn new(iter: I) -> FlattenCompat<I, U> {
FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
const fn new(iter: I) -> FlattenCompat<I, U> {
FlattenCompat { iter: super::Fuse::new(iter), frontiter: None, backiter: None }
}
}

Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/fuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Fuse<I> {
iter: Option<I>,
}
impl<I> Fuse<I> {
pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
pub(in crate::iter) const fn new(iter: I) -> Fuse<I> {
Fuse { iter: Some(iter) }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/inspect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct Inspect<I, F> {
f: F,
}
impl<I, F> Inspect<I, F> {
pub(in crate::iter) fn new(iter: I, f: F) -> Inspect<I, F> {
pub(in crate::iter) const fn new(iter: I, f: F) -> Inspect<I, F> {
Inspect { iter, f }
}
}
Expand Down
10 changes: 6 additions & 4 deletions library/core/src/iter/adapters/intersperse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ impl<I: Iterator> Intersperse<I>
where
I::Item: Clone,
{
pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
Self { iter: iter.peekable(), separator, needs_sep: false }
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
pub(in crate::iter) const fn new(iter: I, separator: I::Item) -> Self {
Self { iter: Peekable::new(iter), separator, needs_sep: false }
}
}

Expand Down Expand Up @@ -108,8 +109,9 @@ where
I: Iterator,
G: FnMut() -> I::Item,
{
pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
Self { iter: iter.peekable(), separator, needs_sep: false }
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
pub(in crate::iter) const fn new(iter: I, separator: G) -> Self {
Self { iter: Peekable::new(iter), separator, needs_sep: false }
}
}

Expand Down
50 changes: 41 additions & 9 deletions library/core/src/iter/adapters/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::iter::adapters::{
zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
use crate::ops::Try;
use crate::ops::{FromResidual, Try};

/// An iterator that maps the values of `iter` with `f`.
///
Expand Down Expand Up @@ -65,7 +65,7 @@ pub struct Map<I, F> {
}

impl<I, F> Map<I, F> {
pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
pub(in crate::iter) const fn new(iter: I, f: F) -> Map<I, F> {
Map { iter, f }
}
}
Expand All @@ -77,6 +77,33 @@ impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
}
}

struct MapFold<F, G>(F, G);
struct MapTryFold<F, G>(F, G);

impl_const_closure! {
impl<F, T, B, G, Acc> const FnMut for MapFold<F, G>
where
F: ~const FnMut(T) -> B,
F: ~const Drop,
G: ~const FnMut(Acc, B) -> Acc,
G: ~const Drop,
= |&mut self, acc: Acc, elt: T| -> Acc {
self.1(acc, self.0(elt))
};
}

impl_const_closure! {
impl<F, T, B, G, R, Acc> const FnMut for MapTryFold<F, G>
where
F: ~const FnMut(T) -> B,
F: ~const Drop,
G: ~const FnMut(Acc, B) -> R,
G: ~const Drop,
= |&mut self, acc: Acc, elt: T| -> R {
self.1(acc, self.0(elt))
};
}

fn map_fold<T, B, Acc>(
mut f: impl FnMut(T) -> B,
mut g: impl FnMut(Acc, B) -> Acc,
Expand All @@ -92,9 +119,10 @@ fn map_try_fold<'a, T, B, Acc, R>(
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<B, I: Iterator, F> Iterator for Map<I, F>
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
impl<B, I: ~const Iterator, F> const Iterator for Map<I, F>
where
F: FnMut(I::Item) -> B,
F: ~const FnMut(I::Item) -> B + ~const Drop,
{
type Item = B;

Expand All @@ -111,17 +139,21 @@ where
fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
where
Self: Sized,
G: FnMut(Acc, Self::Item) -> R,
R: Try<Output = Acc>,
G: ~const FnMut(Acc, B) -> R,
G: ~const Drop,
R: ~const Try<Output = Acc>,
R: ~const FromResidual,
{
self.iter.try_fold(init, map_try_fold(&mut self.f, g))
self.iter.try_fold(init, MapTryFold(&mut self.f, g))
}

fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
where
G: FnMut(Acc, Self::Item) -> Acc,
I: ~const Drop,
G: ~const FnMut(Acc, B) -> Acc,
G: ~const Drop,
{
self.iter.fold(init, map_fold(self.f, g))
self.iter.fold(init, MapFold(self.f, g))
}

#[doc(hidden)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/map_while.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct MapWhile<I, P> {
}

impl<I, P> MapWhile<I, P> {
pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
pub(in crate::iter) const fn new(iter: I, predicate: P) -> MapWhile<I, P> {
MapWhile { iter, predicate }
}
}
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/iter/adapters/peekable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ pub struct Peekable<I: Iterator> {
}

impl<I: Iterator> Peekable<I> {
pub(in crate::iter) fn new(iter: I) -> Peekable<I> {
#[rustc_allow_const_fn_unstable(const_fn_trait_bound)]
pub(in crate::iter) const fn new(iter: I) -> Peekable<I> {
Peekable { iter, peeked: None }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/rev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct Rev<T> {
}

impl<T> Rev<T> {
pub(in crate::iter) fn new(iter: T) -> Rev<T> {
pub(in crate::iter) const fn new(iter: T) -> Rev<T> {
Rev { iter }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct Scan<I, St, F> {
}

impl<I, St, F> Scan<I, St, F> {
pub(in crate::iter) fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
pub(in crate::iter) const fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
Scan { iter, state, f }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/skip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct Skip<I> {
}

impl<I> Skip<I> {
pub(in crate::iter) fn new(iter: I, n: usize) -> Skip<I> {
pub(in crate::iter) const fn new(iter: I, n: usize) -> Skip<I> {
Skip { iter, n }
}
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/skip_while.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct SkipWhile<I, P> {
}

impl<I, P> SkipWhile<I, P> {
pub(in crate::iter) fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
pub(in crate::iter) const fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
SkipWhile { iter, flag: false, predicate }
}
}
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/iter/adapters/step_by.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ pub struct StepBy<I> {
}

impl<I> StepBy<I> {
pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy<I> {
assert!(step != 0);
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
pub(in crate::iter) const fn new(iter: I, step: usize) -> StepBy<I> {
assert!(step != 0, "Step must be non-zero");
StepBy { iter, step: step - 1, first_take: true }
}
}
Expand Down
Loading