Skip to content

Commit 085dff4

Browse files
committed
stabilize new RangeFrom type and iterator
stabilizes `core::range::RangeFrom` stabilizes `core::range::RangeFromIter` add examples for `remainder` method on range iterators `RangeFromIter::remainder` was not stabilized (see issue 154458)
1 parent 6f22f61 commit 085dff4

File tree

12 files changed

+90
-59
lines changed

12 files changed

+90
-59
lines changed

library/core/src/ffi/c_str.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
716716
}
717717
}
718718

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

library/core/src/range.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ mod iter;
2424
#[unstable(feature = "new_range_api", issue = "125687")]
2525
pub mod legacy;
2626

27+
#[doc(inline)]
28+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
29+
pub use iter::RangeFromIter;
2730
#[doc(inline)]
2831
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
2932
pub use iter::RangeInclusiveIter;
3033
#[doc(inline)]
3134
#[unstable(feature = "new_range_api", issue = "125687")]
32-
pub use iter::{RangeFromIter, RangeIter};
35+
pub use iter::RangeIter;
3336

3437
// FIXME(#125687): re-exports temporarily removed
3538
// Because re-exports of stable items (Bound, RangeBounds, RangeFull, RangeTo)
@@ -416,14 +419,13 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
416419
///
417420
/// The `RangeFrom` `start..` contains all values with `x >= start`.
418421
///
419-
/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
422+
/// *Note*: Overflow in the [`IntoIterator`] implementation (when the contained
420423
/// data type reaches its numerical limit) is allowed to panic, wrap, or
421424
/// saturate. This behavior is defined by the implementation of the [`Step`]
422425
/// trait. For primitive integers, this follows the normal rules, and respects
423-
/// the overflow checks profile (panic in debug, wrap in release). Note also
424-
/// that overflow happens earlier than you might assume: the overflow happens
425-
/// in the call to `next` that yields the maximum value, as the range must be
426-
/// set to a state to yield the next value.
426+
/// the overflow checks profile (panic in debug, wrap in release). Unlike
427+
/// its legacy counterpart, the iterator will only panic after yielding the
428+
/// maximum value when overflow checks are enabled.
427429
///
428430
/// [`Step`]: crate::iter::Step
429431
///
@@ -432,7 +434,6 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
432434
/// The `start..` syntax is a `RangeFrom`:
433435
///
434436
/// ```
435-
/// #![feature(new_range_api)]
436437
/// use core::range::RangeFrom;
437438
///
438439
/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
@@ -441,14 +442,14 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
441442
#[lang = "RangeFromCopy"]
442443
#[derive(Copy, Hash)]
443444
#[derive_const(Clone, PartialEq, Eq)]
444-
#[unstable(feature = "new_range_api", issue = "125687")]
445+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
445446
pub struct RangeFrom<Idx> {
446447
/// The lower bound of the range (inclusive).
447-
#[unstable(feature = "new_range_api", issue = "125687")]
448+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
448449
pub start: Idx,
449450
}
450451

451-
#[unstable(feature = "new_range_api", issue = "125687")]
452+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
452453
impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
453454
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
454455
self.start.fmt(fmt)?;
@@ -465,15 +466,14 @@ impl<Idx: Step> RangeFrom<Idx> {
465466
/// # Examples
466467
///
467468
/// ```
468-
/// #![feature(new_range_api)]
469469
/// use core::range::RangeFrom;
470470
///
471471
/// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
472472
/// assert_eq!(i.next(), Some(9));
473473
/// assert_eq!(i.next(), Some(16));
474474
/// assert_eq!(i.next(), Some(25));
475475
/// ```
476-
#[unstable(feature = "new_range_api", issue = "125687")]
476+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
477477
#[inline]
478478
pub fn iter(&self) -> RangeFromIter<Idx> {
479479
self.clone().into_iter()
@@ -486,7 +486,6 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
486486
/// # Examples
487487
///
488488
/// ```
489-
/// #![feature(new_range_api)]
490489
/// use core::range::RangeFrom;
491490
///
492491
/// assert!(!RangeFrom::from(3..).contains(&2));
@@ -498,7 +497,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
498497
/// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
499498
/// ```
500499
#[inline]
501-
#[unstable(feature = "new_range_api", issue = "125687")]
500+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
502501
#[rustc_const_unstable(feature = "const_range", issue = "none")]
503502
pub const fn contains<U>(&self, item: &U) -> bool
504503
where
@@ -509,7 +508,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
509508
}
510509
}
511510

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

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

549547
#[unstable(feature = "one_sided_range", issue = "69780")]
550-
// #[unstable(feature = "new_range_api", issue = "125687")]
551548
#[rustc_const_unstable(feature = "const_range", issue = "none")]
552549
impl<T> const OneSidedRange<T> for RangeFrom<T>
553550
where
@@ -558,15 +555,15 @@ where
558555
}
559556
}
560557

561-
#[unstable(feature = "new_range_api", issue = "125687")]
558+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
562559
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
563560
impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
564561
#[inline]
565562
fn from(value: RangeFrom<T>) -> Self {
566563
Self { start: value.start }
567564
}
568565
}
569-
#[unstable(feature = "new_range_api", issue = "125687")]
566+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
570567
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
571568
impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
572569
#[inline]
@@ -697,7 +694,6 @@ impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
697694
}
698695
}
699696

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

709-
// #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
710705
#[unstable(feature = "one_sided_range", issue = "69780")]
711706
#[rustc_const_unstable(feature = "const_range", issue = "none")]
712707
impl<T> const OneSidedRange<T> for RangeToInclusive<T>

library/core/src/range/iter.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@ pub struct RangeIter<A>(legacy::Range<A>);
1313
impl<A> RangeIter<A> {
1414
#[unstable(feature = "new_range_api", issue = "125687")]
1515
/// Returns the remainder of the range being iterated over.
16+
///
17+
/// # Examples
18+
/// ```
19+
/// #![feature(new_range_api)]
20+
/// let range = core::range::Range::from(3..11);
21+
/// let mut iter = range.into_iter();
22+
/// assert_eq!(iter.clone().remainder(), range);
23+
/// iter.next();
24+
/// assert_eq!(iter.clone().remainder(), core::range::Range::from(4..11));
25+
/// iter.by_ref().for_each(drop);
26+
/// assert!(iter.remainder().is_empty());
27+
/// ```
1628
pub fn remainder(self) -> Range<A> {
1729
Range { start: self.0.start, end: self.0.end }
1830
}
@@ -161,6 +173,17 @@ impl<A: Step> RangeInclusiveIter<A> {
161173
/// Returns the remainder of the range being iterated over.
162174
///
163175
/// If the iterator is exhausted or empty, returns `None`.
176+
///
177+
/// # Examples
178+
/// ```
179+
/// let range = core::range::RangeInclusive::from(3..=11);
180+
/// let mut iter = range.into_iter();
181+
/// assert_eq!(iter.clone().remainder().unwrap(), range);
182+
/// iter.next();
183+
/// assert_eq!(iter.clone().remainder().unwrap(), core::range::RangeInclusive::from(4..=11));
184+
/// iter.by_ref().for_each(drop);
185+
/// assert!(iter.remainder().is_none());
186+
/// ```
164187
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
165188
pub fn remainder(self) -> Option<RangeInclusive<A>> {
166189
if self.0.is_empty() {
@@ -294,7 +317,7 @@ range_incl_exact_iter_impl! {
294317
}
295318

296319
/// By-value [`RangeFrom`] iterator.
297-
#[unstable(feature = "new_range_api", issue = "125687")]
320+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
298321
#[derive(Debug, Clone)]
299322
pub struct RangeFromIter<A> {
300323
start: A,
@@ -305,6 +328,16 @@ pub struct RangeFromIter<A> {
305328

306329
impl<A: Step> RangeFromIter<A> {
307330
/// Returns the remainder of the range being iterated over.
331+
///
332+
/// # Examples
333+
/// ```
334+
/// #![feature(new_range_api)]
335+
/// let range = core::range::RangeFrom::from(3..);
336+
/// let mut iter = range.into_iter();
337+
/// assert_eq!(iter.clone().remainder(), range);
338+
/// iter.next();
339+
/// assert_eq!(iter.remainder(), core::range::RangeFrom::from(4..));
340+
/// ```
308341
#[inline]
309342
#[rustc_inherit_overflow_checks]
310343
#[unstable(feature = "new_range_api", issue = "125687")]
@@ -321,7 +354,7 @@ impl<A: Step> RangeFromIter<A> {
321354
}
322355
}
323356

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

@@ -392,10 +425,10 @@ impl<A: Step> Iterator for RangeFromIter<A> {
392425
#[unstable(feature = "trusted_len", issue = "37572")]
393426
unsafe impl<A: TrustedStep> TrustedLen for RangeFromIter<A> {}
394427

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

398-
#[unstable(feature = "new_range_api", issue = "125687")]
431+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
399432
impl<A: Step> IntoIterator for RangeFrom<A> {
400433
type Item = A;
401434
type IntoIter = RangeFromIter<A>;

library/core/src/slice/index.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ mod private_slice_index {
131131
impl Sealed for range::RangeInclusive<usize> {}
132132
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
133133
impl Sealed for range::RangeToInclusive<usize> {}
134-
#[unstable(feature = "new_range_api", issue = "125687")]
134+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
135135
impl Sealed for range::RangeFrom<usize> {}
136136

137137
impl Sealed for ops::IndexRange {}
@@ -588,7 +588,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
588588
}
589589
}
590590

591-
#[unstable(feature = "new_range_api", issue = "125687")]
591+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
592592
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
593593
unsafe impl<T> const SliceIndex<[T]> for range::RangeFrom<usize> {
594594
type Output = [T];

library/core/src/str/traits.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ unsafe impl const SliceIndex<str> for ops::RangeFrom<usize> {
555555
}
556556
}
557557

558-
#[unstable(feature = "new_range_api", issue = "125687")]
558+
#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
559559
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
560560
unsafe impl const SliceIndex<str> for range::RangeFrom<usize> {
561561
type Output = str;

tests/codegen-llvm/fromrangeiter-overflow-checks.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#![crate_type = "lib"]
1313
#![feature(new_range_api)]
14+
1415
use std::range::RangeFrom;
1516

1617
// CHECK-LABEL: @rangefrom_increments(

tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocno.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//@ compile-flags: -C overflow-checks=no
22

33
#![crate_type = "lib"]
4-
#![feature(new_range_api)]
54

65
use std::range::RangeFromIter;
76

tests/ui/iterators/auxiliary/rangefrom-overflow-2crates-ocyes.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//@ compile-flags: -C overflow-checks=yes
22

33
#![crate_type = "lib"]
4-
#![feature(new_range_api)]
54

65
use std::range::RangeFromIter;
76

tests/ui/iterators/fromrangeiter.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//@ run-pass
22
//@ compile-flags: -C overflow-checks=yes
33

4-
#![feature(new_range_api)]
5-
64
use std::{iter, range};
75

86
fn main() {

tests/ui/iterators/rangefrom-overflow-2crates.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
// Test that two crates with different overflow-checks have the same results,
88
// even when the iterator is passed between them.
99

10-
#![feature(new_range_api)]
11-
1210
extern crate rangefrom_overflow_2crates_ocno;
1311
extern crate rangefrom_overflow_2crates_ocyes;
1412

0 commit comments

Comments
 (0)