core/
range.rs

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