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