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///
52/// The `Range` contains all values with `start <= x < end`.
53/// It is empty if `start >= end`.
54///
55/// # Examples
56///
57/// ```
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///
64/// # Edition notes
65///
66/// It is planned that the syntax `start..end` will construct this
67/// type in a future edition, but it does not do so today.
68#[lang = "RangeCopy"]
69#[derive(Copy, Hash)]
70#[derive_const(Clone, Default, PartialEq, Eq)]
71#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
72pub struct Range<Idx> {
73    /// The lower bound of the range (inclusive).
74    #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
75    pub start: Idx,
76    /// The upper bound of the range (exclusive).
77    #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
78    pub end: Idx,
79}
80
81#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
82impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
83    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
84        self.start.fmt(fmt)?;
85        write!(fmt, "..")?;
86        self.end.fmt(fmt)?;
87        Ok(())
88    }
89}
90
91impl<Idx: Step> Range<Idx> {
92    /// Creates an iterator over the elements within this range.
93    ///
94    /// Shorthand for `.clone().into_iter()`
95    ///
96    /// # Examples
97    ///
98    /// ```
99    /// use core::range::Range;
100    ///
101    /// let mut i = Range::from(3..9).iter().map(|n| n*n);
102    /// assert_eq!(i.next(), Some(9));
103    /// assert_eq!(i.next(), Some(16));
104    /// assert_eq!(i.next(), Some(25));
105    /// ```
106    #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
107    #[inline]
108    pub fn iter(&self) -> RangeIter<Idx> {
109        self.clone().into_iter()
110    }
111}
112
113impl<Idx: PartialOrd<Idx>> Range<Idx> {
114    /// Returns `true` if `item` is contained in the range.
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use core::range::Range;
120    ///
121    /// assert!(!Range::from(3..5).contains(&2));
122    /// assert!( Range::from(3..5).contains(&3));
123    /// assert!( Range::from(3..5).contains(&4));
124    /// assert!(!Range::from(3..5).contains(&5));
125    ///
126    /// assert!(!Range::from(3..3).contains(&3));
127    /// assert!(!Range::from(3..2).contains(&3));
128    ///
129    /// assert!( Range::from(0.0..1.0).contains(&0.5));
130    /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN));
131    /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5));
132    /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5));
133    /// ```
134    #[inline]
135    #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
136    #[rustc_const_unstable(feature = "const_range", issue = "none")]
137    pub const fn contains<U>(&self, item: &U) -> bool
138    where
139        Idx: [const] PartialOrd<U>,
140        U: ?Sized + [const] PartialOrd<Idx>,
141    {
142        <Self as RangeBounds<Idx>>::contains(self, item)
143    }
144
145    /// Returns `true` if the range contains no items.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use core::range::Range;
151    ///
152    /// assert!(!Range::from(3..5).is_empty());
153    /// assert!( Range::from(3..3).is_empty());
154    /// assert!( Range::from(3..2).is_empty());
155    /// ```
156    ///
157    /// The range is empty if either side is incomparable:
158    ///
159    /// ```
160    /// use core::range::Range;
161    ///
162    /// assert!(!Range::from(3.0..5.0).is_empty());
163    /// assert!( Range::from(3.0..f32::NAN).is_empty());
164    /// assert!( Range::from(f32::NAN..5.0).is_empty());
165    /// ```
166    #[inline]
167    #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
168    #[rustc_const_unstable(feature = "const_range", issue = "none")]
169    pub const fn is_empty(&self) -> bool
170    where
171        Idx: [const] PartialOrd,
172    {
173        !(self.start < self.end)
174    }
175}
176
177#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
178#[rustc_const_unstable(feature = "const_range", issue = "none")]
179impl<T> const RangeBounds<T> for Range<T> {
180    fn start_bound(&self) -> Bound<&T> {
181        Included(&self.start)
182    }
183    fn end_bound(&self) -> Bound<&T> {
184        Excluded(&self.end)
185    }
186}
187
188// This impl intentionally does not have `T: ?Sized`;
189// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
190//
191/// If you need to use this implementation where `T` is unsized,
192/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
193/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
194#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
195#[rustc_const_unstable(feature = "const_range", issue = "none")]
196impl<T> const RangeBounds<T> for Range<&T> {
197    fn start_bound(&self) -> Bound<&T> {
198        Included(self.start)
199    }
200    fn end_bound(&self) -> Bound<&T> {
201        Excluded(self.end)
202    }
203}
204
205#[unstable(feature = "range_into_bounds", issue = "136903")]
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#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
222#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
223impl<T> const From<legacy::Range<T>> for Range<T> {
224    #[inline]
225    fn from(value: legacy::Range<T>) -> Self {
226        Self { start: value.start, end: value.end }
227    }
228}
229
230/// A range bounded inclusively below and above.
231///
232/// The `RangeInclusive` contains all values with `x >= start`
233/// and `x <= last`. It is empty unless `start <= last`.
234///
235/// # Examples
236///
237/// ```
238/// use core::range::RangeInclusive;
239///
240/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
241/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
242/// ```
243///
244/// # Edition notes
245///
246/// It is planned that the syntax  `start..=last` will construct this
247/// type in a future edition, but it does not do so today.
248#[lang = "RangeInclusiveCopy"]
249#[derive(Clone, Copy, PartialEq, Eq, Hash)]
250#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
251pub struct RangeInclusive<Idx> {
252    /// The lower bound of the range (inclusive).
253    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
254    pub start: Idx,
255    /// The upper bound of the range (inclusive).
256    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
257    pub last: Idx,
258}
259
260#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
261impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
262    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
263        self.start.fmt(fmt)?;
264        write!(fmt, "..=")?;
265        self.last.fmt(fmt)?;
266        Ok(())
267    }
268}
269
270impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
271    /// Returns `true` if `item` is contained in the range.
272    ///
273    /// # Examples
274    ///
275    /// ```
276    /// use core::range::RangeInclusive;
277    ///
278    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
279    /// assert!( RangeInclusive::from(3..=5).contains(&3));
280    /// assert!( RangeInclusive::from(3..=5).contains(&4));
281    /// assert!( RangeInclusive::from(3..=5).contains(&5));
282    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
283    ///
284    /// assert!( RangeInclusive::from(3..=3).contains(&3));
285    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
286    ///
287    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
288    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
289    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
290    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
291    /// ```
292    #[inline]
293    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
294    #[rustc_const_unstable(feature = "const_range", issue = "none")]
295    pub const fn contains<U>(&self, item: &U) -> bool
296    where
297        Idx: [const] PartialOrd<U>,
298        U: ?Sized + [const] PartialOrd<Idx>,
299    {
300        <Self as RangeBounds<Idx>>::contains(self, item)
301    }
302
303    /// Returns `true` if the range contains no items.
304    ///
305    /// # Examples
306    ///
307    /// ```
308    /// use core::range::RangeInclusive;
309    ///
310    /// assert!(!RangeInclusive::from(3..=5).is_empty());
311    /// assert!(!RangeInclusive::from(3..=3).is_empty());
312    /// assert!( RangeInclusive::from(3..=2).is_empty());
313    /// ```
314    ///
315    /// The range is empty if either side is incomparable:
316    ///
317    /// ```
318    /// use core::range::RangeInclusive;
319    ///
320    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
321    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
322    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
323    /// ```
324    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
325    #[inline]
326    #[rustc_const_unstable(feature = "const_range", issue = "none")]
327    pub const fn is_empty(&self) -> bool
328    where
329        Idx: [const] PartialOrd,
330    {
331        !(self.start <= self.last)
332    }
333}
334
335impl<Idx: Step> RangeInclusive<Idx> {
336    /// Creates an iterator over the elements within this range.
337    ///
338    /// Shorthand for `.clone().into_iter()`
339    ///
340    /// # Examples
341    ///
342    /// ```
343    /// use core::range::RangeInclusive;
344    ///
345    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
346    /// assert_eq!(i.next(), Some(9));
347    /// assert_eq!(i.next(), Some(16));
348    /// assert_eq!(i.next(), Some(25));
349    /// ```
350    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
351    #[inline]
352    pub fn iter(&self) -> RangeInclusiveIter<Idx> {
353        self.clone().into_iter()
354    }
355}
356
357#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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// #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
386#[unstable(feature = "range_into_bounds", issue = "136903")]
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#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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.
418///
419/// The `RangeFrom` contains all values with `x >= start`.
420///
421/// *Note*: Overflow in the [`IntoIterator`] 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). Unlike
426/// its legacy counterpart, the iterator will only panic after yielding the
427/// maximum value when overflow checks are enabled.
428///
429/// [`Step`]: crate::iter::Step
430///
431/// # Examples
432///
433/// ```
434/// use core::range::RangeFrom;
435///
436/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
437/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
438/// ```
439///
440/// # Edition notes
441///
442/// It is planned that the syntax  `start..` will construct this
443/// type in a future edition, but it does not do so today.
444#[lang = "RangeFromCopy"]
445#[derive(Copy, Hash)]
446#[derive_const(Clone, PartialEq, Eq)]
447#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
448pub struct RangeFrom<Idx> {
449    /// The lower bound of the range (inclusive).
450    #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
451    pub start: Idx,
452}
453
454#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
455impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
456    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
457        self.start.fmt(fmt)?;
458        write!(fmt, "..")?;
459        Ok(())
460    }
461}
462
463impl<Idx: Step> RangeFrom<Idx> {
464    /// Creates an iterator over the elements within this range.
465    ///
466    /// Shorthand for `.clone().into_iter()`
467    ///
468    /// # Examples
469    ///
470    /// ```
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    #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
479    #[inline]
480    pub fn iter(&self) -> RangeFromIter<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    /// use core::range::RangeFrom;
492    ///
493    /// assert!(!RangeFrom::from(3..).contains(&2));
494    /// assert!( RangeFrom::from(3..).contains(&3));
495    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
496    ///
497    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
498    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
499    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
500    /// ```
501    #[inline]
502    #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
503    #[rustc_const_unstable(feature = "const_range", issue = "none")]
504    pub const fn contains<U>(&self, item: &U) -> bool
505    where
506        Idx: [const] PartialOrd<U>,
507        U: ?Sized + [const] PartialOrd<Idx>,
508    {
509        <Self as RangeBounds<Idx>>::contains(self, item)
510    }
511}
512
513#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
514#[rustc_const_unstable(feature = "const_range", issue = "none")]
515impl<T> const RangeBounds<T> for RangeFrom<T> {
516    fn start_bound(&self) -> Bound<&T> {
517        Included(&self.start)
518    }
519    fn end_bound(&self) -> Bound<&T> {
520        Unbounded
521    }
522}
523
524// This impl intentionally does not have `T: ?Sized`;
525// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
526//
527/// If you need to use this implementation where `T` is unsized,
528/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
529/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
530#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
531#[rustc_const_unstable(feature = "const_range", issue = "none")]
532impl<T> const RangeBounds<T> for RangeFrom<&T> {
533    fn start_bound(&self) -> Bound<&T> {
534        Included(self.start)
535    }
536    fn end_bound(&self) -> Bound<&T> {
537        Unbounded
538    }
539}
540
541#[unstable(feature = "range_into_bounds", issue = "136903")]
542#[rustc_const_unstable(feature = "const_range", issue = "none")]
543impl<T> const IntoBounds<T> for RangeFrom<T> {
544    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
545        (Included(self.start), Unbounded)
546    }
547}
548
549#[unstable(feature = "one_sided_range", issue = "69780")]
550#[rustc_const_unstable(feature = "const_range", issue = "none")]
551impl<T> const OneSidedRange<T> for RangeFrom<T>
552where
553    Self: RangeBounds<T>,
554{
555    fn bound(self) -> (OneSidedRangeBound, T) {
556        (OneSidedRangeBound::StartInclusive, self.start)
557    }
558}
559
560#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
561#[rustc_const_unstable(feature = "const_index", issue = "143775")]
562impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
563    #[inline]
564    fn from(value: RangeFrom<T>) -> Self {
565        Self { start: value.start }
566    }
567}
568#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
569#[rustc_const_unstable(feature = "const_index", issue = "143775")]
570impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
571    #[inline]
572    fn from(value: legacy::RangeFrom<T>) -> Self {
573        Self { start: value.start }
574    }
575}
576
577/// A range only bounded inclusively above.
578///
579/// The `RangeToInclusive` contains all values with `x <= last`.
580/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
581///
582/// # Examples
583///
584/// ```standalone_crate
585/// #![feature(new_range)]
586/// assert_eq!((..=5), std::range::RangeToInclusive { last: 5 });
587/// ```
588///
589/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
590/// `for` loop directly. This won't compile:
591///
592/// ```compile_fail,E0277
593/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
594/// // std::iter::Iterator` is not satisfied
595/// for i in ..=5 {
596///     // ...
597/// }
598/// ```
599///
600/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
601/// array elements up to and including the index indicated by `last`.
602///
603/// ```
604/// let arr = [0, 1, 2, 3, 4];
605/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
606/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
607/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
608/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
609/// assert_eq!(arr[1.. 3], [   1, 2      ]);
610/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
611/// ```
612///
613/// [slicing index]: crate::slice::SliceIndex
614///
615/// # Edition notes
616///
617/// It is planned that the syntax  `..=last` will construct this
618/// type in a future edition, but it does not do so today.
619#[lang = "RangeToInclusiveCopy"]
620#[doc(alias = "..=")]
621#[derive(Copy, Clone, PartialEq, Eq, Hash)]
622#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
623pub struct RangeToInclusive<Idx> {
624    /// The upper bound of the range (inclusive)
625    #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
626    pub last: Idx,
627}
628
629#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
630impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
631    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
632        write!(fmt, "..=")?;
633        self.last.fmt(fmt)?;
634        Ok(())
635    }
636}
637
638impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
639    /// Returns `true` if `item` is contained in the range.
640    ///
641    /// # Examples
642    ///
643    /// ```
644    /// assert!( (..=5).contains(&-1_000_000_000));
645    /// assert!( (..=5).contains(&5));
646    /// assert!(!(..=5).contains(&6));
647    ///
648    /// assert!( (..=1.0).contains(&1.0));
649    /// assert!(!(..=1.0).contains(&f32::NAN));
650    /// assert!(!(..=f32::NAN).contains(&0.5));
651    /// ```
652    #[inline]
653    #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
654    #[rustc_const_unstable(feature = "const_range", issue = "none")]
655    pub const fn contains<U>(&self, item: &U) -> bool
656    where
657        Idx: [const] PartialOrd<U>,
658        U: ?Sized + [const] PartialOrd<Idx>,
659    {
660        <Self as RangeBounds<Idx>>::contains(self, item)
661    }
662}
663
664#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
665impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
666    fn from(value: legacy::RangeToInclusive<T>) -> Self {
667        Self { last: value.end }
668    }
669}
670#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
671impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
672    fn from(value: RangeToInclusive<T>) -> Self {
673        Self { end: value.last }
674    }
675}
676
677// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
678// because underflow would be possible with (..0).into()
679
680#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
681#[rustc_const_unstable(feature = "const_range", issue = "none")]
682impl<T> const RangeBounds<T> for RangeToInclusive<T> {
683    fn start_bound(&self) -> Bound<&T> {
684        Unbounded
685    }
686    fn end_bound(&self) -> Bound<&T> {
687        Included(&self.last)
688    }
689}
690
691#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
692#[rustc_const_unstable(feature = "const_range", issue = "none")]
693impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
694    fn start_bound(&self) -> Bound<&T> {
695        Unbounded
696    }
697    fn end_bound(&self) -> Bound<&T> {
698        Included(self.last)
699    }
700}
701
702#[unstable(feature = "range_into_bounds", issue = "136903")]
703#[rustc_const_unstable(feature = "const_range", issue = "none")]
704impl<T> const IntoBounds<T> for RangeToInclusive<T> {
705    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
706        (Unbounded, Included(self.last))
707    }
708}
709
710#[unstable(feature = "one_sided_range", issue = "69780")]
711#[rustc_const_unstable(feature = "const_range", issue = "none")]
712impl<T> const OneSidedRange<T> for RangeToInclusive<T>
713where
714    Self: RangeBounds<T>,
715{
716    fn bound(self) -> (OneSidedRangeBound, T) {
717        (OneSidedRangeBound::EndInclusive, self.last)
718    }
719}