Skip to content

Commit

Permalink
Rollup merge of #104100 - ink-feather-org:const_iter_range, r=the8472…
Browse files Browse the repository at this point in the history
…,fee1-dead

Allow using `Range` as an `Iterator` in const contexts.

~~based on #102225 by `@fee1-dead~~`
  • Loading branch information
Dylan-DPC authored Mar 19, 2023
2 parents ab9bb3e + 8a9d6bf commit 993b775
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 31 deletions.
32 changes: 22 additions & 10 deletions library/core/src/iter/range.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::convert::TryFrom;
use crate::marker::Destruct;
use crate::mem;
use crate::ops::{self, Try};

Expand All @@ -20,7 +21,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`
Expand Down Expand Up @@ -234,7 +236,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]
Expand Down Expand Up @@ -266,7 +269,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]
Expand Down Expand Up @@ -330,7 +334,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]
Expand All @@ -355,7 +360,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]
Expand Down Expand Up @@ -405,7 +411,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<usize> {
let start = start as u32;
Expand All @@ -423,6 +430,7 @@ impl Step for char {
}

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

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

/// Specialization implementations for `Range`.
#[const_trait]
trait RangeIteratorImpl {
type Item;

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

impl<A: Step> RangeIteratorImpl for ops::Range<A> {
impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
type Item = A;

#[inline]
Expand Down Expand Up @@ -614,7 +624,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
}
}

impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::Range<T> {
#[inline]
fn spec_next(&mut self) -> Option<T> {
if self.start < self.end {
Expand Down Expand Up @@ -702,7 +712,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
}

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

#[inline]
Expand Down Expand Up @@ -812,7 +823,8 @@ range_incl_exact_iter_impl! {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
impl<A: ~const Step + ~const Destruct> const DoubleEndedIterator for ops::Range<A> {
#[inline]
fn next_back(&mut self) -> Option<A> {
self.spec_next_back()
Expand Down
11 changes: 10 additions & 1 deletion library/core/src/iter/traits/double_ended.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::marker::Destruct;
use crate::ops::{ControlFlow, Try};

/// An iterator able to yield elements from both ends.
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -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)?;
}
Expand Down Expand Up @@ -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::Item> {
self.advance_back_by(n).ok()?;
self.next_back()
Expand Down Expand Up @@ -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<B, F, R>(&mut self, init: B, mut f: F) -> R
where
Self: Sized,
Expand Down Expand Up @@ -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<B, F>(mut self, init: B, mut f: F) -> B
where
Self: Sized,
Expand Down Expand Up @@ -344,6 +352,7 @@ pub trait DoubleEndedIterator: Iterator {
/// ```
#[inline]
#[stable(feature = "iter_rfind", since = "1.27.0")]
#[rustc_do_not_const_check]
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
Self: Sized,
Expand Down
13 changes: 9 additions & 4 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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)?;
}
Expand Down Expand Up @@ -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<Self::Item> {
fn nth(&mut self, n: usize) -> Option<Self::Item>
where
Self::Item: ~const Destruct,
{
self.advance_by(n).ok()?;
self.next()
}
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/iter/traits/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
2 changes: 2 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,11 @@
#![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)]
#![feature(const_iter)]
#![feature(const_likely)]
#![feature(const_maybe_uninit_uninit_array)]
#![feature(const_maybe_uninit_as_mut_ptr)]
Expand Down
36 changes: 36 additions & 0 deletions library/core/tests/iter/consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#[test]
fn const_manual_iter() {
struct S(bool);

impl const Iterator for S {
type Item = ();

fn next(&mut self) -> Option<Self::Item> {
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);
}
}
2 changes: 2 additions & 0 deletions library/core/tests/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ mod range;
mod sources;
mod traits;

mod consts;

use core::cell::Cell;
use core::convert::TryFrom;
use core::iter::*;
Expand Down
3 changes: 3 additions & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
1 change: 0 additions & 1 deletion tests/ui/typeck/typeck_type_placeholder_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
15 changes: 1 addition & 14 deletions tests/ui/typeck/typeck_type_placeholder_item.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -437,19 +437,6 @@ LL | fn evens_squared(n: usize) -> _ {
| not allowed in type signatures
| help: replace with an appropriate return type: `impl Iterator<Item = usize>`

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<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied
--> $DIR/typeck_type_placeholder_item.rs:229:45
|
Expand Down Expand Up @@ -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`.

0 comments on commit 993b775

Please sign in to comment.