Skip to content

Commit ae0212e

Browse files
committed
Mark DoubleEndedIterator as #[const_trait] using rustc_do_not_const_check, implement const Iterator and DoubleEndedIterator for Range.
1 parent 4481b60 commit ae0212e

File tree

5 files changed

+128
-7
lines changed

5 files changed

+128
-7
lines changed

library/core/src/iter/range.rs

+89-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::char;
22
use crate::convert::TryFrom;
3+
use crate::marker::Destruct;
34
use crate::mem;
45
use crate::ops::{self, Try};
56

@@ -523,6 +524,7 @@ macro_rules! range_incl_exact_iter_impl {
523524
}
524525

525526
/// Specialization implementations for `Range`.
527+
#[const_trait]
526528
trait RangeIteratorImpl {
527529
type Item;
528530

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

540-
impl<A: Step> RangeIteratorImpl for ops::Range<A> {
542+
impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
541543
type Item = A;
542544

543545
#[inline]
@@ -623,7 +625,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
623625
}
624626
}
625627

626-
impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
628+
impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::Range<T> {
627629
#[inline]
628630
fn spec_next(&mut self) -> Option<T> {
629631
if self.start < self.end {
@@ -711,6 +713,70 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
711713
}
712714

713715
#[stable(feature = "rust1", since = "1.0.0")]
716+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
717+
#[cfg(not(bootstrap))]
718+
impl<A: ~const Step + ~const Destruct> const Iterator for ops::Range<A> {
719+
type Item = A;
720+
721+
#[inline]
722+
fn next(&mut self) -> Option<A> {
723+
self.spec_next()
724+
}
725+
726+
#[inline]
727+
fn size_hint(&self) -> (usize, Option<usize>) {
728+
if self.start < self.end {
729+
let hint = Step::steps_between(&self.start, &self.end);
730+
(hint.unwrap_or(usize::MAX), hint)
731+
} else {
732+
(0, Some(0))
733+
}
734+
}
735+
736+
#[inline]
737+
fn nth(&mut self, n: usize) -> Option<A> {
738+
self.spec_nth(n)
739+
}
740+
741+
#[inline]
742+
fn last(mut self) -> Option<A> {
743+
self.next_back()
744+
}
745+
746+
#[inline]
747+
fn min(mut self) -> Option<A> {
748+
self.next()
749+
}
750+
751+
#[inline]
752+
fn max(mut self) -> Option<A> {
753+
self.next_back()
754+
}
755+
756+
#[inline]
757+
fn is_sorted(self) -> bool {
758+
true
759+
}
760+
761+
#[inline]
762+
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
763+
self.spec_advance_by(n)
764+
}
765+
766+
#[inline]
767+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
768+
where
769+
Self: TrustedRandomAccessNoCoerce,
770+
{
771+
// SAFETY: The TrustedRandomAccess contract requires that callers only pass an index
772+
// that is in bounds.
773+
// Additionally Self: TrustedRandomAccess is only implemented for Copy types
774+
// which means even repeated reads of the same index would be safe.
775+
unsafe { Step::forward_unchecked(self.start.clone(), idx) }
776+
}
777+
}
778+
#[stable(feature = "rust1", since = "1.0.0")]
779+
#[cfg(bootstrap)]
714780
impl<A: Step> Iterator for ops::Range<A> {
715781
type Item = A;
716782

@@ -821,6 +887,27 @@ range_incl_exact_iter_impl! {
821887
}
822888

823889
#[stable(feature = "rust1", since = "1.0.0")]
890+
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
891+
#[cfg(not(bootstrap))]
892+
impl<A: ~const Step + ~const Destruct> const DoubleEndedIterator for ops::Range<A> {
893+
#[inline]
894+
fn next_back(&mut self) -> Option<A> {
895+
self.spec_next_back()
896+
}
897+
898+
#[inline]
899+
fn nth_back(&mut self, n: usize) -> Option<A> {
900+
self.spec_nth_back(n)
901+
}
902+
903+
#[inline]
904+
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
905+
self.spec_advance_back_by(n)
906+
}
907+
}
908+
909+
#[stable(feature = "rust1", since = "1.0.0")]
910+
#[cfg(bootstrap)]
824911
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
825912
#[inline]
826913
fn next_back(&mut self) -> Option<A> {

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+
#[cfg_attr(not(bootstrap), 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_iter)]
128129
#![feature(const_likely)]
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
#![feature(const_for)]
3+
#![feature(const_mut_refs)]
4+
#![feature(const_trait_impl)]
5+
#![feature(const_iter)]
6+
#![feature(const_intoiterator_identity)]
7+
#![feature(inline_const)]
8+
9+
fn main() {
10+
const {
11+
let mut arr = [0; 3];
12+
for i in 0..arr.len() {
13+
arr[i] = i;
14+
}
15+
assert!(arr[0] == 0);
16+
assert!(arr[1] == 1);
17+
assert!(arr[2] == 2);
18+
}
19+
}

0 commit comments

Comments
 (0)