Skip to main content

core/
range.rs

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