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
2 changes: 1 addition & 1 deletion library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
}
}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
impl ops::Index<range::RangeFrom<usize>> for CStr {
type Output = CStr;

Expand Down
41 changes: 18 additions & 23 deletions library/core/src/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ mod iter;
#[unstable(feature = "new_range_api", issue = "125687")]
pub mod legacy;

#[doc(inline)]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
pub use iter::RangeFromIter;
#[doc(inline)]
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
pub use iter::RangeInclusiveIter;
#[doc(inline)]
#[unstable(feature = "new_range_api", issue = "125687")]
pub use iter::{RangeFromIter, RangeIter};
pub use iter::RangeIter;

// FIXME(#125687): re-exports temporarily removed
// Because re-exports of stable items (Bound, RangeBounds, RangeFull, RangeTo)
Expand Down Expand Up @@ -416,14 +419,13 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
///
/// The `RangeFrom` `start..` contains all values with `x >= start`.
///
/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
/// *Note*: Overflow in the [`IntoIterator`] implementation (when the contained
/// data type reaches its numerical limit) is allowed to panic, wrap, or
/// saturate. This behavior is defined by the implementation of the [`Step`]
/// trait. For primitive integers, this follows the normal rules, and respects
/// the overflow checks profile (panic in debug, wrap in release). Note also
/// that overflow happens earlier than you might assume: the overflow happens
/// in the call to `next` that yields the maximum value, as the range must be
/// set to a state to yield the next value.
/// the overflow checks profile (panic in debug, wrap in release). Unlike
/// its legacy counterpart, the iterator will only panic after yielding the
/// maximum value when overflow checks are enabled.
Comment on lines -419 to +428
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we have a test for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

///
/// [`Step`]: crate::iter::Step
///
Expand All @@ -432,7 +434,6 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
/// The `start..` syntax is a `RangeFrom`:
///
/// ```
/// #![feature(new_range_api)]
/// use core::range::RangeFrom;
///
/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
Expand All @@ -441,14 +442,14 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
#[lang = "RangeFromCopy"]
#[derive(Copy, Hash)]
#[derive_const(Clone, PartialEq, Eq)]
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
pub struct RangeFrom<Idx> {
/// The lower bound of the range (inclusive).
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
pub start: Idx,
}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
self.start.fmt(fmt)?;
Expand All @@ -465,15 +466,14 @@ impl<Idx: Step> RangeFrom<Idx> {
/// # Examples
///
/// ```
/// #![feature(new_range_api)]
/// use core::range::RangeFrom;
///
/// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
/// assert_eq!(i.next(), Some(9));
/// assert_eq!(i.next(), Some(16));
/// assert_eq!(i.next(), Some(25));
/// ```
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub fn iter(&self) -> RangeFromIter<Idx> {
self.clone().into_iter()
Expand All @@ -486,7 +486,6 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// # Examples
///
/// ```
/// #![feature(new_range_api)]
/// use core::range::RangeFrom;
///
/// assert!(!RangeFrom::from(3..).contains(&2));
Expand All @@ -498,7 +497,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
/// ```
#[inline]
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
pub const fn contains<U>(&self, item: &U) -> bool
where
Expand All @@ -509,7 +508,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
}
}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
impl<T> const RangeBounds<T> for RangeFrom<T> {
fn start_bound(&self) -> Bound<&T> {
Expand All @@ -526,7 +525,7 @@ impl<T> const RangeBounds<T> for RangeFrom<T> {
/// If you need to use this implementation where `T` is unsized,
/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
impl<T> const RangeBounds<T> for RangeFrom<&T> {
fn start_bound(&self) -> Bound<&T> {
Expand All @@ -537,8 +536,7 @@ impl<T> const RangeBounds<T> for RangeFrom<&T> {
}
}

// #[unstable(feature = "range_into_bounds", issue = "136903")]
#[unstable(feature = "new_range_api", issue = "125687")]
#[unstable(feature = "range_into_bounds", issue = "136903")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
impl<T> const IntoBounds<T> for RangeFrom<T> {
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
Expand All @@ -547,7 +545,6 @@ impl<T> const IntoBounds<T> for RangeFrom<T> {
}

#[unstable(feature = "one_sided_range", issue = "69780")]
// #[unstable(feature = "new_range_api", issue = "125687")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
impl<T> const OneSidedRange<T> for RangeFrom<T>
where
Expand All @@ -558,15 +555,15 @@ where
}
}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
#[inline]
fn from(value: RangeFrom<T>) -> Self {
Self { start: value.start }
}
}
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
#[inline]
Expand Down Expand Up @@ -697,7 +694,6 @@ impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
}
}

// #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
#[unstable(feature = "range_into_bounds", issue = "136903")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
impl<T> const IntoBounds<T> for RangeToInclusive<T> {
Expand All @@ -706,7 +702,6 @@ impl<T> const IntoBounds<T> for RangeToInclusive<T> {
}
}

// #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
#[unstable(feature = "one_sided_range", issue = "69780")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
impl<T> const OneSidedRange<T> for RangeToInclusive<T>
Expand Down
42 changes: 37 additions & 5 deletions library/core/src/range/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ pub struct RangeIter<A>(legacy::Range<A>);
impl<A> RangeIter<A> {
#[unstable(feature = "new_range_api", issue = "125687")]
/// Returns the remainder of the range being iterated over.
///
/// # Examples
/// ```
/// #![feature(new_range_api)]
/// let range = core::range::Range::from(3..11);
/// let mut iter = range.into_iter();
/// assert_eq!(iter.clone().remainder(), range);
/// iter.next();
/// assert_eq!(iter.clone().remainder(), core::range::Range::from(4..11));
/// iter.by_ref().for_each(drop);
/// assert!(iter.remainder().is_empty());
/// ```
pub fn remainder(self) -> Range<A> {
Range { start: self.0.start, end: self.0.end }
}
Expand Down Expand Up @@ -161,6 +173,17 @@ impl<A: Step> RangeInclusiveIter<A> {
/// Returns the remainder of the range being iterated over.
///
/// If the iterator is exhausted or empty, returns `None`.
///
/// # Examples
/// ```
/// let range = core::range::RangeInclusive::from(3..=11);
/// let mut iter = range.into_iter();
/// assert_eq!(iter.clone().remainder().unwrap(), range);
/// iter.next();
/// assert_eq!(iter.clone().remainder().unwrap(), core::range::RangeInclusive::from(4..=11));
/// iter.by_ref().for_each(drop);
/// assert!(iter.remainder().is_none());
/// ```
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
pub fn remainder(self) -> Option<RangeInclusive<A>> {
if self.0.is_empty() {
Expand Down Expand Up @@ -294,7 +317,7 @@ range_incl_exact_iter_impl! {
}

/// By-value [`RangeFrom`] iterator.
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[derive(Debug, Clone)]
pub struct RangeFromIter<A> {
start: A,
Expand All @@ -305,9 +328,18 @@ pub struct RangeFromIter<A> {

impl<A: Step> RangeFromIter<A> {
/// Returns the remainder of the range being iterated over.
///
/// # Examples
/// ```
/// let range = core::range::RangeFrom::from(3..);
/// let mut iter = range.into_iter();
/// assert_eq!(iter.clone().remainder(), range);
/// iter.next();
/// assert_eq!(iter.remainder(), core::range::RangeFrom::from(4..));
/// ```
#[inline]
#[rustc_inherit_overflow_checks]
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
pub fn remainder(self) -> RangeFrom<A> {
Comment on lines 330 to 343
Copy link
Contributor

Choose a reason for hiding this comment

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

This could probably use an example

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added examples for RangeInclusive::remainder, RangeFrom::remainder, and Range::remainder

if intrinsics::overflow_checks() {
if !self.first {
Expand All @@ -319,7 +351,7 @@ impl<A: Step> RangeFromIter<A> {
}
}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
impl<A: Step> Iterator for RangeFromIter<A> {
type Item = A;

Expand Down Expand Up @@ -371,10 +403,10 @@ impl<A: Step> Iterator for RangeFromIter<A> {
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: TrustedStep> TrustedLen for RangeFromIter<A> {}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
impl<A: Step> FusedIterator for RangeFromIter<A> {}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
impl<A: Step> IntoIterator for RangeFrom<A> {
type Item = A;
type IntoIter = RangeFromIter<A>;
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/slice/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ mod private_slice_index {
impl Sealed for range::RangeInclusive<usize> {}
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
impl Sealed for range::RangeToInclusive<usize> {}
#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
impl Sealed for range::RangeFrom<usize> {}

impl Sealed for ops::IndexRange {}
Expand Down Expand Up @@ -588,7 +588,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
}
}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for range::RangeFrom<usize> {
type Output = [T];
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/str/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> {
}
}

#[unstable(feature = "new_range_api", issue = "125687")]
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl const SliceIndex<str> for range::RangeFrom<usize> {
type Output = str;
Expand Down
1 change: 0 additions & 1 deletion tests/codegen-llvm/fromrangeiter-overflow-checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
//@ [NOCHECKS] compile-flags: -Coverflow-checks=no

#![crate_type = "lib"]
#![feature(new_range_api)]
use std::range::{RangeFrom, RangeFromIter};

// CHECK-LABEL: @iterrangefrom_remainder(
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/iterators/fromrangeiter.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//@ run-pass
//@ compile-flags: -C overflow-checks=yes

#![feature(new_range_api)]

use std::{iter, range};

fn main() {
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/iterators/rangefrom-overflow-debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
//@ needs-unwind
//@ compile-flags: -O -C debug_assertions=yes

#![feature(new_range_api)]

use std::panic;

fn main() {
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/iterators/rangefrom-overflow-ndebug.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
//@ run-pass
//@ compile-flags: -O -C debug_assertions=no

#![feature(new_range_api)]

fn main() {
let mut it = core::range::RangeFrom::from(u8::MAX..).into_iter();
assert_eq!(it.next().unwrap(), 255);
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/iterators/rangefrom-overflow-overflow-checks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
//@ needs-unwind
//@ compile-flags: -O -C overflow-checks=yes

#![feature(new_range_api)]

use std::panic;

fn main() {
Expand Down
22 changes: 19 additions & 3 deletions tests/ui/range/new_range_stability.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// Stable

use std::range::{RangeInclusive, RangeInclusiveIter, RangeToInclusive};
use std::range::{
RangeInclusive,
RangeInclusiveIter,
RangeToInclusive,
RangeFrom,
RangeFromIter,
};

fn range_inclusive(mut r: RangeInclusive<usize>) {
&[1, 2, 3][r]; // Indexing
Expand All @@ -23,15 +29,25 @@ fn range_to_inclusive(mut r: RangeToInclusive<usize>) {
r.contains(&5);
}

fn range_from(mut r: RangeFrom<usize>) {
&[1, 2, 3][r]; // Indexing

r.start;
r.contains(&5);
r.iter();

let mut i = r.into_iter();
i.next();
i.remainder();
}

// Unstable module

use std::range::legacy; //~ ERROR unstable

// Unstable types

use std::range::RangeFrom; //~ ERROR unstable
use std::range::Range; //~ ERROR unstable
use std::range::RangeFromIter; //~ ERROR unstable
use std::range::RangeIter; //~ ERROR unstable

fn main() {}
Loading
Loading