From 7bc67ef6e02d69023c6fb04c2258beab54ac22b8 Mon Sep 17 00:00:00 2001 From: onestacked Date: Sat, 4 Feb 2023 16:36:26 +0100 Subject: [PATCH 1/2] Make the `Step` implementations const. --- library/core/src/iter/range.rs | 20 ++++++++++++++------ library/core/src/iter/traits/marker.rs | 3 ++- library/core/src/lib.rs | 1 + 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 78e27d73065aa..dba2b2291ff6e 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -20,7 +20,8 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi /// The *successor* operation moves towards values that compare greater. /// The *predecessor* operation moves towards values that compare lesser. #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] -pub trait Step: Clone + PartialOrd + Sized { +#[const_trait] +pub trait Step: ~const Clone + ~const PartialOrd + Sized { /// Returns the number of *successor* steps required to get from `start` to `end`. /// /// Returns `None` if the number of steps would overflow `usize` @@ -234,7 +235,8 @@ macro_rules! step_integer_impls { $( #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - impl Step for $u_narrower { + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + impl const Step for $u_narrower { step_identical_methods!(); #[inline] @@ -266,7 +268,8 @@ macro_rules! step_integer_impls { #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - impl Step for $i_narrower { + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + impl const Step for $i_narrower { step_identical_methods!(); #[inline] @@ -330,7 +333,8 @@ macro_rules! step_integer_impls { $( #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - impl Step for $u_wider { + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + impl const Step for $u_wider { step_identical_methods!(); #[inline] @@ -355,7 +359,8 @@ macro_rules! step_integer_impls { #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] - impl Step for $i_wider { + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + impl const Step for $i_wider { step_identical_methods!(); #[inline] @@ -405,7 +410,8 @@ step_integer_impls! { } #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] -impl Step for char { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +impl const Step for char { #[inline] fn steps_between(&start: &char, &end: &char) -> Option { let start = start as u32; @@ -423,6 +429,7 @@ impl Step for char { } #[inline] + #[rustc_allow_const_fn_unstable(const_try)] fn forward_checked(start: char, count: usize) -> Option { let start = start as u32; let mut res = Step::forward_checked(start, count)?; @@ -439,6 +446,7 @@ impl Step for char { } #[inline] + #[rustc_allow_const_fn_unstable(const_try)] fn backward_checked(start: char, count: usize) -> Option { let start = start as u32; let mut res = Step::backward_checked(start, count)?; diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs index af02848233d99..c8f60defff771 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -86,4 +86,5 @@ pub unsafe trait InPlaceIterable: Iterator {} /// for details. Consumers are free to rely on the invariants in unsafe code. #[unstable(feature = "trusted_step", issue = "85731")] #[rustc_specialization_trait] -pub unsafe trait TrustedStep: Step {} +#[const_trait] +pub unsafe trait TrustedStep: ~const Step {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 526232f44ee1e..a8b4b23dc129a 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -126,6 +126,7 @@ #![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] +#![feature(const_iter)] #![feature(const_likely)] #![feature(const_maybe_uninit_uninit_array)] #![feature(const_maybe_uninit_as_mut_ptr)] From 8a9d6bf4fd540b2a2882193cbd6232b86e5dcd7e Mon Sep 17 00:00:00 2001 From: onestacked Date: Sat, 4 Feb 2023 17:48:46 +0100 Subject: [PATCH 2/2] Mark DoubleEndedIterator as #[const_trait] using rustc_do_not_const_check, implement const Iterator and DoubleEndedIterator for Range. --- library/core/src/iter/range.rs | 12 ++++--- library/core/src/iter/traits/double_ended.rs | 11 +++++- library/core/src/iter/traits/iterator.rs | 13 ++++--- library/core/src/lib.rs | 1 + library/core/tests/iter/consts.rs | 36 +++++++++++++++++++ library/core/tests/iter/mod.rs | 2 ++ library/core/tests/lib.rs | 3 ++ .../ui/typeck/typeck_type_placeholder_item.rs | 1 - .../typeck_type_placeholder_item.stderr | 15 +------- 9 files changed, 70 insertions(+), 24 deletions(-) create mode 100644 library/core/tests/iter/consts.rs diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index dba2b2291ff6e..f19636fba5d95 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 @@ macro_rules! range_incl_exact_iter_impl { } /// 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 @@ impl RangeIteratorImpl for ops::Range { } #[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 @@ range_incl_exact_iter_impl! { } #[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 ed23873cdde7c..7a10dea500a96 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 @@ use crate::ops::{ControlFlow, Try}; /// ``` #[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 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[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 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[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 @@ pub trait DoubleEndedIterator: Iterator { #[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 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[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 d48760ab3ebfa..6fc86550b63e7 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 @@ pub trait Iterator { /// ``` #[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 @@ pub trait Iterator { /// ``` #[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 a8b4b23dc129a..1076d357070ef 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 0000000000000..d56687e48c96a --- /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 770b6f7601fa2..cbb18e79e2d43 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/core/tests/iter/mod.rs @@ -20,6 +20,8 @@ mod range; 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 ccb7be68eb1b2..637cc6e9f629b 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 a450dbb82d1bd..e6f7dc410b614 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 bc6c9fd077993..9144ab9e3a6bd 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`.