range.rs - source
Description: Source of the Rust file `library/core/src/range.rs`.

#
core/
range.rs

    1//! # Experimental replacement range types
    2//!
    3//! The types within this module are meant to replace the existing
    4//! `Range`, `RangeInclusive`, and `RangeFrom` types in a future edition.
    5//!
    6//! ```
    7//! #![feature(new_range_api)]
    8//! use core::range::{Range, RangeFrom, RangeInclusive};
    9//!
    10//! let arr = [0, 1, 2, 3, 4];
    11//! assert_eq!(arr[                      ..   ], [0, 1, 2, 3, 4]);
    12//! assert_eq!(arr[                      .. 3 ], [0, 1, 2      ]);
    13//! assert_eq!(arr[                      ..=3 ], [0, 1, 2, 3   ]);
    14//! assert_eq!(arr[     RangeFrom::from(1..  )], [   1, 2, 3, 4]);
    15//! assert_eq!(arr[         Range::from(1..3 )], [   1, 2      ]);
    16//! assert_eq!(arr[RangeInclusive::from(1..=3)], [   1, 2, 3   ]);
    17//! ```
    18
    19use crate::fmt;
    20use crate::hash::Hash;
    21
    22mod iter;
    23
    24#[unstable(feature = "new_range_api", issue = "125687")]
    25pub mod legacy;
    26
    27use Bound::{Excluded, Included, Unbounded};
    28#[doc(inline)]
    29pub use iter::{RangeFromIter, RangeInclusiveIter, RangeIter};
    30
    31#[doc(inline)]
    32pub use crate::iter::Step;
    33#[doc(inline)]
    34pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo};
    35
    36/// A (half-open) range bounded inclusively below and exclusively above
    37/// (`start..end` in a future edition).
    38///
    39/// The range `start..end` contains all values with `start <= x < end`.
    40/// It is empty if `start >= end`.
    41///
    42/// # Examples
    43///
    44/// ```
    45/// #![feature(new_range_api)]
    46/// use core::range::Range;
    47///
    48/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
    49/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
    50/// ```
    51#[lang = "RangeCopy"]
    52#[derive(Copy, Hash)]
    53#[derive_const(Clone, Default, PartialEq, Eq)]
    54#[unstable(feature = "new_range_api", issue = "125687")]
    55pub struct Range<Idx> {
    56    /// The lower bound of the range (inclusive).
    57    #[unstable(feature = "new_range_api", issue = "125687")]
    58    pub start: Idx,
    59    /// The upper bound of the range (exclusive).
    60    #[unstable(feature = "new_range_api", issue = "125687")]
    61    pub end: Idx,
    62}
    63
    64#[unstable(feature = "new_range_api", issue = "125687")]
    65impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
    66    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    67        self.start.fmt(fmt)?;
    68        write!(fmt, "..")?;
    69        self.end.fmt(fmt)?;
    70        Ok(())
    71    }
    72}
    73
    74impl<Idx: Step> Range<Idx> {
    75    /// Creates an iterator over the elements within this range.
    76    ///
    77    /// Shorthand for `.clone().into_iter()`
    78    ///
    79    /// # Examples
    80    ///
    81    /// ```
    82    /// #![feature(new_range_api)]
    83    /// use core::range::Range;
    84    ///
    85    /// let mut i = Range::from(3..9).iter().map(|n| n*n);
    86    /// assert_eq!(i.next(), Some(9));
    87    /// assert_eq!(i.next(), Some(16));
    88    /// assert_eq!(i.next(), Some(25));
    89    /// ```
    90    #[unstable(feature = "new_range_api", issue = "125687")]
    91    #[inline]
    92    pub fn iter(&self) -> RangeIter<Idx> {
    93        self.clone().into_iter()
    94    }
    95}
    96
    97impl<Idx: PartialOrd<Idx>> Range<Idx> {
    98    /// Returns `true` if `item` is contained in the range.
    99    ///
    100    /// # Examples
    101    ///
    102    /// ```
    103    /// #![feature(new_range_api)]
    104    /// use core::range::Range;
    105    ///
    106    /// assert!(!Range::from(3..5).contains(&2));
    107    /// assert!( Range::from(3..5).contains(&3));
    108    /// assert!( Range::from(3..5).contains(&4));
    109    /// assert!(!Range::from(3..5).contains(&5));
    110    ///
    111    /// assert!(!Range::from(3..3).contains(&3));
    112    /// assert!(!Range::from(3..2).contains(&3));
    113    ///
    114    /// assert!( Range::from(0.0..1.0).contains(&0.5));
    115    /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN));
    116    /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5));
    117    /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5));
    118    /// ```
    119    #[inline]
    120    #[unstable(feature = "new_range_api", issue = "125687")]
    121    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    122    pub const fn contains<U>(&self, item: &U) -> bool
    123    where
    124        Idx: [const] PartialOrd<U>,
    125        U: ?Sized + [const] PartialOrd<Idx>,
    126    {
    127        <Self as RangeBounds<Idx>>::contains(self, item)
    128    }
    129
    130    /// Returns `true` if the range contains no items.
    131    ///
    132    /// # Examples
    133    ///
    134    /// ```
    135    /// #![feature(new_range_api)]
    136    /// use core::range::Range;
    137    ///
    138    /// assert!(!Range::from(3..5).is_empty());
    139    /// assert!( Range::from(3..3).is_empty());
    140    /// assert!( Range::from(3..2).is_empty());
    141    /// ```
    142    ///
    143    /// The range is empty if either side is incomparable:
    144    ///
    145    /// ```
    146    /// #![feature(new_range_api)]
    147    /// use core::range::Range;
    148    ///
    149    /// assert!(!Range::from(3.0..5.0).is_empty());
    150    /// assert!( Range::from(3.0..f32::NAN).is_empty());
    151    /// assert!( Range::from(f32::NAN..5.0).is_empty());
    152    /// ```
    153    #[inline]
    154    #[unstable(feature = "new_range_api", issue = "125687")]
    155    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    156    pub const fn is_empty(&self) -> bool
    157    where
    158        Idx: [const] PartialOrd,
    159    {
    160        !(self.start < self.end)
    161    }
    162}
    163
    164#[unstable(feature = "new_range_api", issue = "125687")]
    165#[rustc_const_unstable(feature = "const_range", issue = "none")]
    166impl<T> const RangeBounds<T> for Range<T> {
    167    fn start_bound(&self) -> Bound<&T> {
    168        Included(&self.start)
    169    }
    170    fn end_bound(&self) -> Bound<&T> {
    171        Excluded(&self.end)
    172    }
    173}
    174
    175// This impl intentionally does not have `T: ?Sized`;
    176// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    177//
    178/// If you need to use this implementation where `T` is unsized,
    179/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    180/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
    181#[unstable(feature = "new_range_api", issue = "125687")]
    182#[rustc_const_unstable(feature = "const_range", issue = "none")]
    183impl<T> const RangeBounds<T> for Range<&T> {
    184    fn start_bound(&self) -> Bound<&T> {
    185        Included(self.start)
    186    }
    187    fn end_bound(&self) -> Bound<&T> {
    188        Excluded(self.end)
    189    }
    190}
    191
    192// #[unstable(feature = "range_into_bounds", issue = "136903")]
    193#[unstable(feature = "new_range_api", issue = "125687")]
    194#[rustc_const_unstable(feature = "const_range", issue = "none")]
    195impl<T> const IntoBounds<T> for Range<T> {
    196    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    197        (Included(self.start), Excluded(self.end))
    198    }
    199}
    200
    201#[unstable(feature = "new_range_api", issue = "125687")]
    202#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    203impl<T> const From<Range<T>> for legacy::Range<T> {
    204    #[inline]
    205    fn from(value: Range<T>) -> Self {
    206        Self { start: value.start, end: value.end }
    207    }
    208}
    209
    210#[unstable(feature = "new_range_api", issue = "125687")]
    211#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    212impl<T> const From<legacy::Range<T>> for Range<T> {
    213    #[inline]
    214    fn from(value: legacy::Range<T>) -> Self {
    215        Self { start: value.start, end: value.end }
    216    }
    217}
    218
    219/// A range bounded inclusively below and above (`start..=last`).
    220///
    221/// The `RangeInclusive` `start..=last` contains all values with `x >= start`
    222/// and `x <= last`. It is empty unless `start <= last`.
    223///
    224/// # Examples
    225///
    226/// The `start..=last` syntax is a `RangeInclusive`:
    227///
    228/// ```
    229/// #![feature(new_range_api)]
    230/// use core::range::RangeInclusive;
    231///
    232/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
    233/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
    234/// ```
    235#[lang = "RangeInclusiveCopy"]
    236#[derive(Clone, Copy, PartialEq, Eq, Hash)]
    237#[unstable(feature = "new_range_api", issue = "125687")]
    238pub struct RangeInclusive<Idx> {
    239    /// The lower bound of the range (inclusive).
    240    #[unstable(feature = "new_range_api", issue = "125687")]
    241    pub start: Idx,
    242    /// The upper bound of the range (inclusive).
    243    #[unstable(feature = "new_range_api", issue = "125687")]
    244    pub last: Idx,
    245}
    246
    247#[unstable(feature = "new_range_api", issue = "125687")]
    248impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
    249    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    250        self.start.fmt(fmt)?;
    251        write!(fmt, "..=")?;
    252        self.last.fmt(fmt)?;
    253        Ok(())
    254    }
    255}
    256
    257impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
    258    /// Returns `true` if `item` is contained in the range.
    259    ///
    260    /// # Examples
    261    ///
    262    /// ```
    263    /// #![feature(new_range_api)]
    264    /// use core::range::RangeInclusive;
    265    ///
    266    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
    267    /// assert!( RangeInclusive::from(3..=5).contains(&3));
    268    /// assert!( RangeInclusive::from(3..=5).contains(&4));
    269    /// assert!( RangeInclusive::from(3..=5).contains(&5));
    270    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
    271    ///
    272    /// assert!( RangeInclusive::from(3..=3).contains(&3));
    273    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
    274    ///
    275    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
    276    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
    277    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
    278    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
    279    /// ```
    280    #[inline]
    281    #[unstable(feature = "new_range_api", issue = "125687")]
    282    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    283    pub const fn contains<U>(&self, item: &U) -> bool
    284    where
    285        Idx: [const] PartialOrd<U>,
    286        U: ?Sized + [const] PartialOrd<Idx>,
    287    {
    288        <Self as RangeBounds<Idx>>::contains(self, item)
    289    }
    290
    291    /// Returns `true` if the range contains no items.
    292    ///
    293    /// # Examples
    294    ///
    295    /// ```
    296    /// #![feature(new_range_api)]
    297    /// use core::range::RangeInclusive;
    298    ///
    299    /// assert!(!RangeInclusive::from(3..=5).is_empty());
    300    /// assert!(!RangeInclusive::from(3..=3).is_empty());
    301    /// assert!( RangeInclusive::from(3..=2).is_empty());
    302    /// ```
    303    ///
    304    /// The range is empty if either side is incomparable:
    305    ///
    306    /// ```
    307    /// #![feature(new_range_api)]
    308    /// use core::range::RangeInclusive;
    309    ///
    310    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
    311    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
    312    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
    313    /// ```
    314    #[unstable(feature = "new_range_api", issue = "125687")]
    315    #[inline]
    316    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    317    pub const fn is_empty(&self) -> bool
    318    where
    319        Idx: [const] PartialOrd,
    320    {
    321        !(self.start <= self.last)
    322    }
    323}
    324
    325impl<Idx: Step> RangeInclusive<Idx> {
    326    /// Creates an iterator over the elements within this range.
    327    ///
    328    /// Shorthand for `.clone().into_iter()`
    329    ///
    330    /// # Examples
    331    ///
    332    /// ```
    333    /// #![feature(new_range_api)]
    334    /// use core::range::RangeInclusive;
    335    ///
    336    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
    337    /// assert_eq!(i.next(), Some(9));
    338    /// assert_eq!(i.next(), Some(16));
    339    /// assert_eq!(i.next(), Some(25));
    340    /// ```
    341    #[unstable(feature = "new_range_api", issue = "125687")]
    342    #[inline]
    343    pub fn iter(&self) -> RangeInclusiveIter<Idx> {
    344        self.clone().into_iter()
    345    }
    346}
    347
    348impl RangeInclusive<usize> {
    349    /// Converts to an exclusive `Range` for `SliceIndex` implementations.
    350    /// The caller is responsible for dealing with `last == usize::MAX`.
    351    #[inline]
    352    pub(crate) const fn into_slice_range(self) -> Range<usize> {
    353        Range { start: self.start, end: self.last + 1 }
    354    }
    355}
    356
    357#[unstable(feature = "new_range_api", issue = "125687")]
    358#[rustc_const_unstable(feature = "const_range", issue = "none")]
    359impl<T> const RangeBounds<T> for RangeInclusive<T> {
    360    fn start_bound(&self) -> Bound<&T> {
    361        Included(&self.start)
    362    }
    363    fn end_bound(&self) -> Bound<&T> {
    364        Included(&self.last)
    365    }
    366}
    367
    368// This impl intentionally does not have `T: ?Sized`;
    369// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    370//
    371/// If you need to use this implementation where `T` is unsized,
    372/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    373/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
    374#[unstable(feature = "new_range_api", issue = "125687")]
    375#[rustc_const_unstable(feature = "const_range", issue = "none")]
    376impl<T> const RangeBounds<T> for RangeInclusive<&T> {
    377    fn start_bound(&self) -> Bound<&T> {
    378        Included(self.start)
    379    }
    380    fn end_bound(&self) -> Bound<&T> {
    381        Included(self.last)
    382    }
    383}
    384
    385// #[unstable(feature = "range_into_bounds", issue = "136903")]
    386#[unstable(feature = "new_range_api", issue = "125687")]
    387#[rustc_const_unstable(feature = "const_range", issue = "none")]
    388impl<T> const IntoBounds<T> for RangeInclusive<T> {
    389    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    390        (Included(self.start), Included(self.last))
    391    }
    392}
    393
    394#[unstable(feature = "new_range_api", issue = "125687")]
    395#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    396impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
    397    #[inline]
    398    fn from(value: RangeInclusive<T>) -> Self {
    399        Self::new(value.start, value.last)
    400    }
    401}
    402#[unstable(feature = "new_range_api", issue = "125687")]
    403#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    404impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
    405    #[inline]
    406    fn from(value: legacy::RangeInclusive<T>) -> Self {
    407        assert!(
    408            !value.exhausted,
    409            "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
    410        );
    411
    412        let (start, last) = value.into_inner();
    413        RangeInclusive { start, last }
    414    }
    415}
    416
    417/// A range only bounded inclusively below (`start..`).
    418///
    419/// The `RangeFrom` `start..` contains all values with `x >= start`.
    420///
    421/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
    422/// data type reaches its numerical limit) is allowed to panic, wrap, or
    423/// saturate. This behavior is defined by the implementation of the [`Step`]
    424/// trait. For primitive integers, this follows the normal rules, and respects
    425/// the overflow checks profile (panic in debug, wrap in release). Note also
    426/// that overflow happens earlier than you might assume: the overflow happens
    427/// in the call to `next` that yields the maximum value, as the range must be
    428/// set to a state to yield the next value.
    429///
    430/// [`Step`]: crate::iter::Step
    431///
    432/// # Examples
    433///
    434/// The `start..` syntax is a `RangeFrom`:
    435///
    436/// ```
    437/// #![feature(new_range_api)]
    438/// use core::range::RangeFrom;
    439///
    440/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
    441/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
    442/// ```
    443#[lang = "RangeFromCopy"]
    444#[derive(Copy, Hash)]
    445#[derive_const(Clone, PartialEq, Eq)]
    446#[unstable(feature = "new_range_api", issue = "125687")]
    447pub struct RangeFrom<Idx> {
    448    /// The lower bound of the range (inclusive).
    449    #[unstable(feature = "new_range_api", issue = "125687")]
    450    pub start: Idx,
    451}
    452
    453#[unstable(feature = "new_range_api", issue = "125687")]
    454impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
    455    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    456        self.start.fmt(fmt)?;
    457        write!(fmt, "..")?;
    458        Ok(())
    459    }
    460}
    461
    462impl<Idx: Step> RangeFrom<Idx> {
    463    /// Creates an iterator over the elements within this range.
    464    ///
    465    /// Shorthand for `.clone().into_iter()`
    466    ///
    467    /// # Examples
    468    ///
    469    /// ```
    470    /// #![feature(new_range_api)]
    471    /// use core::range::RangeFrom;
    472    ///
    473    /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
    474    /// assert_eq!(i.next(), Some(9));
    475    /// assert_eq!(i.next(), Some(16));
    476    /// assert_eq!(i.next(), Some(25));
    477    /// ```
    478    #[unstable(feature = "new_range_api", issue = "125687")]
    479    #[inline]
    480    pub fn iter(&self) -> RangeFromIter<Idx> {
    481        self.clone().into_iter()
    482    }
    483}
    484
    485impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
    486    /// Returns `true` if `item` is contained in the range.
    487    ///
    488    /// # Examples
    489    ///
    490    /// ```
    491    /// #![feature(new_range_api)]
    492    /// use core::range::RangeFrom;
    493    ///
    494    /// assert!(!RangeFrom::from(3..).contains(&2));
    495    /// assert!( RangeFrom::from(3..).contains(&3));
    496    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
    497    ///
    498    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
    499    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
    500    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
    501    /// ```
    502    #[inline]
    503    #[unstable(feature = "new_range_api", issue = "125687")]
    504    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    505    pub const fn contains<U>(&self, item: &U) -> bool
    506    where
    507        Idx: [const] PartialOrd<U>,
    508        U: ?Sized + [const] PartialOrd<Idx>,
    509    {
    510        <Self as RangeBounds<Idx>>::contains(self, item)
    511    }
    512}
    513
    514#[unstable(feature = "new_range_api", issue = "125687")]
    515#[rustc_const_unstable(feature = "const_range", issue = "none")]
    516impl<T> const RangeBounds<T> for RangeFrom<T> {
    517    fn start_bound(&self) -> Bound<&T> {
    518        Included(&self.start)
    519    }
    520    fn end_bound(&self) -> Bound<&T> {
    521        Unbounded
    522    }
    523}
    524
    525// This impl intentionally does not have `T: ?Sized`;
    526// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    527//
    528/// If you need to use this implementation where `T` is unsized,
    529/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    530/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
    531#[unstable(feature = "new_range_api", issue = "125687")]
    532#[rustc_const_unstable(feature = "const_range", issue = "none")]
    533impl<T> const RangeBounds<T> for RangeFrom<&T> {
    534    fn start_bound(&self) -> Bound<&T> {
    535        Included(self.start)
    536    }
    537    fn end_bound(&self) -> Bound<&T> {
    538        Unbounded
    539    }
    540}
    541
    542// #[unstable(feature = "range_into_bounds", issue = "136903")]
    543#[unstable(feature = "new_range_api", issue = "125687")]
    544#[rustc_const_unstable(feature = "const_range", issue = "none")]
    545impl<T> const IntoBounds<T> for RangeFrom<T> {
    546    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    547        (Included(self.start), Unbounded)
    548    }
    549}
    550
    551#[unstable(feature = "new_range_api", issue = "125687")]
    552#[rustc_const_unstable(feature = "const_index", issue = "143775")]
    553impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
    554    #[inline]
    555    fn from(value: RangeFrom<T>) -> Self {
    556        Self { start: value.start }
    557    }
    558}
    559#[unstable(feature = "new_range_api", issue = "125687")]
    560#[rustc_const_unstable(feature = "const_index", issue = "143775")]
    561impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
    562    #[inline]
    563    fn from(value: legacy::RangeFrom<T>) -> Self {
    564        Self { start: value.start }
    565    }
    566}
    567
    568/// A range only bounded inclusively above (`..=last`).
    569///
    570/// The `RangeToInclusive` `..=last` contains all values with `x <= last`.
    571/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
    572///
    573/// # Examples
    574///
    575/// The `..=last` syntax is a `RangeToInclusive`:
    576///
    577/// ```
    578/// #![feature(new_range_api)]
    579/// #![feature(new_range)]
    580/// assert_eq!((..=5), std::range::RangeToInclusive{ last: 5 });
    581/// ```
    582///
    583/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
    584/// `for` loop directly. This won't compile:
    585///
    586/// ```compile_fail,E0277
    587/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
    588/// // std::iter::Iterator` is not satisfied
    589/// for i in ..=5 {
    590///     // ...
    591/// }
    592/// ```
    593///
    594/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
    595/// array elements up to and including the index indicated by `last`.
    596///
    597/// ```
    598/// let arr = [0, 1, 2, 3, 4];
    599/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
    600/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
    601/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
    602/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
    603/// assert_eq!(arr[1.. 3], [   1, 2      ]);
    604/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
    605/// ```
    606///
    607/// [slicing index]: crate::slice::SliceIndex
    608#[lang = "RangeToInclusiveCopy"]
    609#[doc(alias = "..=")]
    610#[derive(Copy, Clone, PartialEq, Eq, Hash)]
    611#[unstable(feature = "new_range_api", issue = "125687")]
    612pub struct RangeToInclusive<Idx> {
    613    /// The upper bound of the range (inclusive)
    614    #[unstable(feature = "new_range_api", issue = "125687")]
    615    pub last: Idx,
    616}
    617
    618#[unstable(feature = "new_range_api", issue = "125687")]
    619impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
    620    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    621        write!(fmt, "..=")?;
    622        self.last.fmt(fmt)?;
    623        Ok(())
    624    }
    625}
    626
    627impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
    628    /// Returns `true` if `item` is contained in the range.
    629    ///
    630    /// # Examples
    631    ///
    632    /// ```
    633    /// assert!( (..=5).contains(&-1_000_000_000));
    634    /// assert!( (..=5).contains(&5));
    635    /// assert!(!(..=5).contains(&6));
    636    ///
    637    /// assert!( (..=1.0).contains(&1.0));
    638    /// assert!(!(..=1.0).contains(&f32::NAN));
    639    /// assert!(!(..=f32::NAN).contains(&0.5));
    640    /// ```
    641    #[inline]
    642    #[unstable(feature = "new_range_api", issue = "125687")]
    643    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    644    pub const fn contains<U>(&self, item: &U) -> bool
    645    where
    646        Idx: [const] PartialOrd<U>,
    647        U: ?Sized + [const] PartialOrd<Idx>,
    648    {
    649        <Self as RangeBounds<Idx>>::contains(self, item)
    650    }
    651}
    652
    653impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
    654    fn from(value: legacy::RangeToInclusive<T>) -> Self {
    655        Self { last: value.end }
    656    }
    657}
    658
    659impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
    660    fn from(value: RangeToInclusive<T>) -> Self {
    661        Self { end: value.last }
    662    }
    663}
    664
    665// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
    666// because underflow would be possible with (..0).into()
    667
    668#[unstable(feature = "new_range_api", issue = "125687")]
    669#[rustc_const_unstable(feature = "const_range", issue = "none")]
    670impl<T> const RangeBounds<T> for RangeToInclusive<T> {
    671    fn start_bound(&self) -> Bound<&T> {
    672        Unbounded
    673    }
    674    fn end_bound(&self) -> Bound<&T> {
    675        Included(&self.last)
    676    }
    677}
    678
    679#[unstable(feature = "range_into_bounds", issue = "136903")]
    680#[rustc_const_unstable(feature = "const_range", issue = "none")]
    681impl<T> const IntoBounds<T> for RangeToInclusive<T> {
    682    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    683        (Unbounded, Included(self.last))
    684    }
    685}