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