core/range.rs
1//! # Replacement range types
2//!
3//! The types within this module are meant to replace the legacy `Range`,
4//! `RangeInclusive`, `RangeToInclusive` and `RangeFrom` types in a future edition.
5//!
6//! ```
7//! use core::range::{Range, RangeFrom, RangeInclusive, RangeToInclusive};
8//!
9//! let arr = [0, 1, 2, 3, 4];
10//! assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
11//! assert_eq!(arr[ .. 3 ], [0, 1, 2 ]);
12//! assert_eq!(arr[RangeToInclusive::from( ..=3)], [0, 1, 2, 3 ]);
13//! assert_eq!(arr[ RangeFrom::from(1.. )], [ 1, 2, 3, 4]);
14//! assert_eq!(arr[ Range::from(1..3 )], [ 1, 2 ]);
15//! assert_eq!(arr[ RangeInclusive::from(1..=3)], [ 1, 2, 3 ]);
16//! ```
17
18use crate::fmt;
19use crate::hash::Hash;
20
21mod iter;
22
23#[stable(feature = "new_range_api_legacy", since = "CURRENT_RUSTC_VERSION")]
24pub mod legacy;
25
26use core::ops::Bound::{self, Excluded, Included, Unbounded};
27
28#[doc(inline)]
29#[stable(feature = "new_range_from_api", since = "1.96.0")]
30pub use iter::RangeFromIter;
31#[doc(inline)]
32#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
33pub use iter::RangeInclusiveIter;
34#[doc(inline)]
35#[stable(feature = "new_range_api", since = "1.96.0")]
36pub use iter::RangeIter;
37
38use crate::iter::Step;
39// FIXME(one_sided_range): These types should move into this module.
40// FIXME(range_into_bounds): Ditto. Also consider re-exporting `RangeBounds` and related.
41use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds};
42#[doc(inline)]
43#[stable(feature = "new_range_api_exports", since = "CURRENT_RUSTC_VERSION")]
44pub use crate::ops::{RangeFull, RangeTo};
45
46/// A (half-open) range bounded inclusively below and exclusively above.
47///
48/// The `Range` contains all values with `start <= x < end`.
49/// It is empty if `start >= end`.
50///
51/// # Examples
52///
53/// ```
54/// use core::range::Range;
55///
56/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
57/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
58/// ```
59///
60/// # Edition notes
61///
62/// It is planned that the syntax `start..end` will construct this
63/// type in a future edition, but it does not do so today.
64#[lang = "RangeCopy"]
65#[derive(Copy, Hash)]
66#[derive_const(Clone, Default, PartialEq, Eq)]
67#[stable(feature = "new_range_api", since = "1.96.0")]
68pub struct Range<Idx> {
69 /// The lower bound of the range (inclusive).
70 #[stable(feature = "new_range_api", since = "1.96.0")]
71 pub start: Idx,
72 /// The upper bound of the range (exclusive).
73 #[stable(feature = "new_range_api", since = "1.96.0")]
74 pub end: Idx,
75}
76
77#[stable(feature = "new_range_api", since = "1.96.0")]
78impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
79 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
80 self.start.fmt(fmt)?;
81 write!(fmt, "..")?;
82 self.end.fmt(fmt)?;
83 Ok(())
84 }
85}
86
87impl<Idx: Step> Range<Idx> {
88 /// Creates an iterator over the elements within this range.
89 ///
90 /// Shorthand for `.clone().into_iter()`
91 ///
92 /// # Examples
93 ///
94 /// ```
95 /// use core::range::Range;
96 ///
97 /// let mut i = Range::from(3..9).iter().map(|n| n*n);
98 /// assert_eq!(i.next(), Some(9));
99 /// assert_eq!(i.next(), Some(16));
100 /// assert_eq!(i.next(), Some(25));
101 /// ```
102 #[stable(feature = "new_range_api", since = "1.96.0")]
103 #[inline]
104 pub fn iter(&self) -> RangeIter<Idx> {
105 self.clone().into_iter()
106 }
107}
108
109impl<Idx: PartialOrd<Idx>> Range<Idx> {
110 /// Returns `true` if `item` is contained in the range.
111 ///
112 /// # Examples
113 ///
114 /// ```
115 /// use core::range::Range;
116 ///
117 /// assert!(!Range::from(3..5).contains(&2));
118 /// assert!( Range::from(3..5).contains(&3));
119 /// assert!( Range::from(3..5).contains(&4));
120 /// assert!(!Range::from(3..5).contains(&5));
121 ///
122 /// assert!(!Range::from(3..3).contains(&3));
123 /// assert!(!Range::from(3..2).contains(&3));
124 ///
125 /// assert!( Range::from(0.0..1.0).contains(&0.5));
126 /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN));
127 /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5));
128 /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5));
129 /// ```
130 #[inline]
131 #[stable(feature = "new_range_api", since = "1.96.0")]
132 #[rustc_const_unstable(feature = "const_range", issue = "none")]
133 pub const fn contains<U>(&self, item: &U) -> bool
134 where
135 Idx: [const] PartialOrd<U>,
136 U: ?Sized + [const] PartialOrd<Idx>,
137 {
138 <Self as RangeBounds<Idx>>::contains(self, item)
139 }
140
141 /// Returns `true` if the range contains no items.
142 ///
143 /// # Examples
144 ///
145 /// ```
146 /// use core::range::Range;
147 ///
148 /// assert!(!Range::from(3..5).is_empty());
149 /// assert!( Range::from(3..3).is_empty());
150 /// assert!( Range::from(3..2).is_empty());
151 /// ```
152 ///
153 /// The range is empty if either side is incomparable:
154 ///
155 /// ```
156 /// use core::range::Range;
157 ///
158 /// assert!(!Range::from(3.0..5.0).is_empty());
159 /// assert!( Range::from(3.0..f32::NAN).is_empty());
160 /// assert!( Range::from(f32::NAN..5.0).is_empty());
161 /// ```
162 #[inline]
163 #[stable(feature = "new_range_api", since = "1.96.0")]
164 #[rustc_const_unstable(feature = "const_range", issue = "none")]
165 pub const fn is_empty(&self) -> bool
166 where
167 Idx: [const] PartialOrd,
168 {
169 !(self.start < self.end)
170 }
171}
172
173#[stable(feature = "new_range_api", since = "1.96.0")]
174#[rustc_const_unstable(feature = "const_range", issue = "none")]
175const impl<T> RangeBounds<T> for Range<T> {
176 fn start_bound(&self) -> Bound<&T> {
177 Included(&self.start)
178 }
179 fn end_bound(&self) -> Bound<&T> {
180 Excluded(&self.end)
181 }
182}
183
184// This impl intentionally does not have `T: ?Sized`;
185// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
186//
187/// If you need to use this implementation where `T` is unsized,
188/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
189/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
190#[stable(feature = "new_range_api", since = "1.96.0")]
191#[rustc_const_unstable(feature = "const_range", issue = "none")]
192const impl<T> RangeBounds<T> for Range<&T> {
193 fn start_bound(&self) -> Bound<&T> {
194 Included(self.start)
195 }
196 fn end_bound(&self) -> Bound<&T> {
197 Excluded(self.end)
198 }
199}
200
201#[unstable(feature = "range_into_bounds", issue = "136903")]
202#[rustc_const_unstable(feature = "const_range", issue = "none")]
203const impl<T> IntoBounds<T> for Range<T> {
204 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
205 (Included(self.start), Excluded(self.end))
206 }
207}
208
209#[stable(feature = "new_range_api", since = "1.96.0")]
210#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
211const impl<T> From<Range<T>> for legacy::Range<T> {
212 #[inline]
213 fn from(value: Range<T>) -> Self {
214 Self { start: value.start, end: value.end }
215 }
216}
217#[stable(feature = "new_range_api", since = "1.96.0")]
218#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
219const impl<T> From<legacy::Range<T>> for Range<T> {
220 #[inline]
221 fn from(value: legacy::Range<T>) -> Self {
222 Self { start: value.start, end: value.end }
223 }
224}
225
226/// A range bounded inclusively below and above.
227///
228/// The `RangeInclusive` contains all values with `x >= start`
229/// and `x <= last`. It is empty unless `start <= last`.
230///
231/// # Examples
232///
233/// ```
234/// use core::range::RangeInclusive;
235///
236/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
237/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
238/// ```
239///
240/// # Edition notes
241///
242/// It is planned that the syntax `start..=last` will construct this
243/// type in a future edition, but it does not do so today.
244#[lang = "RangeInclusiveCopy"]
245#[derive(Clone, Copy, PartialEq, Eq, Hash)]
246#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
247pub struct RangeInclusive<Idx> {
248 /// The lower bound of the range (inclusive).
249 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
250 pub start: Idx,
251 /// The upper bound of the range (inclusive).
252 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
253 pub last: Idx,
254}
255
256#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
257impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
258 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
259 self.start.fmt(fmt)?;
260 write!(fmt, "..=")?;
261 self.last.fmt(fmt)?;
262 Ok(())
263 }
264}
265
266impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
267 /// Returns `true` if `item` is contained in the range.
268 ///
269 /// # Examples
270 ///
271 /// ```
272 /// use core::range::RangeInclusive;
273 ///
274 /// assert!(!RangeInclusive::from(3..=5).contains(&2));
275 /// assert!( RangeInclusive::from(3..=5).contains(&3));
276 /// assert!( RangeInclusive::from(3..=5).contains(&4));
277 /// assert!( RangeInclusive::from(3..=5).contains(&5));
278 /// assert!(!RangeInclusive::from(3..=5).contains(&6));
279 ///
280 /// assert!( RangeInclusive::from(3..=3).contains(&3));
281 /// assert!(!RangeInclusive::from(3..=2).contains(&3));
282 ///
283 /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
284 /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
285 /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
286 /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
287 /// ```
288 #[inline]
289 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
290 #[rustc_const_unstable(feature = "const_range", issue = "none")]
291 pub const fn contains<U>(&self, item: &U) -> bool
292 where
293 Idx: [const] PartialOrd<U>,
294 U: ?Sized + [const] PartialOrd<Idx>,
295 {
296 <Self as RangeBounds<Idx>>::contains(self, item)
297 }
298
299 /// Returns `true` if the range contains no items.
300 ///
301 /// # Examples
302 ///
303 /// ```
304 /// use core::range::RangeInclusive;
305 ///
306 /// assert!(!RangeInclusive::from(3..=5).is_empty());
307 /// assert!(!RangeInclusive::from(3..=3).is_empty());
308 /// assert!( RangeInclusive::from(3..=2).is_empty());
309 /// ```
310 ///
311 /// The range is empty if either side is incomparable:
312 ///
313 /// ```
314 /// use core::range::RangeInclusive;
315 ///
316 /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
317 /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
318 /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
319 /// ```
320 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
321 #[inline]
322 #[rustc_const_unstable(feature = "const_range", issue = "none")]
323 pub const fn is_empty(&self) -> bool
324 where
325 Idx: [const] PartialOrd,
326 {
327 !(self.start <= self.last)
328 }
329}
330
331impl<Idx: Step> RangeInclusive<Idx> {
332 /// Creates an iterator over the elements within this range.
333 ///
334 /// Shorthand for `.clone().into_iter()`
335 ///
336 /// # Examples
337 ///
338 /// ```
339 /// use core::range::RangeInclusive;
340 ///
341 /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
342 /// assert_eq!(i.next(), Some(9));
343 /// assert_eq!(i.next(), Some(16));
344 /// assert_eq!(i.next(), Some(25));
345 /// ```
346 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
347 #[inline]
348 pub fn iter(&self) -> RangeInclusiveIter<Idx> {
349 self.clone().into_iter()
350 }
351}
352
353#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
354#[rustc_const_unstable(feature = "const_range", issue = "none")]
355const impl<T> RangeBounds<T> for RangeInclusive<T> {
356 fn start_bound(&self) -> Bound<&T> {
357 Included(&self.start)
358 }
359 fn end_bound(&self) -> Bound<&T> {
360 Included(&self.last)
361 }
362}
363
364// This impl intentionally does not have `T: ?Sized`;
365// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
366//
367/// If you need to use this implementation where `T` is unsized,
368/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
369/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
370#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
371#[rustc_const_unstable(feature = "const_range", issue = "none")]
372const impl<T> RangeBounds<T> for RangeInclusive<&T> {
373 fn start_bound(&self) -> Bound<&T> {
374 Included(self.start)
375 }
376 fn end_bound(&self) -> Bound<&T> {
377 Included(self.last)
378 }
379}
380
381// #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
382#[unstable(feature = "range_into_bounds", issue = "136903")]
383#[rustc_const_unstable(feature = "const_range", issue = "none")]
384const impl<T> IntoBounds<T> for RangeInclusive<T> {
385 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
386 (Included(self.start), Included(self.last))
387 }
388}
389
390#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
391#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
392const impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
393 #[inline]
394 fn from(value: RangeInclusive<T>) -> Self {
395 Self::new(value.start, value.last)
396 }
397}
398#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
399#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
400const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
401 /// Converts from a legacy range to a non-legacy range, potentially panicking.
402 ///
403 /// # Panics
404 ///
405 /// Panics if the legacy range iterator has been exhausted.
406 ///
407 /// # Examples
408 ///
409 /// ```
410 /// use core::range::legacy;
411 /// use core::range::RangeInclusive;
412 ///
413 /// let single: legacy::RangeInclusive<i32> = 0..=1;
414 /// let single = RangeInclusive::from(single);
415 /// assert_eq!((single.start, single.last), (0, 1));
416 ///
417 /// let empty: legacy::RangeInclusive<i32> = 0..=0;
418 /// let empty = RangeInclusive::from(empty);
419 /// assert_eq!((empty.start, empty.last), (0, 0));
420 /// ```
421 ///
422 /// ```should_panic
423 /// use core::range::legacy;
424 /// use core::range::RangeInclusive;
425 ///
426 /// let mut exhausted: legacy::RangeInclusive<i32> = 0..=0;
427 /// exhausted.next();
428 /// # if exhausted.is_empty() {
429 /// # // assert!s don't work correctly in `should_panic` doctests since you
430 /// # // can't assert the panic message. Skip the rest of the test instead,
431 /// # // so that the expected panic doesn't happen and the test fails.
432 /// assert!(exhausted.is_empty());
433 /// let _ = RangeInclusive::from(exhausted); // this panics
434 /// # }
435 /// ```
436 #[inline]
437 fn from(value: legacy::RangeInclusive<T>) -> Self {
438 assert!(
439 !value.exhausted,
440 "attempted to convert from an exhausted `legacy::RangeInclusive`"
441 );
442
443 let (start, last) = value.into_inner();
444 RangeInclusive { start, last }
445 }
446}
447
448/// A range only bounded inclusively below.
449///
450/// The `RangeFrom` contains all values with `x >= start`.
451///
452/// *Note*: Overflow in the [`IntoIterator`] implementation (when the contained
453/// data type reaches its numerical limit) is allowed to panic, wrap, or
454/// saturate. This behavior is defined by the implementation of the [`Step`]
455/// trait. For primitive integers, this follows the normal rules, and respects
456/// the overflow checks profile (panic in debug, wrap in release). Unlike
457/// its legacy counterpart, the iterator will only panic after yielding the
458/// maximum value when overflow checks are enabled.
459///
460/// [`Step`]: crate::iter::Step
461///
462/// # Examples
463///
464/// ```
465/// use core::range::RangeFrom;
466///
467/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
468/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
469/// ```
470///
471/// # Edition notes
472///
473/// It is planned that the syntax `start..` will construct this
474/// type in a future edition, but it does not do so today.
475#[lang = "RangeFromCopy"]
476#[derive(Copy, Hash)]
477#[derive_const(Clone, PartialEq, Eq)]
478#[stable(feature = "new_range_from_api", since = "1.96.0")]
479pub struct RangeFrom<Idx> {
480 /// The lower bound of the range (inclusive).
481 #[stable(feature = "new_range_from_api", since = "1.96.0")]
482 pub start: Idx,
483}
484
485#[stable(feature = "new_range_from_api", since = "1.96.0")]
486impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
487 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
488 self.start.fmt(fmt)?;
489 write!(fmt, "..")?;
490 Ok(())
491 }
492}
493
494impl<Idx: Step> RangeFrom<Idx> {
495 /// Creates an iterator over the elements within this range.
496 ///
497 /// Shorthand for `.clone().into_iter()`
498 ///
499 /// # Examples
500 ///
501 /// ```
502 /// use core::range::RangeFrom;
503 ///
504 /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
505 /// assert_eq!(i.next(), Some(9));
506 /// assert_eq!(i.next(), Some(16));
507 /// assert_eq!(i.next(), Some(25));
508 /// ```
509 #[stable(feature = "new_range_from_api", since = "1.96.0")]
510 #[inline]
511 pub fn iter(&self) -> RangeFromIter<Idx> {
512 self.clone().into_iter()
513 }
514}
515
516impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
517 /// Returns `true` if `item` is contained in the range.
518 ///
519 /// # Examples
520 ///
521 /// ```
522 /// use core::range::RangeFrom;
523 ///
524 /// assert!(!RangeFrom::from(3..).contains(&2));
525 /// assert!( RangeFrom::from(3..).contains(&3));
526 /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
527 ///
528 /// assert!( RangeFrom::from(0.0..).contains(&0.5));
529 /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
530 /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
531 /// ```
532 #[inline]
533 #[stable(feature = "new_range_from_api", since = "1.96.0")]
534 #[rustc_const_unstable(feature = "const_range", issue = "none")]
535 pub const fn contains<U>(&self, item: &U) -> bool
536 where
537 Idx: [const] PartialOrd<U>,
538 U: ?Sized + [const] PartialOrd<Idx>,
539 {
540 <Self as RangeBounds<Idx>>::contains(self, item)
541 }
542}
543
544#[stable(feature = "new_range_from_api", since = "1.96.0")]
545#[rustc_const_unstable(feature = "const_range", issue = "none")]
546const impl<T> RangeBounds<T> for RangeFrom<T> {
547 fn start_bound(&self) -> Bound<&T> {
548 Included(&self.start)
549 }
550 fn end_bound(&self) -> Bound<&T> {
551 Unbounded
552 }
553}
554
555// This impl intentionally does not have `T: ?Sized`;
556// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
557//
558/// If you need to use this implementation where `T` is unsized,
559/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
560/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
561#[stable(feature = "new_range_from_api", since = "1.96.0")]
562#[rustc_const_unstable(feature = "const_range", issue = "none")]
563const impl<T> RangeBounds<T> for RangeFrom<&T> {
564 fn start_bound(&self) -> Bound<&T> {
565 Included(self.start)
566 }
567 fn end_bound(&self) -> Bound<&T> {
568 Unbounded
569 }
570}
571
572#[unstable(feature = "range_into_bounds", issue = "136903")]
573#[rustc_const_unstable(feature = "const_range", issue = "none")]
574const impl<T> IntoBounds<T> for RangeFrom<T> {
575 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
576 (Included(self.start), Unbounded)
577 }
578}
579
580#[unstable(feature = "one_sided_range", issue = "69780")]
581#[rustc_const_unstable(feature = "const_range", issue = "none")]
582const impl<T> OneSidedRange<T> for RangeFrom<T>
583where
584 Self: RangeBounds<T>,
585{
586 fn bound(self) -> (OneSidedRangeBound, T) {
587 (OneSidedRangeBound::StartInclusive, self.start)
588 }
589}
590
591#[stable(feature = "new_range_from_api", since = "1.96.0")]
592#[rustc_const_unstable(feature = "const_index", issue = "143775")]
593const impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
594 #[inline]
595 fn from(value: RangeFrom<T>) -> Self {
596 Self { start: value.start }
597 }
598}
599#[stable(feature = "new_range_from_api", since = "1.96.0")]
600#[rustc_const_unstable(feature = "const_index", issue = "143775")]
601const impl<T> From<legacy::RangeFrom<T>> for RangeFrom<T> {
602 #[inline]
603 fn from(value: legacy::RangeFrom<T>) -> Self {
604 Self { start: value.start }
605 }
606}
607
608/// A range only bounded inclusively above.
609///
610/// The `RangeToInclusive` contains all values with `x <= last`.
611/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
612///
613/// # Examples
614///
615/// ```standalone_crate
616/// #![feature(new_range)]
617/// assert_eq!((..=5), std::range::RangeToInclusive { last: 5 });
618/// ```
619///
620/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
621/// `for` loop directly. This won't compile:
622///
623/// ```compile_fail,E0277
624/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
625/// // std::iter::Iterator` is not satisfied
626/// for i in ..=5 {
627/// // ...
628/// }
629/// ```
630///
631/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
632/// array elements up to and including the index indicated by `last`.
633///
634/// ```
635/// let arr = [0, 1, 2, 3, 4];
636/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
637/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
638/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive`
639/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
640/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
641/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
642/// ```
643///
644/// [slicing index]: crate::slice::SliceIndex
645///
646/// # Edition notes
647///
648/// It is planned that the syntax `..=last` will construct this
649/// type in a future edition, but it does not do so today.
650#[lang = "RangeToInclusiveCopy"]
651#[doc(alias = "..=")]
652#[derive(Copy, Clone, PartialEq, Eq, Hash)]
653#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
654pub struct RangeToInclusive<Idx> {
655 /// The upper bound of the range (inclusive)
656 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
657 pub last: Idx,
658}
659
660#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
661impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
662 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
663 write!(fmt, "..=")?;
664 self.last.fmt(fmt)?;
665 Ok(())
666 }
667}
668
669impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
670 /// Returns `true` if `item` is contained in the range.
671 ///
672 /// # Examples
673 ///
674 /// ```
675 /// assert!( (..=5).contains(&-1_000_000_000));
676 /// assert!( (..=5).contains(&5));
677 /// assert!(!(..=5).contains(&6));
678 ///
679 /// assert!( (..=1.0).contains(&1.0));
680 /// assert!(!(..=1.0).contains(&f32::NAN));
681 /// assert!(!(..=f32::NAN).contains(&0.5));
682 /// ```
683 #[inline]
684 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
685 #[rustc_const_unstable(feature = "const_range", issue = "none")]
686 pub const fn contains<U>(&self, item: &U) -> bool
687 where
688 Idx: [const] PartialOrd<U>,
689 U: ?Sized + [const] PartialOrd<Idx>,
690 {
691 <Self as RangeBounds<Idx>>::contains(self, item)
692 }
693}
694
695#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
696impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
697 fn from(value: legacy::RangeToInclusive<T>) -> Self {
698 Self { last: value.end }
699 }
700}
701#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
702impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
703 fn from(value: RangeToInclusive<T>) -> Self {
704 Self { end: value.last }
705 }
706}
707
708// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
709// because underflow would be possible with (..0).into()
710
711#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
712#[rustc_const_unstable(feature = "const_range", issue = "none")]
713const impl<T> RangeBounds<T> for RangeToInclusive<T> {
714 fn start_bound(&self) -> Bound<&T> {
715 Unbounded
716 }
717 fn end_bound(&self) -> Bound<&T> {
718 Included(&self.last)
719 }
720}
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#[unstable(feature = "range_into_bounds", issue = "136903")]
734#[rustc_const_unstable(feature = "const_range", issue = "none")]
735const impl<T> IntoBounds<T> for RangeToInclusive<T> {
736 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
737 (Unbounded, Included(self.last))
738 }
739}
740
741#[unstable(feature = "one_sided_range", issue = "69780")]
742#[rustc_const_unstable(feature = "const_range", issue = "none")]
743const impl<T> OneSidedRange<T> for RangeToInclusive<T>
744where
745 Self: RangeBounds<T>,
746{
747 fn bound(self) -> (OneSidedRangeBound, T) {
748 (OneSidedRangeBound::EndInclusive, self.last)
749 }
750}