Skip to main content

core/
range.rs

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