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