Skip to main content

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