Skip to content

Commit cc4c7b7

Browse files
committed
Make it possible to have const impls for Iterator
1 parent a34c079 commit cc4c7b7

38 files changed

+883
-344
lines changed

library/core/src/cmp.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,13 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
11921192
#[inline]
11931193
#[must_use]
11941194
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
1195-
pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
1195+
#[rustc_const_unstable(feature = "const_cmp", issue = "none")]
1196+
pub const fn min_by<T, F>(v1: T, v2: T, compare: F) -> T
1197+
where
1198+
F: ~const FnOnce(&T, &T) -> Ordering,
1199+
F: ~const Drop,
1200+
T: ~const Drop,
1201+
{
11961202
match compare(&v1, &v2) {
11971203
Ordering::Less | Ordering::Equal => v1,
11981204
Ordering::Greater => v2,
@@ -1255,7 +1261,13 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
12551261
#[inline]
12561262
#[must_use]
12571263
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
1258-
pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
1264+
#[rustc_const_unstable(feature = "const_cmp", issue = "none")]
1265+
pub const fn max_by<T, F>(v1: T, v2: T, compare: F) -> T
1266+
where
1267+
F: ~const FnOnce(&T, &T) -> Ordering,
1268+
F: ~const Drop,
1269+
T: ~const Drop,
1270+
{
12591271
match compare(&v1, &v2) {
12601272
Ordering::Less | Ordering::Equal => v2,
12611273
Ordering::Greater => v1,

library/core/src/internal_macros.rs

+49
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,52 @@ macro_rules! impl_fn_for_zst {
187187
)+
188188
}
189189
}
190+
191+
macro_rules! impl_const_closure {
192+
(
193+
impl$(<$( $tt : tt ),*>)?
194+
const FnOnce for $Name: path $(where $($WhereTy:ty : $(~ $const:ident)? $Trait:path),+ $(,)?)? =
195+
$(#[$meta:meta])*
196+
|$mutorself:ident $($self:ident)?, $( $arg: tt: $ArgTy: ty ),*| $(-> $ReturnTy: ty)?
197+
$body: block;
198+
) => {
199+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
200+
impl $( < $( $tt ),* > )? const FnOnce<($( $ArgTy, )*)> for $Name
201+
$(where $($WhereTy: $(~$const)? $Trait),+)?
202+
{
203+
#[allow(unused_parens)]
204+
type Output = ( $( $ReturnTy )? );
205+
206+
#[allow(unused_mut)]
207+
$(#[$meta])*
208+
extern "rust-call" fn call_once($mutorself $($self)?, ($( $arg, )*): ($( $ArgTy, )*)) -> Self::Output {
209+
$body
210+
}
211+
}
212+
};
213+
(
214+
impl$(< $( $tt: tt ),* >)?
215+
const FnMut for $Name: path $(where $($WhereTy:ty : $(~ $const:ident)? $Trait:path),+ $(,)?)? =
216+
$(#[$meta:meta])*
217+
|&mut $self:ident, $( $arg: tt: $ArgTy: ty ),*| $(-> $ReturnTy: ty)?
218+
$body: block;
219+
) => {
220+
impl_const_closure! {
221+
impl$(< $( $tt ),* >)?
222+
const FnOnce for $Name $(where $($WhereTy: $(~$const)? $Trait),+)? =
223+
$(#[$meta])*
224+
|mut $self, $( $arg: $ArgTy),*| $(-> $ReturnTy)?
225+
$body;
226+
}
227+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
228+
impl $( < $( $tt ),* > )? const FnMut<($( $ArgTy, )*)> for $Name
229+
$(where $($WhereTy: $(~$const)? $Trait),+)?
230+
{
231+
$(#[$meta])*
232+
#[allow(unused_parens)]
233+
extern "rust-call" fn call_mut(&mut $self, ($( $arg, )*): ($( $ArgTy, )*)) -> ( $($ReturnTy)? ) {
234+
$body
235+
}
236+
}
237+
}
238+
}

library/core/src/iter/adapters/chain.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub struct Chain<A, B> {
3232
b: Option<B>,
3333
}
3434
impl<A, B> Chain<A, B> {
35-
pub(in super::super) fn new(a: A, b: B) -> Chain<A, B> {
35+
pub(in super::super) const fn new(a: A, b: B) -> Chain<A, B> {
3636
Chain { a: Some(a), b: Some(b) }
3737
}
3838
}

library/core/src/iter/adapters/cloned.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct Cloned<I> {
1919
}
2020

2121
impl<I> Cloned<I> {
22-
pub(in crate::iter) fn new(it: I) -> Cloned<I> {
22+
pub(in crate::iter) const fn new(it: I) -> Cloned<I> {
2323
Cloned { it }
2424
}
2525
}

library/core/src/iter/adapters/copied.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct Copied<I> {
1919
}
2020

2121
impl<I> Copied<I> {
22-
pub(in crate::iter) fn new(it: I) -> Copied<I> {
22+
pub(in crate::iter) const fn new(it: I) -> Copied<I> {
2323
Copied { it }
2424
}
2525
}

library/core/src/iter/adapters/cycle.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ pub struct Cycle<I> {
1515
iter: I,
1616
}
1717

18-
impl<I: Clone> Cycle<I> {
19-
pub(in crate::iter) fn new(iter: I) -> Cycle<I> {
18+
impl<I> Cycle<I> {
19+
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
20+
pub(in crate::iter) const fn new(iter: I) -> Cycle<I>
21+
where
22+
I: ~const Clone,
23+
{
2024
Cycle { orig: iter.clone(), iter }
2125
}
2226
}

library/core/src/iter/adapters/enumerate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct Enumerate<I> {
1919
count: usize,
2020
}
2121
impl<I> Enumerate<I> {
22-
pub(in crate::iter) fn new(iter: I) -> Enumerate<I> {
22+
pub(in crate::iter) const fn new(iter: I) -> Enumerate<I> {
2323
Enumerate { iter, count: 0 }
2424
}
2525
}

library/core/src/iter/adapters/filter.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct Filter<I, P> {
1818
predicate: P,
1919
}
2020
impl<I, P> Filter<I, P> {
21-
pub(in crate::iter) fn new(iter: I, predicate: P) -> Filter<I, P> {
21+
pub(in crate::iter) const fn new(iter: I, predicate: P) -> Filter<I, P> {
2222
Filter { iter, predicate }
2323
}
2424
}

library/core/src/iter/adapters/filter_map.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct FilterMap<I, F> {
1717
f: F,
1818
}
1919
impl<I, F> FilterMap<I, F> {
20-
pub(in crate::iter) fn new(iter: I, f: F) -> FilterMap<I, F> {
20+
pub(in crate::iter) const fn new(iter: I, f: F) -> FilterMap<I, F> {
2121
FilterMap { iter, f }
2222
}
2323
}

library/core/src/iter/adapters/flatten.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ pub struct FlatMap<I, U: IntoIterator, F> {
1414
}
1515

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

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

154155
impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
155-
pub(in super::super) fn new(iter: I) -> Flatten<I> {
156+
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
157+
pub(in super::super) const fn new(iter: I) -> Flatten<I> {
156158
Flatten { inner: FlattenCompat::new(iter) }
157159
}
158160
}
@@ -270,13 +272,10 @@ struct FlattenCompat<I, U> {
270272
frontiter: Option<U>,
271273
backiter: Option<U>,
272274
}
273-
impl<I, U> FlattenCompat<I, U>
274-
where
275-
I: Iterator,
276-
{
275+
impl<I, U> FlattenCompat<I, U> {
277276
/// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
278-
fn new(iter: I) -> FlattenCompat<I, U> {
279-
FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
277+
const fn new(iter: I) -> FlattenCompat<I, U> {
278+
FlattenCompat { iter: super::Fuse::new(iter), frontiter: None, backiter: None }
280279
}
281280
}
282281

library/core/src/iter/adapters/fuse.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub struct Fuse<I> {
2121
iter: Option<I>,
2222
}
2323
impl<I> Fuse<I> {
24-
pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
24+
pub(in crate::iter) const fn new(iter: I) -> Fuse<I> {
2525
Fuse { iter: Some(iter) }
2626
}
2727
}

library/core/src/iter/adapters/inspect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct Inspect<I, F> {
1818
f: F,
1919
}
2020
impl<I, F> Inspect<I, F> {
21-
pub(in crate::iter) fn new(iter: I, f: F) -> Inspect<I, F> {
21+
pub(in crate::iter) const fn new(iter: I, f: F) -> Inspect<I, F> {
2222
Inspect { iter, f }
2323
}
2424
}

library/core/src/iter/adapters/intersperse.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ impl<I: Iterator> Intersperse<I>
1919
where
2020
I::Item: Clone,
2121
{
22-
pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
23-
Self { iter: iter.peekable(), separator, needs_sep: false }
22+
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
23+
pub(in crate::iter) const fn new(iter: I, separator: I::Item) -> Self {
24+
Self { iter: Peekable::new(iter), separator, needs_sep: false }
2425
}
2526
}
2627

@@ -108,8 +109,9 @@ where
108109
I: Iterator,
109110
G: FnMut() -> I::Item,
110111
{
111-
pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
112-
Self { iter: iter.peekable(), separator, needs_sep: false }
112+
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
113+
pub(in crate::iter) const fn new(iter: I, separator: G) -> Self {
114+
Self { iter: Peekable::new(iter), separator, needs_sep: false }
113115
}
114116
}
115117

library/core/src/iter/adapters/map.rs

+41-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::iter::adapters::{
33
zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
44
};
55
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
6-
use crate::ops::Try;
6+
use crate::ops::{FromResidual, Try};
77

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

6767
impl<I, F> Map<I, F> {
68-
pub(in crate::iter) fn new(iter: I, f: F) -> Map<I, F> {
68+
pub(in crate::iter) const fn new(iter: I, f: F) -> Map<I, F> {
6969
Map { iter, f }
7070
}
7171
}
@@ -77,6 +77,33 @@ impl<I: fmt::Debug, F> fmt::Debug for Map<I, F> {
7777
}
7878
}
7979

80+
struct MapFold<F, G>(F, G);
81+
struct MapTryFold<F, G>(F, G);
82+
83+
impl_const_closure! {
84+
impl<F, T, B, G, Acc> const FnMut for MapFold<F, G>
85+
where
86+
F: ~const FnMut(T) -> B,
87+
F: ~const Drop,
88+
G: ~const FnMut(Acc, B) -> Acc,
89+
G: ~const Drop,
90+
= |&mut self, acc: Acc, elt: T| -> Acc {
91+
self.1(acc, self.0(elt))
92+
};
93+
}
94+
95+
impl_const_closure! {
96+
impl<F, T, B, G, R, Acc> const FnMut for MapTryFold<F, G>
97+
where
98+
F: ~const FnMut(T) -> B,
99+
F: ~const Drop,
100+
G: ~const FnMut(Acc, B) -> R,
101+
G: ~const Drop,
102+
= |&mut self, acc: Acc, elt: T| -> R {
103+
self.1(acc, self.0(elt))
104+
};
105+
}
106+
80107
fn map_fold<T, B, Acc>(
81108
mut f: impl FnMut(T) -> B,
82109
mut g: impl FnMut(Acc, B) -> Acc,
@@ -92,9 +119,10 @@ fn map_try_fold<'a, T, B, Acc, R>(
92119
}
93120

94121
#[stable(feature = "rust1", since = "1.0.0")]
95-
impl<B, I: Iterator, F> Iterator for Map<I, F>
122+
#[rustc_const_unstable(feature = "const_iter", issue = "none")]
123+
impl<B, I: ~const Iterator, F> const Iterator for Map<I, F>
96124
where
97-
F: FnMut(I::Item) -> B,
125+
F: ~const FnMut(I::Item) -> B + ~const Drop,
98126
{
99127
type Item = B;
100128

@@ -111,17 +139,21 @@ where
111139
fn try_fold<Acc, G, R>(&mut self, init: Acc, g: G) -> R
112140
where
113141
Self: Sized,
114-
G: FnMut(Acc, Self::Item) -> R,
115-
R: Try<Output = Acc>,
142+
G: ~const FnMut(Acc, B) -> R,
143+
G: ~const Drop,
144+
R: ~const Try<Output = Acc>,
145+
R: ~const FromResidual,
116146
{
117-
self.iter.try_fold(init, map_try_fold(&mut self.f, g))
147+
self.iter.try_fold(init, MapTryFold(&mut self.f, g))
118148
}
119149

120150
fn fold<Acc, G>(self, init: Acc, g: G) -> Acc
121151
where
122-
G: FnMut(Acc, Self::Item) -> Acc,
152+
I: ~const Drop,
153+
G: ~const FnMut(Acc, B) -> Acc,
154+
G: ~const Drop,
123155
{
124-
self.iter.fold(init, map_fold(self.f, g))
156+
self.iter.fold(init, MapFold(self.f, g))
125157
}
126158

127159
#[doc(hidden)]

library/core/src/iter/adapters/map_while.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct MapWhile<I, P> {
1818
}
1919

2020
impl<I, P> MapWhile<I, P> {
21-
pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
21+
pub(in crate::iter) const fn new(iter: I, predicate: P) -> MapWhile<I, P> {
2222
MapWhile { iter, predicate }
2323
}
2424
}

library/core/src/iter/adapters/peekable.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ pub struct Peekable<I: Iterator> {
1919
}
2020

2121
impl<I: Iterator> Peekable<I> {
22-
pub(in crate::iter) fn new(iter: I) -> Peekable<I> {
22+
#[rustc_allow_const_fn_unstable(const_fn_trait_bound)]
23+
pub(in crate::iter) const fn new(iter: I) -> Peekable<I> {
2324
Peekable { iter, peeked: None }
2425
}
2526
}

library/core/src/iter/adapters/rev.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct Rev<T> {
1616
}
1717

1818
impl<T> Rev<T> {
19-
pub(in crate::iter) fn new(iter: T) -> Rev<T> {
19+
pub(in crate::iter) const fn new(iter: T) -> Rev<T> {
2020
Rev { iter }
2121
}
2222
}

library/core/src/iter/adapters/scan.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct Scan<I, St, F> {
1919
}
2020

2121
impl<I, St, F> Scan<I, St, F> {
22-
pub(in crate::iter) fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
22+
pub(in crate::iter) const fn new(iter: I, state: St, f: F) -> Scan<I, St, F> {
2323
Scan { iter, state, f }
2424
}
2525
}

library/core/src/iter/adapters/skip.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct Skip<I> {
1818
}
1919

2020
impl<I> Skip<I> {
21-
pub(in crate::iter) fn new(iter: I, n: usize) -> Skip<I> {
21+
pub(in crate::iter) const fn new(iter: I, n: usize) -> Skip<I> {
2222
Skip { iter, n }
2323
}
2424
}

library/core/src/iter/adapters/skip_while.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct SkipWhile<I, P> {
1919
}
2020

2121
impl<I, P> SkipWhile<I, P> {
22-
pub(in crate::iter) fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
22+
pub(in crate::iter) const fn new(iter: I, predicate: P) -> SkipWhile<I, P> {
2323
SkipWhile { iter, flag: false, predicate }
2424
}
2525
}

library/core/src/iter/adapters/step_by.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ pub struct StepBy<I> {
1717
}
1818

1919
impl<I> StepBy<I> {
20-
pub(in crate::iter) fn new(iter: I, step: usize) -> StepBy<I> {
21-
assert!(step != 0);
20+
#[rustc_const_unstable(feature = "iter_internals", issue = "none")]
21+
pub(in crate::iter) const fn new(iter: I, step: usize) -> StepBy<I> {
22+
assert!(step != 0, "Step must be non-zero");
2223
StepBy { iter, step: step - 1, first_take: true }
2324
}
2425
}

0 commit comments

Comments
 (0)