Rollup merge of #144765 - Qelxiros:range-inclusive-last, r=jhpratt
inclusive `Range`s: change `end` to `last` Tracking issue: rust-lang/rust#125687 ACP: rust-lang/libs-team#511
This commit is contained in:
@@ -1536,7 +1536,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
hir::LangItem::Range
|
hir::LangItem::Range
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
|
(None, Some(..), Closed) => {
|
||||||
|
if self.tcx.features().new_range() {
|
||||||
|
hir::LangItem::RangeToInclusiveCopy
|
||||||
|
} else {
|
||||||
|
hir::LangItem::RangeToInclusive
|
||||||
|
}
|
||||||
|
}
|
||||||
(Some(e1), Some(e2), Closed) => {
|
(Some(e1), Some(e2), Closed) => {
|
||||||
if self.tcx.features().new_range() {
|
if self.tcx.features().new_range() {
|
||||||
hir::LangItem::RangeInclusiveCopy
|
hir::LangItem::RangeInclusiveCopy
|
||||||
@@ -1560,13 +1566,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let fields = self.arena.alloc_from_iter(
|
let fields = self.arena.alloc_from_iter(
|
||||||
e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
|
e1.iter()
|
||||||
|(s, e)| {
|
.map(|e| (sym::start, e))
|
||||||
|
.chain(e2.iter().map(|e| {
|
||||||
|
(
|
||||||
|
if matches!(
|
||||||
|
lang_item,
|
||||||
|
hir::LangItem::RangeInclusiveCopy | hir::LangItem::RangeToInclusiveCopy
|
||||||
|
) {
|
||||||
|
sym::last
|
||||||
|
} else {
|
||||||
|
sym::end
|
||||||
|
},
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
.map(|(s, e)| {
|
||||||
let expr = self.lower_expr(e);
|
let expr = self.lower_expr(e);
|
||||||
let ident = Ident::new(s, self.lower_span(e.span));
|
let ident = Ident::new(s, self.lower_span(e.span));
|
||||||
self.expr_field(ident, expr, e.span)
|
self.expr_field(ident, expr, e.span)
|
||||||
},
|
}),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
hir::ExprKind::Struct(
|
hir::ExprKind::Struct(
|
||||||
|
|||||||
@@ -2614,6 +2614,18 @@ impl Expr<'_> {
|
|||||||
StructTailExpr::None,
|
StructTailExpr::None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
| (
|
||||||
|
ExprKind::Struct(
|
||||||
|
QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
|
||||||
|
[val1],
|
||||||
|
StructTailExpr::None,
|
||||||
|
),
|
||||||
|
ExprKind::Struct(
|
||||||
|
QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
|
||||||
|
[val2],
|
||||||
|
StructTailExpr::None,
|
||||||
|
),
|
||||||
|
)
|
||||||
| (
|
| (
|
||||||
ExprKind::Struct(
|
ExprKind::Struct(
|
||||||
QPath::LangItem(LangItem::RangeFrom, _),
|
QPath::LangItem(LangItem::RangeFrom, _),
|
||||||
@@ -2705,7 +2717,8 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
|
|||||||
| LangItem::RangeToInclusive
|
| LangItem::RangeToInclusive
|
||||||
| LangItem::RangeCopy
|
| LangItem::RangeCopy
|
||||||
| LangItem::RangeFromCopy
|
| LangItem::RangeFromCopy
|
||||||
| LangItem::RangeInclusiveCopy,
|
| LangItem::RangeInclusiveCopy
|
||||||
|
| LangItem::RangeToInclusiveCopy,
|
||||||
..
|
..
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ language_item_table! {
|
|||||||
RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
|
RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None;
|
RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None;
|
||||||
RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
|
RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
|
||||||
|
RangeToInclusiveCopy, sym::RangeToInclusiveCopy, range_to_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
|
||||||
|
|
||||||
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
||||||
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
||||||
|
|||||||
@@ -130,7 +130,22 @@ impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeFrom<I> {
|
|||||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
|
||||||
type Output = core::range::RangeInclusive<usize>;
|
type Output = core::range::RangeInclusive<usize>;
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[cfg(bootstrap)]
|
||||||
fn into_slice_idx(self) -> Self::Output {
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
|
core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
core::range::RangeInclusive { start: self.start.index(), last: self.last.index() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "nightly", not(bootstrap)))]
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeToInclusive<I> {
|
||||||
|
type Output = core::range::RangeToInclusive<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
core::range::RangeToInclusive { last: self.last.index() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,6 +326,7 @@ symbols! {
|
|||||||
RangeSub,
|
RangeSub,
|
||||||
RangeTo,
|
RangeTo,
|
||||||
RangeToInclusive,
|
RangeToInclusive,
|
||||||
|
RangeToInclusiveCopy,
|
||||||
Rc,
|
Rc,
|
||||||
RcWeak,
|
RcWeak,
|
||||||
Ready,
|
Ready,
|
||||||
@@ -1280,6 +1281,7 @@ symbols! {
|
|||||||
lang,
|
lang,
|
||||||
lang_items,
|
lang_items,
|
||||||
large_assignments,
|
large_assignments,
|
||||||
|
last,
|
||||||
lateout,
|
lateout,
|
||||||
lazy_normalization_consts,
|
lazy_normalization_consts,
|
||||||
lazy_type_alias,
|
lazy_type_alias,
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
|
|||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::iter::Step;
|
pub use crate::iter::Step;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::ops::{
|
pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo};
|
||||||
Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A (half-open) range bounded inclusively below and exclusively above
|
/// A (half-open) range bounded inclusively below and exclusively above
|
||||||
/// (`start..end` in a future edition).
|
/// (`start..end` in a future edition).
|
||||||
@@ -209,20 +207,20 @@ impl<T> const From<legacy::Range<T>> for Range<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A range bounded inclusively below and above (`start..=end`).
|
/// A range bounded inclusively below and above (`start..=last`).
|
||||||
///
|
///
|
||||||
/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
|
/// The `RangeInclusive` `start..=last` contains all values with `x >= start`
|
||||||
/// and `x <= end`. It is empty unless `start <= end`.
|
/// and `x <= last`. It is empty unless `start <= last`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// The `start..=end` syntax is a `RangeInclusive`:
|
/// The `start..=last` syntax is a `RangeInclusive`:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(new_range_api)]
|
/// #![feature(new_range_api)]
|
||||||
/// use core::range::RangeInclusive;
|
/// use core::range::RangeInclusive;
|
||||||
///
|
///
|
||||||
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
|
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
|
||||||
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
|
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
|
||||||
/// ```
|
/// ```
|
||||||
#[lang = "RangeInclusiveCopy"]
|
#[lang = "RangeInclusiveCopy"]
|
||||||
@@ -234,7 +232,7 @@ pub struct RangeInclusive<Idx> {
|
|||||||
pub start: Idx,
|
pub start: Idx,
|
||||||
/// The upper bound of the range (inclusive).
|
/// The upper bound of the range (inclusive).
|
||||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
pub end: Idx,
|
pub last: Idx,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
@@ -242,7 +240,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
|
|||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
self.start.fmt(fmt)?;
|
self.start.fmt(fmt)?;
|
||||||
write!(fmt, "..=")?;
|
write!(fmt, "..=")?;
|
||||||
self.end.fmt(fmt)?;
|
self.last.fmt(fmt)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,7 +304,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
|
|||||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
!(self.start <= self.end)
|
!(self.start <= self.last)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,10 +333,10 @@ impl<Idx: Step> RangeInclusive<Idx> {
|
|||||||
|
|
||||||
impl RangeInclusive<usize> {
|
impl RangeInclusive<usize> {
|
||||||
/// Converts to an exclusive `Range` for `SliceIndex` implementations.
|
/// Converts to an exclusive `Range` for `SliceIndex` implementations.
|
||||||
/// The caller is responsible for dealing with `end == usize::MAX`.
|
/// The caller is responsible for dealing with `last == usize::MAX`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) const fn into_slice_range(self) -> Range<usize> {
|
pub(crate) const fn into_slice_range(self) -> Range<usize> {
|
||||||
Range { start: self.start, end: self.end + 1 }
|
Range { start: self.start, end: self.last + 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +346,7 @@ impl<T> RangeBounds<T> for RangeInclusive<T> {
|
|||||||
Included(&self.start)
|
Included(&self.start)
|
||||||
}
|
}
|
||||||
fn end_bound(&self) -> Bound<&T> {
|
fn end_bound(&self) -> Bound<&T> {
|
||||||
Included(&self.end)
|
Included(&self.last)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +362,7 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
|
|||||||
Included(self.start)
|
Included(self.start)
|
||||||
}
|
}
|
||||||
fn end_bound(&self) -> Bound<&T> {
|
fn end_bound(&self) -> Bound<&T> {
|
||||||
Included(self.end)
|
Included(self.last)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +370,7 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
|
|||||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
impl<T> IntoBounds<T> for RangeInclusive<T> {
|
impl<T> IntoBounds<T> for RangeInclusive<T> {
|
||||||
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
|
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
|
||||||
(Included(self.start), Included(self.end))
|
(Included(self.start), Included(self.last))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +379,7 @@ impl<T> IntoBounds<T> for RangeInclusive<T> {
|
|||||||
impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
|
impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(value: RangeInclusive<T>) -> Self {
|
fn from(value: RangeInclusive<T>) -> Self {
|
||||||
Self::new(value.start, value.end)
|
Self::new(value.start, value.last)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
@@ -394,8 +392,8 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
|
|||||||
"attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
|
"attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
|
||||||
);
|
);
|
||||||
|
|
||||||
let (start, end) = value.into_inner();
|
let (start, last) = value.into_inner();
|
||||||
RangeInclusive { start, end }
|
RangeInclusive { start, last }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,3 +542,107 @@ impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
|
|||||||
Self { start: value.start }
|
Self { start: value.start }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A range only bounded inclusively above (`..=last`).
|
||||||
|
///
|
||||||
|
/// The `RangeToInclusive` `..=last` contains all values with `x <= last`.
|
||||||
|
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// The `..=last` syntax is a `RangeToInclusive`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(new_range_api)]
|
||||||
|
/// #![feature(new_range)]
|
||||||
|
/// assert_eq!((..=5), std::range::RangeToInclusive{ last: 5 });
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
|
||||||
|
/// `for` loop directly. This won't compile:
|
||||||
|
///
|
||||||
|
/// ```compile_fail,E0277
|
||||||
|
/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
|
||||||
|
/// // std::iter::Iterator` is not satisfied
|
||||||
|
/// for i in ..=5 {
|
||||||
|
/// // ...
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
|
||||||
|
/// array elements up to and including the index indicated by `last`.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// 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 ]); // This is a `RangeToInclusive`
|
||||||
|
/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
|
||||||
|
/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
|
||||||
|
/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [slicing index]: crate::slice::SliceIndex
|
||||||
|
#[lang = "RangeToInclusiveCopy"]
|
||||||
|
#[doc(alias = "..=")]
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
|
pub struct RangeToInclusive<Idx> {
|
||||||
|
/// The upper bound of the range (inclusive)
|
||||||
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
|
pub last: Idx,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
|
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(fmt, "..=")?;
|
||||||
|
self.last.fmt(fmt)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
|
||||||
|
/// Returns `true` if `item` is contained in the range.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// assert!( (..=5).contains(&-1_000_000_000));
|
||||||
|
/// assert!( (..=5).contains(&5));
|
||||||
|
/// assert!(!(..=5).contains(&6));
|
||||||
|
///
|
||||||
|
/// assert!( (..=1.0).contains(&1.0));
|
||||||
|
/// assert!(!(..=1.0).contains(&f32::NAN));
|
||||||
|
/// assert!(!(..=f32::NAN).contains(&0.5));
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
|
pub fn contains<U>(&self, item: &U) -> bool
|
||||||
|
where
|
||||||
|
Idx: PartialOrd<U>,
|
||||||
|
U: ?Sized + PartialOrd<Idx>,
|
||||||
|
{
|
||||||
|
<Self as RangeBounds<Idx>>::contains(self, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
|
||||||
|
// because underflow would be possible with (..0).into()
|
||||||
|
|
||||||
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
|
impl<T> RangeBounds<T> for RangeToInclusive<T> {
|
||||||
|
fn start_bound(&self) -> Bound<&T> {
|
||||||
|
Unbounded
|
||||||
|
}
|
||||||
|
fn end_bound(&self) -> Bound<&T> {
|
||||||
|
Included(&self.last)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "range_into_bounds", issue = "136903")]
|
||||||
|
impl<T> IntoBounds<T> for RangeToInclusive<T> {
|
||||||
|
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
|
||||||
|
(Unbounded, Included(self.last))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ impl<A: Step> IterRangeInclusive<A> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(RangeInclusive { start: self.0.start, end: self.0.end })
|
Some(RangeInclusive { start: self.0.start, last: self.0.end })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
//! # Legacy range types
|
//! # Legacy range types
|
||||||
//!
|
//!
|
||||||
//! The types within this module will be replaced by the types
|
//! The types within this module will be replaced by the types
|
||||||
//! [`Range`], [`RangeInclusive`], and [`RangeFrom`] in the parent
|
//! [`Range`], [`RangeInclusive`], [`RangeToInclusive`], and [`RangeFrom`] in the parent
|
||||||
//! module, [`core::range`].
|
//! module, [`core::range`].
|
||||||
//!
|
//!
|
||||||
//! The types here are equivalent to those in [`core::ops`].
|
//! The types here are equivalent to those in [`core::ops`].
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use crate::ops::{Range, RangeFrom, RangeInclusive};
|
pub use crate::ops::{Range, RangeFrom, RangeInclusive, RangeToInclusive};
|
||||||
|
|||||||
@@ -129,6 +129,8 @@ mod private_slice_index {
|
|||||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
impl Sealed for range::RangeInclusive<usize> {}
|
impl Sealed for range::RangeInclusive<usize> {}
|
||||||
#[unstable(feature = "new_range_api", issue = "125687")]
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
|
impl Sealed for range::RangeToInclusive<usize> {}
|
||||||
|
#[unstable(feature = "new_range_api", issue = "125687")]
|
||||||
impl Sealed for range::RangeFrom<usize> {}
|
impl Sealed for range::RangeFrom<usize> {}
|
||||||
|
|
||||||
impl Sealed for ops::IndexRange {}
|
impl Sealed for ops::IndexRange {}
|
||||||
@@ -788,6 +790,45 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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")]
|
||||||
|
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
|
||||||
|
unsafe impl<T> const SliceIndex<[T]> for range::RangeToInclusive<usize> {
|
||||||
|
type Output = [T];
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get(self, slice: &[T]) -> Option<&[T]> {
|
||||||
|
(0..=self.last).get(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
|
||||||
|
(0..=self.last).get_mut(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
|
||||||
|
// SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
|
||||||
|
unsafe { (0..=self.last).get_unchecked(slice) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
|
||||||
|
// SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
|
||||||
|
unsafe { (0..=self.last).get_unchecked_mut(slice) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn index(self, slice: &[T]) -> &[T] {
|
||||||
|
(0..=self.last).index(slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
|
||||||
|
(0..=self.last).index_mut(slice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs bounds checking of a range.
|
/// Performs bounds checking of a range.
|
||||||
///
|
///
|
||||||
/// This method is similar to [`Index::index`] for slices, but it returns a
|
/// This method is similar to [`Index::index`] for slices, but it returns a
|
||||||
|
|||||||
@@ -677,11 +677,11 @@ unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
|
|||||||
type Output = str;
|
type Output = str;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(self, slice: &str) -> Option<&Self::Output> {
|
fn get(self, slice: &str) -> Option<&Self::Output> {
|
||||||
if self.end == usize::MAX { None } else { self.into_slice_range().get(slice) }
|
if self.last == usize::MAX { None } else { self.into_slice_range().get(slice) }
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
|
||||||
if self.end == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
|
if self.last == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
|
unsafe fn get_unchecked(self, slice: *const str) -> *const Self::Output {
|
||||||
@@ -695,14 +695,14 @@ unsafe impl const SliceIndex<str> for range::RangeInclusive<usize> {
|
|||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(self, slice: &str) -> &Self::Output {
|
fn index(self, slice: &str) -> &Self::Output {
|
||||||
if self.end == usize::MAX {
|
if self.last == usize::MAX {
|
||||||
str_index_overflow_fail();
|
str_index_overflow_fail();
|
||||||
}
|
}
|
||||||
self.into_slice_range().index(slice)
|
self.into_slice_range().index(slice)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
|
||||||
if self.end == usize::MAX {
|
if self.last == usize::MAX {
|
||||||
str_index_overflow_fail();
|
str_index_overflow_fail();
|
||||||
}
|
}
|
||||||
self.into_slice_range().index_mut(slice)
|
self.into_slice_range().index_mut(slice)
|
||||||
|
|||||||
@@ -194,7 +194,6 @@ generate! {
|
|||||||
itertools,
|
itertools,
|
||||||
join,
|
join,
|
||||||
kw,
|
kw,
|
||||||
last,
|
|
||||||
lazy_static,
|
lazy_static,
|
||||||
lint_vec,
|
lint_vec,
|
||||||
ln,
|
ln,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ error[E0741]: `RangeTo<usize>` must implement `ConstParamTy` to be used as the t
|
|||||||
LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>;
|
LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0741]: `RangeToInclusive<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
error[E0741]: `std::ops::RangeToInclusive<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||||
--> $DIR/const-generics-range.rs:34:35
|
--> $DIR/const-generics-range.rs:34:35
|
||||||
|
|
|
|
||||||
LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
|
LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
|
|||||||
LL + #![feature(adt_const_params)]
|
LL + #![feature(adt_const_params)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
|
error: `std::ops::RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
|
||||||
--> $DIR/const-generics-range.rs:34:35
|
--> $DIR/const-generics-range.rs:34:35
|
||||||
|
|
|
|
||||||
LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
|
LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
|
||||||
|
|||||||
@@ -7,32 +7,32 @@
|
|||||||
// `Range` should be usable within const generics:
|
// `Range` should be usable within const generics:
|
||||||
struct _Range<const R: std::ops::Range<usize>>;
|
struct _Range<const R: std::ops::Range<usize>>;
|
||||||
//[min]~^ ERROR `std::ops::Range<usize>` is forbidden
|
//[min]~^ ERROR `std::ops::Range<usize>` is forbidden
|
||||||
const RANGE : _Range<{ 0 .. 1000 }> = _Range;
|
const RANGE: _Range<{ 0..1000 }> = _Range;
|
||||||
|
|
||||||
// `RangeFrom` should be usable within const generics:
|
// `RangeFrom` should be usable within const generics:
|
||||||
struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
|
struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
|
||||||
//[min]~^ ERROR `std::ops::RangeFrom<usize>` is forbidden
|
//[min]~^ ERROR `std::ops::RangeFrom<usize>` is forbidden
|
||||||
const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom;
|
const RANGE_FROM: _RangeFrom<{ 0.. }> = _RangeFrom;
|
||||||
|
|
||||||
// `RangeFull` should be usable within const generics:
|
// `RangeFull` should be usable within const generics:
|
||||||
struct _RangeFull<const R: std::ops::RangeFull>;
|
struct _RangeFull<const R: std::ops::RangeFull>;
|
||||||
//[min]~^ ERROR `RangeFull` is forbidden
|
//[min]~^ ERROR `RangeFull` is forbidden
|
||||||
const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull;
|
const RANGE_FULL: _RangeFull<{ .. }> = _RangeFull;
|
||||||
|
|
||||||
// Regression test for #70155
|
// Regression test for #70155
|
||||||
// `RangeInclusive` should be usable within const generics:
|
// `RangeInclusive` should be usable within const generics:
|
||||||
struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
|
struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
|
||||||
//[min]~^ ERROR `std::ops::RangeInclusive<usize>` is forbidden
|
//[min]~^ ERROR `std::ops::RangeInclusive<usize>` is forbidden
|
||||||
const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive;
|
const RANGE_INCLUSIVE: _RangeInclusive<{ 0..=999 }> = _RangeInclusive;
|
||||||
|
|
||||||
// `RangeTo` should be usable within const generics:
|
// `RangeTo` should be usable within const generics:
|
||||||
struct _RangeTo<const R: std::ops::RangeTo<usize>>;
|
struct _RangeTo<const R: std::ops::RangeTo<usize>>;
|
||||||
//[min]~^ ERROR `RangeTo<usize>` is forbidden
|
//[min]~^ ERROR `RangeTo<usize>` is forbidden
|
||||||
const RANGE_TO : _RangeTo<{ .. 1000 }> = _RangeTo;
|
const RANGE_TO: _RangeTo<{ ..1000 }> = _RangeTo;
|
||||||
|
|
||||||
// `RangeToInclusive` should be usable within const generics:
|
// `RangeToInclusive` should be usable within const generics:
|
||||||
struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
|
struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
|
||||||
//[min]~^ ERROR `RangeToInclusive<usize>` is forbidden
|
//[min]~^ ERROR `std::ops::RangeToInclusive<usize>` is forbidden
|
||||||
const RANGE_TO_INCLUSIVE : _RangeToInclusive<{ ..= 999 }> = _RangeToInclusive;
|
const RANGE_TO_INCLUSIVE: _RangeToInclusive<{ ..=999 }> = _RangeToInclusive;
|
||||||
|
|
||||||
pub fn main() {}
|
pub fn main() {}
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ LL | for _ in ..10 {}
|
|||||||
= note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
|
= note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
|
||||||
= note: required for `RangeTo<{integer}>` to implement `IntoIterator`
|
= note: required for `RangeTo<{integer}>` to implement `IntoIterator`
|
||||||
|
|
||||||
error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
|
error[E0277]: `std::ops::RangeToInclusive<{integer}>` is not an iterator
|
||||||
--> $DIR/ranges.rs:4:14
|
--> $DIR/ranges.rs:4:14
|
||||||
|
|
|
|
||||||
LL | for _ in ..=10 {}
|
LL | for _ in ..=10 {}
|
||||||
| ^^^^^ if you meant to iterate until a value (including it), add a starting value
|
| ^^^^^ if you meant to iterate until a value (including it), add a starting value
|
||||||
|
|
|
|
||||||
= help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
|
= help: the trait `Iterator` is not implemented for `std::ops::RangeToInclusive<{integer}>`
|
||||||
= note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
|
= note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
|
||||||
= note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator`
|
= note: required for `std::ops::RangeToInclusive<{integer}>` to implement `IntoIterator`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|||||||
@@ -6,20 +6,20 @@ fn main() {
|
|||||||
// Unchanged
|
// Unchanged
|
||||||
let a: core::range::RangeFull = ..;
|
let a: core::range::RangeFull = ..;
|
||||||
let b: core::range::RangeTo<u8> = ..2;
|
let b: core::range::RangeTo<u8> = ..2;
|
||||||
let c: core::range::RangeToInclusive<u8> = ..=3;
|
|
||||||
|
|
||||||
let _: core::ops::RangeFull = a;
|
let _: core::ops::RangeFull = a;
|
||||||
let _: core::ops::RangeTo<u8> = b;
|
let _: core::ops::RangeTo<u8> = b;
|
||||||
let _: core::ops::RangeToInclusive<u8> = c;
|
|
||||||
|
|
||||||
// Changed
|
// Changed
|
||||||
let a: core::range::legacy::RangeFrom<u8> = 1..;
|
let a: core::range::legacy::RangeFrom<u8> = 1..;
|
||||||
let b: core::range::legacy::Range<u8> = 2..3;
|
let b: core::range::legacy::Range<u8> = 2..3;
|
||||||
let c: core::range::legacy::RangeInclusive<u8> = 4..=5;
|
let c: core::range::legacy::RangeInclusive<u8> = 4..=5;
|
||||||
|
let d: core::range::legacy::RangeToInclusive<u8> = ..=3;
|
||||||
|
|
||||||
let a: core::ops::RangeFrom<u8> = a;
|
let a: core::ops::RangeFrom<u8> = a;
|
||||||
let b: core::ops::Range<u8> = b;
|
let b: core::ops::Range<u8> = b;
|
||||||
let c: core::ops::RangeInclusive<u8> = c;
|
let c: core::ops::RangeInclusive<u8> = c;
|
||||||
|
let d: core::ops::RangeToInclusive<u8> = d;
|
||||||
|
|
||||||
let _: core::ops::RangeFrom<u8> = a.into_iter();
|
let _: core::ops::RangeFrom<u8> = a.into_iter();
|
||||||
let _: core::ops::Range<u8> = b.into_iter();
|
let _: core::ops::Range<u8> = b.into_iter();
|
||||||
|
|||||||
@@ -7,18 +7,18 @@ fn main() {
|
|||||||
// Unchanged
|
// Unchanged
|
||||||
let a: core::range::RangeFull = ..;
|
let a: core::range::RangeFull = ..;
|
||||||
let b: core::range::RangeTo<u8> = ..2;
|
let b: core::range::RangeTo<u8> = ..2;
|
||||||
let c: core::range::RangeToInclusive<u8> = ..=3;
|
|
||||||
|
|
||||||
let _: core::ops::RangeFull = a;
|
let _: core::ops::RangeFull = a;
|
||||||
let _: core::ops::RangeTo<u8> = b;
|
let _: core::ops::RangeTo<u8> = b;
|
||||||
let _: core::ops::RangeToInclusive<u8> = c;
|
|
||||||
|
|
||||||
// Changed
|
// Changed
|
||||||
let a: core::range::RangeFrom<u8> = 1..;
|
let a: core::range::RangeFrom<u8> = 1..;
|
||||||
let b: core::range::Range<u8> = 2..3;
|
let b: core::range::Range<u8> = 2..3;
|
||||||
let c: core::range::RangeInclusive<u8> = 4..=5;
|
let c: core::range::RangeInclusive<u8> = 4..=5;
|
||||||
|
let d: core::range::RangeToInclusive<u8> = ..=3;
|
||||||
|
|
||||||
let _: core::range::IterRangeFrom<u8> = a.into_iter();
|
let _: core::range::IterRangeFrom<u8> = a.into_iter();
|
||||||
let _: core::range::IterRange<u8> = b.into_iter();
|
let _: core::range::IterRange<u8> = b.into_iter();
|
||||||
let _: core::range::IterRangeInclusive<u8> = c.into_iter();
|
let _: core::range::IterRangeInclusive<u8> = c.into_iter();
|
||||||
|
// RangeToInclusive has no Iterator implementation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ LL | take_range(std::ops::RangeToInclusive { end: 5 });
|
|||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: expected reference `&_`
|
= note: expected reference `&_`
|
||||||
found struct `RangeToInclusive<{integer}>`
|
found struct `std::ops::RangeToInclusive<{integer}>`
|
||||||
note: function defined here
|
note: function defined here
|
||||||
--> $DIR/issue-54505-no-literals.rs:12:4
|
--> $DIR/issue-54505-no-literals.rs:12:4
|
||||||
|
|
|
|
||||||
@@ -227,7 +227,7 @@ LL | take_range(::std::ops::RangeToInclusive { end: 5 });
|
|||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: expected reference `&_`
|
= note: expected reference `&_`
|
||||||
found struct `RangeToInclusive<{integer}>`
|
found struct `std::ops::RangeToInclusive<{integer}>`
|
||||||
note: function defined here
|
note: function defined here
|
||||||
--> $DIR/issue-54505-no-literals.rs:12:4
|
--> $DIR/issue-54505-no-literals.rs:12:4
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ LL | take_range(..=42);
|
|||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: expected reference `&_`
|
= note: expected reference `&_`
|
||||||
found struct `RangeToInclusive<{integer}>`
|
found struct `core::ops::RangeToInclusive<{integer}>`
|
||||||
note: function defined here
|
note: function defined here
|
||||||
--> $DIR/issue-54505-no-std.rs:25:4
|
--> $DIR/issue-54505-no-std.rs:25:4
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ LL | take_range(..=42);
|
|||||||
| arguments to this function are incorrect
|
| arguments to this function are incorrect
|
||||||
|
|
|
|
||||||
= note: expected reference `&_`
|
= note: expected reference `&_`
|
||||||
found struct `RangeToInclusive<{integer}>`
|
found struct `std::ops::RangeToInclusive<{integer}>`
|
||||||
note: function defined here
|
note: function defined here
|
||||||
--> $DIR/issue-54505.rs:10:4
|
--> $DIR/issue-54505.rs:10:4
|
||||||
|
|
|
|
||||||
|
|||||||
Reference in New Issue
Block a user