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