Skip to content

Commit 8a9d6bf

Browse files
committed
Mark DoubleEndedIterator as #[const_trait] using rustc_do_not_const_check, implement const Iterator and DoubleEndedIterator for Range.
1 parent 7bc67ef commit 8a9d6bf

File tree

9 files changed

+70
-24
lines changed

9 files changed

+70
-24
lines changed

library/core/src/iter/range.rs

+8-4
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

@@ -522,6 +523,7 @@ macro_rules! range_incl_exact_iter_impl {
522523
}
523524

524525
/// Specialization implementations for `Range`.
526+
#[const_trait]
525527
trait RangeIteratorImpl {
526528
type Item;
527529

@@ -536,7 +538,7 @@ trait RangeIteratorImpl {
536538
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>;
537539
}
538540

539-
impl<A: Step> RangeIteratorImpl for ops::Range<A> {
541+
impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
540542
type Item = A;
541543

542544
#[inline]
@@ -622,7 +624,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
622624
}
623625
}
624626

625-
impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
627+
impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::Range<T> {
626628
#[inline]
627629
fn spec_next(&mut self) -> Option<T> {
628630
if self.start < self.end {
@@ -710,7 +712,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
710712
}
711713

712714
#[stable(feature = "rust1", since = "1.0.0")]
713-
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> {
714717
type Item = A;
715718

716719
#[inline]
@@ -820,7 +823,8 @@ range_incl_exact_iter_impl! {
820823
}
821824

822825
#[stable(feature = "rust1", since = "1.0.0")]
823-
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> {
824828
#[inline]
825829
fn next_back(&mut self) -> Option<A> {
826830
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/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
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)]

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)