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