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

#
core/ops/
range.rs

    1use crate::fmt;
    2use crate::hash::Hash;
    3use crate::marker::Destruct;
    4/// An unbounded range (`..`).
    5///
    6/// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`.
    7/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
    8///
    9/// # Examples
    10///
    11/// The `..` syntax is a `RangeFull`:
    12///
    13/// ```
    14/// assert_eq!(.., std::ops::RangeFull);
    15/// ```
    16///
    17/// It does not have an [`IntoIterator`] implementation, so you can't use it in
    18/// a `for` loop directly. This won't compile:
    19///
    20/// ```compile_fail,E0277
    21/// for i in .. {
    22///     // ...
    23/// }
    24/// ```
    25///
    26/// Used as a [slicing index], `RangeFull` produces the full array as a slice.
    27///
    28/// ```
    29/// let arr = [0, 1, 2, 3, 4];
    30/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]); // This is the `RangeFull`
    31/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
    32/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]);
    33/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
    34/// assert_eq!(arr[1.. 3], [   1, 2      ]);
    35/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
    36/// ```
    37///
    38/// [slicing index]: crate::slice::SliceIndex
    39#[lang = "RangeFull"]
    40#[doc(alias = "..")]
    41#[derive(Copy, Hash)]
    42#[derive_const(Clone, Default, Eq, PartialEq)]
    43#[stable(feature = "rust1", since = "1.0.0")]
    44pub struct RangeFull;
    45
    46#[stable(feature = "rust1", since = "1.0.0")]
    47impl fmt::Debug for RangeFull {
    48    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    49        write!(fmt, "..")
    50    }
    51}
    52
    53/// A (half-open) range bounded inclusively below and exclusively above
    54/// (`start..end`).
    55///
    56/// The range `start..end` contains all values with `start <= x < end`.
    57/// It is empty if `start >= end`.
    58///
    59/// # Examples
    60///
    61/// The `start..end` syntax is a `Range`:
    62///
    63/// ```
    64/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
    65/// assert_eq!(3 + 4 + 5, (3..6).sum());
    66/// ```
    67///
    68/// ```
    69/// let arr = [0, 1, 2, 3, 4];
    70/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
    71/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
    72/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]);
    73/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
    74/// assert_eq!(arr[1.. 3], [   1, 2      ]); // This is a `Range`
    75/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
    76/// ```
    77#[lang = "Range"]
    78#[doc(alias = "..")]
    79#[derive(Eq, Hash)]
    80#[derive_const(Clone, Default, PartialEq)] // not Copy -- see #27186
    81#[stable(feature = "rust1", since = "1.0.0")]
    82pub struct Range<Idx> {
    83    /// The lower bound of the range (inclusive).
    84    #[stable(feature = "rust1", since = "1.0.0")]
    85    pub start: Idx,
    86    /// The upper bound of the range (exclusive).
    87    #[stable(feature = "rust1", since = "1.0.0")]
    88    pub end: Idx,
    89}
    90
    91#[stable(feature = "rust1", since = "1.0.0")]
    92impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
    93    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    94        self.start.fmt(fmt)?;
    95        write!(fmt, "..")?;
    96        self.end.fmt(fmt)?;
    97        Ok(())
    98    }
    99}
    100
    101impl<Idx: PartialOrd<Idx>> Range<Idx> {
    102    /// Returns `true` if `item` is contained in the range.
    103    ///
    104    /// # Examples
    105    ///
    106    /// ```
    107    /// assert!(!(3..5).contains(&2));
    108    /// assert!( (3..5).contains(&3));
    109    /// assert!( (3..5).contains(&4));
    110    /// assert!(!(3..5).contains(&5));
    111    ///
    112    /// assert!(!(3..3).contains(&3));
    113    /// assert!(!(3..2).contains(&3));
    114    ///
    115    /// assert!( (0.0..1.0).contains(&0.5));
    116    /// assert!(!(0.0..1.0).contains(&f32::NAN));
    117    /// assert!(!(0.0..f32::NAN).contains(&0.5));
    118    /// assert!(!(f32::NAN..1.0).contains(&0.5));
    119    /// ```
    120    #[inline]
    121    #[stable(feature = "range_contains", since = "1.35.0")]
    122    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    123    pub const fn contains<U>(&self, item: &U) -> bool
    124    where
    125        Idx: [const] PartialOrd<U>,
    126        U: ?Sized + [const] PartialOrd<Idx>,
    127    {
    128        <Self as RangeBounds<Idx>>::contains(self, item)
    129    }
    130
    131    /// Returns `true` if the range contains no items.
    132    ///
    133    /// # Examples
    134    ///
    135    /// ```
    136    /// assert!(!(3..5).is_empty());
    137    /// assert!( (3..3).is_empty());
    138    /// assert!( (3..2).is_empty());
    139    /// ```
    140    ///
    141    /// The range is empty if either side is incomparable:
    142    ///
    143    /// ```
    144    /// assert!(!(3.0..5.0).is_empty());
    145    /// assert!( (3.0..f32::NAN).is_empty());
    146    /// assert!( (f32::NAN..5.0).is_empty());
    147    /// ```
    148    #[inline]
    149    #[stable(feature = "range_is_empty", since = "1.47.0")]
    150    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    151    pub const fn is_empty(&self) -> bool
    152    where
    153        Idx: [const] PartialOrd<Idx>,
    154    {
    155        !(self.start < self.end)
    156    }
    157}
    158
    159/// A range only bounded inclusively below (`start..`).
    160///
    161/// The `RangeFrom` `start..` contains all values with `x >= start`.
    162///
    163/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
    164/// data type reaches its numerical limit) is allowed to panic, wrap, or
    165/// saturate. This behavior is defined by the implementation of the [`Step`]
    166/// trait. For primitive integers, this follows the normal rules, and respects
    167/// the overflow checks profile (panic in debug, wrap in release). Note also
    168/// that overflow happens earlier than you might assume: the overflow happens
    169/// in the call to `next` that yields the maximum value, as the range must be
    170/// set to a state to yield the next value.
    171///
    172/// [`Step`]: crate::iter::Step
    173///
    174/// # Examples
    175///
    176/// The `start..` syntax is a `RangeFrom`:
    177///
    178/// ```
    179/// assert_eq!((2..), std::ops::RangeFrom { start: 2 });
    180/// assert_eq!(2 + 3 + 4, (2..).take(3).sum());
    181/// ```
    182///
    183/// ```
    184/// let arr = [0, 1, 2, 3, 4];
    185/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
    186/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
    187/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]);
    188/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]); // This is a `RangeFrom`
    189/// assert_eq!(arr[1.. 3], [   1, 2      ]);
    190/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
    191/// ```
    192#[lang = "RangeFrom"]
    193#[doc(alias = "..")]
    194#[derive(Eq, Hash)]
    195#[derive_const(Clone, PartialEq)] // not Copy -- see #27186
    196#[stable(feature = "rust1", since = "1.0.0")]
    197pub struct RangeFrom<Idx> {
    198    /// The lower bound of the range (inclusive).
    199    #[stable(feature = "rust1", since = "1.0.0")]
    200    pub start: Idx,
    201}
    202
    203#[stable(feature = "rust1", since = "1.0.0")]
    204impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
    205    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    206        self.start.fmt(fmt)?;
    207        write!(fmt, "..")?;
    208        Ok(())
    209    }
    210}
    211
    212impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
    213    /// Returns `true` if `item` is contained in the range.
    214    ///
    215    /// # Examples
    216    ///
    217    /// ```
    218    /// assert!(!(3..).contains(&2));
    219    /// assert!( (3..).contains(&3));
    220    /// assert!( (3..).contains(&1_000_000_000));
    221    ///
    222    /// assert!( (0.0..).contains(&0.5));
    223    /// assert!(!(0.0..).contains(&f32::NAN));
    224    /// assert!(!(f32::NAN..).contains(&0.5));
    225    /// ```
    226    #[inline]
    227    #[stable(feature = "range_contains", since = "1.35.0")]
    228    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    229    pub const fn contains<U>(&self, item: &U) -> bool
    230    where
    231        Idx: [const] PartialOrd<U>,
    232        U: ?Sized + [const] PartialOrd<Idx>,
    233    {
    234        <Self as RangeBounds<Idx>>::contains(self, item)
    235    }
    236}
    237
    238/// A range only bounded exclusively above (`..end`).
    239///
    240/// The `RangeTo` `..end` contains all values with `x < end`.
    241/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
    242///
    243/// # Examples
    244///
    245/// The `..end` syntax is a `RangeTo`:
    246///
    247/// ```
    248/// assert_eq!((..5), std::ops::RangeTo { end: 5 });
    249/// ```
    250///
    251/// It does not have an [`IntoIterator`] implementation, so you can't use it in
    252/// a `for` loop directly. This won't compile:
    253///
    254/// ```compile_fail,E0277
    255/// // error[E0277]: the trait bound `std::ops::RangeTo<{integer}>:
    256/// // std::iter::Iterator` is not satisfied
    257/// for i in ..5 {
    258///     // ...
    259/// }
    260/// ```
    261///
    262/// When used as a [slicing index], `RangeTo` produces a slice of all array
    263/// elements before the index indicated by `end`.
    264///
    265/// ```
    266/// let arr = [0, 1, 2, 3, 4];
    267/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
    268/// assert_eq!(arr[ .. 3], [0, 1, 2      ]); // This is a `RangeTo`
    269/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]);
    270/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
    271/// assert_eq!(arr[1.. 3], [   1, 2      ]);
    272/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
    273/// ```
    274///
    275/// [slicing index]: crate::slice::SliceIndex
    276#[lang = "RangeTo"]
    277#[doc(alias = "..")]
    278#[derive(Copy, Eq, Hash)]
    279#[derive_const(Clone, PartialEq)]
    280#[stable(feature = "rust1", since = "1.0.0")]
    281pub struct RangeTo<Idx> {
    282    /// The upper bound of the range (exclusive).
    283    #[stable(feature = "rust1", since = "1.0.0")]
    284    pub end: Idx,
    285}
    286
    287#[stable(feature = "rust1", since = "1.0.0")]
    288impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
    289    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    290        write!(fmt, "..")?;
    291        self.end.fmt(fmt)?;
    292        Ok(())
    293    }
    294}
    295
    296impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
    297    /// Returns `true` if `item` is contained in the range.
    298    ///
    299    /// # Examples
    300    ///
    301    /// ```
    302    /// assert!( (..5).contains(&-1_000_000_000));
    303    /// assert!( (..5).contains(&4));
    304    /// assert!(!(..5).contains(&5));
    305    ///
    306    /// assert!( (..1.0).contains(&0.5));
    307    /// assert!(!(..1.0).contains(&f32::NAN));
    308    /// assert!(!(..f32::NAN).contains(&0.5));
    309    /// ```
    310    #[inline]
    311    #[stable(feature = "range_contains", since = "1.35.0")]
    312    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    313    pub const fn contains<U>(&self, item: &U) -> bool
    314    where
    315        Idx: [const] PartialOrd<U>,
    316        U: ?Sized + [const] PartialOrd<Idx>,
    317    {
    318        <Self as RangeBounds<Idx>>::contains(self, item)
    319    }
    320}
    321
    322/// A range bounded inclusively below and above (`start..=end`).
    323///
    324/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
    325/// and `x <= end`. It is empty unless `start <= end`.
    326///
    327/// This iterator is [fused], but the specific values of `start` and `end` after
    328/// iteration has finished are **unspecified** other than that [`.is_empty()`]
    329/// will return `true` once no more values will be produced.
    330///
    331/// [fused]: crate::iter::FusedIterator
    332/// [`.is_empty()`]: RangeInclusive::is_empty
    333///
    334/// # Examples
    335///
    336/// The `start..=end` syntax is a `RangeInclusive`:
    337///
    338/// ```
    339/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
    340/// assert_eq!(3 + 4 + 5, (3..=5).sum());
    341/// ```
    342///
    343/// ```
    344/// let arr = [0, 1, 2, 3, 4];
    345/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
    346/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
    347/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]);
    348/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
    349/// assert_eq!(arr[1.. 3], [   1, 2      ]);
    350/// assert_eq!(arr[1..=3], [   1, 2, 3   ]); // This is a `RangeInclusive`
    351/// ```
    352#[lang = "RangeInclusive"]
    353#[doc(alias = "..=")]
    354#[derive(Clone, Hash)]
    355#[derive_const(Eq, PartialEq)] // not Copy -- see #27186
    356#[stable(feature = "inclusive_range", since = "1.26.0")]
    357pub struct RangeInclusive<Idx> {
    358    // Note that the fields here are not public to allow changing the
    359    // representation in the future; in particular, while we could plausibly
    360    // expose start/end, modifying them without changing (future/current)
    361    // private fields may lead to incorrect behavior, so we don't want to
    362    // support that mode.
    363    pub(crate) start: Idx,
    364    pub(crate) end: Idx,
    365
    366    // This field is:
    367    //  - `false` upon construction
    368    //  - `false` when iteration has yielded an element and the iterator is not exhausted
    369    //  - `true` when iteration has been used to exhaust the iterator
    370    //
    371    // This is required to support PartialEq and Hash without a PartialOrd bound or specialization.
    372    pub(crate) exhausted: bool,
    373}
    374
    375impl<Idx> RangeInclusive<Idx> {
    376    /// Creates a new inclusive range. Equivalent to writing `start..=end`.
    377    ///
    378    /// # Examples
    379    ///
    380    /// ```
    381    /// use std::ops::RangeInclusive;
    382    ///
    383    /// assert_eq!(3..=5, RangeInclusive::new(3, 5));
    384    /// ```
    385    #[lang = "range_inclusive_new"]
    386    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
    387    #[inline]
    388    #[rustc_promotable]
    389    #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")]
    390    pub const fn new(start: Idx, end: Idx) -> Self {
    391        Self { start, end, exhausted: false }
    392    }
    393
    394    /// Returns the lower bound of the range (inclusive).
    395    ///
    396    /// When using an inclusive range for iteration, the values of `start()` and
    397    /// [`end()`] are unspecified after the iteration ended. To determine
    398    /// whether the inclusive range is empty, use the [`is_empty()`] method
    399    /// instead of comparing `start() > end()`.
    400    ///
    401    /// Note: the value returned by this method is unspecified after the range
    402    /// has been iterated to exhaustion.
    403    ///
    404    /// [`end()`]: RangeInclusive::end
    405    /// [`is_empty()`]: RangeInclusive::is_empty
    406    ///
    407    /// # Examples
    408    ///
    409    /// ```
    410    /// assert_eq!((3..=5).start(), &3);
    411    /// ```
    412    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
    413    #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")]
    414    #[inline]
    415    pub const fn start(&self) -> &Idx {
    416        &self.start
    417    }
    418
    419    /// Returns the upper bound of the range (inclusive).
    420    ///
    421    /// When using an inclusive range for iteration, the values of [`start()`]
    422    /// and `end()` are unspecified after the iteration ended. To determine
    423    /// whether the inclusive range is empty, use the [`is_empty()`] method
    424    /// instead of comparing `start() > end()`.
    425    ///
    426    /// Note: the value returned by this method is unspecified after the range
    427    /// has been iterated to exhaustion.
    428    ///
    429    /// [`start()`]: RangeInclusive::start
    430    /// [`is_empty()`]: RangeInclusive::is_empty
    431    ///
    432    /// # Examples
    433    ///
    434    /// ```
    435    /// assert_eq!((3..=5).end(), &5);
    436    /// ```
    437    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
    438    #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")]
    439    #[inline]
    440    pub const fn end(&self) -> &Idx {
    441        &self.end
    442    }
    443
    444    /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound).
    445    ///
    446    /// Note: the value returned by this method is unspecified after the range
    447    /// has been iterated to exhaustion.
    448    ///
    449    /// # Examples
    450    ///
    451    /// ```
    452    /// assert_eq!((3..=5).into_inner(), (3, 5));
    453    /// ```
    454    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
    455    #[inline]
    456    #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
    457    pub const fn into_inner(self) -> (Idx, Idx) {
    458        (self.start, self.end)
    459    }
    460}
    461
    462impl RangeInclusive<usize> {
    463    /// Converts to an exclusive `Range` for `SliceIndex` implementations.
    464    /// The caller is responsible for dealing with `end == usize::MAX`.
    465    #[inline]
    466    pub(crate) const fn into_slice_range(self) -> Range<usize> {
    467        // If we're not exhausted, we want to simply slice `start..end + 1`.
    468        // If we are exhausted, then slicing with `end + 1..end + 1` gives us an
    469        // empty range that is still subject to bounds-checks for that endpoint.
    470        let exclusive_end = self.end + 1;
    471        let start = if self.exhausted { exclusive_end } else { self.start };
    472        start..exclusive_end
    473    }
    474}
    475
    476#[stable(feature = "inclusive_range", since = "1.26.0")]
    477impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
    478    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    479        self.start.fmt(fmt)?;
    480        write!(fmt, "..=")?;
    481        self.end.fmt(fmt)?;
    482        if self.exhausted {
    483            write!(fmt, " (exhausted)")?;
    484        }
    485        Ok(())
    486    }
    487}
    488
    489impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
    490    /// Returns `true` if `item` is contained in the range.
    491    ///
    492    /// # Examples
    493    ///
    494    /// ```
    495    /// assert!(!(3..=5).contains(&2));
    496    /// assert!( (3..=5).contains(&3));
    497    /// assert!( (3..=5).contains(&4));
    498    /// assert!( (3..=5).contains(&5));
    499    /// assert!(!(3..=5).contains(&6));
    500    ///
    501    /// assert!( (3..=3).contains(&3));
    502    /// assert!(!(3..=2).contains(&3));
    503    ///
    504    /// assert!( (0.0..=1.0).contains(&1.0));
    505    /// assert!(!(0.0..=1.0).contains(&f32::NAN));
    506    /// assert!(!(0.0..=f32::NAN).contains(&0.0));
    507    /// assert!(!(f32::NAN..=1.0).contains(&1.0));
    508    /// ```
    509    ///
    510    /// This method always returns `false` after iteration has finished:
    511    ///
    512    /// ```
    513    /// let mut r = 3..=5;
    514    /// assert!(r.contains(&3) && r.contains(&5));
    515    /// for _ in r.by_ref() {}
    516    /// // Precise field values are unspecified here
    517    /// assert!(!r.contains(&3) && !r.contains(&5));
    518    /// ```
    519    #[inline]
    520    #[stable(feature = "range_contains", since = "1.35.0")]
    521    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    522    pub const fn contains<U>(&self, item: &U) -> bool
    523    where
    524        Idx: [const] PartialOrd<U>,
    525        U: ?Sized + [const] PartialOrd<Idx>,
    526    {
    527        <Self as RangeBounds<Idx>>::contains(self, item)
    528    }
    529
    530    /// Returns `true` if the range contains no items.
    531    ///
    532    /// # Examples
    533    ///
    534    /// ```
    535    /// assert!(!(3..=5).is_empty());
    536    /// assert!(!(3..=3).is_empty());
    537    /// assert!( (3..=2).is_empty());
    538    /// ```
    539    ///
    540    /// The range is empty if either side is incomparable:
    541    ///
    542    /// ```
    543    /// assert!(!(3.0..=5.0).is_empty());
    544    /// assert!( (3.0..=f32::NAN).is_empty());
    545    /// assert!( (f32::NAN..=5.0).is_empty());
    546    /// ```
    547    ///
    548    /// This method returns `true` after iteration has finished:
    549    ///
    550    /// ```
    551    /// let mut r = 3..=5;
    552    /// for _ in r.by_ref() {}
    553    /// // Precise field values are unspecified here
    554    /// assert!(r.is_empty());
    555    /// ```
    556    #[stable(feature = "range_is_empty", since = "1.47.0")]
    557    #[inline]
    558    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    559    pub const fn is_empty(&self) -> bool
    560    where
    561        Idx: [const] PartialOrd,
    562    {
    563        self.exhausted || !(self.start <= self.end)
    564    }
    565}
    566
    567/// A range only bounded inclusively above (`..=end`).
    568///
    569/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
    570/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
    571///
    572/// # Examples
    573///
    574/// The `..=end` syntax is a `RangeToInclusive`:
    575///
    576/// ```
    577/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
    578/// ```
    579///
    580/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
    581/// `for` loop directly. This won't compile:
    582///
    583/// ```compile_fail,E0277
    584/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
    585/// // std::iter::Iterator` is not satisfied
    586/// for i in ..=5 {
    587///     // ...
    588/// }
    589/// ```
    590///
    591/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
    592/// array elements up to and including the index indicated by `end`.
    593///
    594/// ```
    595/// let arr = [0, 1, 2, 3, 4];
    596/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
    597/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
    598/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
    599/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
    600/// assert_eq!(arr[1.. 3], [   1, 2      ]);
    601/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
    602/// ```
    603///
    604/// [slicing index]: crate::slice::SliceIndex
    605#[lang = "RangeToInclusive"]
    606#[doc(alias = "..=")]
    607#[derive(Copy, Hash)]
    608#[derive(Clone, PartialEq, Eq)]
    609#[stable(feature = "inclusive_range", since = "1.26.0")]
    610pub struct RangeToInclusive<Idx> {
    611    /// The upper bound of the range (inclusive)
    612    #[stable(feature = "inclusive_range", since = "1.26.0")]
    613    pub end: Idx,
    614}
    615
    616#[stable(feature = "inclusive_range", since = "1.26.0")]
    617impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
    618    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
    619        write!(fmt, "..=")?;
    620        self.end.fmt(fmt)?;
    621        Ok(())
    622    }
    623}
    624
    625impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
    626    /// Returns `true` if `item` is contained in the range.
    627    ///
    628    /// # Examples
    629    ///
    630    /// ```
    631    /// assert!( (..=5).contains(&-1_000_000_000));
    632    /// assert!( (..=5).contains(&5));
    633    /// assert!(!(..=5).contains(&6));
    634    ///
    635    /// assert!( (..=1.0).contains(&1.0));
    636    /// assert!(!(..=1.0).contains(&f32::NAN));
    637    /// assert!(!(..=f32::NAN).contains(&0.5));
    638    /// ```
    639    #[inline]
    640    #[stable(feature = "range_contains", since = "1.35.0")]
    641    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    642    pub const fn contains<U>(&self, item: &U) -> bool
    643    where
    644        Idx: [const] PartialOrd<U>,
    645        U: ?Sized + [const] PartialOrd<Idx>,
    646    {
    647        <Self as RangeBounds<Idx>>::contains(self, item)
    648    }
    649}
    650
    651// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
    652// because underflow would be possible with (..0).into()
    653
    654/// An endpoint of a range of keys.
    655///
    656/// # Examples
    657///
    658/// `Bound`s are range endpoints:
    659///
    660/// ```
    661/// use std::ops::Bound::*;
    662/// use std::ops::RangeBounds;
    663///
    664/// assert_eq!((..100).start_bound(), Unbounded);
    665/// assert_eq!((1..12).start_bound(), Included(&1));
    666/// assert_eq!((1..12).end_bound(), Excluded(&12));
    667/// ```
    668///
    669/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
    670/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
    671///
    672/// ```
    673/// use std::collections::BTreeMap;
    674/// use std::ops::Bound::{Excluded, Included, Unbounded};
    675///
    676/// let mut map = BTreeMap::new();
    677/// map.insert(3, "a");
    678/// map.insert(5, "b");
    679/// map.insert(8, "c");
    680///
    681/// for (key, value) in map.range((Excluded(3), Included(8))) {
    682///     println!("{key}: {value}");
    683/// }
    684///
    685/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
    686/// ```
    687///
    688/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range
    689#[stable(feature = "collections_bound", since = "1.17.0")]
    690#[derive(Copy, Debug, Hash)]
    691#[derive_const(Clone, Eq, PartialEq)]
    692pub enum Bound<T> {
    693    /// An inclusive bound.
    694    #[stable(feature = "collections_bound", since = "1.17.0")]
    695    Included(#[stable(feature = "collections_bound", since = "1.17.0")] T),
    696    /// An exclusive bound.
    697    #[stable(feature = "collections_bound", since = "1.17.0")]
    698    Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T),
    699    /// An infinite endpoint. Indicates that there is no bound in this direction.
    700    #[stable(feature = "collections_bound", since = "1.17.0")]
    701    Unbounded,
    702}
    703
    704impl<T> Bound<T> {
    705    /// Converts from `&Bound<T>` to `Bound<&T>`.
    706    #[inline]
    707    #[stable(feature = "bound_as_ref_shared", since = "1.65.0")]
    708    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    709    pub const fn as_ref(&self) -> Bound<&T> {
    710        match *self {
    711            Included(ref x) => Included(x),
    712            Excluded(ref x) => Excluded(x),
    713            Unbounded => Unbounded,
    714        }
    715    }
    716
    717    /// Converts from `&mut Bound<T>` to `Bound<&mut T>`.
    718    #[inline]
    719    #[unstable(feature = "bound_as_ref", issue = "80996")]
    720    pub const fn as_mut(&mut self) -> Bound<&mut T> {
    721        match *self {
    722            Included(ref mut x) => Included(x),
    723            Excluded(ref mut x) => Excluded(x),
    724            Unbounded => Unbounded,
    725        }
    726    }
    727
    728    /// Maps a `Bound<T>` to a `Bound<U>` by applying a function to the contained value (including
    729    /// both `Included` and `Excluded`), returning a `Bound` of the same kind.
    730    ///
    731    /// # Examples
    732    ///
    733    /// ```
    734    /// use std::ops::Bound::*;
    735    ///
    736    /// let bound_string = Included("Hello, World!");
    737    ///
    738    /// assert_eq!(bound_string.map(|s| s.len()), Included(13));
    739    /// ```
    740    ///
    741    /// ```
    742    /// use std::ops::Bound;
    743    /// use Bound::*;
    744    ///
    745    /// let unbounded_string: Bound<String> = Unbounded;
    746    ///
    747    /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded);
    748    /// ```
    749    #[inline]
    750    #[stable(feature = "bound_map", since = "1.77.0")]
    751    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Bound<U> {
    752        match self {
    753            Unbounded => Unbounded,
    754            Included(x) => Included(f(x)),
    755            Excluded(x) => Excluded(f(x)),
    756        }
    757    }
    758}
    759
    760impl<T: Copy> Bound<&T> {
    761    /// Map a `Bound<&T>` to a `Bound<T>` by copying the contents of the bound.
    762    ///
    763    /// # Examples
    764    ///
    765    /// ```
    766    /// #![feature(bound_copied)]
    767    ///
    768    /// use std::ops::Bound::*;
    769    /// use std::ops::RangeBounds;
    770    ///
    771    /// assert_eq!((1..12).start_bound(), Included(&1));
    772    /// assert_eq!((1..12).start_bound().copied(), Included(1));
    773    /// ```
    774    #[unstable(feature = "bound_copied", issue = "145966")]
    775    #[must_use]
    776    pub fn copied(self) -> Bound<T> {
    777        match self {
    778            Bound::Unbounded => Bound::Unbounded,
    779            Bound::Included(x) => Bound::Included(*x),
    780            Bound::Excluded(x) => Bound::Excluded(*x),
    781        }
    782    }
    783}
    784
    785impl<T: Clone> Bound<&T> {
    786    /// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
    787    ///
    788    /// # Examples
    789    ///
    790    /// ```
    791    /// use std::ops::Bound::*;
    792    /// use std::ops::RangeBounds;
    793    ///
    794    /// let a1 = String::from("a");
    795    /// let (a2, a3, a4) = (a1.clone(), a1.clone(), a1.clone());
    796    ///
    797    /// assert_eq!(Included(&a1), (a2..).start_bound());
    798    /// assert_eq!(Included(a3), (a4..).start_bound().cloned());
    799    /// ```
    800    #[must_use = "`self` will be dropped if the result is not used"]
    801    #[stable(feature = "bound_cloned", since = "1.55.0")]
    802    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    803    pub const fn cloned(self) -> Bound<T>
    804    where
    805        T: [const] Clone,
    806    {
    807        match self {
    808            Bound::Unbounded => Bound::Unbounded,
    809            Bound::Included(x) => Bound::Included(x.clone()),
    810            Bound::Excluded(x) => Bound::Excluded(x.clone()),
    811        }
    812    }
    813}
    814
    815/// `RangeBounds` is implemented by Rust's built-in range types, produced
    816/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
    817#[stable(feature = "collections_range", since = "1.28.0")]
    818#[rustc_diagnostic_item = "RangeBounds"]
    819#[rustc_const_unstable(feature = "const_range", issue = "none")]
    820pub const trait RangeBounds<T: ?Sized> {
    821    /// Start index bound.
    822    ///
    823    /// Returns the start value as a `Bound`.
    824    ///
    825    /// # Examples
    826    ///
    827    /// ```
    828    /// use std::ops::Bound::*;
    829    /// use std::ops::RangeBounds;
    830    ///
    831    /// assert_eq!((..10).start_bound(), Unbounded);
    832    /// assert_eq!((3..10).start_bound(), Included(&3));
    833    /// ```
    834    #[stable(feature = "collections_range", since = "1.28.0")]
    835    fn start_bound(&self) -> Bound<&T>;
    836
    837    /// End index bound.
    838    ///
    839    /// Returns the end value as a `Bound`.
    840    ///
    841    /// # Examples
    842    ///
    843    /// ```
    844    /// use std::ops::Bound::*;
    845    /// use std::ops::RangeBounds;
    846    ///
    847    /// assert_eq!((3..).end_bound(), Unbounded);
    848    /// assert_eq!((3..10).end_bound(), Excluded(&10));
    849    /// ```
    850    #[stable(feature = "collections_range", since = "1.28.0")]
    851    fn end_bound(&self) -> Bound<&T>;
    852
    853    /// Returns `true` if `item` is contained in the range.
    854    ///
    855    /// # Examples
    856    ///
    857    /// ```
    858    /// assert!( (3..5).contains(&4));
    859    /// assert!(!(3..5).contains(&2));
    860    ///
    861    /// assert!( (0.0..1.0).contains(&0.5));
    862    /// assert!(!(0.0..1.0).contains(&f32::NAN));
    863    /// assert!(!(0.0..f32::NAN).contains(&0.5));
    864    /// assert!(!(f32::NAN..1.0).contains(&0.5));
    865    /// ```
    866    #[inline]
    867    #[stable(feature = "range_contains", since = "1.35.0")]
    868    fn contains<U>(&self, item: &U) -> bool
    869    where
    870        T: [const] PartialOrd<U>,
    871        U: ?Sized + [const] PartialOrd<T>,
    872    {
    873        (match self.start_bound() {
    874            Included(start) => start <= item,
    875            Excluded(start) => start < item,
    876            Unbounded => true,
    877        }) && (match self.end_bound() {
    878            Included(end) => item <= end,
    879            Excluded(end) => item < end,
    880            Unbounded => true,
    881        })
    882    }
    883
    884    /// Returns `true` if the range contains no items.
    885    /// One-sided ranges (`RangeFrom`, etc) always return `false`.
    886    ///
    887    /// # Examples
    888    ///
    889    /// ```
    890    /// #![feature(range_bounds_is_empty)]
    891    /// use std::ops::RangeBounds;
    892    ///
    893    /// assert!(!(3..).is_empty());
    894    /// assert!(!(..2).is_empty());
    895    /// assert!(!RangeBounds::is_empty(&(3..5)));
    896    /// assert!( RangeBounds::is_empty(&(3..3)));
    897    /// assert!( RangeBounds::is_empty(&(3..2)));
    898    /// ```
    899    ///
    900    /// The range is empty if either side is incomparable:
    901    ///
    902    /// ```
    903    /// #![feature(range_bounds_is_empty)]
    904    /// use std::ops::RangeBounds;
    905    ///
    906    /// assert!(!RangeBounds::is_empty(&(3.0..5.0)));
    907    /// assert!( RangeBounds::is_empty(&(3.0..f32::NAN)));
    908    /// assert!( RangeBounds::is_empty(&(f32::NAN..5.0)));
    909    /// ```
    910    ///
    911    /// But never empty if either side is unbounded:
    912    ///
    913    /// ```
    914    /// #![feature(range_bounds_is_empty)]
    915    /// use std::ops::RangeBounds;
    916    ///
    917    /// assert!(!(..0).is_empty());
    918    /// assert!(!(i32::MAX..).is_empty());
    919    /// assert!(!RangeBounds::<u8>::is_empty(&(..)));
    920    /// ```
    921    ///
    922    /// `(Excluded(a), Excluded(b))` is only empty if `a >= b`:
    923    ///
    924    /// ```
    925    /// #![feature(range_bounds_is_empty)]
    926    /// use std::ops::Bound::*;
    927    /// use std::ops::RangeBounds;
    928    ///
    929    /// assert!(!(Excluded(1), Excluded(3)).is_empty());
    930    /// assert!(!(Excluded(1), Excluded(2)).is_empty());
    931    /// assert!( (Excluded(1), Excluded(1)).is_empty());
    932    /// assert!( (Excluded(2), Excluded(1)).is_empty());
    933    /// assert!( (Excluded(3), Excluded(1)).is_empty());
    934    /// ```
    935    #[unstable(feature = "range_bounds_is_empty", issue = "137300")]
    936    fn is_empty(&self) -> bool
    937    where
    938        T: [const] PartialOrd,
    939    {
    940        !match (self.start_bound(), self.end_bound()) {
    941            (Unbounded, _) | (_, Unbounded) => true,
    942            (Included(start), Excluded(end))
    943            | (Excluded(start), Included(end))
    944            | (Excluded(start), Excluded(end)) => start < end,
    945            (Included(start), Included(end)) => start <= end,
    946        }
    947    }
    948}
    949
    950/// Used to convert a range into start and end bounds, consuming the
    951/// range by value.
    952///
    953/// `IntoBounds` is implemented by Rust’s built-in range types, produced
    954/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
    955#[unstable(feature = "range_into_bounds", issue = "136903")]
    956#[rustc_const_unstable(feature = "const_range", issue = "none")]
    957pub const trait IntoBounds<T>: [const] RangeBounds<T> {
    958    /// Convert this range into the start and end bounds.
    959    /// Returns `(start_bound, end_bound)`.
    960    ///
    961    /// # Examples
    962    ///
    963    /// ```
    964    /// #![feature(range_into_bounds)]
    965    /// use std::ops::Bound::*;
    966    /// use std::ops::IntoBounds;
    967    ///
    968    /// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5)));
    969    /// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7)));
    970    /// ```
    971    fn into_bounds(self) -> (Bound<T>, Bound<T>);
    972
    973    /// Compute the intersection of  `self` and `other`.
    974    ///
    975    /// # Examples
    976    ///
    977    /// ```
    978    /// #![feature(range_into_bounds)]
    979    /// use std::ops::Bound::*;
    980    /// use std::ops::IntoBounds;
    981    ///
    982    /// assert_eq!((3..).intersect(..5), (Included(3), Excluded(5)));
    983    /// assert_eq!((-12..387).intersect(0..256), (Included(0), Excluded(256)));
    984    /// assert_eq!((1..5).intersect(..), (Included(1), Excluded(5)));
    985    /// assert_eq!((1..=9).intersect(0..10), (Included(1), Included(9)));
    986    /// assert_eq!((7..=13).intersect(8..13), (Included(8), Excluded(13)));
    987    /// ```
    988    ///
    989    /// Combine with `is_empty` to determine if two ranges overlap.
    990    ///
    991    /// ```
    992    /// #![feature(range_into_bounds)]
    993    /// #![feature(range_bounds_is_empty)]
    994    /// use std::ops::{RangeBounds, IntoBounds};
    995    ///
    996    /// assert!(!(3..).intersect(..5).is_empty());
    997    /// assert!(!(-12..387).intersect(0..256).is_empty());
    998    /// assert!((1..5).intersect(6..).is_empty());
    999    /// ```
    1000    fn intersect<R>(self, other: R) -> (Bound<T>, Bound<T>)
    1001    where
    1002        Self: Sized,
    1003        T: [const] Ord + [const] Destruct,
    1004        R: Sized + [const] IntoBounds<T>,
    1005    {
    1006        let (self_start, self_end) = IntoBounds::into_bounds(self);
    1007        let (other_start, other_end) = IntoBounds::into_bounds(other);
    1008
    1009        let start = match (self_start, other_start) {
    1010            (Included(a), Included(b)) => Included(Ord::max(a, b)),
    1011            (Excluded(a), Excluded(b)) => Excluded(Ord::max(a, b)),
    1012            (Unbounded, Unbounded) => Unbounded,
    1013
    1014            (x, Unbounded) | (Unbounded, x) => x,
    1015
    1016            (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
    1017                if i > e {
    1018                    Included(i)
    1019                } else {
    1020                    Excluded(e)
    1021                }
    1022            }
    1023        };
    1024        let end = match (self_end, other_end) {
    1025            (Included(a), Included(b)) => Included(Ord::min(a, b)),
    1026            (Excluded(a), Excluded(b)) => Excluded(Ord::min(a, b)),
    1027            (Unbounded, Unbounded) => Unbounded,
    1028
    1029            (x, Unbounded) | (Unbounded, x) => x,
    1030
    1031            (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
    1032                if i < e {
    1033                    Included(i)
    1034                } else {
    1035                    Excluded(e)
    1036                }
    1037            }
    1038        };
    1039
    1040        (start, end)
    1041    }
    1042}
    1043
    1044use self::Bound::{Excluded, Included, Unbounded};
    1045
    1046#[stable(feature = "collections_range", since = "1.28.0")]
    1047#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1048impl<T: ?Sized> const RangeBounds<T> for RangeFull {
    1049    fn start_bound(&self) -> Bound<&T> {
    1050        Unbounded
    1051    }
    1052    fn end_bound(&self) -> Bound<&T> {
    1053        Unbounded
    1054    }
    1055}
    1056
    1057#[unstable(feature = "range_into_bounds", issue = "136903")]
    1058#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1059impl<T> const IntoBounds<T> for RangeFull {
    1060    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    1061        (Unbounded, Unbounded)
    1062    }
    1063}
    1064
    1065#[stable(feature = "collections_range", since = "1.28.0")]
    1066#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1067impl<T> const RangeBounds<T> for RangeFrom<T> {
    1068    fn start_bound(&self) -> Bound<&T> {
    1069        Included(&self.start)
    1070    }
    1071    fn end_bound(&self) -> Bound<&T> {
    1072        Unbounded
    1073    }
    1074}
    1075
    1076#[unstable(feature = "range_into_bounds", issue = "136903")]
    1077#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1078impl<T> const IntoBounds<T> for RangeFrom<T> {
    1079    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    1080        (Included(self.start), Unbounded)
    1081    }
    1082}
    1083
    1084#[stable(feature = "collections_range", since = "1.28.0")]
    1085#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1086impl<T> const RangeBounds<T> for RangeTo<T> {
    1087    fn start_bound(&self) -> Bound<&T> {
    1088        Unbounded
    1089    }
    1090    fn end_bound(&self) -> Bound<&T> {
    1091        Excluded(&self.end)
    1092    }
    1093}
    1094
    1095#[unstable(feature = "range_into_bounds", issue = "136903")]
    1096#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1097impl<T> const IntoBounds<T> for RangeTo<T> {
    1098    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    1099        (Unbounded, Excluded(self.end))
    1100    }
    1101}
    1102
    1103#[stable(feature = "collections_range", since = "1.28.0")]
    1104#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1105impl<T> const RangeBounds<T> for Range<T> {
    1106    fn start_bound(&self) -> Bound<&T> {
    1107        Included(&self.start)
    1108    }
    1109    fn end_bound(&self) -> Bound<&T> {
    1110        Excluded(&self.end)
    1111    }
    1112}
    1113
    1114#[unstable(feature = "range_into_bounds", issue = "136903")]
    1115#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1116impl<T> const IntoBounds<T> for Range<T> {
    1117    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    1118        (Included(self.start), Excluded(self.end))
    1119    }
    1120}
    1121
    1122#[stable(feature = "collections_range", since = "1.28.0")]
    1123#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1124impl<T> const RangeBounds<T> for RangeInclusive<T> {
    1125    fn start_bound(&self) -> Bound<&T> {
    1126        Included(&self.start)
    1127    }
    1128    fn end_bound(&self) -> Bound<&T> {
    1129        if self.exhausted {
    1130            // When the iterator is exhausted, we usually have start == end,
    1131            // but we want the range to appear empty, containing nothing.
    1132            Excluded(&self.end)
    1133        } else {
    1134            Included(&self.end)
    1135        }
    1136    }
    1137}
    1138
    1139#[unstable(feature = "range_into_bounds", issue = "136903")]
    1140#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1141impl<T> const IntoBounds<T> for RangeInclusive<T> {
    1142    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    1143        (
    1144            Included(self.start),
    1145            if self.exhausted {
    1146                // When the iterator is exhausted, we usually have start == end,
    1147                // but we want the range to appear empty, containing nothing.
    1148                Excluded(self.end)
    1149            } else {
    1150                Included(self.end)
    1151            },
    1152        )
    1153    }
    1154}
    1155
    1156#[stable(feature = "collections_range", since = "1.28.0")]
    1157#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1158impl<T> const RangeBounds<T> for RangeToInclusive<T> {
    1159    fn start_bound(&self) -> Bound<&T> {
    1160        Unbounded
    1161    }
    1162    fn end_bound(&self) -> Bound<&T> {
    1163        Included(&self.end)
    1164    }
    1165}
    1166
    1167#[unstable(feature = "range_into_bounds", issue = "136903")]
    1168#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1169impl<T> const IntoBounds<T> for RangeToInclusive<T> {
    1170    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    1171        (Unbounded, Included(self.end))
    1172    }
    1173}
    1174
    1175#[stable(feature = "collections_range", since = "1.28.0")]
    1176#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1177impl<T> const RangeBounds<T> for (Bound<T>, Bound<T>) {
    1178    fn start_bound(&self) -> Bound<&T> {
    1179        match *self {
    1180            (Included(ref start), _) => Included(start),
    1181            (Excluded(ref start), _) => Excluded(start),
    1182            (Unbounded, _) => Unbounded,
    1183        }
    1184    }
    1185
    1186    fn end_bound(&self) -> Bound<&T> {
    1187        match *self {
    1188            (_, Included(ref end)) => Included(end),
    1189            (_, Excluded(ref end)) => Excluded(end),
    1190            (_, Unbounded) => Unbounded,
    1191        }
    1192    }
    1193}
    1194
    1195#[unstable(feature = "range_into_bounds", issue = "136903")]
    1196#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1197impl<T> const IntoBounds<T> for (Bound<T>, Bound<T>) {
    1198    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
    1199        self
    1200    }
    1201}
    1202
    1203#[stable(feature = "collections_range", since = "1.28.0")]
    1204#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1205impl<'a, T: ?Sized + 'a> const RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
    1206    fn start_bound(&self) -> Bound<&T> {
    1207        self.0
    1208    }
    1209
    1210    fn end_bound(&self) -> Bound<&T> {
    1211        self.1
    1212    }
    1213}
    1214
    1215// This impl intentionally does not have `T: ?Sized`;
    1216// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    1217//
    1218/// If you need to use this implementation where `T` is unsized,
    1219/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    1220/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
    1221#[stable(feature = "collections_range", since = "1.28.0")]
    1222#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1223impl<T> const RangeBounds<T> for RangeFrom<&T> {
    1224    fn start_bound(&self) -> Bound<&T> {
    1225        Included(self.start)
    1226    }
    1227    fn end_bound(&self) -> Bound<&T> {
    1228        Unbounded
    1229    }
    1230}
    1231
    1232// This impl intentionally does not have `T: ?Sized`;
    1233// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    1234//
    1235/// If you need to use this implementation where `T` is unsized,
    1236/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    1237/// i.e. replace `..end` with `(Bound::Unbounded, Bound::Excluded(end))`.
    1238#[stable(feature = "collections_range", since = "1.28.0")]
    1239#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1240impl<T> const RangeBounds<T> for RangeTo<&T> {
    1241    fn start_bound(&self) -> Bound<&T> {
    1242        Unbounded
    1243    }
    1244    fn end_bound(&self) -> Bound<&T> {
    1245        Excluded(self.end)
    1246    }
    1247}
    1248
    1249// This impl intentionally does not have `T: ?Sized`;
    1250// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    1251//
    1252/// If you need to use this implementation where `T` is unsized,
    1253/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    1254/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
    1255#[stable(feature = "collections_range", since = "1.28.0")]
    1256#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1257impl<T> const RangeBounds<T> for Range<&T> {
    1258    fn start_bound(&self) -> Bound<&T> {
    1259        Included(self.start)
    1260    }
    1261    fn end_bound(&self) -> Bound<&T> {
    1262        Excluded(self.end)
    1263    }
    1264}
    1265
    1266// This impl intentionally does not have `T: ?Sized`;
    1267// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    1268//
    1269/// If you need to use this implementation where `T` is unsized,
    1270/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    1271/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
    1272#[stable(feature = "collections_range", since = "1.28.0")]
    1273#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1274impl<T> const RangeBounds<T> for RangeInclusive<&T> {
    1275    fn start_bound(&self) -> Bound<&T> {
    1276        Included(self.start)
    1277    }
    1278    fn end_bound(&self) -> Bound<&T> {
    1279        Included(self.end)
    1280    }
    1281}
    1282
    1283// This impl intentionally does not have `T: ?Sized`;
    1284// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
    1285//
    1286/// If you need to use this implementation where `T` is unsized,
    1287/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
    1288/// i.e. replace `..=end` with `(Bound::Unbounded, Bound::Included(end))`.
    1289#[stable(feature = "collections_range", since = "1.28.0")]
    1290#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1291impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
    1292    fn start_bound(&self) -> Bound<&T> {
    1293        Unbounded
    1294    }
    1295    fn end_bound(&self) -> Bound<&T> {
    1296        Included(self.end)
    1297    }
    1298}
    1299
    1300/// An internal helper for `split_off` functions indicating
    1301/// which end a `OneSidedRange` is bounded on.
    1302#[unstable(feature = "one_sided_range", issue = "69780")]
    1303#[allow(missing_debug_implementations)]
    1304pub enum OneSidedRangeBound {
    1305    /// The range is bounded inclusively from below and is unbounded above.
    1306    StartInclusive,
    1307    /// The range is bounded exclusively from above and is unbounded below.
    1308    End,
    1309    /// The range is bounded inclusively from above and is unbounded below.
    1310    EndInclusive,
    1311}
    1312
    1313/// `OneSidedRange` is implemented for built-in range types that are unbounded
    1314/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
    1315/// but `..`, `d..e`, and `f..=g` do not.
    1316///
    1317/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
    1318/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
    1319#[unstable(feature = "one_sided_range", issue = "69780")]
    1320#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1321pub const trait OneSidedRange<T>: RangeBounds<T> {
    1322    /// An internal-only helper function for `split_off` and
    1323    /// `split_off_mut` that returns the bound of the one-sided range.
    1324    fn bound(self) -> (OneSidedRangeBound, T);
    1325}
    1326
    1327#[unstable(feature = "one_sided_range", issue = "69780")]
    1328#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1329impl<T> const OneSidedRange<T> for RangeTo<T>
    1330where
    1331    Self: RangeBounds<T>,
    1332{
    1333    fn bound(self) -> (OneSidedRangeBound, T) {
    1334        (OneSidedRangeBound::End, self.end)
    1335    }
    1336}
    1337
    1338#[unstable(feature = "one_sided_range", issue = "69780")]
    1339#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1340impl<T> const OneSidedRange<T> for RangeFrom<T>
    1341where
    1342    Self: RangeBounds<T>,
    1343{
    1344    fn bound(self) -> (OneSidedRangeBound, T) {
    1345        (OneSidedRangeBound::StartInclusive, self.start)
    1346    }
    1347}
    1348
    1349#[unstable(feature = "one_sided_range", issue = "69780")]
    1350#[rustc_const_unstable(feature = "const_range", issue = "none")]
    1351impl<T> const OneSidedRange<T> for RangeToInclusive<T>
    1352where
    1353    Self: RangeBounds<T>,
    1354{
    1355    fn bound(self) -> (OneSidedRangeBound, T) {
    1356        (OneSidedRangeBound::EndInclusive, self.end)
    1357    }
    1358}