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#[stable(feature = "new_range_api_legacy", since = "CURRENT_RUSTC_VERSION")]
24pub mod legacy;
25
26use core::ops::Bound::{self, Excluded, Included, Unbounded};
27
28#[doc(inline)]
29#[stable(feature = "new_range_from_api", since = "1.96.0")]
30pub use iter::RangeFromIter;
31#[doc(inline)]
32#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
33pub use iter::RangeInclusiveIter;
34#[doc(inline)]
35#[stable(feature = "new_range_api", since = "1.96.0")]
36pub use iter::RangeIter;
37
38use crate::iter::Step;
39// FIXME(one_sided_range): These types should move into this module.
40// FIXME(range_into_bounds): Ditto. Also consider re-exporting `RangeBounds` and related.
41use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds};
42#[doc(inline)]
43#[stable(feature = "new_range_api_exports", since = "CURRENT_RUSTC_VERSION")]
44pub use crate::ops::{RangeFull, RangeTo};
45
46/// A (half-open) range bounded inclusively below and exclusively above.
47///
48/// The `Range` contains all values with `start <= x < end`.
49/// It is empty if `start >= end`.
50///
51/// # Examples
52///
53/// ```
54/// use core::range::Range;
55///
56/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
57/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
58/// ```
59///
60/// # Edition notes
61///
62/// It is planned that the syntax `start..end` will construct this
63/// type in a future edition, but it does not do so today.
64#[lang = "RangeCopy"]
65#[derive(Copy, Hash)]
66#[derive_const(Clone, Default, PartialEq, Eq)]
67#[stable(feature = "new_range_api", since = "1.96.0")]
68pub struct Range<Idx> {
69    /// The lower bound of the range (inclusive).
70    #[stable(feature = "new_range_api", since = "1.96.0")]
71    pub start: Idx,
72    /// The upper bound of the range (exclusive).
73    #[stable(feature = "new_range_api", since = "1.96.0")]
74    pub end: Idx,
75}
76
77#[stable(feature = "new_range_api", since = "1.96.0")]
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 = "1.96.0")]
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 = "1.96.0")]
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 = "1.96.0")]
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 = "1.96.0")]
174#[rustc_const_unstable(feature = "const_range", issue = "none")]
175const impl<T> 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 = "1.96.0")]
191#[rustc_const_unstable(feature = "const_range", issue = "none")]
192const impl<T> 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")]
203const impl<T> 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 = "1.96.0")]
210#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
211const impl<T> 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 = "1.96.0")]
218#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
219const impl<T> 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.
227///
228/// The `RangeInclusive` contains all values with `x >= start`
229/// and `x <= last`. It is empty unless `start <= last`.
230///
231/// # Examples
232///
233/// ```
234/// use core::range::RangeInclusive;
235///
236/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
237/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
238/// ```
239///
240/// # Edition notes
241///
242/// It is planned that the syntax  `start..=last` will construct this
243/// type in a future edition, but it does not do so today.
244#[lang = "RangeInclusiveCopy"]
245#[derive(Clone, Copy, PartialEq, Eq, Hash)]
246#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
247pub struct RangeInclusive<Idx> {
248    /// The lower bound of the range (inclusive).
249    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
250    pub start: Idx,
251    /// The upper bound of the range (inclusive).
252    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
253    pub last: Idx,
254}
255
256#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
257impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
258    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
259        self.start.fmt(fmt)?;
260        write!(fmt, "..=")?;
261        self.last.fmt(fmt)?;
262        Ok(())
263    }
264}
265
266impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
267    /// Returns `true` if `item` is contained in the range.
268    ///
269    /// # Examples
270    ///
271    /// ```
272    /// use core::range::RangeInclusive;
273    ///
274    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
275    /// assert!( RangeInclusive::from(3..=5).contains(&3));
276    /// assert!( RangeInclusive::from(3..=5).contains(&4));
277    /// assert!( RangeInclusive::from(3..=5).contains(&5));
278    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
279    ///
280    /// assert!( RangeInclusive::from(3..=3).contains(&3));
281    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
282    ///
283    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
284    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
285    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
286    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
287    /// ```
288    #[inline]
289    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
290    #[rustc_const_unstable(feature = "const_range", issue = "none")]
291    pub const fn contains<U>(&self, item: &U) -> bool
292    where
293        Idx: [const] PartialOrd<U>,
294        U: ?Sized + [const] PartialOrd<Idx>,
295    {
296        <Self as RangeBounds<Idx>>::contains(self, item)
297    }
298
299    /// Returns `true` if the range contains no items.
300    ///
301    /// # Examples
302    ///
303    /// ```
304    /// use core::range::RangeInclusive;
305    ///
306    /// assert!(!RangeInclusive::from(3..=5).is_empty());
307    /// assert!(!RangeInclusive::from(3..=3).is_empty());
308    /// assert!( RangeInclusive::from(3..=2).is_empty());
309    /// ```
310    ///
311    /// The range is empty if either side is incomparable:
312    ///
313    /// ```
314    /// use core::range::RangeInclusive;
315    ///
316    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
317    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
318    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
319    /// ```
320    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
321    #[inline]
322    #[rustc_const_unstable(feature = "const_range", issue = "none")]
323    pub const fn is_empty(&self) -> bool
324    where
325        Idx: [const] PartialOrd,
326    {
327        !(self.start <= self.last)
328    }
329}
330
331impl<Idx: Step> RangeInclusive<Idx> {
332    /// Creates an iterator over the elements within this range.
333    ///
334    /// Shorthand for `.clone().into_iter()`
335    ///
336    /// # Examples
337    ///
338    /// ```
339    /// use core::range::RangeInclusive;
340    ///
341    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
342    /// assert_eq!(i.next(), Some(9));
343    /// assert_eq!(i.next(), Some(16));
344    /// assert_eq!(i.next(), Some(25));
345    /// ```
346    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
347    #[inline]
348    pub fn iter(&self) -> RangeInclusiveIter<Idx> {
349        self.clone().into_iter()
350    }
351}
352
353#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
354#[rustc_const_unstable(feature = "const_range", issue = "none")]
355const impl<T> RangeBounds<T> for RangeInclusive<T> {
356    fn start_bound(&self) -> Bound<&T> {
357        Included(&self.start)
358    }
359    fn end_bound(&self) -> Bound<&T> {
360        Included(&self.last)
361    }
362}
363
364// This impl intentionally does not have `T: ?Sized`;
365// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
366//
367/// If you need to use this implementation where `T` is unsized,
368/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
369/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
370#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
371#[rustc_const_unstable(feature = "const_range", issue = "none")]
372const impl<T> RangeBounds<T> for RangeInclusive<&T> {
373    fn start_bound(&self) -> Bound<&T> {
374        Included(self.start)
375    }
376    fn end_bound(&self) -> Bound<&T> {
377        Included(self.last)
378    }
379}
380
381// #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
382#[unstable(feature = "range_into_bounds", issue = "136903")]
383#[rustc_const_unstable(feature = "const_range", issue = "none")]
384const impl<T> IntoBounds<T> for RangeInclusive<T> {
385    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
386        (Included(self.start), Included(self.last))
387    }
388}
389
390#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
391#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
392const impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
393    #[inline]
394    fn from(value: RangeInclusive<T>) -> Self {
395        Self::new(value.start, value.last)
396    }
397}
398#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
399#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
400const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
401    #[inline]
402    fn from(value: legacy::RangeInclusive<T>) -> Self {
403        assert!(
404            !value.exhausted,
405            "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
406        );
407
408        let (start, last) = value.into_inner();
409        RangeInclusive { start, last }
410    }
411}
412
413/// A range only bounded inclusively below.
414///
415/// The `RangeFrom` contains all values with `x >= start`.
416///
417/// *Note*: Overflow in the [`IntoIterator`] implementation (when the contained
418/// data type reaches its numerical limit) is allowed to panic, wrap, or
419/// saturate. This behavior is defined by the implementation of the [`Step`]
420/// trait. For primitive integers, this follows the normal rules, and respects
421/// the overflow checks profile (panic in debug, wrap in release). Unlike
422/// its legacy counterpart, the iterator will only panic after yielding the
423/// maximum value when overflow checks are enabled.
424///
425/// [`Step`]: crate::iter::Step
426///
427/// # Examples
428///
429/// ```
430/// use core::range::RangeFrom;
431///
432/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
433/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
434/// ```
435///
436/// # Edition notes
437///
438/// It is planned that the syntax  `start..` will construct this
439/// type in a future edition, but it does not do so today.
440#[lang = "RangeFromCopy"]
441#[derive(Copy, Hash)]
442#[derive_const(Clone, PartialEq, Eq)]
443#[stable(feature = "new_range_from_api", since = "1.96.0")]
444pub struct RangeFrom<Idx> {
445    /// The lower bound of the range (inclusive).
446    #[stable(feature = "new_range_from_api", since = "1.96.0")]
447    pub start: Idx,
448}
449
450#[stable(feature = "new_range_from_api", since = "1.96.0")]
451impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
452    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
453        self.start.fmt(fmt)?;
454        write!(fmt, "..")?;
455        Ok(())
456    }
457}
458
459impl<Idx: Step> RangeFrom<Idx> {
460    /// Creates an iterator over the elements within this range.
461    ///
462    /// Shorthand for `.clone().into_iter()`
463    ///
464    /// # Examples
465    ///
466    /// ```
467    /// use core::range::RangeFrom;
468    ///
469    /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
470    /// assert_eq!(i.next(), Some(9));
471    /// assert_eq!(i.next(), Some(16));
472    /// assert_eq!(i.next(), Some(25));
473    /// ```
474    #[stable(feature = "new_range_from_api", since = "1.96.0")]
475    #[inline]
476    pub fn iter(&self) -> RangeFromIter<Idx> {
477        self.clone().into_iter()
478    }
479}
480
481impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
482    /// Returns `true` if `item` is contained in the range.
483    ///
484    /// # Examples
485    ///
486    /// ```
487    /// use core::range::RangeFrom;
488    ///
489    /// assert!(!RangeFrom::from(3..).contains(&2));
490    /// assert!( RangeFrom::from(3..).contains(&3));
491    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
492    ///
493    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
494    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
495    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
496    /// ```
497    #[inline]
498    #[stable(feature = "new_range_from_api", since = "1.96.0")]
499    #[rustc_const_unstable(feature = "const_range", issue = "none")]
500    pub const fn contains<U>(&self, item: &U) -> bool
501    where
502        Idx: [const] PartialOrd<U>,
503        U: ?Sized + [const] PartialOrd<Idx>,
504    {
505        <Self as RangeBounds<Idx>>::contains(self, item)
506    }
507}
508
509#[stable(feature = "new_range_from_api", since = "1.96.0")]
510#[rustc_const_unstable(feature = "const_range", issue = "none")]
511const impl<T> RangeBounds<T> for RangeFrom<T> {
512    fn start_bound(&self) -> Bound<&T> {
513        Included(&self.start)
514    }
515    fn end_bound(&self) -> Bound<&T> {
516        Unbounded
517    }
518}
519
520// This impl intentionally does not have `T: ?Sized`;
521// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
522//
523/// If you need to use this implementation where `T` is unsized,
524/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
525/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
526#[stable(feature = "new_range_from_api", since = "1.96.0")]
527#[rustc_const_unstable(feature = "const_range", issue = "none")]
528const impl<T> RangeBounds<T> for RangeFrom<&T> {
529    fn start_bound(&self) -> Bound<&T> {
530        Included(self.start)
531    }
532    fn end_bound(&self) -> Bound<&T> {
533        Unbounded
534    }
535}
536
537#[unstable(feature = "range_into_bounds", issue = "136903")]
538#[rustc_const_unstable(feature = "const_range", issue = "none")]
539const impl<T> IntoBounds<T> for RangeFrom<T> {
540    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
541        (Included(self.start), Unbounded)
542    }
543}
544
545#[unstable(feature = "one_sided_range", issue = "69780")]
546#[rustc_const_unstable(feature = "const_range", issue = "none")]
547const impl<T> OneSidedRange<T> for RangeFrom<T>
548where
549    Self: RangeBounds<T>,
550{
551    fn bound(self) -> (OneSidedRangeBound, T) {
552        (OneSidedRangeBound::StartInclusive, self.start)
553    }
554}
555
556#[stable(feature = "new_range_from_api", since = "1.96.0")]
557#[rustc_const_unstable(feature = "const_index", issue = "143775")]
558const impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
559    #[inline]
560    fn from(value: RangeFrom<T>) -> Self {
561        Self { start: value.start }
562    }
563}
564#[stable(feature = "new_range_from_api", since = "1.96.0")]
565#[rustc_const_unstable(feature = "const_index", issue = "143775")]
566const impl<T> From<legacy::RangeFrom<T>> for RangeFrom<T> {
567    #[inline]
568    fn from(value: legacy::RangeFrom<T>) -> Self {
569        Self { start: value.start }
570    }
571}
572
573/// A range only bounded inclusively above.
574///
575/// The `RangeToInclusive` contains all values with `x <= last`.
576/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
577///
578/// # Examples
579///
580/// ```standalone_crate
581/// #![feature(new_range)]
582/// assert_eq!((..=5), std::range::RangeToInclusive { last: 5 });
583/// ```
584///
585/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
586/// `for` loop directly. This won't compile:
587///
588/// ```compile_fail,E0277
589/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
590/// // std::iter::Iterator` is not satisfied
591/// for i in ..=5 {
592///     // ...
593/// }
594/// ```
595///
596/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
597/// array elements up to and including the index indicated by `last`.
598///
599/// ```
600/// let arr = [0, 1, 2, 3, 4];
601/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
602/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
603/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
604/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
605/// assert_eq!(arr[1.. 3], [   1, 2      ]);
606/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
607/// ```
608///
609/// [slicing index]: crate::slice::SliceIndex
610///
611/// # Edition notes
612///
613/// It is planned that the syntax  `..=last` will construct this
614/// type in a future edition, but it does not do so today.
615#[lang = "RangeToInclusiveCopy"]
616#[doc(alias = "..=")]
617#[derive(Copy, Clone, PartialEq, Eq, Hash)]
618#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
619pub struct RangeToInclusive<Idx> {
620    /// The upper bound of the range (inclusive)
621    #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
622    pub last: Idx,
623}
624
625#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
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    #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
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#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
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#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
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#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
677#[rustc_const_unstable(feature = "const_range", issue = "none")]
678const impl<T> 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#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
688#[rustc_const_unstable(feature = "const_range", issue = "none")]
689const impl<T> RangeBounds<T> for RangeToInclusive<&T> {
690    fn start_bound(&self) -> Bound<&T> {
691        Unbounded
692    }
693    fn end_bound(&self) -> Bound<&T> {
694        Included(self.last)
695    }
696}
697
698#[unstable(feature = "range_into_bounds", issue = "136903")]
699#[rustc_const_unstable(feature = "const_range", issue = "none")]
700const impl<T> IntoBounds<T> for RangeToInclusive<T> {
701    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
702        (Unbounded, Included(self.last))
703    }
704}
705
706#[unstable(feature = "one_sided_range", issue = "69780")]
707#[rustc_const_unstable(feature = "const_range", issue = "none")]
708const impl<T> OneSidedRange<T> for RangeToInclusive<T>
709where
710    Self: RangeBounds<T>,
711{
712    fn bound(self) -> (OneSidedRangeBound, T) {
713        (OneSidedRangeBound::EndInclusive, self.last)
714    }
715}