From 620e92f0166738113eac8ec774253501324a6e75 Mon Sep 17 00:00:00 2001 From: Peter Jaszkowiak Date: Tue, 3 Mar 2026 18:49:37 -0700 Subject: [PATCH] stabilize new Range type and iterator stabilizes `core::range::Range` stabilizes `core::range::RangeIter` stabilizes `std::range` which was missed in prior PRs Updates docs to reflect stabilization (removed "experimental") `RangeIter::remainder` is excluded from stabilization --- compiler/rustc_index/src/lib.rs | 6 +- library/core/src/range.rs | 56 ++++++++----------- library/core/src/range/iter.rs | 13 ++--- library/core/src/slice/index.rs | 4 +- library/core/src/str/traits.rs | 2 +- library/coretests/tests/lib.rs | 1 - library/std/src/lib.rs | 2 +- .../feature-gates/feature-gate-new_range.rs | 2 - .../feature-gate-new_range.stderr | 6 +- tests/ui/new-range/disabled.rs | 2 +- tests/ui/new-range/enabled.rs | 1 - tests/ui/range/new_range_stability.rs | 22 ++++++-- tests/ui/range/new_range_stability.stderr | 42 ++++++-------- 13 files changed, 76 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index dc7fe03dcf3c..1b8c8e3bd2c8 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -2,9 +2,13 @@ #![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))] #![cfg_attr(all(feature = "nightly", test), feature(test))] #![cfg_attr(feature = "nightly", feature(extend_one, step_trait))] -#![cfg_attr(feature = "nightly", feature(new_range_api))] // tidy-alphabetical-end +// FIXME(#125687): new_range_api recently stabilized +// Remove this when it hits stable. cfg(bootstrap) +#![allow(stable_features)] +#![cfg_attr(feature = "nightly", feature(new_range_api))] + pub mod bit_set; #[cfg(feature = "nightly")] pub mod interval; diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 2007533e68e5..d4be1b67d386 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -1,19 +1,18 @@ -//! # Experimental replacement range types +//! # Replacement range types //! -//! The types within this module are meant to replace the existing -//! `Range`, `RangeInclusive`, and `RangeFrom` types in a future edition. +//! The types within this module are meant to replace the legacy `Range`, +//! `RangeInclusive`, `RangeToInclusive` and `RangeFrom` types in a future edition. //! //! ``` -//! #![feature(new_range_api)] -//! use core::range::{Range, RangeFrom, RangeInclusive}; +//! use core::range::{Range, RangeFrom, RangeInclusive, RangeToInclusive}; //! //! let arr = [0, 1, 2, 3, 4]; -//! assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); -//! assert_eq!(arr[ .. 3 ], [0, 1, 2 ]); -//! assert_eq!(arr[ ..=3 ], [0, 1, 2, 3 ]); -//! assert_eq!(arr[ RangeFrom::from(1.. )], [ 1, 2, 3, 4]); -//! assert_eq!(arr[ Range::from(1..3 )], [ 1, 2 ]); -//! assert_eq!(arr[RangeInclusive::from(1..=3)], [ 1, 2, 3 ]); +//! assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); +//! assert_eq!(arr[ .. 3 ], [0, 1, 2 ]); +//! assert_eq!(arr[RangeToInclusive::from( ..=3)], [0, 1, 2, 3 ]); +//! assert_eq!(arr[ RangeFrom::from(1.. )], [ 1, 2, 3, 4]); +//! assert_eq!(arr[ Range::from(1..3 )], [ 1, 2 ]); +//! assert_eq!(arr[ RangeInclusive::from(1..=3)], [ 1, 2, 3 ]); //! ``` use crate::fmt; @@ -21,7 +20,7 @@ mod iter; -#[unstable(feature = "new_range_api", issue = "125687")] +#[unstable(feature = "new_range_api_legacy", issue = "125687")] pub mod legacy; #[doc(inline)] @@ -31,7 +30,7 @@ #[stable(feature = "new_range_inclusive_api", since = "1.95.0")] pub use iter::RangeInclusiveIter; #[doc(inline)] -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] pub use iter::RangeIter; // FIXME(#125687): re-exports temporarily removed @@ -57,7 +56,6 @@ /// # Examples /// /// ``` -/// #![feature(new_range_api)] /// use core::range::Range; /// /// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 }); @@ -66,17 +64,17 @@ #[lang = "RangeCopy"] #[derive(Copy, Hash)] #[derive_const(Clone, Default, PartialEq, Eq)] -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] pub struct Range { /// The lower bound of the range (inclusive). - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] pub start: Idx, /// The upper bound of the range (exclusive). - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] pub end: Idx, } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for Range { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.start.fmt(fmt)?; @@ -94,7 +92,6 @@ impl Range { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::Range; /// /// let mut i = Range::from(3..9).iter().map(|n| n*n); @@ -102,7 +99,7 @@ impl Range { /// assert_eq!(i.next(), Some(16)); /// assert_eq!(i.next(), Some(25)); /// ``` - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn iter(&self) -> RangeIter { self.clone().into_iter() @@ -115,7 +112,6 @@ impl> Range { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::Range; /// /// assert!(!Range::from(3..5).contains(&2)); @@ -132,7 +128,7 @@ impl> Range { /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5)); /// ``` #[inline] - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] pub const fn contains(&self, item: &U) -> bool where @@ -147,7 +143,6 @@ pub const fn contains(&self, item: &U) -> bool /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// use core::range::Range; /// /// assert!(!Range::from(3..5).is_empty()); @@ -158,7 +153,6 @@ pub const fn contains(&self, item: &U) -> bool /// The range is empty if either side is incomparable: /// /// ``` - /// #![feature(new_range_api)] /// use core::range::Range; /// /// assert!(!Range::from(3.0..5.0).is_empty()); @@ -166,7 +160,7 @@ pub const fn contains(&self, item: &U) -> bool /// assert!( Range::from(f32::NAN..5.0).is_empty()); /// ``` #[inline] - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] pub const fn is_empty(&self) -> bool where @@ -176,7 +170,7 @@ pub const fn is_empty(&self) -> bool } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const RangeBounds for Range { fn start_bound(&self) -> Bound<&T> { @@ -193,7 +187,7 @@ fn end_bound(&self) -> Bound<&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..end` with `(Bound::Included(start), Bound::Excluded(end))`. -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_range", issue = "none")] impl const RangeBounds for Range<&T> { fn start_bound(&self) -> Bound<&T> { @@ -204,8 +198,7 @@ fn end_bound(&self) -> Bound<&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 const IntoBounds for Range { fn into_bounds(self) -> (Bound, Bound) { @@ -213,7 +206,7 @@ fn into_bounds(self) -> (Bound, Bound) { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const From> for legacy::Range { #[inline] @@ -221,8 +214,7 @@ fn from(value: Range) -> Self { Self { start: value.start, end: value.end } } } - -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const From> for Range { #[inline] diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs index c29b498bd25f..a5db3699bc40 100644 --- a/library/core/src/range/iter.rs +++ b/library/core/src/range/iter.rs @@ -6,7 +6,7 @@ use crate::{intrinsics, mem}; /// By-value [`Range`] iterator. -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug, Clone)] pub struct RangeIter(legacy::Range); @@ -17,7 +17,6 @@ impl RangeIter { /// # Examples /// /// ``` - /// #![feature(new_range_api)] /// #![feature(new_range_remainder)] /// /// let range = core::range::Range::from(3..11); @@ -65,7 +64,7 @@ unsafe impl TrustedRandomAccessNoCoerce for RangeIter<$t> { u64 i64 } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] impl Iterator for RangeIter { type Item = A; @@ -133,7 +132,7 @@ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] impl DoubleEndedIterator for RangeIter { #[inline] fn next_back(&mut self) -> Option { @@ -154,10 +153,10 @@ fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for RangeIter {} -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] impl FusedIterator for RangeIter {} -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] impl IntoIterator for Range { type Item = A; type IntoIter = RangeIter; @@ -300,7 +299,7 @@ fn into_iter(self) -> Self::IntoIter { // since e.g. `(0..=u64::MAX).len()` would be `u64::MAX + 1`. macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] impl ExactSizeIterator for RangeIter<$t> { } )*) } diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index b30f82a5783a..f1727a1f629c 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -125,7 +125,7 @@ impl Sealed for ops::RangeToInclusive {} #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")] impl Sealed for (ops::Bound, ops::Bound) {} - #[unstable(feature = "new_range_api", issue = "125687")] + #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] impl Sealed for range::Range {} #[stable(feature = "new_range_inclusive_api", since = "1.95.0")] impl Sealed for range::RangeInclusive {} @@ -458,7 +458,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] unsafe impl const SliceIndex<[T]> for range::Range { type Output = [T]; diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 336f074883d2..da0039f055fd 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -258,7 +258,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output { } } -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_index", issue = "143775")] unsafe impl const SliceIndex for range::Range { type Output = str; diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index fba144c0e983..90a33aeead15 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -85,7 +85,6 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(min_specialization)] #![feature(never_type)] -#![feature(new_range_api)] #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] #![feature(nonzero_from_str_radix)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 7497fa100eb9..1730742dffe9 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -537,7 +537,7 @@ pub use core::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use core::ptr; -#[unstable(feature = "new_range_api", issue = "125687")] +#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")] pub use core::range; #[stable(feature = "rust1", since = "1.0.0")] pub use core::result; diff --git a/tests/ui/feature-gates/feature-gate-new_range.rs b/tests/ui/feature-gates/feature-gate-new_range.rs index 32eeb0424b64..6fd4f19fa8dc 100644 --- a/tests/ui/feature-gates/feature-gate-new_range.rs +++ b/tests/ui/feature-gates/feature-gate-new_range.rs @@ -1,5 +1,3 @@ -#![feature(new_range_api)] - fn main() { let a: core::range::RangeFrom = 1..; //~^ ERROR mismatched types diff --git a/tests/ui/feature-gates/feature-gate-new_range.stderr b/tests/ui/feature-gates/feature-gate-new_range.stderr index b7f70d30bfa0..c7f2d2171b10 100644 --- a/tests/ui/feature-gates/feature-gate-new_range.stderr +++ b/tests/ui/feature-gates/feature-gate-new_range.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/feature-gate-new_range.rs:4:41 + --> $DIR/feature-gate-new_range.rs:2:41 | LL | let a: core::range::RangeFrom = 1..; | -------------------------- ^^^ expected `RangeFrom`, found `RangeFrom<{integer}>` @@ -14,7 +14,7 @@ LL | let a: core::range::RangeFrom = (1..).into(); | + ++++++++ error[E0308]: mismatched types - --> $DIR/feature-gate-new_range.rs:6:37 + --> $DIR/feature-gate-new_range.rs:4:37 | LL | let b: core::range::Range = 2..3; | ---------------------- ^^^^ expected `Range`, found `Range<{integer}>` @@ -29,7 +29,7 @@ LL | let b: core::range::Range = (2..3).into(); | + ++++++++ error[E0308]: mismatched types - --> $DIR/feature-gate-new_range.rs:8:46 + --> $DIR/feature-gate-new_range.rs:6:46 | LL | let c: core::range::RangeInclusive = 4..=5; | ------------------------------- ^^^^^ expected `RangeInclusive`, found `RangeInclusive<{integer}>` diff --git a/tests/ui/new-range/disabled.rs b/tests/ui/new-range/disabled.rs index ab6fbd3276b3..528c464117a1 100644 --- a/tests/ui/new-range/disabled.rs +++ b/tests/ui/new-range/disabled.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(new_range_api)] +#![feature(new_range_api_legacy)] fn main() { // Unchanged diff --git a/tests/ui/new-range/enabled.rs b/tests/ui/new-range/enabled.rs index b49681eaacde..6d9a1259b775 100644 --- a/tests/ui/new-range/enabled.rs +++ b/tests/ui/new-range/enabled.rs @@ -1,6 +1,5 @@ //@ check-pass -#![feature(new_range_api)] #![feature(new_range)] fn main() { diff --git a/tests/ui/range/new_range_stability.rs b/tests/ui/range/new_range_stability.rs index 71a0f02e5896..965be17efa74 100644 --- a/tests/ui/range/new_range_stability.rs +++ b/tests/ui/range/new_range_stability.rs @@ -6,6 +6,7 @@ RangeToInclusive, RangeFrom, RangeFromIter, + Range, }; fn range_inclusive(mut r: RangeInclusive) { @@ -43,13 +44,24 @@ fn range_from(mut r: RangeFrom) { i.remainder(); //~ ERROR unstable } +fn range(mut r: Range) { + &[1, 2, 3][r]; + + r.start; + r.end; + r.contains(&5); + r.is_empty(); + r.iter(); + + let mut i = r.into_iter(); + i.next(); + + // Left unstable + i.remainder(); //~ ERROR unstable +} + // Unstable module use std::range::legacy; //~ ERROR unstable -// Unstable types - -use std::range::Range; //~ ERROR unstable -use std::range::RangeIter; //~ ERROR unstable - fn main() {} diff --git a/tests/ui/range/new_range_stability.stderr b/tests/ui/range/new_range_stability.stderr index 64ef6a416687..ac269a2b2227 100644 --- a/tests/ui/range/new_range_stability.stderr +++ b/tests/ui/range/new_range_stability.stderr @@ -1,35 +1,15 @@ -error[E0658]: use of unstable library feature `new_range_api` - --> $DIR/new_range_stability.rs:48:5 +error[E0658]: use of unstable library feature `new_range_api_legacy` + --> $DIR/new_range_stability.rs:65:5 | LL | use std::range::legacy; | ^^^^^^^^^^^^^^^^^^ | = note: see issue #125687 for more information - = help: add `#![feature(new_range_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature `new_range_api` - --> $DIR/new_range_stability.rs:52:5 - | -LL | use std::range::Range; - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #125687 for more information - = help: add `#![feature(new_range_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature `new_range_api` - --> $DIR/new_range_stability.rs:53:5 - | -LL | use std::range::RangeIter; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #125687 for more information - = help: add `#![feature(new_range_api)]` to the crate attributes to enable + = help: add `#![feature(new_range_api_legacy)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `new_range_remainder` - --> $DIR/new_range_stability.rs:22:7 + --> $DIR/new_range_stability.rs:23:7 | LL | i.remainder(); | ^^^^^^^^^ @@ -39,7 +19,7 @@ LL | i.remainder(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `new_range_remainder` - --> $DIR/new_range_stability.rs:43:7 + --> $DIR/new_range_stability.rs:44:7 | LL | i.remainder(); | ^^^^^^^^^ @@ -48,6 +28,16 @@ LL | i.remainder(); = help: add `#![feature(new_range_remainder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 5 previous errors +error[E0658]: use of unstable library feature `new_range_remainder` + --> $DIR/new_range_stability.rs:60:7 + | +LL | i.remainder(); + | ^^^^^^^^^ + | + = note: see issue #154458 for more information + = help: add `#![feature(new_range_remainder)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`.