1use 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 = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
34pub use iter::RangeIter;
35
36use crate::iter::Step;
47use crate::ops::Bound::{self, Excluded, Included, Unbounded};
48use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds};
49
50#[lang = "RangeCopy"]
69#[derive(Copy, Hash)]
70#[derive_const(Clone, Default, PartialEq, Eq)]
71#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
72pub struct Range<Idx> {
73 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
75 pub start: Idx,
76 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
78 pub end: Idx,
79}
80
81#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
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 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
107 #[inline]
108 pub fn iter(&self) -> RangeIter<Idx> {
109 self.clone().into_iter()
110 }
111}
112
113impl<Idx: PartialOrd<Idx>> Range<Idx> {
114 #[inline]
135 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
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 #[inline]
167 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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#[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 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
254 pub start: Idx,
255 #[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 #[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 #[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 #[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#[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#[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#[lang = "RangeFromCopy"]
445#[derive(Copy, Hash)]
446#[derive_const(Clone, PartialEq, Eq)]
447#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
448pub struct RangeFrom<Idx> {
449 #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
451 pub start: Idx,
452}
453
454#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
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 #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
479 #[inline]
480 pub fn iter(&self) -> RangeFromIter<Idx> {
481 self.clone().into_iter()
482 }
483}
484
485impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
486 #[inline]
502 #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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#[lang = "RangeToInclusiveCopy"]
620#[doc(alias = "..=")]
621#[derive(Copy, Clone, PartialEq, Eq, Hash)]
622#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
623pub struct RangeToInclusive<Idx> {
624 #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
626 pub last: Idx,
627}
628
629#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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 #[inline]
653 #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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 = "CURRENT_RUSTC_VERSION")]
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}