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#[unstable(feature = "new_range_api_legacy", issue = "125687")]
24pub mod legacy;
25
26#[doc(inline)]
27#[stable(feature = "new_range_from_api", since = "1.96.0")]
28pub use iter::RangeFromIter;
29#[doc(inline)]
30#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
31pub use iter::RangeInclusiveIter;
32#[doc(inline)]
33#[stable(feature = "new_range_api", since = "1.96.0")]
34pub use iter::RangeIter;
35
36// FIXME(#125687): re-exports temporarily removed
37// Because re-exports of stable items (Bound, RangeBounds, RangeFull, RangeTo)
38// can't be made unstable.
39//
40// #[doc(inline)]
41// #[unstable(feature = "new_range_api", issue = "125687")]
42// pub use crate::iter::Step;
43// #[doc(inline)]
44// #[unstable(feature = "new_range_api", issue = "125687")]
45// pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo};
46use crate::iter::Step;
47use crate::ops::Bound::{self, Excluded, Included, Unbounded};
48use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds};
49
50/// A (half-open) range bounded inclusively below and exclusively above.
51///
52/// The `Range` contains all values with `start <= x < end`.
53/// It is empty if `start >= end`.
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 pub const fn is_empty(&self) -> bool
170 where
171 Idx: [const] PartialOrd,
172 {
173 !(self.start < self.end)
174 }
175}
176
177#[stable(feature = "new_range_api", since = "1.96.0")]
178#[rustc_const_unstable(feature = "const_range", issue = "none")]
179impl<T> const RangeBounds<T> for Range<T> {
180 fn start_bound(&self) -> Bound<&T> {
181 Included(&self.start)
182 }
183 fn end_bound(&self) -> Bound<&T> {
184 Excluded(&self.end)
185 }
186}
187
188// This impl intentionally does not have `T: ?Sized`;
189// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
190//
191/// If you need to use this implementation where `T` is unsized,
192/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
193/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
194#[stable(feature = "new_range_api", since = "1.96.0")]
195#[rustc_const_unstable(feature = "const_range", issue = "none")]
196impl<T> const RangeBounds<T> for Range<&T> {
197 fn start_bound(&self) -> Bound<&T> {
198 Included(self.start)
199 }
200 fn end_bound(&self) -> Bound<&T> {
201 Excluded(self.end)
202 }
203}
204
205#[unstable(feature = "range_into_bounds", issue = "136903")]
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#[stable(feature = "new_range_api", since = "1.96.0")]
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#[stable(feature = "new_range_api", since = "1.96.0")]
222#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
223impl<T> const From<legacy::Range<T>> for Range<T> {
224 #[inline]
225 fn from(value: legacy::Range<T>) -> Self {
226 Self { start: value.start, end: value.end }
227 }
228}
229
230/// A range bounded inclusively below and above.
231///
232/// The `RangeInclusive` contains all values with `x >= start`
233/// and `x <= last`. It is empty unless `start <= last`.
234///
235/// # Examples
236///
237/// ```
238/// use core::range::RangeInclusive;
239///
240/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
241/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
242/// ```
243///
244/// # Edition notes
245///
246/// It is planned that the syntax `start..=last` will construct this
247/// type in a future edition, but it does not do so today.
248#[lang = "RangeInclusiveCopy"]
249#[derive(Clone, Copy, PartialEq, Eq, Hash)]
250#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
251pub struct RangeInclusive<Idx> {
252 /// The lower bound of the range (inclusive).
253 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
254 pub start: Idx,
255 /// The upper bound of the range (inclusive).
256 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
257 pub last: Idx,
258}
259
260#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
261impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
262 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
263 self.start.fmt(fmt)?;
264 write!(fmt, "..=")?;
265 self.last.fmt(fmt)?;
266 Ok(())
267 }
268}
269
270impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
271 /// Returns `true` if `item` is contained in the range.
272 ///
273 /// # Examples
274 ///
275 /// ```
276 /// use core::range::RangeInclusive;
277 ///
278 /// assert!(!RangeInclusive::from(3..=5).contains(&2));
279 /// assert!( RangeInclusive::from(3..=5).contains(&3));
280 /// assert!( RangeInclusive::from(3..=5).contains(&4));
281 /// assert!( RangeInclusive::from(3..=5).contains(&5));
282 /// assert!(!RangeInclusive::from(3..=5).contains(&6));
283 ///
284 /// assert!( RangeInclusive::from(3..=3).contains(&3));
285 /// assert!(!RangeInclusive::from(3..=2).contains(&3));
286 ///
287 /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
288 /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
289 /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
290 /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
291 /// ```
292 #[inline]
293 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
294 #[rustc_const_unstable(feature = "const_range", issue = "none")]
295 pub const fn contains<U>(&self, item: &U) -> bool
296 where
297 Idx: [const] PartialOrd<U>,
298 U: ?Sized + [const] PartialOrd<Idx>,
299 {
300 <Self as RangeBounds<Idx>>::contains(self, item)
301 }
302
303 /// Returns `true` if the range contains no items.
304 ///
305 /// # Examples
306 ///
307 /// ```
308 /// use core::range::RangeInclusive;
309 ///
310 /// assert!(!RangeInclusive::from(3..=5).is_empty());
311 /// assert!(!RangeInclusive::from(3..=3).is_empty());
312 /// assert!( RangeInclusive::from(3..=2).is_empty());
313 /// ```
314 ///
315 /// The range is empty if either side is incomparable:
316 ///
317 /// ```
318 /// use core::range::RangeInclusive;
319 ///
320 /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
321 /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
322 /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
323 /// ```
324 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
325 #[inline]
326 #[rustc_const_unstable(feature = "const_range", issue = "none")]
327 pub const fn is_empty(&self) -> bool
328 where
329 Idx: [const] PartialOrd,
330 {
331 !(self.start <= self.last)
332 }
333}
334
335impl<Idx: Step> RangeInclusive<Idx> {
336 /// Creates an iterator over the elements within this range.
337 ///
338 /// Shorthand for `.clone().into_iter()`
339 ///
340 /// # Examples
341 ///
342 /// ```
343 /// use core::range::RangeInclusive;
344 ///
345 /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
346 /// assert_eq!(i.next(), Some(9));
347 /// assert_eq!(i.next(), Some(16));
348 /// assert_eq!(i.next(), Some(25));
349 /// ```
350 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
351 #[inline]
352 pub fn iter(&self) -> RangeInclusiveIter<Idx> {
353 self.clone().into_iter()
354 }
355}
356
357#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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// #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
386#[unstable(feature = "range_into_bounds", issue = "136903")]
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#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
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.
418///
419/// The `RangeFrom` contains all values with `x >= start`.
420///
421/// *Note*: Overflow in the [`IntoIterator`] 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). Unlike
426/// its legacy counterpart, the iterator will only panic after yielding the
427/// maximum value when overflow checks are enabled.
428///
429/// [`Step`]: crate::iter::Step
430///
431/// # Examples
432///
433/// ```
434/// use core::range::RangeFrom;
435///
436/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
437/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
438/// ```
439///
440/// # Edition notes
441///
442/// It is planned that the syntax `start..` will construct this
443/// type in a future edition, but it does not do so today.
444#[lang = "RangeFromCopy"]
445#[derive(Copy, Hash)]
446#[derive_const(Clone, PartialEq, Eq)]
447#[stable(feature = "new_range_from_api", since = "1.96.0")]
448pub struct RangeFrom<Idx> {
449 /// The lower bound of the range (inclusive).
450 #[stable(feature = "new_range_from_api", since = "1.96.0")]
451 pub start: Idx,
452}
453
454#[stable(feature = "new_range_from_api", since = "1.96.0")]
455impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
456 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
457 self.start.fmt(fmt)?;
458 write!(fmt, "..")?;
459 Ok(())
460 }
461}
462
463impl<Idx: Step> RangeFrom<Idx> {
464 /// Creates an iterator over the elements within this range.
465 ///
466 /// Shorthand for `.clone().into_iter()`
467 ///
468 /// # Examples
469 ///
470 /// ```
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 #[stable(feature = "new_range_from_api", since = "1.96.0")]
479 #[inline]
480 pub fn iter(&self) -> RangeFromIter<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 /// use core::range::RangeFrom;
492 ///
493 /// assert!(!RangeFrom::from(3..).contains(&2));
494 /// assert!( RangeFrom::from(3..).contains(&3));
495 /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
496 ///
497 /// assert!( RangeFrom::from(0.0..).contains(&0.5));
498 /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
499 /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
500 /// ```
501 #[inline]
502 #[stable(feature = "new_range_from_api", since = "1.96.0")]
503 #[rustc_const_unstable(feature = "const_range", issue = "none")]
504 pub const fn contains<U>(&self, item: &U) -> bool
505 where
506 Idx: [const] PartialOrd<U>,
507 U: ?Sized + [const] PartialOrd<Idx>,
508 {
509 <Self as RangeBounds<Idx>>::contains(self, item)
510 }
511}
512
513#[stable(feature = "new_range_from_api", since = "1.96.0")]
514#[rustc_const_unstable(feature = "const_range", issue = "none")]
515impl<T> const RangeBounds<T> for RangeFrom<T> {
516 fn start_bound(&self) -> Bound<&T> {
517 Included(&self.start)
518 }
519 fn end_bound(&self) -> Bound<&T> {
520 Unbounded
521 }
522}
523
524// This impl intentionally does not have `T: ?Sized`;
525// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
526//
527/// If you need to use this implementation where `T` is unsized,
528/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
529/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
530#[stable(feature = "new_range_from_api", since = "1.96.0")]
531#[rustc_const_unstable(feature = "const_range", issue = "none")]
532impl<T> const RangeBounds<T> for RangeFrom<&T> {
533 fn start_bound(&self) -> Bound<&T> {
534 Included(self.start)
535 }
536 fn end_bound(&self) -> Bound<&T> {
537 Unbounded
538 }
539}
540
541#[unstable(feature = "range_into_bounds", issue = "136903")]
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 = "one_sided_range", issue = "69780")]
550#[rustc_const_unstable(feature = "const_range", issue = "none")]
551impl<T> const OneSidedRange<T> for RangeFrom<T>
552where
553 Self: RangeBounds<T>,
554{
555 fn bound(self) -> (OneSidedRangeBound, T) {
556 (OneSidedRangeBound::StartInclusive, self.start)
557 }
558}
559
560#[stable(feature = "new_range_from_api", since = "1.96.0")]
561#[rustc_const_unstable(feature = "const_index", issue = "143775")]
562impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
563 #[inline]
564 fn from(value: RangeFrom<T>) -> Self {
565 Self { start: value.start }
566 }
567}
568#[stable(feature = "new_range_from_api", since = "1.96.0")]
569#[rustc_const_unstable(feature = "const_index", issue = "143775")]
570impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
571 #[inline]
572 fn from(value: legacy::RangeFrom<T>) -> Self {
573 Self { start: value.start }
574 }
575}
576
577/// A range only bounded inclusively above.
578///
579/// The `RangeToInclusive` contains all values with `x <= last`.
580/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
581///
582/// # Examples
583///
584/// ```standalone_crate
585/// #![feature(new_range)]
586/// assert_eq!((..=5), std::range::RangeToInclusive { last: 5 });
587/// ```
588///
589/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
590/// `for` loop directly. This won't compile:
591///
592/// ```compile_fail,E0277
593/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
594/// // std::iter::Iterator` is not satisfied
595/// for i in ..=5 {
596/// // ...
597/// }
598/// ```
599///
600/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
601/// array elements up to and including the index indicated by `last`.
602///
603/// ```
604/// let arr = [0, 1, 2, 3, 4];
605/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
606/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
607/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive`
608/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
609/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
610/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
611/// ```
612///
613/// [slicing index]: crate::slice::SliceIndex
614///
615/// # Edition notes
616///
617/// It is planned that the syntax `..=last` will construct this
618/// type in a future edition, but it does not do so today.
619#[lang = "RangeToInclusiveCopy"]
620#[doc(alias = "..=")]
621#[derive(Copy, Clone, PartialEq, Eq, Hash)]
622#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
623pub struct RangeToInclusive<Idx> {
624 /// The upper bound of the range (inclusive)
625 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
626 pub last: Idx,
627}
628
629#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
630impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
631 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
632 write!(fmt, "..=")?;
633 self.last.fmt(fmt)?;
634 Ok(())
635 }
636}
637
638impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
639 /// Returns `true` if `item` is contained in the range.
640 ///
641 /// # Examples
642 ///
643 /// ```
644 /// assert!( (..=5).contains(&-1_000_000_000));
645 /// assert!( (..=5).contains(&5));
646 /// assert!(!(..=5).contains(&6));
647 ///
648 /// assert!( (..=1.0).contains(&1.0));
649 /// assert!(!(..=1.0).contains(&f32::NAN));
650 /// assert!(!(..=f32::NAN).contains(&0.5));
651 /// ```
652 #[inline]
653 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
654 #[rustc_const_unstable(feature = "const_range", issue = "none")]
655 pub const fn contains<U>(&self, item: &U) -> bool
656 where
657 Idx: [const] PartialOrd<U>,
658 U: ?Sized + [const] PartialOrd<Idx>,
659 {
660 <Self as RangeBounds<Idx>>::contains(self, item)
661 }
662}
663
664#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
665impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
666 fn from(value: legacy::RangeToInclusive<T>) -> Self {
667 Self { last: value.end }
668 }
669}
670#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
671impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
672 fn from(value: RangeToInclusive<T>) -> Self {
673 Self { end: value.last }
674 }
675}
676
677// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
678// because underflow would be possible with (..0).into()
679
680#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
681#[rustc_const_unstable(feature = "const_range", issue = "none")]
682impl<T> const RangeBounds<T> for RangeToInclusive<T> {
683 fn start_bound(&self) -> Bound<&T> {
684 Unbounded
685 }
686 fn end_bound(&self) -> Bound<&T> {
687 Included(&self.last)
688 }
689}
690
691#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
692#[rustc_const_unstable(feature = "const_range", issue = "none")]
693impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
694 fn start_bound(&self) -> Bound<&T> {
695 Unbounded
696 }
697 fn end_bound(&self) -> Bound<&T> {
698 Included(self.last)
699 }
700}
701
702#[unstable(feature = "range_into_bounds", issue = "136903")]
703#[rustc_const_unstable(feature = "const_range", issue = "none")]
704impl<T> const IntoBounds<T> for RangeToInclusive<T> {
705 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
706 (Unbounded, Included(self.last))
707 }
708}
709
710#[unstable(feature = "one_sided_range", issue = "69780")]
711#[rustc_const_unstable(feature = "const_range", issue = "none")]
712impl<T> const OneSidedRange<T> for RangeToInclusive<T>
713where
714 Self: RangeBounds<T>,
715{
716 fn bound(self) -> (OneSidedRangeBound, T) {
717 (OneSidedRangeBound::EndInclusive, self.last)
718 }
719}