Skip to content

Commit 993b775

Browse files
authored
Rollup merge of #104100 - ink-feather-org:const_iter_range, r=the8472,fee1-dead
Allow using `Range` as an `Iterator` in const contexts. ~~based on #102225 by `@fee1-dead~~`
2 parents ab9bb3e + 8a9d6bf commit 993b775

File tree

10 files changed

+87
-31
lines changed

10 files changed

+87
-31
lines changed

library/core/src/iter/range.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::convert::TryFrom;
2+
use crate::marker::Destruct;
23
use crate::mem;
34
use crate::ops::{self, Try};
45

@@ -20,7 +21,8 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi
2021
/// The *successor* operation moves towards values that compare greater.
2122
/// The *predecessor* operation moves towards values that compare lesser.
2223
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
23-
pub trait Step: Clone + PartialOrd + Sized {
24+
#[const_trait]
25+
pub trait Step: ~const Clone + ~const PartialOrd + Sized {
2426
/// Returns the number of *successor* steps required to get from `start` to `end`.
2527
///
2628
/// Returns `None` if the number of steps would overflow `usize`
@@ -234,7 +236,8 @@ macro_rules! step_integer_impls {
234236
$(
235237
#[allow(unreachable_patterns)]
236238
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
237-
impl Step for $u_narrower {
239+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
240+
impl const Step for $u_narrower {
238241
step_identical_methods!();
239242

240243
#[inline]
@@ -266,7 +269,8 @@ macro_rules! step_integer_impls {
266269

267270
#[allow(unreachable_patterns)]
268271
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
269-
impl Step for $i_narrower {
272+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
273+
impl const Step for $i_narrower {
270274
step_identical_methods!();
271275

272276
#[inline]
@@ -330,7 +334,8 @@ macro_rules! step_integer_impls {
330334
$(
331335
#[allow(unreachable_patterns)]
332336
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
333-
impl Step for $u_wider {
337+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
338+
impl const Step for $u_wider {
334339
step_identical_methods!();
335340

336341
#[inline]
@@ -355,7 +360,8 @@ macro_rules! step_integer_impls {
355360

356361
#[allow(unreachable_patterns)]
357362
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
358-
impl Step for $i_wider {
363+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
364+
impl const Step for $i_wider {
359365
step_identical_methods!();
360366

361367
#[inline]
@@ -405,7 +411,8 @@ step_integer_impls! {
405411
}
406412

407413
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
408-
impl Step for char {
414+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
415+
impl const Step for char {
409416
#[inline]
410417
fn steps_between(&start: &char, &end: &char) -> Option<usize> {
411418
let start = start as u32;
@@ -423,6 +430,7 @@ impl Step for char {
423430
}
424431

425432
#[inline]
433+
#[rustc_allow_const_fn_unstable(const_try)]
426434
fn forward_checked(start: char, count: usize) -> Option<char> {
427435
let start = start as u32;
428436
let mut res = Step::forward_checked(start, count)?;
@@ -439,6 +447,7 @@ impl Step for char {
439447
}
440448

441449
#[inline]
450+
#[rustc_allow_const_fn_unstable(const_try)]
442451
fn backward_checked(start: char, count: usize) -> Option<char> {
443452
let start = start as u32;
444453
let mut res = Step::backward_checked(start, count)?;
@@ -514,6 +523,7 @@ macro_rules! range_incl_exact_iter_impl {
514523
}
515524

516525
/// Specialization implementations for `Range`.
526+
#[const_trait]
517527
trait RangeIteratorImpl {
518528
type Item;
519529

@@ -528,7 +538,7 @@ trait RangeIteratorImpl {
528538
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>;
529539
}
530540

531-
impl<A: Step> RangeIteratorImpl for ops::Range<A> {
541+
impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
532542
type Item = A;
533543

534544
#[inline]
@@ -614,7 +624,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
614624
}
615625
}
616626

617-
impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
627+
impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::Range<T> {
618628
#[inline]
619629
fn spec_next(&mut self) -> Option<T> {
620630
if self.start < self.end {
@@ -702,7 +712,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
702712
}
703713

704714
#[stable(feature = "rust1", since = "1.0.0")]
705-
impl<A: Step> Iterator for ops::Range<A> {
715+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
716+
impl<A: ~const Step + ~const Destruct> const Iterator for ops::Range<A> {
706717
type Item = A;
707718

708719
#[inline]
@@ -812,7 +823,8 @@ range_incl_exact_iter_impl! {
812823
}
813824

814825
#[stable(feature = "rust1", since = "1.0.0")]
815-
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
826+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
827+
impl<A: ~const Step + ~const Destruct> const DoubleEndedIterator for ops::Range<A> {
816828
#[inline]
817829
fn next_back(&mut self) -> Option<A> {
818830
self.spec_next_back()

library/core/src/iter/traits/double_ended.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::marker::Destruct;
12
use crate::ops::{ControlFlow, Try};
23

34
/// An iterator able to yield elements from both ends.
@@ -37,6 +38,7 @@ use crate::ops::{ControlFlow, Try};
3738
/// ```
3839
#[stable(feature = "rust1", since = "1.0.0")]
3940
#[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")]
41+
#[const_trait]
4042
pub trait DoubleEndedIterator: Iterator {
4143
/// Removes and returns an element from the end of the iterator.
4244
///
@@ -131,7 +133,10 @@ pub trait DoubleEndedIterator: Iterator {
131133
/// [`Err(k)`]: Err
132134
#[inline]
133135
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
134-
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
136+
fn advance_back_by(&mut self, n: usize) -> Result<(), usize>
137+
where
138+
Self::Item: ~const Destruct,
139+
{
135140
for i in 0..n {
136141
self.next_back().ok_or(i)?;
137142
}
@@ -181,6 +186,7 @@ pub trait DoubleEndedIterator: Iterator {
181186
/// ```
182187
#[inline]
183188
#[stable(feature = "iter_nth_back", since = "1.37.0")]
189+
#[rustc_do_not_const_check]
184190
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
185191
self.advance_back_by(n).ok()?;
186192
self.next_back()
@@ -218,6 +224,7 @@ pub trait DoubleEndedIterator: Iterator {
218224
/// ```
219225
#[inline]
220226
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
227+
#[rustc_do_not_const_check]
221228
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
222229
where
223230
Self: Sized,
@@ -289,6 +296,7 @@ pub trait DoubleEndedIterator: Iterator {
289296
#[doc(alias = "foldr")]
290297
#[inline]
291298
#[stable(feature = "iter_rfold", since = "1.27.0")]
299+
#[rustc_do_not_const_check]
292300
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
293301
where
294302
Self: Sized,
@@ -344,6 +352,7 @@ pub trait DoubleEndedIterator: Iterator {
344352
/// ```
345353
#[inline]
346354
#[stable(feature = "iter_rfind", since = "1.27.0")]
355+
#[rustc_do_not_const_check]
347356
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
348357
where
349358
Self: Sized,

library/core/src/iter/traits/iterator.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::array;
22
use crate::cmp::{self, Ordering};
3+
use crate::marker::Destruct;
34
use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
45

56
use super::super::try_process;
@@ -336,8 +337,10 @@ pub trait Iterator {
336337
/// ```
337338
#[inline]
338339
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
339-
#[rustc_do_not_const_check]
340-
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
340+
fn advance_by(&mut self, n: usize) -> Result<(), usize>
341+
where
342+
Self::Item: ~const Destruct,
343+
{
341344
for i in 0..n {
342345
self.next().ok_or(i)?;
343346
}
@@ -385,8 +388,10 @@ pub trait Iterator {
385388
/// ```
386389
#[inline]
387390
#[stable(feature = "rust1", since = "1.0.0")]
388-
#[rustc_do_not_const_check]
389-
fn nth(&mut self, n: usize) -> Option<Self::Item> {
391+
fn nth(&mut self, n: usize) -> Option<Self::Item>
392+
where
393+
Self::Item: ~const Destruct,
394+
{
390395
self.advance_by(n).ok()?;
391396
self.next()
392397
}

library/core/src/iter/traits/marker.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,5 @@ pub unsafe trait InPlaceIterable: Iterator {}
8686
/// for details. Consumers are free to rely on the invariants in unsafe code.
8787
#[unstable(feature = "trusted_step", issue = "85731")]
8888
#[rustc_specialization_trait]
89-
pub unsafe trait TrustedStep: Step {}
89+
#[const_trait]
90+
pub unsafe trait TrustedStep: ~const Step {}

library/core/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,11 @@
123123
#![feature(const_index_range_slice_index)]
124124
#![feature(const_inherent_unchecked_arith)]
125125
#![feature(const_int_unchecked_arith)]
126+
#![feature(const_intoiterator_identity)]
126127
#![feature(const_intrinsic_forget)]
127128
#![feature(const_ipv4)]
128129
#![feature(const_ipv6)]
130+
#![feature(const_iter)]
129131
#![feature(const_likely)]
130132
#![feature(const_maybe_uninit_uninit_array)]
131133
#![feature(const_maybe_uninit_as_mut_ptr)]

library/core/tests/iter/consts.rs

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#[test]
2+
fn const_manual_iter() {
3+
struct S(bool);
4+
5+
impl const Iterator for S {
6+
type Item = ();
7+
8+
fn next(&mut self) -> Option<Self::Item> {
9+
if self.0 == false {
10+
self.0 = true;
11+
Some(())
12+
} else {
13+
None
14+
}
15+
}
16+
}
17+
const {
18+
let mut val = S(false);
19+
assert!(val.next().is_some());
20+
assert!(val.next().is_none());
21+
assert!(val.next().is_none());
22+
}
23+
}
24+
25+
#[test]
26+
fn const_range() {
27+
const {
28+
let mut arr = [0; 3];
29+
for i in 0..arr.len() {
30+
arr[i] = i;
31+
}
32+
assert!(arr[0] == 0);
33+
assert!(arr[1] == 1);
34+
assert!(arr[2] == 2);
35+
}
36+
}

library/core/tests/iter/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ mod range;
2020
mod sources;
2121
mod traits;
2222

23+
mod consts;
24+
2325
use core::cell::Cell;
2426
use core::convert::TryFrom;
2527
use core::iter::*;

library/core/tests/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
#![feature(const_caller_location)]
1313
#![feature(const_cell_into_inner)]
1414
#![feature(const_convert)]
15+
#![feature(const_for)]
1516
#![feature(const_hash)]
1617
#![feature(const_heap)]
18+
#![feature(const_intoiterator_identity)]
19+
#![feature(const_iter)]
1720
#![feature(const_maybe_uninit_as_mut_ptr)]
1821
#![feature(const_maybe_uninit_assume_init_read)]
1922
#![feature(const_nonnull_new)]

tests/ui/typeck/typeck_type_placeholder_item.rs

-1
Original file line numberDiff line numberDiff line change
@@ -228,5 +228,4 @@ fn evens_squared(n: usize) -> _ {
228228

229229
const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
230230
//~^ ERROR the trait bound
231-
//~| ERROR the trait bound
232231
//~| ERROR the placeholder

tests/ui/typeck/typeck_type_placeholder_item.stderr

+1-14
Original file line numberDiff line numberDiff line change
@@ -437,19 +437,6 @@ LL | fn evens_squared(n: usize) -> _ {
437437
| not allowed in type signatures
438438
| help: replace with an appropriate return type: `impl Iterator<Item = usize>`
439439

440-
error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied
441-
--> $DIR/typeck_type_placeholder_item.rs:229:22
442-
|
443-
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
444-
| ^^^^^^ `std::ops::Range<{integer}>` is not an iterator
445-
|
446-
= help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>`
447-
note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const`
448-
--> $DIR/typeck_type_placeholder_item.rs:229:14
449-
|
450-
LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
451-
| ^^^^^^^
452-
453440
error[E0277]: the trait bound `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied
454441
--> $DIR/typeck_type_placeholder_item.rs:229:45
455442
|
@@ -677,7 +664,7 @@ LL | const D: _ = 42;
677664
| not allowed in type signatures
678665
| help: replace with the correct type: `i32`
679666

680-
error: aborting due to 73 previous errors
667+
error: aborting due to 72 previous errors
681668

682669
Some errors have detailed explanations: E0121, E0277, E0282, E0403.
683670
For more information about an error, try `rustc --explain E0121`.

0 commit comments

Comments
 (0)