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
27use Bound::{Excluded, Included, Unbounded};
28#[doc(inline)]
29pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
30
31#[doc(inline)]
32pub use crate::iter::Step;
33#[doc(inline)]
34pub use crate::ops::{
35    Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive,
36};
37
38/// A (half-open) range bounded inclusively below and exclusively above
39/// (`start..end` in a future edition).
40///
41/// The range `start..end` contains all values with `start <= x < end`.
42/// It is empty if `start >= end`.
43///
44/// # Examples
45///
46/// ```
47/// #![feature(new_range_api)]
48/// use core::range::Range;
49///
50/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
51/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
52/// ```
53#[lang = "RangeCopy"]
54#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
55#[unstable(feature = "new_range_api", issue = "125687")]
56pub struct Range<Idx> {
57    /// The lower bound of the range (inclusive).
58    #[unstable(feature = "new_range_api", issue = "125687")]
59    pub start: Idx,
60    /// The upper bound of the range (exclusive).
61    #[unstable(feature = "new_range_api", issue = "125687")]
62    pub end: Idx,
63}
64
65#[unstable(feature = "new_range_api", issue = "125687")]
66impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
67    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
68        self.start.fmt(fmt)?;
69        write!(fmt, "..")?;
70        self.end.fmt(fmt)?;
71        Ok(())
72    }
73}
74
75impl<Idx: Step> Range<Idx> {
76    /// Creates an iterator over the elements within this range.
77    ///
78    /// Shorthand for `.clone().into_iter()`
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// #![feature(new_range_api)]
84    /// use core::range::Range;
85    ///
86    /// let mut i = Range::from(3..9).iter().map(|n| n*n);
87    /// assert_eq!(i.next(), Some(9));
88    /// assert_eq!(i.next(), Some(16));
89    /// assert_eq!(i.next(), Some(25));
90    /// ```
91    #[unstable(feature = "new_range_api", issue = "125687")]
92    #[inline]
93    pub fn iter(&self) -> IterRange<Idx> {
94        self.clone().into_iter()
95    }
96}
97
98impl<Idx: PartialOrd<Idx>> Range<Idx> {
99    /// Returns `true` if `item` is contained in the range.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// #![feature(new_range_api)]
105    /// use core::range::Range;
106    ///
107    /// assert!(!Range::from(3..5).contains(&2));
108    /// assert!( Range::from(3..5).contains(&3));
109    /// assert!( Range::from(3..5).contains(&4));
110    /// assert!(!Range::from(3..5).contains(&5));
111    ///
112    /// assert!(!Range::from(3..3).contains(&3));
113    /// assert!(!Range::from(3..2).contains(&3));
114    ///
115    /// assert!( Range::from(0.0..1.0).contains(&0.5));
116    /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN));
117    /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5));
118    /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5));
119    /// ```
120    #[inline]
121    #[unstable(feature = "new_range_api", issue = "125687")]
122    pub fn contains<U>(&self, item: &U) -> bool
123    where
124        Idx: PartialOrd<U>,
125        U: ?Sized + PartialOrd<Idx>,
126    {
127        <Self as RangeBounds<Idx>>::contains(self, item)
128    }
129
130    /// Returns `true` if the range contains no items.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// #![feature(new_range_api)]
136    /// use core::range::Range;
137    ///
138    /// assert!(!Range::from(3..5).is_empty());
139    /// assert!( Range::from(3..3).is_empty());
140    /// assert!( Range::from(3..2).is_empty());
141    /// ```
142    ///
143    /// The range is empty if either side is incomparable:
144    ///
145    /// ```
146    /// #![feature(new_range_api)]
147    /// use core::range::Range;
148    ///
149    /// assert!(!Range::from(3.0..5.0).is_empty());
150    /// assert!( Range::from(3.0..f32::NAN).is_empty());
151    /// assert!( Range::from(f32::NAN..5.0).is_empty());
152    /// ```
153    #[inline]
154    #[unstable(feature = "new_range_api", issue = "125687")]
155    pub fn is_empty(&self) -> bool {
156        !(self.start < self.end)
157    }
158}
159
160#[unstable(feature = "new_range_api", issue = "125687")]
161impl<T> RangeBounds<T> for Range<T> {
162    fn start_bound(&self) -> Bound<&T> {
163        Included(&self.start)
164    }
165    fn end_bound(&self) -> Bound<&T> {
166        Excluded(&self.end)
167    }
168}
169
170#[unstable(feature = "new_range_api", issue = "125687")]
171impl<T> RangeBounds<T> for Range<&T> {
172    fn start_bound(&self) -> Bound<&T> {
173        Included(self.start)
174    }
175    fn end_bound(&self) -> Bound<&T> {
176        Excluded(self.end)
177    }
178}
179
180// #[unstable(feature = "range_into_bounds", issue = "136903")]
181#[unstable(feature = "new_range_api", issue = "125687")]
182impl<T> IntoBounds<T> for Range<T> {
183    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
184        (Included(self.start), Excluded(self.end))
185    }
186}
187
188#[unstable(feature = "new_range_api", issue = "125687")]
189#[rustc_const_unstable(feature = "const_index", issue = "143775")]
190impl<T> const From<Range<T>> for legacy::Range<T> {
191    #[inline]
192    fn from(value: Range<T>) -> Self {
193        Self { start: value.start, end: value.end }
194    }
195}
196
197#[unstable(feature = "new_range_api", issue = "125687")]
198#[rustc_const_unstable(feature = "const_index", issue = "143775")]
199impl<T> const From<legacy::Range<T>> for Range<T> {
200    #[inline]
201    fn from(value: legacy::Range<T>) -> Self {
202        Self { start: value.start, end: value.end }
203    }
204}
205
206/// A range bounded inclusively below and above (`start..=end`).
207///
208/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
209/// and `x <= end`. It is empty unless `start <= end`.
210///
211/// # Examples
212///
213/// The `start..=end` syntax is a `RangeInclusive`:
214///
215/// ```
216/// #![feature(new_range_api)]
217/// use core::range::RangeInclusive;
218///
219/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
220/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
221/// ```
222#[lang = "RangeInclusiveCopy"]
223#[derive(Clone, Copy, PartialEq, Eq, Hash)]
224#[unstable(feature = "new_range_api", issue = "125687")]
225pub struct RangeInclusive<Idx> {
226    /// The lower bound of the range (inclusive).
227    #[unstable(feature = "new_range_api", issue = "125687")]
228    pub start: Idx,
229    /// The upper bound of the range (inclusive).
230    #[unstable(feature = "new_range_api", issue = "125687")]
231    pub end: Idx,
232}
233
234#[unstable(feature = "new_range_api", issue = "125687")]
235impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
236    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
237        self.start.fmt(fmt)?;
238        write!(fmt, "..=")?;
239        self.end.fmt(fmt)?;
240        Ok(())
241    }
242}
243
244impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
245    /// Returns `true` if `item` is contained in the range.
246    ///
247    /// # Examples
248    ///
249    /// ```
250    /// #![feature(new_range_api)]
251    /// use core::range::RangeInclusive;
252    ///
253    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
254    /// assert!( RangeInclusive::from(3..=5).contains(&3));
255    /// assert!( RangeInclusive::from(3..=5).contains(&4));
256    /// assert!( RangeInclusive::from(3..=5).contains(&5));
257    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
258    ///
259    /// assert!( RangeInclusive::from(3..=3).contains(&3));
260    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
261    ///
262    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
263    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
264    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
265    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
266    /// ```
267    #[inline]
268    #[unstable(feature = "new_range_api", issue = "125687")]
269    pub fn contains<U>(&self, item: &U) -> bool
270    where
271        Idx: PartialOrd<U>,
272        U: ?Sized + PartialOrd<Idx>,
273    {
274        <Self as RangeBounds<Idx>>::contains(self, item)
275    }
276
277    /// Returns `true` if the range contains no items.
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// #![feature(new_range_api)]
283    /// use core::range::RangeInclusive;
284    ///
285    /// assert!(!RangeInclusive::from(3..=5).is_empty());
286    /// assert!(!RangeInclusive::from(3..=3).is_empty());
287    /// assert!( RangeInclusive::from(3..=2).is_empty());
288    /// ```
289    ///
290    /// The range is empty if either side is incomparable:
291    ///
292    /// ```
293    /// #![feature(new_range_api)]
294    /// use core::range::RangeInclusive;
295    ///
296    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
297    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
298    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
299    /// ```
300    #[unstable(feature = "new_range_api", issue = "125687")]
301    #[inline]
302    pub fn is_empty(&self) -> bool {
303        !(self.start <= self.end)
304    }
305}
306
307impl<Idx: Step> RangeInclusive<Idx> {
308    /// Creates an iterator over the elements within this range.
309    ///
310    /// Shorthand for `.clone().into_iter()`
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// #![feature(new_range_api)]
316    /// use core::range::RangeInclusive;
317    ///
318    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
319    /// assert_eq!(i.next(), Some(9));
320    /// assert_eq!(i.next(), Some(16));
321    /// assert_eq!(i.next(), Some(25));
322    /// ```
323    #[unstable(feature = "new_range_api", issue = "125687")]
324    #[inline]
325    pub fn iter(&self) -> IterRangeInclusive<Idx> {
326        self.clone().into_iter()
327    }
328}
329
330impl RangeInclusive<usize> {
331    /// Converts to an exclusive `Range` for `SliceIndex` implementations.
332    /// The caller is responsible for dealing with `end == usize::MAX`.
333    #[inline]
334    pub(crate) const fn into_slice_range(self) -> Range<usize> {
335        Range { start: self.start, end: self.end + 1 }
336    }
337}
338
339#[unstable(feature = "new_range_api", issue = "125687")]
340impl<T> RangeBounds<T> for RangeInclusive<T> {
341    fn start_bound(&self) -> Bound<&T> {
342        Included(&self.start)
343    }
344    fn end_bound(&self) -> Bound<&T> {
345        Included(&self.end)
346    }
347}
348
349#[unstable(feature = "new_range_api", issue = "125687")]
350impl<T> RangeBounds<T> for RangeInclusive<&T> {
351    fn start_bound(&self) -> Bound<&T> {
352        Included(self.start)
353    }
354    fn end_bound(&self) -> Bound<&T> {
355        Included(self.end)
356    }
357}
358
359// #[unstable(feature = "range_into_bounds", issue = "136903")]
360#[unstable(feature = "new_range_api", issue = "125687")]
361impl<T> IntoBounds<T> for RangeInclusive<T> {
362    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
363        (Included(self.start), Included(self.end))
364    }
365}
366
367#[unstable(feature = "new_range_api", issue = "125687")]
368#[rustc_const_unstable(feature = "const_index", issue = "143775")]
369impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
370    #[inline]
371    fn from(value: RangeInclusive<T>) -> Self {
372        Self::new(value.start, value.end)
373    }
374}
375#[unstable(feature = "new_range_api", issue = "125687")]
376impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
377    #[inline]
378    fn from(value: legacy::RangeInclusive<T>) -> Self {
379        assert!(
380            !value.exhausted,
381            "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
382        );
383
384        let (start, end) = value.into_inner();
385        RangeInclusive { start, end }
386    }
387}
388
389/// A range only bounded inclusively below (`start..`).
390///
391/// The `RangeFrom` `start..` contains all values with `x >= start`.
392///
393/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
394/// data type reaches its numerical limit) is allowed to panic, wrap, or
395/// saturate. This behavior is defined by the implementation of the [`Step`]
396/// trait. For primitive integers, this follows the normal rules, and respects
397/// the overflow checks profile (panic in debug, wrap in release). Note also
398/// that overflow happens earlier than you might assume: the overflow happens
399/// in the call to `next` that yields the maximum value, as the range must be
400/// set to a state to yield the next value.
401///
402/// [`Step`]: crate::iter::Step
403///
404/// # Examples
405///
406/// The `start..` syntax is a `RangeFrom`:
407///
408/// ```
409/// #![feature(new_range_api)]
410/// use core::range::RangeFrom;
411///
412/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
413/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
414/// ```
415#[lang = "RangeFromCopy"]
416#[derive(Clone, Copy, PartialEq, Eq, Hash)]
417#[unstable(feature = "new_range_api", issue = "125687")]
418pub struct RangeFrom<Idx> {
419    /// The lower bound of the range (inclusive).
420    #[unstable(feature = "new_range_api", issue = "125687")]
421    pub start: Idx,
422}
423
424#[unstable(feature = "new_range_api", issue = "125687")]
425impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
426    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
427        self.start.fmt(fmt)?;
428        write!(fmt, "..")?;
429        Ok(())
430    }
431}
432
433impl<Idx: Step> RangeFrom<Idx> {
434    /// Creates an iterator over the elements within this range.
435    ///
436    /// Shorthand for `.clone().into_iter()`
437    ///
438    /// # Examples
439    ///
440    /// ```
441    /// #![feature(new_range_api)]
442    /// use core::range::RangeFrom;
443    ///
444    /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
445    /// assert_eq!(i.next(), Some(9));
446    /// assert_eq!(i.next(), Some(16));
447    /// assert_eq!(i.next(), Some(25));
448    /// ```
449    #[unstable(feature = "new_range_api", issue = "125687")]
450    #[inline]
451    pub fn iter(&self) -> IterRangeFrom<Idx> {
452        self.clone().into_iter()
453    }
454}
455
456impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
457    /// Returns `true` if `item` is contained in the range.
458    ///
459    /// # Examples
460    ///
461    /// ```
462    /// #![feature(new_range_api)]
463    /// use core::range::RangeFrom;
464    ///
465    /// assert!(!RangeFrom::from(3..).contains(&2));
466    /// assert!( RangeFrom::from(3..).contains(&3));
467    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
468    ///
469    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
470    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
471    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
472    /// ```
473    #[inline]
474    #[unstable(feature = "new_range_api", issue = "125687")]
475    pub fn contains<U>(&self, item: &U) -> bool
476    where
477        Idx: PartialOrd<U>,
478        U: ?Sized + PartialOrd<Idx>,
479    {
480        <Self as RangeBounds<Idx>>::contains(self, item)
481    }
482}
483
484#[unstable(feature = "new_range_api", issue = "125687")]
485impl<T> RangeBounds<T> for RangeFrom<T> {
486    fn start_bound(&self) -> Bound<&T> {
487        Included(&self.start)
488    }
489    fn end_bound(&self) -> Bound<&T> {
490        Unbounded
491    }
492}
493
494#[unstable(feature = "new_range_api", issue = "125687")]
495impl<T> RangeBounds<T> for RangeFrom<&T> {
496    fn start_bound(&self) -> Bound<&T> {
497        Included(self.start)
498    }
499    fn end_bound(&self) -> Bound<&T> {
500        Unbounded
501    }
502}
503
504// #[unstable(feature = "range_into_bounds", issue = "136903")]
505#[unstable(feature = "new_range_api", issue = "125687")]
506impl<T> IntoBounds<T> for RangeFrom<T> {
507    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
508        (Included(self.start), Unbounded)
509    }
510}
511
512#[unstable(feature = "new_range_api", issue = "125687")]
513#[rustc_const_unstable(feature = "const_index", issue = "143775")]
514impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
515    #[inline]
516    fn from(value: RangeFrom<T>) -> Self {
517        Self { start: value.start }
518    }
519}
520#[unstable(feature = "new_range_api", issue = "125687")]
521#[rustc_const_unstable(feature = "const_index", issue = "143775")]
522impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
523    #[inline]
524    fn from(value: legacy::RangeFrom<T>) -> Self {
525        Self { start: value.start }
526    }
527}