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