Skip to main content

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 represents an overflow flag for either bound (start or end):
367    //  - `false` upon construction
368    //  - `false` when iteration has yielded an element and
369    //    neither bound has overflowed the valid range of `Idx`
370    //  - `true` when iteration has caused either bound to
371    //    overflow the valid range of `Idx`
372    //
373    // When this is true, `start` or `end` may be left in an unspecified state,
374    // often wrapping (modular arithmetic) around at the boundary of `Idx`.
375    //
376    // This is required to support PartialEq and Hash without a PartialOrd bound or specialization.
377    pub(crate) exhausted: bool,
378}
379
380impl<Idx> RangeInclusive<Idx> {
381    /// Creates a new inclusive range. Equivalent to writing `start..=end`.
382    ///
383    /// # Examples
384    ///
385    /// ```
386    /// use std::ops::RangeInclusive;
387    ///
388    /// assert_eq!(3..=5, RangeInclusive::new(3, 5));
389    /// ```
390    #[lang = "range_inclusive_new"]
391    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
392    #[inline]
393    #[rustc_promotable]
394    #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")]
395    pub const fn new(start: Idx, end: Idx) -> Self {
396        Self { start, end, exhausted: false }
397    }
398
399    /// Returns the lower bound of the range (inclusive).
400    ///
401    /// When using an inclusive range for iteration, the values of `start()` and
402    /// [`end()`] are unspecified after the iteration ended. To determine
403    /// whether the inclusive range is empty, use the [`is_empty()`] method
404    /// instead of comparing `start() > end()`.
405    ///
406    /// Note: the value returned by this method is unspecified after the range
407    /// has been iterated to exhaustion.
408    ///
409    /// [`end()`]: RangeInclusive::end
410    /// [`is_empty()`]: RangeInclusive::is_empty
411    ///
412    /// # Examples
413    ///
414    /// ```
415    /// assert_eq!((3..=5).start(), &3);
416    /// ```
417    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
418    #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")]
419    #[inline]
420    pub const fn start(&self) -> &Idx {
421        &self.start
422    }
423
424    /// Returns the upper bound of the range (inclusive).
425    ///
426    /// When using an inclusive range for iteration, the values of [`start()`]
427    /// and `end()` are unspecified after the iteration ended. To determine
428    /// whether the inclusive range is empty, use the [`is_empty()`] method
429    /// instead of comparing `start() > end()`.
430    ///
431    /// Note: the value returned by this method is unspecified after the range
432    /// has been iterated to exhaustion.
433    ///
434    /// [`start()`]: RangeInclusive::start
435    /// [`is_empty()`]: RangeInclusive::is_empty
436    ///
437    /// # Examples
438    ///
439    /// ```
440    /// assert_eq!((3..=5).end(), &5);
441    /// ```
442    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
443    #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")]
444    #[inline]
445    pub const fn end(&self) -> &Idx {
446        &self.end
447    }
448
449    /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound).
450    ///
451    /// Note: the value returned by this method is unspecified after the range
452    /// has been iterated to exhaustion.
453    ///
454    /// # Examples
455    ///
456    /// ```
457    /// assert_eq!((3..=5).into_inner(), (3, 5));
458    /// ```
459    #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
460    #[inline]
461    #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
462    pub const fn into_inner(self) -> (Idx, Idx) {
463        (self.start, self.end)
464    }
465}
466
467impl RangeInclusive<usize> {
468    /// Converts to an exclusive `Range` for `SliceIndex` implementations.
469    /// The caller is responsible for dealing with `end == usize::MAX`.
470    #[inline]
471    pub(crate) const fn into_slice_range(self) -> Range<usize> {
472        // Typically users should not be indexing with exhausted instances,
473        // but this heuristic should apply to most cases. This doesn't
474        // handle reverse iteration well (`next_back` and `nth_back` can
475        // cause `end` to wrap around to values at or near `usize::MAX`),
476        // but using an exhausted `RangeInclusive` after reverse iteration
477        // is an exceedingly rare case.
478
479        // If we're not exhausted, we want to simply slice `start..end + 1`.
480        // If we are exhausted, then slicing with `end + 1..end + 1` gives us an
481        // empty range that is still subject to bounds-checks for that endpoint.
482        let exclusive_end = self.end + 1;
483        let start = if self.exhausted { exclusive_end } else { self.start };
484        start..exclusive_end
485    }
486}
487
488#[stable(feature = "inclusive_range", since = "1.26.0")]
489impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
490    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
491        self.start.fmt(fmt)?;
492        write!(fmt, "..=")?;
493        self.end.fmt(fmt)?;
494        if self.exhausted {
495            write!(fmt, " (exhausted)")?;
496        }
497        Ok(())
498    }
499}
500
501impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
502    /// Returns `true` if `item` is contained in the range.
503    ///
504    /// # Examples
505    ///
506    /// ```
507    /// assert!(!(3..=5).contains(&2));
508    /// assert!( (3..=5).contains(&3));
509    /// assert!( (3..=5).contains(&4));
510    /// assert!( (3..=5).contains(&5));
511    /// assert!(!(3..=5).contains(&6));
512    ///
513    /// assert!( (3..=3).contains(&3));
514    /// assert!(!(3..=2).contains(&3));
515    ///
516    /// assert!( (0.0..=1.0).contains(&1.0));
517    /// assert!(!(0.0..=1.0).contains(&f32::NAN));
518    /// assert!(!(0.0..=f32::NAN).contains(&0.0));
519    /// assert!(!(f32::NAN..=1.0).contains(&1.0));
520    /// ```
521    ///
522    /// This method always returns `false` after iteration has finished:
523    ///
524    /// ```
525    /// let mut r = 3..=5;
526    /// assert!(r.contains(&3) && r.contains(&5));
527    /// for _ in r.by_ref() {}
528    /// // Precise field values are unspecified here
529    /// assert!(!r.contains(&3) && !r.contains(&5));
530    /// ```
531    #[inline]
532    #[stable(feature = "range_contains", since = "1.35.0")]
533    #[rustc_const_unstable(feature = "const_range", issue = "none")]
534    pub const fn contains<U>(&self, item: &U) -> bool
535    where
536        Idx: [const] PartialOrd<U>,
537        U: ?Sized + [const] PartialOrd<Idx>,
538    {
539        <Self as RangeBounds<Idx>>::contains(self, item)
540    }
541
542    /// Returns `true` if the range contains no items.
543    ///
544    /// # Examples
545    ///
546    /// ```
547    /// assert!(!(3..=5).is_empty());
548    /// assert!(!(3..=3).is_empty());
549    /// assert!( (3..=2).is_empty());
550    /// ```
551    ///
552    /// The range is empty if either side is incomparable:
553    ///
554    /// ```
555    /// assert!(!(3.0..=5.0).is_empty());
556    /// assert!( (3.0..=f32::NAN).is_empty());
557    /// assert!( (f32::NAN..=5.0).is_empty());
558    /// ```
559    ///
560    /// This method returns `true` after iteration has finished:
561    ///
562    /// ```
563    /// let mut r = 3..=5;
564    /// for _ in r.by_ref() {}
565    /// // Precise field values are unspecified here
566    /// assert!(r.is_empty());
567    /// ```
568    #[stable(feature = "range_is_empty", since = "1.47.0")]
569    #[inline]
570    #[rustc_const_unstable(feature = "const_range", issue = "none")]
571    pub const fn is_empty(&self) -> bool
572    where
573        Idx: [const] PartialOrd,
574    {
575        self.exhausted || !(self.start <= self.end)
576    }
577}
578
579/// A range only bounded inclusively above (`..=end`).
580///
581/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
582/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
583///
584/// # Examples
585///
586/// The `..=end` syntax is a `RangeToInclusive`:
587///
588/// ```
589/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
590/// ```
591///
592/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
593/// `for` loop directly. This won't compile:
594///
595/// ```compile_fail,E0277
596/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
597/// // std::iter::Iterator` is not satisfied
598/// for i in ..=5 {
599///     // ...
600/// }
601/// ```
602///
603/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
604/// array elements up to and including the index indicated by `end`.
605///
606/// ```
607/// let arr = [0, 1, 2, 3, 4];
608/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
609/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
610/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
611/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
612/// assert_eq!(arr[1.. 3], [   1, 2      ]);
613/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
614/// ```
615///
616/// [slicing index]: crate::slice::SliceIndex
617#[lang = "RangeToInclusive"]
618#[doc(alias = "..=")]
619#[derive(Copy, Hash)]
620#[derive(Clone, PartialEq, Eq)]
621#[stable(feature = "inclusive_range", since = "1.26.0")]
622pub struct RangeToInclusive<Idx> {
623    /// The upper bound of the range (inclusive)
624    #[stable(feature = "inclusive_range", since = "1.26.0")]
625    pub end: Idx,
626}
627
628#[stable(feature = "inclusive_range", since = "1.26.0")]
629impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
630    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
631        write!(fmt, "..=")?;
632        self.end.fmt(fmt)?;
633        Ok(())
634    }
635}
636
637impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
638    /// Returns `true` if `item` is contained in the range.
639    ///
640    /// # Examples
641    ///
642    /// ```
643    /// assert!( (..=5).contains(&-1_000_000_000));
644    /// assert!( (..=5).contains(&5));
645    /// assert!(!(..=5).contains(&6));
646    ///
647    /// assert!( (..=1.0).contains(&1.0));
648    /// assert!(!(..=1.0).contains(&f32::NAN));
649    /// assert!(!(..=f32::NAN).contains(&0.5));
650    /// ```
651    #[inline]
652    #[stable(feature = "range_contains", since = "1.35.0")]
653    #[rustc_const_unstable(feature = "const_range", issue = "none")]
654    pub const fn contains<U>(&self, item: &U) -> bool
655    where
656        Idx: [const] PartialOrd<U>,
657        U: ?Sized + [const] PartialOrd<Idx>,
658    {
659        <Self as RangeBounds<Idx>>::contains(self, item)
660    }
661}
662
663// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
664// because underflow would be possible with (..0).into()
665
666/// An endpoint of a range of keys.
667///
668/// # Examples
669///
670/// `Bound`s are range endpoints:
671///
672/// ```
673/// use std::ops::Bound::*;
674/// use std::ops::RangeBounds;
675///
676/// assert_eq!((..100).start_bound(), Unbounded);
677/// assert_eq!((1..12).start_bound(), Included(&1));
678/// assert_eq!((1..12).end_bound(), Excluded(&12));
679/// ```
680///
681/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
682/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
683///
684/// ```
685/// use std::collections::BTreeMap;
686/// use std::ops::Bound::{Excluded, Included, Unbounded};
687///
688/// let mut map = BTreeMap::new();
689/// map.insert(3, "a");
690/// map.insert(5, "b");
691/// map.insert(8, "c");
692///
693/// for (key, value) in map.range((Excluded(3), Included(8))) {
694///     println!("{key}: {value}");
695/// }
696///
697/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
698/// ```
699///
700/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range
701#[stable(feature = "collections_bound", since = "1.17.0")]
702#[derive(Copy, Debug, Hash)]
703#[derive_const(Clone, Eq, PartialEq)]
704pub enum Bound<T> {
705    /// An inclusive bound.
706    #[stable(feature = "collections_bound", since = "1.17.0")]
707    Included(#[stable(feature = "collections_bound", since = "1.17.0")] T),
708    /// An exclusive bound.
709    #[stable(feature = "collections_bound", since = "1.17.0")]
710    Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T),
711    /// An infinite endpoint. Indicates that there is no bound in this direction.
712    #[stable(feature = "collections_bound", since = "1.17.0")]
713    Unbounded,
714}
715
716impl<T> Bound<T> {
717    /// Converts from `&Bound<T>` to `Bound<&T>`.
718    #[inline]
719    #[stable(feature = "bound_as_ref_shared", since = "1.65.0")]
720    #[rustc_const_unstable(feature = "const_range", issue = "none")]
721    pub const fn as_ref(&self) -> Bound<&T> {
722        match *self {
723            Included(ref x) => Included(x),
724            Excluded(ref x) => Excluded(x),
725            Unbounded => Unbounded,
726        }
727    }
728
729    /// Converts from `&mut Bound<T>` to `Bound<&mut T>`.
730    #[inline]
731    #[unstable(feature = "bound_as_ref", issue = "80996")]
732    pub const fn as_mut(&mut self) -> Bound<&mut T> {
733        match *self {
734            Included(ref mut x) => Included(x),
735            Excluded(ref mut x) => Excluded(x),
736            Unbounded => Unbounded,
737        }
738    }
739
740    /// Maps a `Bound<T>` to a `Bound<U>` by applying a function to the contained value (including
741    /// both `Included` and `Excluded`), returning a `Bound` of the same kind.
742    ///
743    /// # Examples
744    ///
745    /// ```
746    /// use std::ops::Bound::*;
747    ///
748    /// let bound_string = Included("Hello, World!");
749    ///
750    /// assert_eq!(bound_string.map(|s| s.len()), Included(13));
751    /// ```
752    ///
753    /// ```
754    /// use std::ops::Bound;
755    /// use Bound::*;
756    ///
757    /// let unbounded_string: Bound<String> = Unbounded;
758    ///
759    /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded);
760    /// ```
761    #[inline]
762    #[stable(feature = "bound_map", since = "1.77.0")]
763    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Bound<U> {
764        match self {
765            Unbounded => Unbounded,
766            Included(x) => Included(f(x)),
767            Excluded(x) => Excluded(f(x)),
768        }
769    }
770}
771
772impl<T: Copy> Bound<&T> {
773    /// Map a `Bound<&T>` to a `Bound<T>` by copying the contents of the bound.
774    ///
775    /// # Examples
776    ///
777    /// ```
778    /// #![feature(bound_copied)]
779    ///
780    /// use std::ops::Bound::*;
781    /// use std::ops::RangeBounds;
782    ///
783    /// assert_eq!((1..12).start_bound(), Included(&1));
784    /// assert_eq!((1..12).start_bound().copied(), Included(1));
785    /// ```
786    #[unstable(feature = "bound_copied", issue = "145966")]
787    #[must_use]
788    pub const fn copied(self) -> Bound<T> {
789        match self {
790            Bound::Unbounded => Bound::Unbounded,
791            Bound::Included(x) => Bound::Included(*x),
792            Bound::Excluded(x) => Bound::Excluded(*x),
793        }
794    }
795}
796
797impl<T: Clone> Bound<&T> {
798    /// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
799    ///
800    /// # Examples
801    ///
802    /// ```
803    /// use std::ops::Bound::*;
804    /// use std::ops::RangeBounds;
805    ///
806    /// let a1 = String::from("a");
807    /// let (a2, a3, a4) = (a1.clone(), a1.clone(), a1.clone());
808    ///
809    /// assert_eq!(Included(&a1), (a2..).start_bound());
810    /// assert_eq!(Included(a3), (a4..).start_bound().cloned());
811    /// ```
812    #[must_use = "`self` will be dropped if the result is not used"]
813    #[stable(feature = "bound_cloned", since = "1.55.0")]
814    #[rustc_const_unstable(feature = "const_range", issue = "none")]
815    pub const fn cloned(self) -> Bound<T>
816    where
817        T: [const] Clone,
818    {
819        match self {
820            Bound::Unbounded => Bound::Unbounded,
821            Bound::Included(x) => Bound::Included(x.clone()),
822            Bound::Excluded(x) => Bound::Excluded(x.clone()),
823        }
824    }
825}
826
827/// `RangeBounds` is implemented by Rust's built-in range types, produced
828/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
829#[stable(feature = "collections_range", since = "1.28.0")]
830#[rustc_diagnostic_item = "RangeBounds"]
831#[rustc_const_unstable(feature = "const_range", issue = "none")]
832pub const trait RangeBounds<T: ?Sized> {
833    /// Start index bound.
834    ///
835    /// Returns the start value as a `Bound`.
836    ///
837    /// # Examples
838    ///
839    /// ```
840    /// use std::ops::Bound::*;
841    /// use std::ops::RangeBounds;
842    ///
843    /// assert_eq!((..10).start_bound(), Unbounded);
844    /// assert_eq!((3..10).start_bound(), Included(&3));
845    /// ```
846    #[stable(feature = "collections_range", since = "1.28.0")]
847    fn start_bound(&self) -> Bound<&T>;
848
849    /// End index bound.
850    ///
851    /// Returns the end value as a `Bound`.
852    ///
853    /// # Examples
854    ///
855    /// ```
856    /// use std::ops::Bound::*;
857    /// use std::ops::RangeBounds;
858    ///
859    /// assert_eq!((3..).end_bound(), Unbounded);
860    /// assert_eq!((3..10).end_bound(), Excluded(&10));
861    /// ```
862    #[stable(feature = "collections_range", since = "1.28.0")]
863    fn end_bound(&self) -> Bound<&T>;
864
865    /// Returns `true` if `item` is contained in the range.
866    ///
867    /// # Examples
868    ///
869    /// ```
870    /// assert!( (3..5).contains(&4));
871    /// assert!(!(3..5).contains(&2));
872    ///
873    /// assert!( (0.0..1.0).contains(&0.5));
874    /// assert!(!(0.0..1.0).contains(&f32::NAN));
875    /// assert!(!(0.0..f32::NAN).contains(&0.5));
876    /// assert!(!(f32::NAN..1.0).contains(&0.5));
877    /// ```
878    #[inline]
879    #[stable(feature = "range_contains", since = "1.35.0")]
880    fn contains<U>(&self, item: &U) -> bool
881    where
882        T: [const] PartialOrd<U>,
883        U: ?Sized + [const] PartialOrd<T>,
884    {
885        (match self.start_bound() {
886            Included(start) => start <= item,
887            Excluded(start) => start < item,
888            Unbounded => true,
889        }) && (match self.end_bound() {
890            Included(end) => item <= end,
891            Excluded(end) => item < end,
892            Unbounded => true,
893        })
894    }
895
896    /// Returns `true` if the range contains no items.
897    /// One-sided ranges (`RangeFrom`, etc) always return `false`.
898    ///
899    /// # Examples
900    ///
901    /// ```
902    /// #![feature(range_bounds_is_empty)]
903    /// use std::ops::RangeBounds;
904    ///
905    /// assert!(!(3..).is_empty());
906    /// assert!(!(..2).is_empty());
907    /// assert!(!RangeBounds::is_empty(&(3..5)));
908    /// assert!( RangeBounds::is_empty(&(3..3)));
909    /// assert!( RangeBounds::is_empty(&(3..2)));
910    /// ```
911    ///
912    /// The range is empty if either side is incomparable:
913    ///
914    /// ```
915    /// #![feature(range_bounds_is_empty)]
916    /// use std::ops::RangeBounds;
917    ///
918    /// assert!(!RangeBounds::is_empty(&(3.0..5.0)));
919    /// assert!( RangeBounds::is_empty(&(3.0..f32::NAN)));
920    /// assert!( RangeBounds::is_empty(&(f32::NAN..5.0)));
921    /// ```
922    ///
923    /// But never empty if either side is unbounded:
924    ///
925    /// ```
926    /// #![feature(range_bounds_is_empty)]
927    /// use std::ops::RangeBounds;
928    ///
929    /// assert!(!(..0).is_empty());
930    /// assert!(!(i32::MAX..).is_empty());
931    /// assert!(!RangeBounds::<u8>::is_empty(&(..)));
932    /// ```
933    ///
934    /// `(Excluded(a), Excluded(b))` is only empty if `a >= b`:
935    ///
936    /// ```
937    /// #![feature(range_bounds_is_empty)]
938    /// use std::ops::Bound::*;
939    /// use std::ops::RangeBounds;
940    ///
941    /// assert!(!(Excluded(1), Excluded(3)).is_empty());
942    /// assert!(!(Excluded(1), Excluded(2)).is_empty());
943    /// assert!( (Excluded(1), Excluded(1)).is_empty());
944    /// assert!( (Excluded(2), Excluded(1)).is_empty());
945    /// assert!( (Excluded(3), Excluded(1)).is_empty());
946    /// ```
947    #[unstable(feature = "range_bounds_is_empty", issue = "137300")]
948    fn is_empty(&self) -> bool
949    where
950        T: [const] PartialOrd,
951    {
952        !match (self.start_bound(), self.end_bound()) {
953            (Unbounded, _) | (_, Unbounded) => true,
954            (Included(start), Excluded(end))
955            | (Excluded(start), Included(end))
956            | (Excluded(start), Excluded(end)) => start < end,
957            (Included(start), Included(end)) => start <= end,
958        }
959    }
960}
961
962/// Used to convert a range into start and end bounds, consuming the
963/// range by value.
964///
965/// `IntoBounds` is implemented by Rust’s built-in range types, produced
966/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
967#[unstable(feature = "range_into_bounds", issue = "136903")]
968#[rustc_const_unstable(feature = "const_range", issue = "none")]
969pub const trait IntoBounds<T>: [const] RangeBounds<T> {
970    /// Convert this range into the start and end bounds.
971    /// Returns `(start_bound, end_bound)`.
972    ///
973    /// # Examples
974    ///
975    /// ```
976    /// #![feature(range_into_bounds)]
977    /// use std::ops::Bound::*;
978    /// use std::ops::IntoBounds;
979    ///
980    /// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5)));
981    /// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7)));
982    /// ```
983    fn into_bounds(self) -> (Bound<T>, Bound<T>);
984
985    /// Compute the intersection of  `self` and `other`.
986    ///
987    /// # Examples
988    ///
989    /// ```
990    /// #![feature(range_into_bounds)]
991    /// use std::ops::Bound::*;
992    /// use std::ops::IntoBounds;
993    ///
994    /// assert_eq!((3..).intersect(..5), (Included(3), Excluded(5)));
995    /// assert_eq!((-12..387).intersect(0..256), (Included(0), Excluded(256)));
996    /// assert_eq!((1..5).intersect(..), (Included(1), Excluded(5)));
997    /// assert_eq!((1..=9).intersect(0..10), (Included(1), Included(9)));
998    /// assert_eq!((7..=13).intersect(8..13), (Included(8), Excluded(13)));
999    /// ```
1000    ///
1001    /// Combine with `is_empty` to determine if two ranges overlap.
1002    ///
1003    /// ```
1004    /// #![feature(range_into_bounds)]
1005    /// #![feature(range_bounds_is_empty)]
1006    /// use std::ops::{RangeBounds, IntoBounds};
1007    ///
1008    /// assert!(!(3..).intersect(..5).is_empty());
1009    /// assert!(!(-12..387).intersect(0..256).is_empty());
1010    /// assert!((1..5).intersect(6..).is_empty());
1011    /// ```
1012    fn intersect<R>(self, other: R) -> (Bound<T>, Bound<T>)
1013    where
1014        Self: Sized,
1015        T: [const] Ord + [const] Destruct,
1016        R: Sized + [const] IntoBounds<T>,
1017    {
1018        let (self_start, self_end) = IntoBounds::into_bounds(self);
1019        let (other_start, other_end) = IntoBounds::into_bounds(other);
1020
1021        let start = match (self_start, other_start) {
1022            (Included(a), Included(b)) => Included(Ord::max(a, b)),
1023            (Excluded(a), Excluded(b)) => Excluded(Ord::max(a, b)),
1024            (Unbounded, Unbounded) => Unbounded,
1025
1026            (x, Unbounded) | (Unbounded, x) => x,
1027
1028            (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
1029                if i > e {
1030                    Included(i)
1031                } else {
1032                    Excluded(e)
1033                }
1034            }
1035        };
1036        let end = match (self_end, other_end) {
1037            (Included(a), Included(b)) => Included(Ord::min(a, b)),
1038            (Excluded(a), Excluded(b)) => Excluded(Ord::min(a, b)),
1039            (Unbounded, Unbounded) => Unbounded,
1040
1041            (x, Unbounded) | (Unbounded, x) => x,
1042
1043            (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
1044                if i < e {
1045                    Included(i)
1046                } else {
1047                    Excluded(e)
1048                }
1049            }
1050        };
1051
1052        (start, end)
1053    }
1054}
1055
1056use self::Bound::{Excluded, Included, Unbounded};
1057
1058#[stable(feature = "collections_range", since = "1.28.0")]
1059#[rustc_const_unstable(feature = "const_range", issue = "none")]
1060const impl<T: ?Sized> RangeBounds<T> for RangeFull {
1061    fn start_bound(&self) -> Bound<&T> {
1062        Unbounded
1063    }
1064    fn end_bound(&self) -> Bound<&T> {
1065        Unbounded
1066    }
1067}
1068
1069#[unstable(feature = "range_into_bounds", issue = "136903")]
1070#[rustc_const_unstable(feature = "const_range", issue = "none")]
1071const impl<T> IntoBounds<T> for RangeFull {
1072    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1073        (Unbounded, Unbounded)
1074    }
1075}
1076
1077#[stable(feature = "collections_range", since = "1.28.0")]
1078#[rustc_const_unstable(feature = "const_range", issue = "none")]
1079const impl<T> RangeBounds<T> for RangeFrom<T> {
1080    fn start_bound(&self) -> Bound<&T> {
1081        Included(&self.start)
1082    }
1083    fn end_bound(&self) -> Bound<&T> {
1084        Unbounded
1085    }
1086}
1087
1088#[unstable(feature = "range_into_bounds", issue = "136903")]
1089#[rustc_const_unstable(feature = "const_range", issue = "none")]
1090const impl<T> IntoBounds<T> for RangeFrom<T> {
1091    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1092        (Included(self.start), Unbounded)
1093    }
1094}
1095
1096#[stable(feature = "collections_range", since = "1.28.0")]
1097#[rustc_const_unstable(feature = "const_range", issue = "none")]
1098const impl<T> RangeBounds<T> for RangeTo<T> {
1099    fn start_bound(&self) -> Bound<&T> {
1100        Unbounded
1101    }
1102    fn end_bound(&self) -> Bound<&T> {
1103        Excluded(&self.end)
1104    }
1105}
1106
1107#[unstable(feature = "range_into_bounds", issue = "136903")]
1108#[rustc_const_unstable(feature = "const_range", issue = "none")]
1109const impl<T> IntoBounds<T> for RangeTo<T> {
1110    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1111        (Unbounded, Excluded(self.end))
1112    }
1113}
1114
1115#[stable(feature = "collections_range", since = "1.28.0")]
1116#[rustc_const_unstable(feature = "const_range", issue = "none")]
1117const impl<T> RangeBounds<T> for Range<T> {
1118    fn start_bound(&self) -> Bound<&T> {
1119        Included(&self.start)
1120    }
1121    fn end_bound(&self) -> Bound<&T> {
1122        Excluded(&self.end)
1123    }
1124}
1125
1126#[unstable(feature = "range_into_bounds", issue = "136903")]
1127#[rustc_const_unstable(feature = "const_range", issue = "none")]
1128const impl<T> IntoBounds<T> for Range<T> {
1129    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1130        (Included(self.start), Excluded(self.end))
1131    }
1132}
1133
1134#[stable(feature = "collections_range", since = "1.28.0")]
1135#[rustc_const_unstable(feature = "const_range", issue = "none")]
1136const impl<T> RangeBounds<T> for RangeInclusive<T> {
1137    fn start_bound(&self) -> Bound<&T> {
1138        Included(&self.start)
1139    }
1140    fn end_bound(&self) -> Bound<&T> {
1141        if self.exhausted {
1142            // When the iterator is exhausted, it might have overflowed,
1143            // but we want the range to appear empty, containing nothing.
1144            // So in that case, we return bounds which are always empty:
1145            // Included(start)..Excluded(start)
1146            Excluded(&self.start)
1147        } else {
1148            Included(&self.end)
1149        }
1150    }
1151}
1152
1153#[unstable(feature = "range_into_bounds", issue = "136903")]
1154#[rustc_const_unstable(feature = "const_range", issue = "none")]
1155const impl<T> IntoBounds<T> for RangeInclusive<T> {
1156    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1157        assert!(
1158            !self.exhausted,
1159            "attempted to convert from an exhausted `RangeInclusive` (unspecified behavior)"
1160        );
1161
1162        (Included(self.start), Included(self.end))
1163    }
1164}
1165
1166#[stable(feature = "collections_range", since = "1.28.0")]
1167#[rustc_const_unstable(feature = "const_range", issue = "none")]
1168const impl<T> RangeBounds<T> for RangeToInclusive<T> {
1169    fn start_bound(&self) -> Bound<&T> {
1170        Unbounded
1171    }
1172    fn end_bound(&self) -> Bound<&T> {
1173        Included(&self.end)
1174    }
1175}
1176
1177#[unstable(feature = "range_into_bounds", issue = "136903")]
1178#[rustc_const_unstable(feature = "const_range", issue = "none")]
1179const impl<T> IntoBounds<T> for RangeToInclusive<T> {
1180    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1181        (Unbounded, Included(self.end))
1182    }
1183}
1184
1185#[stable(feature = "collections_range", since = "1.28.0")]
1186#[rustc_const_unstable(feature = "const_range", issue = "none")]
1187const impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
1188    fn start_bound(&self) -> Bound<&T> {
1189        match *self {
1190            (Included(ref start), _) => Included(start),
1191            (Excluded(ref start), _) => Excluded(start),
1192            (Unbounded, _) => Unbounded,
1193        }
1194    }
1195
1196    fn end_bound(&self) -> Bound<&T> {
1197        match *self {
1198            (_, Included(ref end)) => Included(end),
1199            (_, Excluded(ref end)) => Excluded(end),
1200            (_, Unbounded) => Unbounded,
1201        }
1202    }
1203}
1204
1205#[unstable(feature = "range_into_bounds", issue = "136903")]
1206#[rustc_const_unstable(feature = "const_range", issue = "none")]
1207const impl<T> IntoBounds<T> for (Bound<T>, Bound<T>) {
1208    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1209        self
1210    }
1211}
1212
1213#[stable(feature = "collections_range", since = "1.28.0")]
1214#[rustc_const_unstable(feature = "const_range", issue = "none")]
1215const impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
1216    fn start_bound(&self) -> Bound<&T> {
1217        self.0
1218    }
1219
1220    fn end_bound(&self) -> Bound<&T> {
1221        self.1
1222    }
1223}
1224
1225// This impl intentionally does not have `T: ?Sized`;
1226// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1227//
1228/// If you need to use this implementation where `T` is unsized,
1229/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1230/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
1231#[stable(feature = "collections_range", since = "1.28.0")]
1232#[rustc_const_unstable(feature = "const_range", issue = "none")]
1233const impl<T> RangeBounds<T> for RangeFrom<&T> {
1234    fn start_bound(&self) -> Bound<&T> {
1235        Included(self.start)
1236    }
1237    fn end_bound(&self) -> Bound<&T> {
1238        Unbounded
1239    }
1240}
1241
1242// This impl intentionally does not have `T: ?Sized`;
1243// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1244//
1245/// If you need to use this implementation where `T` is unsized,
1246/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1247/// i.e. replace `..end` with `(Bound::Unbounded, Bound::Excluded(end))`.
1248#[stable(feature = "collections_range", since = "1.28.0")]
1249#[rustc_const_unstable(feature = "const_range", issue = "none")]
1250const impl<T> RangeBounds<T> for RangeTo<&T> {
1251    fn start_bound(&self) -> Bound<&T> {
1252        Unbounded
1253    }
1254    fn end_bound(&self) -> Bound<&T> {
1255        Excluded(self.end)
1256    }
1257}
1258
1259// This impl intentionally does not have `T: ?Sized`;
1260// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1261//
1262/// If you need to use this implementation where `T` is unsized,
1263/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1264/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
1265#[stable(feature = "collections_range", since = "1.28.0")]
1266#[rustc_const_unstable(feature = "const_range", issue = "none")]
1267const impl<T> RangeBounds<T> for Range<&T> {
1268    fn start_bound(&self) -> Bound<&T> {
1269        Included(self.start)
1270    }
1271    fn end_bound(&self) -> Bound<&T> {
1272        Excluded(self.end)
1273    }
1274}
1275
1276// This impl intentionally does not have `T: ?Sized`;
1277// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1278//
1279/// If you need to use this implementation where `T` is unsized,
1280/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1281/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
1282#[stable(feature = "collections_range", since = "1.28.0")]
1283#[rustc_const_unstable(feature = "const_range", issue = "none")]
1284const impl<T> RangeBounds<T> for RangeInclusive<&T> {
1285    fn start_bound(&self) -> Bound<&T> {
1286        Included(self.start)
1287    }
1288    fn end_bound(&self) -> Bound<&T> {
1289        Included(self.end)
1290    }
1291}
1292
1293// This impl intentionally does not have `T: ?Sized`;
1294// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1295//
1296/// If you need to use this implementation where `T` is unsized,
1297/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1298/// i.e. replace `..=end` with `(Bound::Unbounded, Bound::Included(end))`.
1299#[stable(feature = "collections_range", since = "1.28.0")]
1300#[rustc_const_unstable(feature = "const_range", issue = "none")]
1301const impl<T> RangeBounds<T> for RangeToInclusive<&T> {
1302    fn start_bound(&self) -> Bound<&T> {
1303        Unbounded
1304    }
1305    fn end_bound(&self) -> Bound<&T> {
1306        Included(self.end)
1307    }
1308}
1309
1310/// An internal helper for `split_off` functions indicating
1311/// which end a `OneSidedRange` is bounded on.
1312#[unstable(feature = "one_sided_range", issue = "69780")]
1313#[allow(missing_debug_implementations)]
1314pub enum OneSidedRangeBound {
1315    /// The range is bounded inclusively from below and is unbounded above.
1316    StartInclusive,
1317    /// The range is bounded exclusively from above and is unbounded below.
1318    End,
1319    /// The range is bounded inclusively from above and is unbounded below.
1320    EndInclusive,
1321}
1322
1323/// `OneSidedRange` is implemented for built-in range types that are unbounded
1324/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
1325/// but `..`, `d..e`, and `f..=g` do not.
1326///
1327/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
1328/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
1329#[unstable(feature = "one_sided_range", issue = "69780")]
1330#[rustc_const_unstable(feature = "const_range", issue = "none")]
1331pub const trait OneSidedRange<T>: RangeBounds<T> {
1332    /// An internal-only helper function for `split_off` and
1333    /// `split_off_mut` that returns the bound of the one-sided range.
1334    fn bound(self) -> (OneSidedRangeBound, T);
1335}
1336
1337#[unstable(feature = "one_sided_range", issue = "69780")]
1338#[rustc_const_unstable(feature = "const_range", issue = "none")]
1339const impl<T> OneSidedRange<T> for RangeTo<T>
1340where
1341    Self: RangeBounds<T>,
1342{
1343    fn bound(self) -> (OneSidedRangeBound, T) {
1344        (OneSidedRangeBound::End, self.end)
1345    }
1346}
1347
1348#[unstable(feature = "one_sided_range", issue = "69780")]
1349#[rustc_const_unstable(feature = "const_range", issue = "none")]
1350const impl<T> OneSidedRange<T> for RangeFrom<T>
1351where
1352    Self: RangeBounds<T>,
1353{
1354    fn bound(self) -> (OneSidedRangeBound, T) {
1355        (OneSidedRangeBound::StartInclusive, self.start)
1356    }
1357}
1358
1359#[unstable(feature = "one_sided_range", issue = "69780")]
1360#[rustc_const_unstable(feature = "const_range", issue = "none")]
1361const impl<T> OneSidedRange<T> for RangeToInclusive<T>
1362where
1363    Self: RangeBounds<T>,
1364{
1365    fn bound(self) -> (OneSidedRangeBound, T) {
1366        (OneSidedRangeBound::EndInclusive, self.end)
1367    }
1368}