diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index dba2b2291ff..f19636fba5d 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -1,4 +1,5 @@ use crate::convert::TryFrom; +use crate::marker::Destruct; use crate::mem; use crate::ops::{self, Try}; @@ -522,6 +523,7 @@ impl ExactSizeIterator for ops::RangeInclusive<$t> { } } /// Specialization implementations for `Range`. +#[const_trait] trait RangeIteratorImpl { type Item; @@ -536,7 +538,7 @@ trait RangeIteratorImpl { fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>; } -impl RangeIteratorImpl for ops::Range { +impl const RangeIteratorImpl for ops::Range { type Item = A; #[inline] @@ -622,7 +624,7 @@ impl RangeIteratorImpl for ops::Range { } } -impl RangeIteratorImpl for ops::Range { +impl const RangeIteratorImpl for ops::Range { #[inline] fn spec_next(&mut self) -> Option { if self.start < self.end { @@ -710,7 +712,8 @@ fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize> { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Iterator for ops::Range { type Item = A; #[inline] @@ -820,7 +823,8 @@ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const DoubleEndedIterator for ops::Range { #[inline] fn next_back(&mut self) -> Option { self.spec_next_back() diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index ed23873cdde..7a10dea500a 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -1,3 +1,4 @@ +use crate::marker::Destruct; use crate::ops::{ControlFlow, Try}; /// An iterator able to yield elements from both ends. @@ -37,6 +38,7 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")] +#[const_trait] pub trait DoubleEndedIterator: Iterator { /// Removes and returns an element from the end of the iterator. /// @@ -131,7 +133,10 @@ pub trait DoubleEndedIterator: Iterator { /// [`Err(k)`]: Err #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> + where + Self::Item: ~const Destruct, + { for i in 0..n { self.next_back().ok_or(i)?; } @@ -181,6 +186,7 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { /// ``` #[inline] #[stable(feature = "iter_nth_back", since = "1.37.0")] + #[rustc_do_not_const_check] fn nth_back(&mut self, n: usize) -> Option { self.advance_back_by(n).ok()?; self.next_back() @@ -218,6 +224,7 @@ fn nth_back(&mut self, n: usize) -> Option { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] + #[rustc_do_not_const_check] fn try_rfold(&mut self, init: B, mut f: F) -> R where Self: Sized, @@ -289,6 +296,7 @@ fn try_rfold(&mut self, init: B, mut f: F) -> R #[doc(alias = "foldr")] #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] + #[rustc_do_not_const_check] fn rfold(mut self, init: B, mut f: F) -> B where Self: Sized, @@ -344,6 +352,7 @@ fn rfold(mut self, init: B, mut f: F) -> B /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] + #[rustc_do_not_const_check] fn rfind

(&mut self, predicate: P) -> Option where Self: Sized, diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index d48760ab3eb..6fc86550b63 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1,5 +1,6 @@ use crate::array; use crate::cmp::{self, Ordering}; +use crate::marker::Destruct; use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try}; use super::super::try_process; @@ -336,8 +337,10 @@ fn some(_: Option, x: T) -> Option { /// ``` #[inline] #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")] - #[rustc_do_not_const_check] - fn advance_by(&mut self, n: usize) -> Result<(), usize> { + fn advance_by(&mut self, n: usize) -> Result<(), usize> + where + Self::Item: ~const Destruct, + { for i in 0..n { self.next().ok_or(i)?; } @@ -385,8 +388,10 @@ fn advance_by(&mut self, n: usize) -> Result<(), usize> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_do_not_const_check] - fn nth(&mut self, n: usize) -> Option { + fn nth(&mut self, n: usize) -> Option + where + Self::Item: ~const Destruct, + { self.advance_by(n).ok()?; self.next() } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a8b4b23dc12..1076d357070 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -123,6 +123,7 @@ #![feature(const_index_range_slice_index)] #![feature(const_inherent_unchecked_arith)] #![feature(const_int_unchecked_arith)] +#![feature(const_intoiterator_identity)] #![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] diff --git a/library/core/tests/iter/consts.rs b/library/core/tests/iter/consts.rs new file mode 100644 index 00000000000..d56687e48c9 --- /dev/null +++ b/library/core/tests/iter/consts.rs @@ -0,0 +1,36 @@ +#[test] +fn const_manual_iter() { + struct S(bool); + + impl const Iterator for S { + type Item = (); + + fn next(&mut self) -> Option { + if self.0 == false { + self.0 = true; + Some(()) + } else { + None + } + } + } + const { + let mut val = S(false); + assert!(val.next().is_some()); + assert!(val.next().is_none()); + assert!(val.next().is_none()); + } +} + +#[test] +fn const_range() { + const { + let mut arr = [0; 3]; + for i in 0..arr.len() { + arr[i] = i; + } + assert!(arr[0] == 0); + assert!(arr[1] == 1); + assert!(arr[2] == 2); + } +} diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs index 770b6f7601f..cbb18e79e2d 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -20,6 +20,8 @@ mod sources; mod traits; +mod consts; + use core::cell::Cell; use core::convert::TryFrom; use core::iter::*; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index ccb7be68eb1..637cc6e9f62 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -12,8 +12,11 @@ #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_convert)] +#![feature(const_for)] #![feature(const_hash)] #![feature(const_heap)] +#![feature(const_intoiterator_identity)] +#![feature(const_iter)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init_read)] #![feature(const_nonnull_new)] diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index a450dbb82d1..e6f7dc410b6 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -228,5 +228,4 @@ fn evens_squared(n: usize) -> _ { const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); //~^ ERROR the trait bound -//~| ERROR the trait bound //~| ERROR the placeholder diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index bc6c9fd0779..9144ab9e3a6 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -437,19 +437,6 @@ LL | fn evens_squared(n: usize) -> _ { | not allowed in type signatures | help: replace with an appropriate return type: `impl Iterator` -error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied - --> $DIR/typeck_type_placeholder_item.rs:229:22 - | -LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); - | ^^^^^^ `std::ops::Range<{integer}>` is not an iterator - | - = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>` -note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const` - --> $DIR/typeck_type_placeholder_item.rs:229:14 - | -LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); - | ^^^^^^^ - error[E0277]: the trait bound `Filter, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied --> $DIR/typeck_type_placeholder_item.rs:229:45 | @@ -677,7 +664,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error: aborting due to 73 previous errors +error: aborting due to 72 previous errors Some errors have detailed explanations: E0121, E0277, E0282, E0403. For more information about an error, try `rustc --explain E0121`.