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