Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions library/core/src/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{
FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep,
};
use crate::ascii::Char as AsciiChar;
use crate::marker::Destruct;
use crate::mem;
use crate::net::{Ipv4Addr, Ipv6Addr};
use crate::num::NonZero;
Expand Down Expand Up @@ -800,7 +801,7 @@ macro_rules! range_incl_exact_iter_impl {
}

/// Specialization implementations for `Range`.
trait RangeIteratorImpl {
const trait RangeIteratorImpl {
type Item;

// Iterator
Expand All @@ -814,7 +815,8 @@ trait RangeIteratorImpl {
fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>>;
}

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

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

impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
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 @@ -977,7 +980,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 @@ -1030,7 +1034,10 @@ impl<A: Step> Iterator for ops::Range<A> {
}

#[inline]
fn is_sorted(self) -> bool {
fn is_sorted(self) -> bool
where
Self: [const] Destruct,
{
true
}

Expand Down Expand Up @@ -1110,7 +1117,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> {
Copy link
Copy Markdown
Contributor

@oli-obk oli-obk May 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change needed for the MVP? should at least be a separate commit unless the rest of this commit requires it

View changes since the review

#[inline]
fn next_back(&mut self) -> Option<A> {
self.spec_next_back()
Expand Down
26 changes: 18 additions & 8 deletions library/core/src/iter/traits/double_ended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ pub const trait DoubleEndedIterator: [const] Iterator {
/// [`Err(k)`]: Err
#[inline]
#[unstable(feature = "iter_advance_by", issue = "77404")]
#[rustc_non_const_trait_method]
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
where
Self::Item: [const] Destruct,
{
for i in 0..n {
if self.next_back().is_none() {
// SAFETY: `i` is always less than `n`.
Expand Down Expand Up @@ -191,8 +193,10 @@ pub const trait DoubleEndedIterator: [const] Iterator {
/// ```
#[inline]
#[stable(feature = "iter_nth_back", since = "1.37.0")]
#[rustc_non_const_trait_method]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
fn nth_back(&mut self, n: usize) -> Option<Self::Item>
where
Self::Item: [const] Destruct,
{
if self.advance_back_by(n).is_err() {
return None;
}
Expand Down Expand Up @@ -367,15 +371,21 @@ pub const trait DoubleEndedIterator: [const] Iterator {
/// ```
#[inline]
#[stable(feature = "iter_rfind", since = "1.27.0")]
#[rustc_non_const_trait_method]
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
where
Self: Sized,
P: FnMut(&Self::Item) -> bool,
P: [const] FnMut(&Self::Item) -> bool + [const] Destruct,
Self::Item: [const] Destruct,
{
#[inline]
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
move |(), x| {
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const fn check<T>(
mut predicate: impl [const] FnMut(&T) -> bool + [const] Destruct,
) -> impl [const] FnMut((), T) -> ControlFlow<T> + [const] Destruct
where
T: [const] Destruct,
{
const move |(), x| {
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::Continue(()) }
}
}
Expand Down
111 changes: 70 additions & 41 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,22 @@ pub const trait Iterator {
/// ```
#[inline]
#[unstable(feature = "iter_advance_by", issue = "77404")]
#[rustc_non_const_trait_method]
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>
where
Self::Item: [const] Destruct,
{
/// Helper trait to specialize `advance_by` via `try_fold` for `Sized` iterators.
trait SpecAdvanceBy {

#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const trait SpecAdvanceBy {
fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>>;
}

impl<I: Iterator + ?Sized> SpecAdvanceBy for I {
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
impl<I: [const] Iterator + ?Sized> const SpecAdvanceBy for I
where
I::Item: [const] Destruct,
{
default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
for i in 0..n {
if self.next().is_none() {
Expand All @@ -325,13 +333,17 @@ pub const trait Iterator {
}
}

impl<I: Iterator> SpecAdvanceBy for I {
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
impl<I: [const] Iterator> const SpecAdvanceBy for I
where
I::Item: [const] Destruct,
{
fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
let Some(n) = NonZero::new(n) else {
return Ok(());
};

let res = self.try_fold(n, |n, _| NonZero::new(n.get() - 1));
let res = self.try_fold(n, const |n, _| NonZero::new(n.get() - 1));

match res {
None => Ok(()),
Expand Down Expand Up @@ -384,8 +396,10 @@ pub const trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_non_const_trait_method]
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 Expand Up @@ -2827,15 +2841,17 @@ pub const trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_non_const_trait_method]
fn all<F>(&mut self, f: F) -> bool
where
Self: Sized,
F: FnMut(Self::Item) -> bool,
F: [const] FnMut(Self::Item) -> bool + [const] Destruct,
{
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
#[inline]
fn check<T>(mut f: impl FnMut(T) -> bool) -> impl FnMut((), T) -> ControlFlow<()> {
move |(), x| {
const fn check<T>(
mut f: impl [const] FnMut(T) -> bool + [const] Destruct,
) -> impl [const] FnMut((), T) -> ControlFlow<()> + [const] Destruct {
const move |(), x| {
if f(x) { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
}
}
Expand Down Expand Up @@ -3246,11 +3262,10 @@ pub const trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_non_const_trait_method]
fn max(self) -> Option<Self::Item>
where
Self: Sized,
Self::Item: Ord,
Self: Sized + [const] Destruct,
Self::Item: [const] Ord + [const] Destruct,
{
self.max_by(Ord::cmp)
}
Expand Down Expand Up @@ -3283,11 +3298,10 @@ pub const trait Iterator {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_non_const_trait_method]
fn min(self) -> Option<Self::Item>
where
Self: Sized,
Self::Item: Ord,
Self: Sized + [const] Destruct,
Self::Item: [const] Ord + [const] Destruct,
{
self.min_by(Ord::cmp)
}
Expand Down Expand Up @@ -3340,15 +3354,21 @@ pub const trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_max_by", since = "1.15.0")]
#[rustc_non_const_trait_method]
fn max_by<F>(self, compare: F) -> Option<Self::Item>
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
Self: Sized + [const] Destruct,
Self::Item: [const] Destruct,
F: [const] FnMut(&Self::Item, &Self::Item) -> Ordering + [const] Destruct,
{
#[inline]
fn fold<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T {
move |x, y| cmp::max_by(x, y, &mut compare)
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const fn fold<T>(
mut compare: impl [const] FnMut(&T, &T) -> Ordering + [const] Destruct,
) -> impl [const] FnMut(T, T) -> T + [const] Destruct
where
T: [const] Destruct,
{
const move |x, y| cmp::max_by(x, y, &mut compare)
}

self.reduce(fold(compare))
Expand Down Expand Up @@ -3402,15 +3422,21 @@ pub const trait Iterator {
/// ```
#[inline]
#[stable(feature = "iter_min_by", since = "1.15.0")]
#[rustc_non_const_trait_method]
fn min_by<F>(self, compare: F) -> Option<Self::Item>
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Ordering,
Self: Sized + [const] Destruct,
F: [const] FnMut(&Self::Item, &Self::Item) -> Ordering + [const] Destruct,
Self::Item: [const] Destruct,
{
#[inline]
fn fold<T>(mut compare: impl FnMut(&T, &T) -> Ordering) -> impl FnMut(T, T) -> T {
move |x, y| cmp::min_by(x, y, &mut compare)
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const fn fold<T>(
mut compare: impl [const] FnMut(&T, &T) -> Ordering + [const] Destruct,
) -> impl [const] FnMut(T, T) -> T + [const] Destruct
where
T: [const] Destruct,
{
const move |x, y| cmp::min_by(x, y, &mut compare)
}

self.reduce(fold(compare))
Expand Down Expand Up @@ -4047,13 +4073,12 @@ pub const trait Iterator {
/// ```
#[inline]
#[stable(feature = "is_sorted", since = "1.82.0")]
#[rustc_non_const_trait_method]
fn is_sorted(self) -> bool
where
Self: Sized,
Self::Item: PartialOrd,
Self: Sized + [const] Destruct,
Self::Item: [const] PartialOrd + [const] Destruct,
{
self.is_sorted_by(|a, b| a <= b)
self.is_sorted_by(const |a, b| a <= b)
}

/// Checks if the elements of this iterator are sorted using the given comparator function.
Expand All @@ -4074,18 +4099,22 @@ pub const trait Iterator {
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| true));
/// ```
#[stable(feature = "is_sorted", since = "1.82.0")]
#[rustc_non_const_trait_method]
fn is_sorted_by<F>(mut self, compare: F) -> bool
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> bool,
Self: Sized + [const] Destruct,
Self::Item: [const] Destruct,
F: [const] FnMut(&Self::Item, &Self::Item) -> bool + [const] Destruct,
{
#[inline]
fn check<'a, T>(
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
const fn check<'a, T>(
last: &'a mut T,
mut compare: impl FnMut(&T, &T) -> bool + 'a,
) -> impl FnMut(T) -> bool + 'a {
move |curr| {
mut compare: impl [const] FnMut(&T, &T) -> bool + 'a + [const] Destruct,
) -> impl [const] FnMut(T) -> bool + 'a + [const] Destruct
where
T: [const] Destruct,
{
const move |curr| {
if !compare(&last, &curr) {
return false;
}
Expand Down Expand Up @@ -4135,12 +4164,12 @@ pub const trait Iterator {
#[inline]
#[doc(hidden)]
#[unstable(feature = "trusted_random_access", issue = "none")]
#[rustc_non_const_trait_method]
unsafe fn __iterator_get_unchecked(&mut self, _idx: usize) -> Self::Item
where
Self: TrustedRandomAccessNoCoerce,
{
unreachable!("Always specialized");
// FIXME(const-hack): use unreachable! once that works in const
panic!("Always specialized");
}
}

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 @@ -113,4 +113,5 @@ pub unsafe trait InPlaceIterable {
/// 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 + Copy {}
#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
pub const unsafe trait TrustedStep: [const] Step + Copy {}
10 changes: 2 additions & 8 deletions library/core/src/slice/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,11 @@ where
// Implemented as explicit indexing rather
// than zipped iterators for performance reasons.
// See PR https://github.com/rust-lang/rust/pull/116846
// FIXME(const_hack): make this a `for idx in 0..len` loop.
let mut idx = 0;
while idx < len {
for idx in 0..len {
// SAFETY: idx < len, so both are in-bounds and readable
if unsafe { *lhs.add(idx) != *rhs.add(idx) } {
return false;
}
idx += 1;
}

true
Expand Down Expand Up @@ -224,11 +221,8 @@ const fn chaining_impl<'l, 'r, A: PartialOrd, B, C>(
let lhs = &left[..l];
let rhs = &right[..l];

// FIXME(const-hack): revert this to `for i in 0..l` once `impl const Iterator for Range<T>`
let mut i: usize = 0;
while i < l {
for i in 0..l {
elem_chain(&lhs[i], &rhs[i])?;
i += 1;
}

len_chain(&left.len(), &right.len())
Expand Down
7 changes: 2 additions & 5 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5606,11 +5606,8 @@ where
// But since it can't be relied on we also have an explicit specialization for T: Copy.
let len = self.len();
let src = &src[..len];
// FIXME(const_hack): make this a `for idx in 0..self.len()` loop.
let mut idx = 0;
while idx < self.len() {
self[idx].clone_from(&src[idx]);
idx += 1;
for i in 0..len {
self[i].clone_from(&src[i]);
}
}
}
Expand Down
Loading
Loading