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