Thanks to visit codestin.com
Credit goes to doc.rust-lang.org

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#[const_trait]
820#[rustc_const_unstable(feature = "const_range", issue = "none")]
821pub trait RangeBounds<T: ?Sized> {
822    /// Start index bound.
823    ///
824    /// Returns the start value as a `Bound`.
825    ///
826    /// # Examples
827    ///
828    /// ```
829    /// use std::ops::Bound::*;
830    /// use std::ops::RangeBounds;
831    ///
832    /// assert_eq!((..10).start_bound(), Unbounded);
833    /// assert_eq!((3..10).start_bound(), Included(&3));
834    /// ```
835    #[stable(feature = "collections_range", since = "1.28.0")]
836    fn start_bound(&self) -> Bound<&T>;
837
838    /// End index bound.
839    ///
840    /// Returns the end value as a `Bound`.
841    ///
842    /// # Examples
843    ///
844    /// ```
845    /// use std::ops::Bound::*;
846    /// use std::ops::RangeBounds;
847    ///
848    /// assert_eq!((3..).end_bound(), Unbounded);
849    /// assert_eq!((3..10).end_bound(), Excluded(&10));
850    /// ```
851    #[stable(feature = "collections_range", since = "1.28.0")]
852    fn end_bound(&self) -> Bound<&T>;
853
854    /// Returns `true` if `item` is contained in the range.
855    ///
856    /// # Examples
857    ///
858    /// ```
859    /// assert!( (3..5).contains(&4));
860    /// assert!(!(3..5).contains(&2));
861    ///
862    /// assert!( (0.0..1.0).contains(&0.5));
863    /// assert!(!(0.0..1.0).contains(&f32::NAN));
864    /// assert!(!(0.0..f32::NAN).contains(&0.5));
865    /// assert!(!(f32::NAN..1.0).contains(&0.5));
866    /// ```
867    #[inline]
868    #[stable(feature = "range_contains", since = "1.35.0")]
869    fn contains<U>(&self, item: &U) -> bool
870    where
871        T: [const] PartialOrd<U>,
872        U: ?Sized + [const] PartialOrd<T>,
873    {
874        (match self.start_bound() {
875            Included(start) => start <= item,
876            Excluded(start) => start < item,
877            Unbounded => true,
878        }) && (match self.end_bound() {
879            Included(end) => item <= end,
880            Excluded(end) => item < end,
881            Unbounded => true,
882        })
883    }
884
885    /// Returns `true` if the range contains no items.
886    /// One-sided ranges (`RangeFrom`, etc) always return `false`.
887    ///
888    /// # Examples
889    ///
890    /// ```
891    /// #![feature(range_bounds_is_empty)]
892    /// use std::ops::RangeBounds;
893    ///
894    /// assert!(!(3..).is_empty());
895    /// assert!(!(..2).is_empty());
896    /// assert!(!RangeBounds::is_empty(&(3..5)));
897    /// assert!( RangeBounds::is_empty(&(3..3)));
898    /// assert!( RangeBounds::is_empty(&(3..2)));
899    /// ```
900    ///
901    /// The range is empty if either side is incomparable:
902    ///
903    /// ```
904    /// #![feature(range_bounds_is_empty)]
905    /// use std::ops::RangeBounds;
906    ///
907    /// assert!(!RangeBounds::is_empty(&(3.0..5.0)));
908    /// assert!( RangeBounds::is_empty(&(3.0..f32::NAN)));
909    /// assert!( RangeBounds::is_empty(&(f32::NAN..5.0)));
910    /// ```
911    ///
912    /// But never empty if either side is unbounded:
913    ///
914    /// ```
915    /// #![feature(range_bounds_is_empty)]
916    /// use std::ops::RangeBounds;
917    ///
918    /// assert!(!(..0).is_empty());
919    /// assert!(!(i32::MAX..).is_empty());
920    /// assert!(!RangeBounds::<u8>::is_empty(&(..)));
921    /// ```
922    ///
923    /// `(Excluded(a), Excluded(b))` is only empty if `a >= b`:
924    ///
925    /// ```
926    /// #![feature(range_bounds_is_empty)]
927    /// use std::ops::Bound::*;
928    /// use std::ops::RangeBounds;
929    ///
930    /// assert!(!(Excluded(1), Excluded(3)).is_empty());
931    /// assert!(!(Excluded(1), Excluded(2)).is_empty());
932    /// assert!( (Excluded(1), Excluded(1)).is_empty());
933    /// assert!( (Excluded(2), Excluded(1)).is_empty());
934    /// assert!( (Excluded(3), Excluded(1)).is_empty());
935    /// ```
936    #[unstable(feature = "range_bounds_is_empty", issue = "137300")]
937    fn is_empty(&self) -> bool
938    where
939        T: [const] PartialOrd,
940    {
941        !match (self.start_bound(), self.end_bound()) {
942            (Unbounded, _) | (_, Unbounded) => true,
943            (Included(start), Excluded(end))
944            | (Excluded(start), Included(end))
945            | (Excluded(start), Excluded(end)) => start < end,
946            (Included(start), Included(end)) => start <= end,
947        }
948    }
949}
950
951/// Used to convert a range into start and end bounds, consuming the
952/// range by value.
953///
954/// `IntoBounds` is implemented by Rust’s built-in range types, produced
955/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
956#[unstable(feature = "range_into_bounds", issue = "136903")]
957#[const_trait]
958#[rustc_const_unstable(feature = "const_range", issue = "none")]
959pub trait IntoBounds<T>: [const] RangeBounds<T> {
960    /// Convert this range into the start and end bounds.
961    /// Returns `(start_bound, end_bound)`.
962    ///
963    /// # Examples
964    ///
965    /// ```
966    /// #![feature(range_into_bounds)]
967    /// use std::ops::Bound::*;
968    /// use std::ops::IntoBounds;
969    ///
970    /// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5)));
971    /// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7)));
972    /// ```
973    fn into_bounds(self) -> (Bound<T>, Bound<T>);
974
975    /// Compute the intersection of  `self` and `other`.
976    ///
977    /// # Examples
978    ///
979    /// ```
980    /// #![feature(range_into_bounds)]
981    /// use std::ops::Bound::*;
982    /// use std::ops::IntoBounds;
983    ///
984    /// assert_eq!((3..).intersect(..5), (Included(3), Excluded(5)));
985    /// assert_eq!((-12..387).intersect(0..256), (Included(0), Excluded(256)));
986    /// assert_eq!((1..5).intersect(..), (Included(1), Excluded(5)));
987    /// assert_eq!((1..=9).intersect(0..10), (Included(1), Included(9)));
988    /// assert_eq!((7..=13).intersect(8..13), (Included(8), Excluded(13)));
989    /// ```
990    ///
991    /// Combine with `is_empty` to determine if two ranges overlap.
992    ///
993    /// ```
994    /// #![feature(range_into_bounds)]
995    /// #![feature(range_bounds_is_empty)]
996    /// use std::ops::{RangeBounds, IntoBounds};
997    ///
998    /// assert!(!(3..).intersect(..5).is_empty());
999    /// assert!(!(-12..387).intersect(0..256).is_empty());
1000    /// assert!((1..5).intersect(6..).is_empty());
1001    /// ```
1002    fn intersect<R>(self, other: R) -> (Bound<T>, Bound<T>)
1003    where
1004        Self: Sized,
1005        T: [const] Ord + [const] Destruct,
1006        R: Sized + [const] IntoBounds<T>,
1007    {
1008        let (self_start, self_end) = IntoBounds::into_bounds(self);
1009        let (other_start, other_end) = IntoBounds::into_bounds(other);
1010
1011        let start = match (self_start, other_start) {
1012            (Included(a), Included(b)) => Included(Ord::max(a, b)),
1013            (Excluded(a), Excluded(b)) => Excluded(Ord::max(a, b)),
1014            (Unbounded, Unbounded) => Unbounded,
1015
1016            (x, Unbounded) | (Unbounded, x) => x,
1017
1018            (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
1019                if i > e {
1020                    Included(i)
1021                } else {
1022                    Excluded(e)
1023                }
1024            }
1025        };
1026        let end = match (self_end, other_end) {
1027            (Included(a), Included(b)) => Included(Ord::min(a, b)),
1028            (Excluded(a), Excluded(b)) => Excluded(Ord::min(a, b)),
1029            (Unbounded, Unbounded) => Unbounded,
1030
1031            (x, Unbounded) | (Unbounded, x) => x,
1032
1033            (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
1034                if i < e {
1035                    Included(i)
1036                } else {
1037                    Excluded(e)
1038                }
1039            }
1040        };
1041
1042        (start, end)
1043    }
1044}
1045
1046use self::Bound::{Excluded, Included, Unbounded};
1047
1048#[stable(feature = "collections_range", since = "1.28.0")]
1049#[rustc_const_unstable(feature = "const_range", issue = "none")]
1050impl<T: ?Sized> const RangeBounds<T> for RangeFull {
1051    fn start_bound(&self) -> Bound<&T> {
1052        Unbounded
1053    }
1054    fn end_bound(&self) -> Bound<&T> {
1055        Unbounded
1056    }
1057}
1058
1059#[unstable(feature = "range_into_bounds", issue = "136903")]
1060#[rustc_const_unstable(feature = "const_range", issue = "none")]
1061impl<T> const IntoBounds<T> for RangeFull {
1062    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1063        (Unbounded, Unbounded)
1064    }
1065}
1066
1067#[stable(feature = "collections_range", since = "1.28.0")]
1068#[rustc_const_unstable(feature = "const_range", issue = "none")]
1069impl<T> const RangeBounds<T> for RangeFrom<T> {
1070    fn start_bound(&self) -> Bound<&T> {
1071        Included(&self.start)
1072    }
1073    fn end_bound(&self) -> Bound<&T> {
1074        Unbounded
1075    }
1076}
1077
1078#[unstable(feature = "range_into_bounds", issue = "136903")]
1079#[rustc_const_unstable(feature = "const_range", issue = "none")]
1080impl<T> const IntoBounds<T> for RangeFrom<T> {
1081    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1082        (Included(self.start), Unbounded)
1083    }
1084}
1085
1086#[stable(feature = "collections_range", since = "1.28.0")]
1087#[rustc_const_unstable(feature = "const_range", issue = "none")]
1088impl<T> const RangeBounds<T> for RangeTo<T> {
1089    fn start_bound(&self) -> Bound<&T> {
1090        Unbounded
1091    }
1092    fn end_bound(&self) -> Bound<&T> {
1093        Excluded(&self.end)
1094    }
1095}
1096
1097#[unstable(feature = "range_into_bounds", issue = "136903")]
1098#[rustc_const_unstable(feature = "const_range", issue = "none")]
1099impl<T> const IntoBounds<T> for RangeTo<T> {
1100    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1101        (Unbounded, Excluded(self.end))
1102    }
1103}
1104
1105#[stable(feature = "collections_range", since = "1.28.0")]
1106#[rustc_const_unstable(feature = "const_range", issue = "none")]
1107impl<T> const RangeBounds<T> for Range<T> {
1108    fn start_bound(&self) -> Bound<&T> {
1109        Included(&self.start)
1110    }
1111    fn end_bound(&self) -> Bound<&T> {
1112        Excluded(&self.end)
1113    }
1114}
1115
1116#[unstable(feature = "range_into_bounds", issue = "136903")]
1117#[rustc_const_unstable(feature = "const_range", issue = "none")]
1118impl<T> const IntoBounds<T> for Range<T> {
1119    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1120        (Included(self.start), Excluded(self.end))
1121    }
1122}
1123
1124#[stable(feature = "collections_range", since = "1.28.0")]
1125#[rustc_const_unstable(feature = "const_range", issue = "none")]
1126impl<T> const RangeBounds<T> for RangeInclusive<T> {
1127    fn start_bound(&self) -> Bound<&T> {
1128        Included(&self.start)
1129    }
1130    fn end_bound(&self) -> Bound<&T> {
1131        if self.exhausted {
1132            // When the iterator is exhausted, we usually have start == end,
1133            // but we want the range to appear empty, containing nothing.
1134            Excluded(&self.end)
1135        } else {
1136            Included(&self.end)
1137        }
1138    }
1139}
1140
1141#[unstable(feature = "range_into_bounds", issue = "136903")]
1142#[rustc_const_unstable(feature = "const_range", issue = "none")]
1143impl<T> const IntoBounds<T> for RangeInclusive<T> {
1144    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1145        (
1146            Included(self.start),
1147            if self.exhausted {
1148                // When the iterator is exhausted, we usually have start == end,
1149                // but we want the range to appear empty, containing nothing.
1150                Excluded(self.end)
1151            } else {
1152                Included(self.end)
1153            },
1154        )
1155    }
1156}
1157
1158#[stable(feature = "collections_range", since = "1.28.0")]
1159#[rustc_const_unstable(feature = "const_range", issue = "none")]
1160impl<T> const RangeBounds<T> for RangeToInclusive<T> {
1161    fn start_bound(&self) -> Bound<&T> {
1162        Unbounded
1163    }
1164    fn end_bound(&self) -> Bound<&T> {
1165        Included(&self.end)
1166    }
1167}
1168
1169#[unstable(feature = "range_into_bounds", issue = "136903")]
1170#[rustc_const_unstable(feature = "const_range", issue = "none")]
1171impl<T> const IntoBounds<T> for RangeToInclusive<T> {
1172    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1173        (Unbounded, Included(self.end))
1174    }
1175}
1176
1177#[stable(feature = "collections_range", since = "1.28.0")]
1178#[rustc_const_unstable(feature = "const_range", issue = "none")]
1179impl<T> const RangeBounds<T> for (Bound<T>, Bound<T>) {
1180    fn start_bound(&self) -> Bound<&T> {
1181        match *self {
1182            (Included(ref start), _) => Included(start),
1183            (Excluded(ref start), _) => Excluded(start),
1184            (Unbounded, _) => Unbounded,
1185        }
1186    }
1187
1188    fn end_bound(&self) -> Bound<&T> {
1189        match *self {
1190            (_, Included(ref end)) => Included(end),
1191            (_, Excluded(ref end)) => Excluded(end),
1192            (_, Unbounded) => Unbounded,
1193        }
1194    }
1195}
1196
1197#[unstable(feature = "range_into_bounds", issue = "136903")]
1198#[rustc_const_unstable(feature = "const_range", issue = "none")]
1199impl<T> const IntoBounds<T> for (Bound<T>, Bound<T>) {
1200    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1201        self
1202    }
1203}
1204
1205#[stable(feature = "collections_range", since = "1.28.0")]
1206#[rustc_const_unstable(feature = "const_range", issue = "none")]
1207impl<'a, T: ?Sized + 'a> const RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
1208    fn start_bound(&self) -> Bound<&T> {
1209        self.0
1210    }
1211
1212    fn end_bound(&self) -> Bound<&T> {
1213        self.1
1214    }
1215}
1216
1217// This impl intentionally does not have `T: ?Sized`;
1218// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1219//
1220/// If you need to use this implementation where `T` is unsized,
1221/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1222/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
1223#[stable(feature = "collections_range", since = "1.28.0")]
1224#[rustc_const_unstable(feature = "const_range", issue = "none")]
1225impl<T> const RangeBounds<T> for RangeFrom<&T> {
1226    fn start_bound(&self) -> Bound<&T> {
1227        Included(self.start)
1228    }
1229    fn end_bound(&self) -> Bound<&T> {
1230        Unbounded
1231    }
1232}
1233
1234// This impl intentionally does not have `T: ?Sized`;
1235// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1236//
1237/// If you need to use this implementation where `T` is unsized,
1238/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1239/// i.e. replace `..end` with `(Bound::Unbounded, Bound::Excluded(end))`.
1240#[stable(feature = "collections_range", since = "1.28.0")]
1241#[rustc_const_unstable(feature = "const_range", issue = "none")]
1242impl<T> const RangeBounds<T> for RangeTo<&T> {
1243    fn start_bound(&self) -> Bound<&T> {
1244        Unbounded
1245    }
1246    fn end_bound(&self) -> Bound<&T> {
1247        Excluded(self.end)
1248    }
1249}
1250
1251// This impl intentionally does not have `T: ?Sized`;
1252// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1253//
1254/// If you need to use this implementation where `T` is unsized,
1255/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1256/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
1257#[stable(feature = "collections_range", since = "1.28.0")]
1258#[rustc_const_unstable(feature = "const_range", issue = "none")]
1259impl<T> const RangeBounds<T> for Range<&T> {
1260    fn start_bound(&self) -> Bound<&T> {
1261        Included(self.start)
1262    }
1263    fn end_bound(&self) -> Bound<&T> {
1264        Excluded(self.end)
1265    }
1266}
1267
1268// This impl intentionally does not have `T: ?Sized`;
1269// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1270//
1271/// If you need to use this implementation where `T` is unsized,
1272/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1273/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
1274#[stable(feature = "collections_range", since = "1.28.0")]
1275#[rustc_const_unstable(feature = "const_range", issue = "none")]
1276impl<T> const RangeBounds<T> for RangeInclusive<&T> {
1277    fn start_bound(&self) -> Bound<&T> {
1278        Included(self.start)
1279    }
1280    fn end_bound(&self) -> Bound<&T> {
1281        Included(self.end)
1282    }
1283}
1284
1285// This impl intentionally does not have `T: ?Sized`;
1286// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1287//
1288/// If you need to use this implementation where `T` is unsized,
1289/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1290/// i.e. replace `..=end` with `(Bound::Unbounded, Bound::Included(end))`.
1291#[stable(feature = "collections_range", since = "1.28.0")]
1292#[rustc_const_unstable(feature = "const_range", issue = "none")]
1293impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
1294    fn start_bound(&self) -> Bound<&T> {
1295        Unbounded
1296    }
1297    fn end_bound(&self) -> Bound<&T> {
1298        Included(self.end)
1299    }
1300}
1301
1302/// An internal helper for `split_off` functions indicating
1303/// which end a `OneSidedRange` is bounded on.
1304#[unstable(feature = "one_sided_range", issue = "69780")]
1305#[allow(missing_debug_implementations)]
1306pub enum OneSidedRangeBound {
1307    /// The range is bounded inclusively from below and is unbounded above.
1308    StartInclusive,
1309    /// The range is bounded exclusively from above and is unbounded below.
1310    End,
1311    /// The range is bounded inclusively from above and is unbounded below.
1312    EndInclusive,
1313}
1314
1315/// `OneSidedRange` is implemented for built-in range types that are unbounded
1316/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
1317/// but `..`, `d..e`, and `f..=g` do not.
1318///
1319/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
1320/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
1321#[unstable(feature = "one_sided_range", issue = "69780")]
1322#[const_trait]
1323#[rustc_const_unstable(feature = "const_range", issue = "none")]
1324pub trait OneSidedRange<T>: RangeBounds<T> {
1325    /// An internal-only helper function for `split_off` and
1326    /// `split_off_mut` that returns the bound of the one-sided range.
1327    fn bound(self) -> (OneSidedRangeBound, T);
1328}
1329
1330#[unstable(feature = "one_sided_range", issue = "69780")]
1331#[rustc_const_unstable(feature = "const_range", issue = "none")]
1332impl<T> const OneSidedRange<T> for RangeTo<T>
1333where
1334    Self: RangeBounds<T>,
1335{
1336    fn bound(self) -> (OneSidedRangeBound, T) {
1337        (OneSidedRangeBound::End, self.end)
1338    }
1339}
1340
1341#[unstable(feature = "one_sided_range", issue = "69780")]
1342#[rustc_const_unstable(feature = "const_range", issue = "none")]
1343impl<T> const OneSidedRange<T> for RangeFrom<T>
1344where
1345    Self: RangeBounds<T>,
1346{
1347    fn bound(self) -> (OneSidedRangeBound, T) {
1348        (OneSidedRangeBound::StartInclusive, self.start)
1349    }
1350}
1351
1352#[unstable(feature = "one_sided_range", issue = "69780")]
1353#[rustc_const_unstable(feature = "const_range", issue = "none")]
1354impl<T> const OneSidedRange<T> for RangeToInclusive<T>
1355where
1356    Self: RangeBounds<T>,
1357{
1358    fn bound(self) -> (OneSidedRangeBound, T) {
1359        (OneSidedRangeBound::EndInclusive, self.end)
1360    }
1361}