mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #152304 - pitaj:stabilize-new_range_api, r=tgross35
stabilize new RangeToInclusive type
stabilizes `core::range::RangeToInclusive`
```rust
// in core::range
pub struct RangeToInclusive<Idx> {
pub last: Idx,
}
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> { /* ... */ }
impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
pub const fn contains<U>(&self, item: &U) -> bool
where
Idx: [const] PartialOrd<U>,
U: ?Sized + [const] PartialOrd<Idx>;
}
impl<T> const RangeBounds<T> for RangeToInclusive<T> { /* ... */ }
impl<T> const RangeBounds<T> for RangeToInclusive<&T> { /* ... */ }
impl<T> const From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> { /* ... */ }
impl<T> const From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> { /* ... */ }
unsafe impl<T> const SliceIndex<[T]> for range::RangeToInclusive<usize> {
type Output = [T];
/* ... */
}
unsafe impl const SliceIndex<str> for range::RangeToInclusive<usize> {
type Output = str;
/* ... */
}
```
Tracking issue: https://github.com/rust-lang/rust/issues/125687
This commit is contained in:
@@ -268,4 +268,5 @@ fn index_mut(self, slice: &mut ByteStr) -> &mut Self::Output {
|
||||
impl_slice_index!(ops::RangeInclusive<usize>);
|
||||
impl_slice_index!(range::RangeInclusive<usize>);
|
||||
impl_slice_index!(ops::RangeToInclusive<usize>);
|
||||
impl_slice_index!(range::RangeToInclusive<usize>);
|
||||
impl_slice_index!((ops::Bound<usize>, ops::Bound<usize>));
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
use crate::marker::PhantomData;
|
||||
use crate::ptr::NonNull;
|
||||
use crate::slice::memchr;
|
||||
use crate::{fmt, ops, slice, str};
|
||||
use crate::{fmt, ops, range, slice, str};
|
||||
|
||||
// FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link
|
||||
// depends on where the item is being documented. however, since this is libcore, we can't
|
||||
@@ -716,6 +716,16 @@ fn index(&self, index: ops::RangeFrom<usize>) -> &CStr {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
impl ops::Index<range::RangeFrom<usize>> for CStr {
|
||||
type Output = CStr;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: range::RangeFrom<usize>) -> &CStr {
|
||||
ops::Index::index(self, ops::RangeFrom::from(index))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "cstring_asref", since = "1.7.0")]
|
||||
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
|
||||
impl const AsRef<CStr> for CStr {
|
||||
|
||||
+45
-10
@@ -43,7 +43,7 @@
|
||||
// pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo};
|
||||
use crate::iter::Step;
|
||||
use crate::ops::Bound::{self, Excluded, Included, Unbounded};
|
||||
use crate::ops::{IntoBounds, RangeBounds};
|
||||
use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds};
|
||||
|
||||
/// A (half-open) range bounded inclusively below and exclusively above
|
||||
/// (`start..end` in a future edition).
|
||||
@@ -546,6 +546,18 @@ fn into_bounds(self) -> (Bound<T>, Bound<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
|
||||
Self: RangeBounds<T>,
|
||||
{
|
||||
fn bound(self) -> (OneSidedRangeBound, T) {
|
||||
(OneSidedRangeBound::StartInclusive, self.start)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
|
||||
impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
|
||||
@@ -573,9 +585,8 @@ fn from(value: legacy::RangeFrom<T>) -> Self {
|
||||
/// The `..=last` syntax is a `RangeToInclusive`:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(new_range_api)]
|
||||
/// #![feature(new_range)]
|
||||
/// assert_eq!((..=5), std::range::RangeToInclusive{ last: 5 });
|
||||
/// assert_eq!((..=5), std::range::RangeToInclusive { last: 5 });
|
||||
/// ```
|
||||
///
|
||||
/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
|
||||
@@ -606,14 +617,14 @@ fn from(value: legacy::RangeFrom<T>) -> Self {
|
||||
#[lang = "RangeToInclusiveCopy"]
|
||||
#[doc(alias = "..=")]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub struct RangeToInclusive<Idx> {
|
||||
/// The upper bound of the range (inclusive)
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub last: Idx,
|
||||
}
|
||||
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "..=")?;
|
||||
@@ -637,7 +648,7 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
|
||||
/// assert!(!(..=f32::NAN).contains(&0.5));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_unstable(feature = "const_range", issue = "none")]
|
||||
pub const fn contains<U>(&self, item: &U) -> bool
|
||||
where
|
||||
@@ -648,13 +659,13 @@ pub const fn contains<U>(&self, item: &U) -> bool
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
|
||||
fn from(value: legacy::RangeToInclusive<T>) -> Self {
|
||||
Self { last: value.end }
|
||||
}
|
||||
}
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
|
||||
fn from(value: RangeToInclusive<T>) -> Self {
|
||||
Self { end: value.last }
|
||||
@@ -664,7 +675,7 @@ fn from(value: RangeToInclusive<T>) -> Self {
|
||||
// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
|
||||
// because underflow would be possible with (..0).into()
|
||||
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_unstable(feature = "const_range", issue = "none")]
|
||||
impl<T> const RangeBounds<T> for RangeToInclusive<T> {
|
||||
fn start_bound(&self) -> Bound<&T> {
|
||||
@@ -675,6 +686,18 @@ fn end_bound(&self) -> Bound<&T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_unstable(feature = "const_range", issue = "none")]
|
||||
impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
|
||||
fn start_bound(&self) -> Bound<&T> {
|
||||
Unbounded
|
||||
}
|
||||
fn end_bound(&self) -> Bound<&T> {
|
||||
Included(self.last)
|
||||
}
|
||||
}
|
||||
|
||||
// #[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> {
|
||||
@@ -682,3 +705,15 @@ fn into_bounds(self) -> (Bound<T>, Bound<T>) {
|
||||
(Unbounded, Included(self.last))
|
||||
}
|
||||
}
|
||||
|
||||
// #[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>
|
||||
where
|
||||
Self: RangeBounds<T>,
|
||||
{
|
||||
fn bound(self) -> (OneSidedRangeBound, T) {
|
||||
(OneSidedRangeBound::EndInclusive, self.last)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
|
||||
impl Sealed for range::Range<usize> {}
|
||||
#[stable(feature = "new_range_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Sealed for range::RangeInclusive<usize> {}
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Sealed for range::RangeToInclusive<usize> {}
|
||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||
impl Sealed for range::RangeFrom<usize> {}
|
||||
@@ -801,7 +801,7 @@ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
||||
}
|
||||
|
||||
/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
|
||||
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
|
||||
unsafe impl<T> const SliceIndex<[T]> for range::RangeToInclusive<usize> {
|
||||
type Output = [T];
|
||||
|
||||
@@ -763,6 +763,52 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements substring slicing with syntax `&self[..= last]` or `&mut
|
||||
/// self[..= last]`.
|
||||
///
|
||||
/// Returns a slice of the given string from the byte range \[0, `last`\].
|
||||
/// Equivalent to `&self [0 .. last + 1]`, except if `last` has the maximum
|
||||
/// value for `usize`.
|
||||
///
|
||||
/// This operation is *O*(1).
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `last` does not point to the ending byte offset of a character
|
||||
/// (`last + 1` is either a starting byte offset as defined by
|
||||
/// `is_char_boundary`, or equal to `len`), or if `last >= len`.
|
||||
#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
|
||||
unsafe impl const SliceIndex<str> for range::RangeToInclusive<usize> {
|
||||
type Output = str;
|
||||
#[inline]
|
||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||
(0..=self.last).get(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||
(0..=self.last).get_mut(slice)
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
|
||||
// SAFETY: the caller must uphold the safety contract for `get_unchecked`.
|
||||
unsafe { (0..=self.last).get_unchecked(slice) }
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn get_unchecked_mut(self, slice: *mut str) -> *mut Self::Output {
|
||||
// SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`.
|
||||
unsafe { (0..=self.last).get_unchecked_mut(slice) }
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
(0..=self.last).index(slice)
|
||||
}
|
||||
#[inline]
|
||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||
(0..=self.last).index_mut(slice)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a value from a string
|
||||
///
|
||||
/// `FromStr`'s [`from_str`] method is often used implicitly, through
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// Stable
|
||||
|
||||
use std::range::{RangeInclusive, RangeInclusiveIter};
|
||||
use std::range::{RangeInclusive, RangeInclusiveIter, RangeToInclusive};
|
||||
|
||||
fn range_inclusive(mut r: RangeInclusive<usize>) {
|
||||
&[1, 2, 3][r]; // Indexing
|
||||
|
||||
r.start;
|
||||
r.last;
|
||||
r.contains(&5);
|
||||
@@ -14,6 +16,13 @@ fn range_inclusive(mut r: RangeInclusive<usize>) {
|
||||
i.remainder();
|
||||
}
|
||||
|
||||
fn range_to_inclusive(mut r: RangeToInclusive<usize>) {
|
||||
&[1, 2, 3][r]; // Indexing
|
||||
|
||||
r.last;
|
||||
r.contains(&5);
|
||||
}
|
||||
|
||||
// Unstable module
|
||||
|
||||
use std::range::legacy; //~ ERROR unstable
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
error[E0658]: use of unstable library feature `new_range_api`
|
||||
--> $DIR/new_range_stability.rs:19:5
|
||||
--> $DIR/new_range_stability.rs:28:5
|
||||
|
|
||||
LL | use std::range::legacy;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
@@ -9,7 +9,7 @@ LL | use std::range::legacy;
|
||||
= 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:23:5
|
||||
--> $DIR/new_range_stability.rs:32:5
|
||||
|
|
||||
LL | use std::range::RangeFrom;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -19,7 +19,7 @@ LL | use std::range::RangeFrom;
|
||||
= 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:24:5
|
||||
--> $DIR/new_range_stability.rs:33:5
|
||||
|
|
||||
LL | use std::range::Range;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@@ -29,7 +29,7 @@ LL | use std::range::Range;
|
||||
= 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:25:5
|
||||
--> $DIR/new_range_stability.rs:34:5
|
||||
|
|
||||
LL | use std::range::RangeFromIter;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -39,7 +39,7 @@ LL | use std::range::RangeFromIter;
|
||||
= 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:26:5
|
||||
--> $DIR/new_range_stability.rs:35:5
|
||||
|
|
||||
LL | use std::range::RangeIter;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Reference in New Issue
Block a user