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 = "1.98.0")]
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 = "1.98.0")]
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    #[ferrocene::prevalidated]
221    #[inline]
222    fn from(value: legacy::Range<T>) -> Self {
223        Self { start: value.start, end: value.end }
224    }
225}
226
227/// A range bounded inclusively below and above.
228///
229/// The `RangeInclusive` contains all values with `x >= start`
230/// and `x <= last`. It is empty unless `start <= last`.
231///
232/// # Examples
233///
234/// ```
235/// use core::range::RangeInclusive;
236///
237/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
238/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
239/// ```
240///
241/// # Edition notes
242///
243/// It is planned that the syntax  `start..=last` will construct this
244/// type in a future edition, but it does not do so today.
245#[lang = "RangeInclusiveCopy"]
246#[derive(Clone, Copy, PartialEq, Eq, Hash)]
247#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
248pub struct RangeInclusive<Idx> {
249    /// The lower bound of the range (inclusive).
250    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
251    pub start: Idx,
252    /// The upper bound of the range (inclusive).
253    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
254    pub last: Idx,
255}
256
257#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
258impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
259    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
260        self.start.fmt(fmt)?;
261        write!(fmt, "..=")?;
262        self.last.fmt(fmt)?;
263        Ok(())
264    }
265}
266
267impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
268    /// Returns `true` if `item` is contained in the range.
269    ///
270    /// # Examples
271    ///
272    /// ```
273    /// use core::range::RangeInclusive;
274    ///
275    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
276    /// assert!( RangeInclusive::from(3..=5).contains(&3));
277    /// assert!( RangeInclusive::from(3..=5).contains(&4));
278    /// assert!( RangeInclusive::from(3..=5).contains(&5));
279    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
280    ///
281    /// assert!( RangeInclusive::from(3..=3).contains(&3));
282    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
283    ///
284    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
285    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
286    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
287    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
288    /// ```
289    #[inline]
290    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
291    #[rustc_const_unstable(feature = "const_range", issue = "none")]
292    pub const fn contains<U>(&self, item: &U) -> bool
293    where
294        Idx: [const] PartialOrd<U>,
295        U: ?Sized + [const] PartialOrd<Idx>,
296    {
297        <Self as RangeBounds<Idx>>::contains(self, item)
298    }
299
300    /// Returns `true` if the range contains no items.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// use core::range::RangeInclusive;
306    ///
307    /// assert!(!RangeInclusive::from(3..=5).is_empty());
308    /// assert!(!RangeInclusive::from(3..=3).is_empty());
309    /// assert!( RangeInclusive::from(3..=2).is_empty());
310    /// ```
311    ///
312    /// The range is empty if either side is incomparable:
313    ///
314    /// ```
315    /// use core::range::RangeInclusive;
316    ///
317    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
318    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
319    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
320    /// ```
321    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
322    #[inline]
323    #[rustc_const_unstable(feature = "const_range", issue = "none")]
324    pub const fn is_empty(&self) -> bool
325    where
326        Idx: [const] PartialOrd,
327    {
328        !(self.start <= self.last)
329    }
330}
331
332impl<Idx: Step> RangeInclusive<Idx> {
333    /// Creates an iterator over the elements within this range.
334    ///
335    /// Shorthand for `.clone().into_iter()`
336    ///
337    /// # Examples
338    ///
339    /// ```
340    /// use core::range::RangeInclusive;
341    ///
342    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
343    /// assert_eq!(i.next(), Some(9));
344    /// assert_eq!(i.next(), Some(16));
345    /// assert_eq!(i.next(), Some(25));
346    /// ```
347    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
348    #[inline]
349    pub fn iter(&self) -> RangeInclusiveIter<Idx> {
350        self.clone().into_iter()
351    }
352}
353
354#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
355#[rustc_const_unstable(feature = "const_range", issue = "none")]
356const impl<T> RangeBounds<T> for RangeInclusive<T> {
357    fn start_bound(&self) -> Bound<&T> {
358        Included(&self.start)
359    }
360    fn end_bound(&self) -> Bound<&T> {
361        Included(&self.last)
362    }
363}
364
365// This impl intentionally does not have `T: ?Sized`;
366// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
367//
368/// If you need to use this implementation where `T` is unsized,
369/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
370/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
371#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
372#[rustc_const_unstable(feature = "const_range", issue = "none")]
373const impl<T> RangeBounds<T> for RangeInclusive<&T> {
374    fn start_bound(&self) -> Bound<&T> {
375        Included(self.start)
376    }
377    fn end_bound(&self) -> Bound<&T> {
378        Included(self.last)
379    }
380}
381
382// #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
383#[unstable(feature = "range_into_bounds", issue = "136903")]
384#[rustc_const_unstable(feature = "const_range", issue = "none")]
385const impl<T> IntoBounds<T> for RangeInclusive<T> {
386    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
387        (Included(self.start), Included(self.last))
388    }
389}
390
391#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
392#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
393const impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
394    #[inline]
395    fn from(value: RangeInclusive<T>) -> Self {
396        Self::new(value.start, value.last)
397    }
398}
399#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
400#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
401const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
402    /// Converts from a legacy range to a non-legacy range, potentially panicking.
403    ///
404    /// # Panics
405    ///
406    /// If the legacy range iterator has been exhausted,
407    /// this function will either panic or return an empty range.
408    ///
409    /// # Examples
410    ///
411    /// ```
412    /// use core::range::legacy;
413    /// use core::range::RangeInclusive;
414    ///
415    /// let single: legacy::RangeInclusive<i32> = 0..=1;
416    /// let single = RangeInclusive::from(single);
417    /// assert_eq!((single.start, single.last), (0, 1));
418    ///
419    /// let empty: legacy::RangeInclusive<i32> = 0..=0;
420    /// let empty = RangeInclusive::from(empty);
421    /// assert_eq!((empty.start, empty.last), (0, 0));
422    /// ```
423    ///
424    /// ```
425    /// # // This test requires unwinding to work.
426    /// # // Disable it when unwinding isn't available.
427    /// # #[cfg(panic = "unwind")]
428    /// # fn main() {
429    /// use core::range::legacy;
430    /// use core::range::RangeInclusive;
431    /// use std::panic::catch_unwind;
432    ///
433    /// let mut exhausted: legacy::RangeInclusive<i32> = 0..=0;
434    /// exhausted.next();
435    /// let result = catch_unwind(|| RangeInclusive::from(exhausted));
436    /// // The `from` call either panicked or returned an empty range.
437    /// assert!(result.is_err() || result.is_ok_and(|range| range.is_empty()));
438    /// # }
439    /// # #[cfg(not(panic = "unwind"))]
440    /// # fn main() {}
441    /// ```
442    #[inline]
443    fn from(value: legacy::RangeInclusive<T>) -> Self {
444        assert!(
445            !value.exhausted,
446            "attempted to convert from an exhausted `legacy::RangeInclusive`"
447        );
448
449        let (start, last) = value.into_inner();
450        RangeInclusive { start, last }
451    }
452}
453
454/// A range only bounded inclusively below.
455///
456/// The `RangeFrom` contains all values with `x >= start`.
457///
458/// *Note*: Overflow in the [`IntoIterator`] implementation (when the contained
459/// data type reaches its numerical limit) is allowed to panic, wrap, or
460/// saturate. This behavior is defined by the implementation of the [`Step`]
461/// trait. For primitive integers, this follows the normal rules, and respects
462/// the overflow checks profile (panic in debug, wrap in release). Unlike
463/// its legacy counterpart, the iterator will only panic after yielding the
464/// maximum value when overflow checks are enabled.
465///
466/// [`Step`]: crate::iter::Step
467///
468/// # Examples
469///
470/// ```
471/// use core::range::RangeFrom;
472///
473/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
474/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
475/// ```
476///
477/// # Edition notes
478///
479/// It is planned that the syntax  `start..` will construct this
480/// type in a future edition, but it does not do so today.
481#[lang = "RangeFromCopy"]
482#[derive(Copy, Hash)]
483#[derive_const(Clone, PartialEq, Eq)]
484#[stable(feature = "new_range_from_api", since = "1.96.0")]
485pub struct RangeFrom<Idx> {
486    /// The lower bound of the range (inclusive).
487    #[stable(feature = "new_range_from_api", since = "1.96.0")]
488    pub start: Idx,
489}
490
491#[stable(feature = "new_range_from_api", since = "1.96.0")]
492impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
493    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
494        self.start.fmt(fmt)?;
495        write!(fmt, "..")?;
496        Ok(())
497    }
498}
499
500impl<Idx: Step> RangeFrom<Idx> {
501    /// Creates an iterator over the elements within this range.
502    ///
503    /// Shorthand for `.clone().into_iter()`
504    ///
505    /// # Examples
506    ///
507    /// ```
508    /// use core::range::RangeFrom;
509    ///
510    /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
511    /// assert_eq!(i.next(), Some(9));
512    /// assert_eq!(i.next(), Some(16));
513    /// assert_eq!(i.next(), Some(25));
514    /// ```
515    #[stable(feature = "new_range_from_api", since = "1.96.0")]
516    #[inline]
517    pub fn iter(&self) -> RangeFromIter<Idx> {
518        self.clone().into_iter()
519    }
520}
521
522impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
523    /// Returns `true` if `item` is contained in the range.
524    ///
525    /// # Examples
526    ///
527    /// ```
528    /// use core::range::RangeFrom;
529    ///
530    /// assert!(!RangeFrom::from(3..).contains(&2));
531    /// assert!( RangeFrom::from(3..).contains(&3));
532    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
533    ///
534    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
535    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
536    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
537    /// ```
538    #[inline]
539    #[stable(feature = "new_range_from_api", since = "1.96.0")]
540    #[rustc_const_unstable(feature = "const_range", issue = "none")]
541    pub const fn contains<U>(&self, item: &U) -> bool
542    where
543        Idx: [const] PartialOrd<U>,
544        U: ?Sized + [const] PartialOrd<Idx>,
545    {
546        <Self as RangeBounds<Idx>>::contains(self, item)
547    }
548}
549
550#[stable(feature = "new_range_from_api", since = "1.96.0")]
551#[rustc_const_unstable(feature = "const_range", issue = "none")]
552const impl<T> RangeBounds<T> for RangeFrom<T> {
553    fn start_bound(&self) -> Bound<&T> {
554        Included(&self.start)
555    }
556    fn end_bound(&self) -> Bound<&T> {
557        Unbounded
558    }
559}
560
561// This impl intentionally does not have `T: ?Sized`;
562// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
563//
564/// If you need to use this implementation where `T` is unsized,
565/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
566/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
567#[stable(feature = "new_range_from_api", since = "1.96.0")]
568#[rustc_const_unstable(feature = "const_range", issue = "none")]
569const impl<T> RangeBounds<T> for RangeFrom<&T> {
570    fn start_bound(&self) -> Bound<&T> {
571        Included(self.start)
572    }
573    fn end_bound(&self) -> Bound<&T> {
574        Unbounded
575    }
576}
577
578#[unstable(feature = "range_into_bounds", issue = "136903")]
579#[rustc_const_unstable(feature = "const_range", issue = "none")]
580const impl<T> IntoBounds<T> for RangeFrom<T> {
581    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
582        (Included(self.start), Unbounded)
583    }
584}
585
586#[unstable(feature = "one_sided_range", issue = "69780")]
587#[rustc_const_unstable(feature = "const_range", issue = "none")]
588const impl<T> OneSidedRange<T> for RangeFrom<T>
589where
590    Self: RangeBounds<T>,
591{
592    fn bound(self) -> (OneSidedRangeBound, T) {
593        (OneSidedRangeBound::StartInclusive, self.start)
594    }
595}
596
597#[stable(feature = "new_range_from_api", since = "1.96.0")]
598#[rustc_const_unstable(feature = "const_index", issue = "143775")]
599const impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
600    #[inline]
601    fn from(value: RangeFrom<T>) -> Self {
602        Self { start: value.start }
603    }
604}
605#[stable(feature = "new_range_from_api", since = "1.96.0")]
606#[rustc_const_unstable(feature = "const_index", issue = "143775")]
607const impl<T> From<legacy::RangeFrom<T>> for RangeFrom<T> {
608    #[inline]
609    fn from(value: legacy::RangeFrom<T>) -> Self {
610        Self { start: value.start }
611    }
612}
613
614/// A range only bounded inclusively above.
615///
616/// The `RangeToInclusive` contains all values with `x <= last`.
617/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
618///
619/// # Examples
620///
621/// ```standalone_crate
622/// #![feature(new_range)]
623/// assert_eq!((..=5), std::range::RangeToInclusive { last: 5 });
624/// ```
625///
626/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
627/// `for` loop directly. This won't compile:
628///
629/// ```compile_fail,E0277
630/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
631/// // std::iter::Iterator` is not satisfied
632/// for i in ..=5 {
633///     // ...
634/// }
635/// ```
636///
637/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
638/// array elements up to and including the index indicated by `last`.
639///
640/// ```
641/// let arr = [0, 1, 2, 3, 4];
642/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
643/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
644/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
645/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
646/// assert_eq!(arr[1.. 3], [   1, 2      ]);
647/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
648/// ```
649///
650/// [slicing index]: crate::slice::SliceIndex
651///
652/// # Edition notes
653///
654/// It is planned that the syntax  `..=last` will construct this
655/// type in a future edition, but it does not do so today.
656#[lang = "RangeToInclusiveCopy"]
657#[doc(alias = "..=")]
658#[derive(Copy, Clone, PartialEq, Eq, Hash)]
659#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
660pub struct RangeToInclusive<Idx> {
661    /// The upper bound of the range (inclusive)
662    #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
663    pub last: Idx,
664}
665
666#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
667impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
668    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
669        write!(fmt, "..=")?;
670        self.last.fmt(fmt)?;
671        Ok(())
672    }
673}
674
675impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
676    /// Returns `true` if `item` is contained in the range.
677    ///
678    /// # Examples
679    ///
680    /// ```
681    /// assert!( (..=5).contains(&-1_000_000_000));
682    /// assert!( (..=5).contains(&5));
683    /// assert!(!(..=5).contains(&6));
684    ///
685    /// assert!( (..=1.0).contains(&1.0));
686    /// assert!(!(..=1.0).contains(&f32::NAN));
687    /// assert!(!(..=f32::NAN).contains(&0.5));
688    /// ```
689    #[inline]
690    #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
691    #[rustc_const_unstable(feature = "const_range", issue = "none")]
692    pub const fn contains<U>(&self, item: &U) -> bool
693    where
694        Idx: [const] PartialOrd<U>,
695        U: ?Sized + [const] PartialOrd<Idx>,
696    {
697        <Self as RangeBounds<Idx>>::contains(self, item)
698    }
699}
700
701#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
702impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
703    fn from(value: legacy::RangeToInclusive<T>) -> Self {
704        Self { last: value.end }
705    }
706}
707#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
708impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
709    fn from(value: RangeToInclusive<T>) -> Self {
710        Self { end: value.last }
711    }
712}
713
714// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
715// because underflow would be possible with (..0).into()
716
717#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
718#[rustc_const_unstable(feature = "const_range", issue = "none")]
719const impl<T> RangeBounds<T> for RangeToInclusive<T> {
720    fn start_bound(&self) -> Bound<&T> {
721        Unbounded
722    }
723    fn end_bound(&self) -> Bound<&T> {
724        Included(&self.last)
725    }
726}
727
728#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
729#[rustc_const_unstable(feature = "const_range", issue = "none")]
730const impl<T> RangeBounds<T> for RangeToInclusive<&T> {
731    fn start_bound(&self) -> Bound<&T> {
732        Unbounded
733    }
734    fn end_bound(&self) -> Bound<&T> {
735        Included(self.last)
736    }
737}
738
739#[unstable(feature = "range_into_bounds", issue = "136903")]
740#[rustc_const_unstable(feature = "const_range", issue = "none")]
741const impl<T> IntoBounds<T> for RangeToInclusive<T> {
742    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
743        (Unbounded, Included(self.last))
744    }
745}
746
747#[unstable(feature = "one_sided_range", issue = "69780")]
748#[rustc_const_unstable(feature = "const_range", issue = "none")]
749const impl<T> OneSidedRange<T> for RangeToInclusive<T>
750where
751    Self: RangeBounds<T>,
752{
753    fn bound(self) -> (OneSidedRangeBound, T) {
754        (OneSidedRangeBound::EndInclusive, self.last)
755    }
756}