core/ops/range.rs
1use crate::fmt;
2use crate::hash::Hash;
3use crate::marker::Destruct;
4/// An unbounded range (`..`).
5///
6/// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`.
7/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
8///
9/// # Examples
10///
11/// The `..` syntax is a `RangeFull`:
12///
13/// ```
14/// assert_eq!(.., std::ops::RangeFull);
15/// ```
16///
17/// It does not have an [`IntoIterator`] implementation, so you can't use it in
18/// a `for` loop directly. This won't compile:
19///
20/// ```compile_fail,E0277
21/// for i in .. {
22/// // ...
23/// }
24/// ```
25///
26/// Used as a [slicing index], `RangeFull` produces the full array as a slice.
27///
28/// ```
29/// let arr = [0, 1, 2, 3, 4];
30/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]); // This is the `RangeFull`
31/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
32/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
33/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
34/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
35/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
36/// ```
37///
38/// [slicing index]: crate::slice::SliceIndex
39#[lang = "RangeFull"]
40#[doc(alias = "..")]
41#[derive(Copy, Hash)]
42#[derive_const(Clone, Default, Eq, PartialEq)]
43#[stable(feature = "rust1", since = "1.0.0")]
44pub struct RangeFull;
45
46#[stable(feature = "rust1", since = "1.0.0")]
47impl fmt::Debug for RangeFull {
48 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
49 write!(fmt, "..")
50 }
51}
52
53/// A (half-open) range bounded inclusively below and exclusively above
54/// (`start..end`).
55///
56/// The range `start..end` contains all values with `start <= x < end`.
57/// It is empty if `start >= end`.
58///
59/// # Examples
60///
61/// The `start..end` syntax is a `Range`:
62///
63/// ```
64/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
65/// assert_eq!(3 + 4 + 5, (3..6).sum());
66/// ```
67///
68/// ```
69/// let arr = [0, 1, 2, 3, 4];
70/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
71/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
72/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
73/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
74/// assert_eq!(arr[1.. 3], [ 1, 2 ]); // This is a `Range`
75/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
76/// ```
77#[lang = "Range"]
78#[doc(alias = "..")]
79#[derive(Eq, Hash)]
80#[derive_const(Clone, Default, PartialEq)] // not Copy -- see #27186
81#[stable(feature = "rust1", since = "1.0.0")]
82pub struct Range<Idx> {
83 /// The lower bound of the range (inclusive).
84 #[stable(feature = "rust1", since = "1.0.0")]
85 pub start: Idx,
86 /// The upper bound of the range (exclusive).
87 #[stable(feature = "rust1", since = "1.0.0")]
88 pub end: Idx,
89}
90
91#[stable(feature = "rust1", since = "1.0.0")]
92impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
93 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
94 self.start.fmt(fmt)?;
95 write!(fmt, "..")?;
96 self.end.fmt(fmt)?;
97 Ok(())
98 }
99}
100
101impl<Idx: PartialOrd<Idx>> Range<Idx> {
102 /// Returns `true` if `item` is contained in the range.
103 ///
104 /// # Examples
105 ///
106 /// ```
107 /// assert!(!(3..5).contains(&2));
108 /// assert!( (3..5).contains(&3));
109 /// assert!( (3..5).contains(&4));
110 /// assert!(!(3..5).contains(&5));
111 ///
112 /// assert!(!(3..3).contains(&3));
113 /// assert!(!(3..2).contains(&3));
114 ///
115 /// assert!( (0.0..1.0).contains(&0.5));
116 /// assert!(!(0.0..1.0).contains(&f32::NAN));
117 /// assert!(!(0.0..f32::NAN).contains(&0.5));
118 /// assert!(!(f32::NAN..1.0).contains(&0.5));
119 /// ```
120 #[inline]
121 #[stable(feature = "range_contains", since = "1.35.0")]
122 #[rustc_const_unstable(feature = "const_range", issue = "none")]
123 pub const fn contains<U>(&self, item: &U) -> bool
124 where
125 Idx: [const] PartialOrd<U>,
126 U: ?Sized + [const] PartialOrd<Idx>,
127 {
128 <Self as RangeBounds<Idx>>::contains(self, item)
129 }
130
131 /// Returns `true` if the range contains no items.
132 ///
133 /// # Examples
134 ///
135 /// ```
136 /// assert!(!(3..5).is_empty());
137 /// assert!( (3..3).is_empty());
138 /// assert!( (3..2).is_empty());
139 /// ```
140 ///
141 /// The range is empty if either side is incomparable:
142 ///
143 /// ```
144 /// assert!(!(3.0..5.0).is_empty());
145 /// assert!( (3.0..f32::NAN).is_empty());
146 /// assert!( (f32::NAN..5.0).is_empty());
147 /// ```
148 #[inline]
149 #[stable(feature = "range_is_empty", since = "1.47.0")]
150 #[rustc_const_unstable(feature = "const_range", issue = "none")]
151 pub const fn is_empty(&self) -> bool
152 where
153 Idx: [const] PartialOrd<Idx>,
154 {
155 !(self.start < self.end)
156 }
157}
158
159/// A range only bounded inclusively below (`start..`).
160///
161/// The `RangeFrom` `start..` contains all values with `x >= start`.
162///
163/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
164/// data type reaches its numerical limit) is allowed to panic, wrap, or
165/// saturate. This behavior is defined by the implementation of the [`Step`]
166/// trait. For primitive integers, this follows the normal rules, and respects
167/// the overflow checks profile (panic in debug, wrap in release). Note also
168/// that overflow happens earlier than you might assume: the overflow happens
169/// in the call to `next` that yields the maximum value, as the range must be
170/// set to a state to yield the next value.
171///
172/// [`Step`]: crate::iter::Step
173///
174/// # Examples
175///
176/// The `start..` syntax is a `RangeFrom`:
177///
178/// ```
179/// assert_eq!((2..), std::ops::RangeFrom { start: 2 });
180/// assert_eq!(2 + 3 + 4, (2..).take(3).sum());
181/// ```
182///
183/// ```
184/// let arr = [0, 1, 2, 3, 4];
185/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
186/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
187/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
188/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]); // This is a `RangeFrom`
189/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
190/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
191/// ```
192#[lang = "RangeFrom"]
193#[doc(alias = "..")]
194#[derive(Eq, Hash)]
195#[derive_const(Clone, PartialEq)] // not Copy -- see #27186
196#[stable(feature = "rust1", since = "1.0.0")]
197pub struct RangeFrom<Idx> {
198 /// The lower bound of the range (inclusive).
199 #[stable(feature = "rust1", since = "1.0.0")]
200 pub start: Idx,
201}
202
203#[stable(feature = "rust1", since = "1.0.0")]
204impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
205 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
206 self.start.fmt(fmt)?;
207 write!(fmt, "..")?;
208 Ok(())
209 }
210}
211
212impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
213 /// Returns `true` if `item` is contained in the range.
214 ///
215 /// # Examples
216 ///
217 /// ```
218 /// assert!(!(3..).contains(&2));
219 /// assert!( (3..).contains(&3));
220 /// assert!( (3..).contains(&1_000_000_000));
221 ///
222 /// assert!( (0.0..).contains(&0.5));
223 /// assert!(!(0.0..).contains(&f32::NAN));
224 /// assert!(!(f32::NAN..).contains(&0.5));
225 /// ```
226 #[inline]
227 #[stable(feature = "range_contains", since = "1.35.0")]
228 #[rustc_const_unstable(feature = "const_range", issue = "none")]
229 pub const fn contains<U>(&self, item: &U) -> bool
230 where
231 Idx: [const] PartialOrd<U>,
232 U: ?Sized + [const] PartialOrd<Idx>,
233 {
234 <Self as RangeBounds<Idx>>::contains(self, item)
235 }
236}
237
238/// A range only bounded exclusively above (`..end`).
239///
240/// The `RangeTo` `..end` contains all values with `x < end`.
241/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
242///
243/// # Examples
244///
245/// The `..end` syntax is a `RangeTo`:
246///
247/// ```
248/// assert_eq!((..5), std::ops::RangeTo { end: 5 });
249/// ```
250///
251/// It does not have an [`IntoIterator`] implementation, so you can't use it in
252/// a `for` loop directly. This won't compile:
253///
254/// ```compile_fail,E0277
255/// // error[E0277]: the trait bound `std::ops::RangeTo<{integer}>:
256/// // std::iter::Iterator` is not satisfied
257/// for i in ..5 {
258/// // ...
259/// }
260/// ```
261///
262/// When used as a [slicing index], `RangeTo` produces a slice of all array
263/// elements before the index indicated by `end`.
264///
265/// ```
266/// let arr = [0, 1, 2, 3, 4];
267/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
268/// assert_eq!(arr[ .. 3], [0, 1, 2 ]); // This is a `RangeTo`
269/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
270/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
271/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
272/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
273/// ```
274///
275/// [slicing index]: crate::slice::SliceIndex
276#[lang = "RangeTo"]
277#[doc(alias = "..")]
278#[derive(Copy, Eq, Hash)]
279#[derive_const(Clone, PartialEq)]
280#[stable(feature = "rust1", since = "1.0.0")]
281pub struct RangeTo<Idx> {
282 /// The upper bound of the range (exclusive).
283 #[stable(feature = "rust1", since = "1.0.0")]
284 pub end: Idx,
285}
286
287#[stable(feature = "rust1", since = "1.0.0")]
288impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
289 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
290 write!(fmt, "..")?;
291 self.end.fmt(fmt)?;
292 Ok(())
293 }
294}
295
296impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
297 /// Returns `true` if `item` is contained in the range.
298 ///
299 /// # Examples
300 ///
301 /// ```
302 /// assert!( (..5).contains(&-1_000_000_000));
303 /// assert!( (..5).contains(&4));
304 /// assert!(!(..5).contains(&5));
305 ///
306 /// assert!( (..1.0).contains(&0.5));
307 /// assert!(!(..1.0).contains(&f32::NAN));
308 /// assert!(!(..f32::NAN).contains(&0.5));
309 /// ```
310 #[inline]
311 #[stable(feature = "range_contains", since = "1.35.0")]
312 #[rustc_const_unstable(feature = "const_range", issue = "none")]
313 pub const fn contains<U>(&self, item: &U) -> bool
314 where
315 Idx: [const] PartialOrd<U>,
316 U: ?Sized + [const] PartialOrd<Idx>,
317 {
318 <Self as RangeBounds<Idx>>::contains(self, item)
319 }
320}
321
322/// A range bounded inclusively below and above (`start..=end`).
323///
324/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
325/// and `x <= end`. It is empty unless `start <= end`.
326///
327/// This iterator is [fused], but the specific values of `start` and `end` after
328/// iteration has finished are **unspecified** other than that [`.is_empty()`]
329/// will return `true` once no more values will be produced.
330///
331/// [fused]: crate::iter::FusedIterator
332/// [`.is_empty()`]: RangeInclusive::is_empty
333///
334/// # Examples
335///
336/// The `start..=end` syntax is a `RangeInclusive`:
337///
338/// ```
339/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
340/// assert_eq!(3 + 4 + 5, (3..=5).sum());
341/// ```
342///
343/// ```
344/// let arr = [0, 1, 2, 3, 4];
345/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
346/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
347/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]);
348/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
349/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
350/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]); // This is a `RangeInclusive`
351/// ```
352#[lang = "RangeInclusive"]
353#[doc(alias = "..=")]
354#[derive(Clone, Hash)]
355#[derive_const(Eq, PartialEq)] // not Copy -- see #27186
356#[stable(feature = "inclusive_range", since = "1.26.0")]
357pub struct RangeInclusive<Idx> {
358 // Note that the fields here are not public to allow changing the
359 // representation in the future; in particular, while we could plausibly
360 // expose start/end, modifying them without changing (future/current)
361 // private fields may lead to incorrect behavior, so we don't want to
362 // support that mode.
363 pub(crate) start: Idx,
364 pub(crate) end: Idx,
365
366 // This field is:
367 // - `false` upon construction
368 // - `false` when iteration has yielded an element and the iterator is not exhausted
369 // - `true` when iteration has been used to exhaust the iterator
370 //
371 // This is required to support PartialEq and Hash without a PartialOrd bound or specialization.
372 pub(crate) exhausted: bool,
373}
374
375impl<Idx> RangeInclusive<Idx> {
376 /// Creates a new inclusive range. Equivalent to writing `start..=end`.
377 ///
378 /// # Examples
379 ///
380 /// ```
381 /// use std::ops::RangeInclusive;
382 ///
383 /// assert_eq!(3..=5, RangeInclusive::new(3, 5));
384 /// ```
385 #[lang = "range_inclusive_new"]
386 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
387 #[inline]
388 #[rustc_promotable]
389 #[rustc_const_stable(feature = "const_range_new", since = "1.32.0")]
390 pub const fn new(start: Idx, end: Idx) -> Self {
391 Self { start, end, exhausted: false }
392 }
393
394 /// Returns the lower bound of the range (inclusive).
395 ///
396 /// When using an inclusive range for iteration, the values of `start()` and
397 /// [`end()`] are unspecified after the iteration ended. To determine
398 /// whether the inclusive range is empty, use the [`is_empty()`] method
399 /// instead of comparing `start() > end()`.
400 ///
401 /// Note: the value returned by this method is unspecified after the range
402 /// has been iterated to exhaustion.
403 ///
404 /// [`end()`]: RangeInclusive::end
405 /// [`is_empty()`]: RangeInclusive::is_empty
406 ///
407 /// # Examples
408 ///
409 /// ```
410 /// assert_eq!((3..=5).start(), &3);
411 /// ```
412 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
413 #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")]
414 #[inline]
415 pub const fn start(&self) -> &Idx {
416 &self.start
417 }
418
419 /// Returns the upper bound of the range (inclusive).
420 ///
421 /// When using an inclusive range for iteration, the values of [`start()`]
422 /// and `end()` are unspecified after the iteration ended. To determine
423 /// whether the inclusive range is empty, use the [`is_empty()`] method
424 /// instead of comparing `start() > end()`.
425 ///
426 /// Note: the value returned by this method is unspecified after the range
427 /// has been iterated to exhaustion.
428 ///
429 /// [`start()`]: RangeInclusive::start
430 /// [`is_empty()`]: RangeInclusive::is_empty
431 ///
432 /// # Examples
433 ///
434 /// ```
435 /// assert_eq!((3..=5).end(), &5);
436 /// ```
437 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
438 #[rustc_const_stable(feature = "const_inclusive_range_methods", since = "1.32.0")]
439 #[inline]
440 pub const fn end(&self) -> &Idx {
441 &self.end
442 }
443
444 /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound).
445 ///
446 /// Note: the value returned by this method is unspecified after the range
447 /// has been iterated to exhaustion.
448 ///
449 /// # Examples
450 ///
451 /// ```
452 /// assert_eq!((3..=5).into_inner(), (3, 5));
453 /// ```
454 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
455 #[inline]
456 #[rustc_const_unstable(feature = "const_range_bounds", issue = "108082")]
457 pub const fn into_inner(self) -> (Idx, Idx) {
458 (self.start, self.end)
459 }
460}
461
462impl RangeInclusive<usize> {
463 /// Converts to an exclusive `Range` for `SliceIndex` implementations.
464 /// The caller is responsible for dealing with `end == usize::MAX`.
465 #[inline]
466 pub(crate) const fn into_slice_range(self) -> Range<usize> {
467 // If we're not exhausted, we want to simply slice `start..end + 1`.
468 // If we are exhausted, then slicing with `end + 1..end + 1` gives us an
469 // empty range that is still subject to bounds-checks for that endpoint.
470 let exclusive_end = self.end + 1;
471 let start = if self.exhausted { exclusive_end } else { self.start };
472 start..exclusive_end
473 }
474}
475
476#[stable(feature = "inclusive_range", since = "1.26.0")]
477impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
478 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
479 self.start.fmt(fmt)?;
480 write!(fmt, "..=")?;
481 self.end.fmt(fmt)?;
482 if self.exhausted {
483 write!(fmt, " (exhausted)")?;
484 }
485 Ok(())
486 }
487}
488
489impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
490 /// Returns `true` if `item` is contained in the range.
491 ///
492 /// # Examples
493 ///
494 /// ```
495 /// assert!(!(3..=5).contains(&2));
496 /// assert!( (3..=5).contains(&3));
497 /// assert!( (3..=5).contains(&4));
498 /// assert!( (3..=5).contains(&5));
499 /// assert!(!(3..=5).contains(&6));
500 ///
501 /// assert!( (3..=3).contains(&3));
502 /// assert!(!(3..=2).contains(&3));
503 ///
504 /// assert!( (0.0..=1.0).contains(&1.0));
505 /// assert!(!(0.0..=1.0).contains(&f32::NAN));
506 /// assert!(!(0.0..=f32::NAN).contains(&0.0));
507 /// assert!(!(f32::NAN..=1.0).contains(&1.0));
508 /// ```
509 ///
510 /// This method always returns `false` after iteration has finished:
511 ///
512 /// ```
513 /// let mut r = 3..=5;
514 /// assert!(r.contains(&3) && r.contains(&5));
515 /// for _ in r.by_ref() {}
516 /// // Precise field values are unspecified here
517 /// assert!(!r.contains(&3) && !r.contains(&5));
518 /// ```
519 #[inline]
520 #[stable(feature = "range_contains", since = "1.35.0")]
521 #[rustc_const_unstable(feature = "const_range", issue = "none")]
522 pub const fn contains<U>(&self, item: &U) -> bool
523 where
524 Idx: [const] PartialOrd<U>,
525 U: ?Sized + [const] PartialOrd<Idx>,
526 {
527 <Self as RangeBounds<Idx>>::contains(self, item)
528 }
529
530 /// Returns `true` if the range contains no items.
531 ///
532 /// # Examples
533 ///
534 /// ```
535 /// assert!(!(3..=5).is_empty());
536 /// assert!(!(3..=3).is_empty());
537 /// assert!( (3..=2).is_empty());
538 /// ```
539 ///
540 /// The range is empty if either side is incomparable:
541 ///
542 /// ```
543 /// assert!(!(3.0..=5.0).is_empty());
544 /// assert!( (3.0..=f32::NAN).is_empty());
545 /// assert!( (f32::NAN..=5.0).is_empty());
546 /// ```
547 ///
548 /// This method returns `true` after iteration has finished:
549 ///
550 /// ```
551 /// let mut r = 3..=5;
552 /// for _ in r.by_ref() {}
553 /// // Precise field values are unspecified here
554 /// assert!(r.is_empty());
555 /// ```
556 #[stable(feature = "range_is_empty", since = "1.47.0")]
557 #[inline]
558 #[rustc_const_unstable(feature = "const_range", issue = "none")]
559 pub const fn is_empty(&self) -> bool
560 where
561 Idx: [const] PartialOrd,
562 {
563 self.exhausted || !(self.start <= self.end)
564 }
565}
566
567/// A range only bounded inclusively above (`..=end`).
568///
569/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
570/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
571///
572/// # Examples
573///
574/// The `..=end` syntax is a `RangeToInclusive`:
575///
576/// ```
577/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
578/// ```
579///
580/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
581/// `for` loop directly. This won't compile:
582///
583/// ```compile_fail,E0277
584/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
585/// // std::iter::Iterator` is not satisfied
586/// for i in ..=5 {
587/// // ...
588/// }
589/// ```
590///
591/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
592/// array elements up to and including the index indicated by `end`.
593///
594/// ```
595/// let arr = [0, 1, 2, 3, 4];
596/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
597/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
598/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive`
599/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
600/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
601/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
602/// ```
603///
604/// [slicing index]: crate::slice::SliceIndex
605#[lang = "RangeToInclusive"]
606#[doc(alias = "..=")]
607#[derive(Copy, Hash)]
608#[derive(Clone, PartialEq, Eq)]
609#[stable(feature = "inclusive_range", since = "1.26.0")]
610pub struct RangeToInclusive<Idx> {
611 /// The upper bound of the range (inclusive)
612 #[stable(feature = "inclusive_range", since = "1.26.0")]
613 pub end: Idx,
614}
615
616#[stable(feature = "inclusive_range", since = "1.26.0")]
617impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
618 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
619 write!(fmt, "..=")?;
620 self.end.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 #[stable(feature = "range_contains", since = "1.35.0")]
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// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
652// because underflow would be possible with (..0).into()
653
654/// An endpoint of a range of keys.
655///
656/// # Examples
657///
658/// `Bound`s are range endpoints:
659///
660/// ```
661/// use std::ops::Bound::*;
662/// use std::ops::RangeBounds;
663///
664/// assert_eq!((..100).start_bound(), Unbounded);
665/// assert_eq!((1..12).start_bound(), Included(&1));
666/// assert_eq!((1..12).end_bound(), Excluded(&12));
667/// ```
668///
669/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
670/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
671///
672/// ```
673/// use std::collections::BTreeMap;
674/// use std::ops::Bound::{Excluded, Included, Unbounded};
675///
676/// let mut map = BTreeMap::new();
677/// map.insert(3, "a");
678/// map.insert(5, "b");
679/// map.insert(8, "c");
680///
681/// for (key, value) in map.range((Excluded(3), Included(8))) {
682/// println!("{key}: {value}");
683/// }
684///
685/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
686/// ```
687///
688/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range
689#[stable(feature = "collections_bound", since = "1.17.0")]
690#[derive(Copy, Debug, Hash)]
691#[derive_const(Clone, Eq, PartialEq)]
692pub enum Bound<T> {
693 /// An inclusive bound.
694 #[stable(feature = "collections_bound", since = "1.17.0")]
695 Included(#[stable(feature = "collections_bound", since = "1.17.0")] T),
696 /// An exclusive bound.
697 #[stable(feature = "collections_bound", since = "1.17.0")]
698 Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T),
699 /// An infinite endpoint. Indicates that there is no bound in this direction.
700 #[stable(feature = "collections_bound", since = "1.17.0")]
701 Unbounded,
702}
703
704impl<T> Bound<T> {
705 /// Converts from `&Bound<T>` to `Bound<&T>`.
706 #[inline]
707 #[stable(feature = "bound_as_ref_shared", since = "1.65.0")]
708 #[rustc_const_unstable(feature = "const_range", issue = "none")]
709 pub const fn as_ref(&self) -> Bound<&T> {
710 match *self {
711 Included(ref x) => Included(x),
712 Excluded(ref x) => Excluded(x),
713 Unbounded => Unbounded,
714 }
715 }
716
717 /// Converts from `&mut Bound<T>` to `Bound<&mut T>`.
718 #[inline]
719 #[unstable(feature = "bound_as_ref", issue = "80996")]
720 pub const fn as_mut(&mut self) -> Bound<&mut T> {
721 match *self {
722 Included(ref mut x) => Included(x),
723 Excluded(ref mut x) => Excluded(x),
724 Unbounded => Unbounded,
725 }
726 }
727
728 /// Maps a `Bound<T>` to a `Bound<U>` by applying a function to the contained value (including
729 /// both `Included` and `Excluded`), returning a `Bound` of the same kind.
730 ///
731 /// # Examples
732 ///
733 /// ```
734 /// use std::ops::Bound::*;
735 ///
736 /// let bound_string = Included("Hello, World!");
737 ///
738 /// assert_eq!(bound_string.map(|s| s.len()), Included(13));
739 /// ```
740 ///
741 /// ```
742 /// use std::ops::Bound;
743 /// use Bound::*;
744 ///
745 /// let unbounded_string: Bound<String> = Unbounded;
746 ///
747 /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded);
748 /// ```
749 #[inline]
750 #[stable(feature = "bound_map", since = "1.77.0")]
751 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Bound<U> {
752 match self {
753 Unbounded => Unbounded,
754 Included(x) => Included(f(x)),
755 Excluded(x) => Excluded(f(x)),
756 }
757 }
758}
759
760impl<T: Copy> Bound<&T> {
761 /// Map a `Bound<&T>` to a `Bound<T>` by copying the contents of the bound.
762 ///
763 /// # Examples
764 ///
765 /// ```
766 /// #![feature(bound_copied)]
767 ///
768 /// use std::ops::Bound::*;
769 /// use std::ops::RangeBounds;
770 ///
771 /// assert_eq!((1..12).start_bound(), Included(&1));
772 /// assert_eq!((1..12).start_bound().copied(), Included(1));
773 /// ```
774 #[unstable(feature = "bound_copied", issue = "145966")]
775 #[must_use]
776 pub fn copied(self) -> Bound<T> {
777 match self {
778 Bound::Unbounded => Bound::Unbounded,
779 Bound::Included(x) => Bound::Included(*x),
780 Bound::Excluded(x) => Bound::Excluded(*x),
781 }
782 }
783}
784
785impl<T: Clone> Bound<&T> {
786 /// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound.
787 ///
788 /// # Examples
789 ///
790 /// ```
791 /// use std::ops::Bound::*;
792 /// use std::ops::RangeBounds;
793 ///
794 /// let a1 = String::from("a");
795 /// let (a2, a3, a4) = (a1.clone(), a1.clone(), a1.clone());
796 ///
797 /// assert_eq!(Included(&a1), (a2..).start_bound());
798 /// assert_eq!(Included(a3), (a4..).start_bound().cloned());
799 /// ```
800 #[must_use = "`self` will be dropped if the result is not used"]
801 #[stable(feature = "bound_cloned", since = "1.55.0")]
802 #[rustc_const_unstable(feature = "const_range", issue = "none")]
803 pub const fn cloned(self) -> Bound<T>
804 where
805 T: [const] Clone,
806 {
807 match self {
808 Bound::Unbounded => Bound::Unbounded,
809 Bound::Included(x) => Bound::Included(x.clone()),
810 Bound::Excluded(x) => Bound::Excluded(x.clone()),
811 }
812 }
813}
814
815/// `RangeBounds` is implemented by Rust's built-in range types, produced
816/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
817#[stable(feature = "collections_range", since = "1.28.0")]
818#[rustc_diagnostic_item = "RangeBounds"]
819#[rustc_const_unstable(feature = "const_range", issue = "none")]
820pub const trait RangeBounds<T: ?Sized> {
821 /// Start index bound.
822 ///
823 /// Returns the start value as a `Bound`.
824 ///
825 /// # Examples
826 ///
827 /// ```
828 /// use std::ops::Bound::*;
829 /// use std::ops::RangeBounds;
830 ///
831 /// assert_eq!((..10).start_bound(), Unbounded);
832 /// assert_eq!((3..10).start_bound(), Included(&3));
833 /// ```
834 #[stable(feature = "collections_range", since = "1.28.0")]
835 fn start_bound(&self) -> Bound<&T>;
836
837 /// End index bound.
838 ///
839 /// Returns the end value as a `Bound`.
840 ///
841 /// # Examples
842 ///
843 /// ```
844 /// use std::ops::Bound::*;
845 /// use std::ops::RangeBounds;
846 ///
847 /// assert_eq!((3..).end_bound(), Unbounded);
848 /// assert_eq!((3..10).end_bound(), Excluded(&10));
849 /// ```
850 #[stable(feature = "collections_range", since = "1.28.0")]
851 fn end_bound(&self) -> Bound<&T>;
852
853 /// Returns `true` if `item` is contained in the range.
854 ///
855 /// # Examples
856 ///
857 /// ```
858 /// assert!( (3..5).contains(&4));
859 /// assert!(!(3..5).contains(&2));
860 ///
861 /// assert!( (0.0..1.0).contains(&0.5));
862 /// assert!(!(0.0..1.0).contains(&f32::NAN));
863 /// assert!(!(0.0..f32::NAN).contains(&0.5));
864 /// assert!(!(f32::NAN..1.0).contains(&0.5));
865 /// ```
866 #[inline]
867 #[stable(feature = "range_contains", since = "1.35.0")]
868 fn contains<U>(&self, item: &U) -> bool
869 where
870 T: [const] PartialOrd<U>,
871 U: ?Sized + [const] PartialOrd<T>,
872 {
873 (match self.start_bound() {
874 Included(start) => start <= item,
875 Excluded(start) => start < item,
876 Unbounded => true,
877 }) && (match self.end_bound() {
878 Included(end) => item <= end,
879 Excluded(end) => item < end,
880 Unbounded => true,
881 })
882 }
883
884 /// Returns `true` if the range contains no items.
885 /// One-sided ranges (`RangeFrom`, etc) always return `false`.
886 ///
887 /// # Examples
888 ///
889 /// ```
890 /// #![feature(range_bounds_is_empty)]
891 /// use std::ops::RangeBounds;
892 ///
893 /// assert!(!(3..).is_empty());
894 /// assert!(!(..2).is_empty());
895 /// assert!(!RangeBounds::is_empty(&(3..5)));
896 /// assert!( RangeBounds::is_empty(&(3..3)));
897 /// assert!( RangeBounds::is_empty(&(3..2)));
898 /// ```
899 ///
900 /// The range is empty if either side is incomparable:
901 ///
902 /// ```
903 /// #![feature(range_bounds_is_empty)]
904 /// use std::ops::RangeBounds;
905 ///
906 /// assert!(!RangeBounds::is_empty(&(3.0..5.0)));
907 /// assert!( RangeBounds::is_empty(&(3.0..f32::NAN)));
908 /// assert!( RangeBounds::is_empty(&(f32::NAN..5.0)));
909 /// ```
910 ///
911 /// But never empty if either side is unbounded:
912 ///
913 /// ```
914 /// #![feature(range_bounds_is_empty)]
915 /// use std::ops::RangeBounds;
916 ///
917 /// assert!(!(..0).is_empty());
918 /// assert!(!(i32::MAX..).is_empty());
919 /// assert!(!RangeBounds::<u8>::is_empty(&(..)));
920 /// ```
921 ///
922 /// `(Excluded(a), Excluded(b))` is only empty if `a >= b`:
923 ///
924 /// ```
925 /// #![feature(range_bounds_is_empty)]
926 /// use std::ops::Bound::*;
927 /// use std::ops::RangeBounds;
928 ///
929 /// assert!(!(Excluded(1), Excluded(3)).is_empty());
930 /// assert!(!(Excluded(1), Excluded(2)).is_empty());
931 /// assert!( (Excluded(1), Excluded(1)).is_empty());
932 /// assert!( (Excluded(2), Excluded(1)).is_empty());
933 /// assert!( (Excluded(3), Excluded(1)).is_empty());
934 /// ```
935 #[unstable(feature = "range_bounds_is_empty", issue = "137300")]
936 fn is_empty(&self) -> bool
937 where
938 T: [const] PartialOrd,
939 {
940 !match (self.start_bound(), self.end_bound()) {
941 (Unbounded, _) | (_, Unbounded) => true,
942 (Included(start), Excluded(end))
943 | (Excluded(start), Included(end))
944 | (Excluded(start), Excluded(end)) => start < end,
945 (Included(start), Included(end)) => start <= end,
946 }
947 }
948}
949
950/// Used to convert a range into start and end bounds, consuming the
951/// range by value.
952///
953/// `IntoBounds` is implemented by Rust’s built-in range types, produced
954/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
955#[unstable(feature = "range_into_bounds", issue = "136903")]
956#[rustc_const_unstable(feature = "const_range", issue = "none")]
957pub const trait IntoBounds<T>: [const] RangeBounds<T> {
958 /// Convert this range into the start and end bounds.
959 /// Returns `(start_bound, end_bound)`.
960 ///
961 /// # Examples
962 ///
963 /// ```
964 /// #![feature(range_into_bounds)]
965 /// use std::ops::Bound::*;
966 /// use std::ops::IntoBounds;
967 ///
968 /// assert_eq!((0..5).into_bounds(), (Included(0), Excluded(5)));
969 /// assert_eq!((..=7).into_bounds(), (Unbounded, Included(7)));
970 /// ```
971 fn into_bounds(self) -> (Bound<T>, Bound<T>);
972
973 /// Compute the intersection of `self` and `other`.
974 ///
975 /// # Examples
976 ///
977 /// ```
978 /// #![feature(range_into_bounds)]
979 /// use std::ops::Bound::*;
980 /// use std::ops::IntoBounds;
981 ///
982 /// assert_eq!((3..).intersect(..5), (Included(3), Excluded(5)));
983 /// assert_eq!((-12..387).intersect(0..256), (Included(0), Excluded(256)));
984 /// assert_eq!((1..5).intersect(..), (Included(1), Excluded(5)));
985 /// assert_eq!((1..=9).intersect(0..10), (Included(1), Included(9)));
986 /// assert_eq!((7..=13).intersect(8..13), (Included(8), Excluded(13)));
987 /// ```
988 ///
989 /// Combine with `is_empty` to determine if two ranges overlap.
990 ///
991 /// ```
992 /// #![feature(range_into_bounds)]
993 /// #![feature(range_bounds_is_empty)]
994 /// use std::ops::{RangeBounds, IntoBounds};
995 ///
996 /// assert!(!(3..).intersect(..5).is_empty());
997 /// assert!(!(-12..387).intersect(0..256).is_empty());
998 /// assert!((1..5).intersect(6..).is_empty());
999 /// ```
1000 fn intersect<R>(self, other: R) -> (Bound<T>, Bound<T>)
1001 where
1002 Self: Sized,
1003 T: [const] Ord + [const] Destruct,
1004 R: Sized + [const] IntoBounds<T>,
1005 {
1006 let (self_start, self_end) = IntoBounds::into_bounds(self);
1007 let (other_start, other_end) = IntoBounds::into_bounds(other);
1008
1009 let start = match (self_start, other_start) {
1010 (Included(a), Included(b)) => Included(Ord::max(a, b)),
1011 (Excluded(a), Excluded(b)) => Excluded(Ord::max(a, b)),
1012 (Unbounded, Unbounded) => Unbounded,
1013
1014 (x, Unbounded) | (Unbounded, x) => x,
1015
1016 (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
1017 if i > e {
1018 Included(i)
1019 } else {
1020 Excluded(e)
1021 }
1022 }
1023 };
1024 let end = match (self_end, other_end) {
1025 (Included(a), Included(b)) => Included(Ord::min(a, b)),
1026 (Excluded(a), Excluded(b)) => Excluded(Ord::min(a, b)),
1027 (Unbounded, Unbounded) => Unbounded,
1028
1029 (x, Unbounded) | (Unbounded, x) => x,
1030
1031 (Included(i), Excluded(e)) | (Excluded(e), Included(i)) => {
1032 if i < e {
1033 Included(i)
1034 } else {
1035 Excluded(e)
1036 }
1037 }
1038 };
1039
1040 (start, end)
1041 }
1042}
1043
1044use self::Bound::{Excluded, Included, Unbounded};
1045
1046#[stable(feature = "collections_range", since = "1.28.0")]
1047#[rustc_const_unstable(feature = "const_range", issue = "none")]
1048impl<T: ?Sized> const RangeBounds<T> for RangeFull {
1049 fn start_bound(&self) -> Bound<&T> {
1050 Unbounded
1051 }
1052 fn end_bound(&self) -> Bound<&T> {
1053 Unbounded
1054 }
1055}
1056
1057#[unstable(feature = "range_into_bounds", issue = "136903")]
1058#[rustc_const_unstable(feature = "const_range", issue = "none")]
1059impl<T> const IntoBounds<T> for RangeFull {
1060 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1061 (Unbounded, Unbounded)
1062 }
1063}
1064
1065#[stable(feature = "collections_range", since = "1.28.0")]
1066#[rustc_const_unstable(feature = "const_range", issue = "none")]
1067impl<T> const RangeBounds<T> for RangeFrom<T> {
1068 fn start_bound(&self) -> Bound<&T> {
1069 Included(&self.start)
1070 }
1071 fn end_bound(&self) -> Bound<&T> {
1072 Unbounded
1073 }
1074}
1075
1076#[unstable(feature = "range_into_bounds", issue = "136903")]
1077#[rustc_const_unstable(feature = "const_range", issue = "none")]
1078impl<T> const IntoBounds<T> for RangeFrom<T> {
1079 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1080 (Included(self.start), Unbounded)
1081 }
1082}
1083
1084#[stable(feature = "collections_range", since = "1.28.0")]
1085#[rustc_const_unstable(feature = "const_range", issue = "none")]
1086impl<T> const RangeBounds<T> for RangeTo<T> {
1087 fn start_bound(&self) -> Bound<&T> {
1088 Unbounded
1089 }
1090 fn end_bound(&self) -> Bound<&T> {
1091 Excluded(&self.end)
1092 }
1093}
1094
1095#[unstable(feature = "range_into_bounds", issue = "136903")]
1096#[rustc_const_unstable(feature = "const_range", issue = "none")]
1097impl<T> const IntoBounds<T> for RangeTo<T> {
1098 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1099 (Unbounded, Excluded(self.end))
1100 }
1101}
1102
1103#[stable(feature = "collections_range", since = "1.28.0")]
1104#[rustc_const_unstable(feature = "const_range", issue = "none")]
1105impl<T> const RangeBounds<T> for Range<T> {
1106 fn start_bound(&self) -> Bound<&T> {
1107 Included(&self.start)
1108 }
1109 fn end_bound(&self) -> Bound<&T> {
1110 Excluded(&self.end)
1111 }
1112}
1113
1114#[unstable(feature = "range_into_bounds", issue = "136903")]
1115#[rustc_const_unstable(feature = "const_range", issue = "none")]
1116impl<T> const IntoBounds<T> for Range<T> {
1117 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1118 (Included(self.start), Excluded(self.end))
1119 }
1120}
1121
1122#[stable(feature = "collections_range", since = "1.28.0")]
1123#[rustc_const_unstable(feature = "const_range", issue = "none")]
1124impl<T> const RangeBounds<T> for RangeInclusive<T> {
1125 fn start_bound(&self) -> Bound<&T> {
1126 Included(&self.start)
1127 }
1128 fn end_bound(&self) -> Bound<&T> {
1129 if self.exhausted {
1130 // When the iterator is exhausted, we usually have start == end,
1131 // but we want the range to appear empty, containing nothing.
1132 Excluded(&self.end)
1133 } else {
1134 Included(&self.end)
1135 }
1136 }
1137}
1138
1139#[unstable(feature = "range_into_bounds", issue = "136903")]
1140#[rustc_const_unstable(feature = "const_range", issue = "none")]
1141impl<T> const IntoBounds<T> for RangeInclusive<T> {
1142 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1143 (
1144 Included(self.start),
1145 if self.exhausted {
1146 // When the iterator is exhausted, we usually have start == end,
1147 // but we want the range to appear empty, containing nothing.
1148 Excluded(self.end)
1149 } else {
1150 Included(self.end)
1151 },
1152 )
1153 }
1154}
1155
1156#[stable(feature = "collections_range", since = "1.28.0")]
1157#[rustc_const_unstable(feature = "const_range", issue = "none")]
1158impl<T> const RangeBounds<T> for RangeToInclusive<T> {
1159 fn start_bound(&self) -> Bound<&T> {
1160 Unbounded
1161 }
1162 fn end_bound(&self) -> Bound<&T> {
1163 Included(&self.end)
1164 }
1165}
1166
1167#[unstable(feature = "range_into_bounds", issue = "136903")]
1168#[rustc_const_unstable(feature = "const_range", issue = "none")]
1169impl<T> const IntoBounds<T> for RangeToInclusive<T> {
1170 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1171 (Unbounded, Included(self.end))
1172 }
1173}
1174
1175#[stable(feature = "collections_range", since = "1.28.0")]
1176#[rustc_const_unstable(feature = "const_range", issue = "none")]
1177impl<T> const RangeBounds<T> for (Bound<T>, Bound<T>) {
1178 fn start_bound(&self) -> Bound<&T> {
1179 match *self {
1180 (Included(ref start), _) => Included(start),
1181 (Excluded(ref start), _) => Excluded(start),
1182 (Unbounded, _) => Unbounded,
1183 }
1184 }
1185
1186 fn end_bound(&self) -> Bound<&T> {
1187 match *self {
1188 (_, Included(ref end)) => Included(end),
1189 (_, Excluded(ref end)) => Excluded(end),
1190 (_, Unbounded) => Unbounded,
1191 }
1192 }
1193}
1194
1195#[unstable(feature = "range_into_bounds", issue = "136903")]
1196#[rustc_const_unstable(feature = "const_range", issue = "none")]
1197impl<T> const IntoBounds<T> for (Bound<T>, Bound<T>) {
1198 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
1199 self
1200 }
1201}
1202
1203#[stable(feature = "collections_range", since = "1.28.0")]
1204#[rustc_const_unstable(feature = "const_range", issue = "none")]
1205impl<'a, T: ?Sized + 'a> const RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
1206 fn start_bound(&self) -> Bound<&T> {
1207 self.0
1208 }
1209
1210 fn end_bound(&self) -> Bound<&T> {
1211 self.1
1212 }
1213}
1214
1215// This impl intentionally does not have `T: ?Sized`;
1216// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1217//
1218/// If you need to use this implementation where `T` is unsized,
1219/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1220/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
1221#[stable(feature = "collections_range", since = "1.28.0")]
1222#[rustc_const_unstable(feature = "const_range", issue = "none")]
1223impl<T> const RangeBounds<T> for RangeFrom<&T> {
1224 fn start_bound(&self) -> Bound<&T> {
1225 Included(self.start)
1226 }
1227 fn end_bound(&self) -> Bound<&T> {
1228 Unbounded
1229 }
1230}
1231
1232// This impl intentionally does not have `T: ?Sized`;
1233// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1234//
1235/// If you need to use this implementation where `T` is unsized,
1236/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1237/// i.e. replace `..end` with `(Bound::Unbounded, Bound::Excluded(end))`.
1238#[stable(feature = "collections_range", since = "1.28.0")]
1239#[rustc_const_unstable(feature = "const_range", issue = "none")]
1240impl<T> const RangeBounds<T> for RangeTo<&T> {
1241 fn start_bound(&self) -> Bound<&T> {
1242 Unbounded
1243 }
1244 fn end_bound(&self) -> Bound<&T> {
1245 Excluded(self.end)
1246 }
1247}
1248
1249// This impl intentionally does not have `T: ?Sized`;
1250// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1251//
1252/// If you need to use this implementation where `T` is unsized,
1253/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1254/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
1255#[stable(feature = "collections_range", since = "1.28.0")]
1256#[rustc_const_unstable(feature = "const_range", issue = "none")]
1257impl<T> const RangeBounds<T> for Range<&T> {
1258 fn start_bound(&self) -> Bound<&T> {
1259 Included(self.start)
1260 }
1261 fn end_bound(&self) -> Bound<&T> {
1262 Excluded(self.end)
1263 }
1264}
1265
1266// This impl intentionally does not have `T: ?Sized`;
1267// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1268//
1269/// If you need to use this implementation where `T` is unsized,
1270/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1271/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
1272#[stable(feature = "collections_range", since = "1.28.0")]
1273#[rustc_const_unstable(feature = "const_range", issue = "none")]
1274impl<T> const RangeBounds<T> for RangeInclusive<&T> {
1275 fn start_bound(&self) -> Bound<&T> {
1276 Included(self.start)
1277 }
1278 fn end_bound(&self) -> Bound<&T> {
1279 Included(self.end)
1280 }
1281}
1282
1283// This impl intentionally does not have `T: ?Sized`;
1284// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
1285//
1286/// If you need to use this implementation where `T` is unsized,
1287/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
1288/// i.e. replace `..=end` with `(Bound::Unbounded, Bound::Included(end))`.
1289#[stable(feature = "collections_range", since = "1.28.0")]
1290#[rustc_const_unstable(feature = "const_range", issue = "none")]
1291impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
1292 fn start_bound(&self) -> Bound<&T> {
1293 Unbounded
1294 }
1295 fn end_bound(&self) -> Bound<&T> {
1296 Included(self.end)
1297 }
1298}
1299
1300/// An internal helper for `split_off` functions indicating
1301/// which end a `OneSidedRange` is bounded on.
1302#[unstable(feature = "one_sided_range", issue = "69780")]
1303#[allow(missing_debug_implementations)]
1304pub enum OneSidedRangeBound {
1305 /// The range is bounded inclusively from below and is unbounded above.
1306 StartInclusive,
1307 /// The range is bounded exclusively from above and is unbounded below.
1308 End,
1309 /// The range is bounded inclusively from above and is unbounded below.
1310 EndInclusive,
1311}
1312
1313/// `OneSidedRange` is implemented for built-in range types that are unbounded
1314/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`,
1315/// but `..`, `d..e`, and `f..=g` do not.
1316///
1317/// Types that implement `OneSidedRange<T>` must return `Bound::Unbounded`
1318/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`.
1319#[unstable(feature = "one_sided_range", issue = "69780")]
1320#[rustc_const_unstable(feature = "const_range", issue = "none")]
1321pub const trait OneSidedRange<T>: RangeBounds<T> {
1322 /// An internal-only helper function for `split_off` and
1323 /// `split_off_mut` that returns the bound of the one-sided range.
1324 fn bound(self) -> (OneSidedRangeBound, T);
1325}
1326
1327#[unstable(feature = "one_sided_range", issue = "69780")]
1328#[rustc_const_unstable(feature = "const_range", issue = "none")]
1329impl<T> const OneSidedRange<T> for RangeTo<T>
1330where
1331 Self: RangeBounds<T>,
1332{
1333 fn bound(self) -> (OneSidedRangeBound, T) {
1334 (OneSidedRangeBound::End, self.end)
1335 }
1336}
1337
1338#[unstable(feature = "one_sided_range", issue = "69780")]
1339#[rustc_const_unstable(feature = "const_range", issue = "none")]
1340impl<T> const OneSidedRange<T> for RangeFrom<T>
1341where
1342 Self: RangeBounds<T>,
1343{
1344 fn bound(self) -> (OneSidedRangeBound, T) {
1345 (OneSidedRangeBound::StartInclusive, self.start)
1346 }
1347}
1348
1349#[unstable(feature = "one_sided_range", issue = "69780")]
1350#[rustc_const_unstable(feature = "const_range", issue = "none")]
1351impl<T> const OneSidedRange<T> for RangeToInclusive<T>
1352where
1353 Self: RangeBounds<T>,
1354{
1355 fn bound(self) -> (OneSidedRangeBound, T) {
1356 (OneSidedRangeBound::EndInclusive, self.end)
1357 }
1358}