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"]
65#[derive(Copy, Hash)]
66#[derive_const(Clone, Default, PartialEq, Eq)]
67#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
68pub struct Range<Idx> {
69 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
71 pub start: Idx,
72 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
74 pub end: Idx,
75}
76
77#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
78impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
79 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
80 self.start.fmt(fmt)?;
81 write!(fmt, "..")?;
82 self.end.fmt(fmt)?;
83 Ok(())
84 }
85}
86
87impl<Idx: Step> Range<Idx> {
88 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
103 #[inline]
104 pub fn iter(&self) -> RangeIter<Idx> {
105 self.clone().into_iter()
106 }
107}
108
109impl<Idx: PartialOrd<Idx>> Range<Idx> {
110 #[inline]
131 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
132 #[rustc_const_unstable(feature = "const_range", issue = "none")]
133 pub const fn contains<U>(&self, item: &U) -> bool
134 where
135 Idx: [const] PartialOrd<U>,
136 U: ?Sized + [const] PartialOrd<Idx>,
137 {
138 <Self as RangeBounds<Idx>>::contains(self, item)
139 }
140
141 #[inline]
163 #[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
164 #[rustc_const_unstable(feature = "const_range", issue = "none")]
165 pub const fn is_empty(&self) -> bool
166 where
167 Idx: [const] PartialOrd,
168 {
169 !(self.start < self.end)
170 }
171}
172
173#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
174#[rustc_const_unstable(feature = "const_range", issue = "none")]
175impl<T> const RangeBounds<T> for Range<T> {
176 fn start_bound(&self) -> Bound<&T> {
177 Included(&self.start)
178 }
179 fn end_bound(&self) -> Bound<&T> {
180 Excluded(&self.end)
181 }
182}
183
184#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
191#[rustc_const_unstable(feature = "const_range", issue = "none")]
192impl<T> const RangeBounds<T> for Range<&T> {
193 fn start_bound(&self) -> Bound<&T> {
194 Included(self.start)
195 }
196 fn end_bound(&self) -> Bound<&T> {
197 Excluded(self.end)
198 }
199}
200
201#[unstable(feature = "range_into_bounds", issue = "136903")]
202#[rustc_const_unstable(feature = "const_range", issue = "none")]
203impl<T> const IntoBounds<T> for Range<T> {
204 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
205 (Included(self.start), Excluded(self.end))
206 }
207}
208
209#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
210#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
211impl<T> const From<Range<T>> for legacy::Range<T> {
212 #[inline]
213 fn from(value: Range<T>) -> Self {
214 Self { start: value.start, end: value.end }
215 }
216}
217#[stable(feature = "new_range_api", since = "CURRENT_RUSTC_VERSION")]
218#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
219impl<T> const From<legacy::Range<T>> for Range<T> {
220 #[inline]
221 fn from(value: legacy::Range<T>) -> Self {
222 Self { start: value.start, end: value.end }
223 }
224}
225
226#[lang = "RangeInclusiveCopy"]
242#[derive(Clone, Copy, PartialEq, Eq, Hash)]
243#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
244pub struct RangeInclusive<Idx> {
245 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
247 pub start: Idx,
248 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
250 pub last: Idx,
251}
252
253#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
254impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
255 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
256 self.start.fmt(fmt)?;
257 write!(fmt, "..=")?;
258 self.last.fmt(fmt)?;
259 Ok(())
260 }
261}
262
263impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
264 #[inline]
286 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
287 #[rustc_const_unstable(feature = "const_range", issue = "none")]
288 pub const fn contains<U>(&self, item: &U) -> bool
289 where
290 Idx: [const] PartialOrd<U>,
291 U: ?Sized + [const] PartialOrd<Idx>,
292 {
293 <Self as RangeBounds<Idx>>::contains(self, item)
294 }
295
296 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
318 #[inline]
319 #[rustc_const_unstable(feature = "const_range", issue = "none")]
320 pub const fn is_empty(&self) -> bool
321 where
322 Idx: [const] PartialOrd,
323 {
324 !(self.start <= self.last)
325 }
326}
327
328impl<Idx: Step> RangeInclusive<Idx> {
329 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
344 #[inline]
345 pub fn iter(&self) -> RangeInclusiveIter<Idx> {
346 self.clone().into_iter()
347 }
348}
349
350#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
351#[rustc_const_unstable(feature = "const_range", issue = "none")]
352impl<T> const RangeBounds<T> for RangeInclusive<T> {
353 fn start_bound(&self) -> Bound<&T> {
354 Included(&self.start)
355 }
356 fn end_bound(&self) -> Bound<&T> {
357 Included(&self.last)
358 }
359}
360
361#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
368#[rustc_const_unstable(feature = "const_range", issue = "none")]
369impl<T> const RangeBounds<T> for RangeInclusive<&T> {
370 fn start_bound(&self) -> Bound<&T> {
371 Included(self.start)
372 }
373 fn end_bound(&self) -> Bound<&T> {
374 Included(self.last)
375 }
376}
377
378#[unstable(feature = "range_into_bounds", issue = "136903")]
380#[rustc_const_unstable(feature = "const_range", issue = "none")]
381impl<T> const IntoBounds<T> for RangeInclusive<T> {
382 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
383 (Included(self.start), Included(self.last))
384 }
385}
386
387#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
388#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
389impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
390 #[inline]
391 fn from(value: RangeInclusive<T>) -> Self {
392 Self::new(value.start, value.last)
393 }
394}
395#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
396#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
397impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
398 #[inline]
399 fn from(value: legacy::RangeInclusive<T>) -> Self {
400 assert!(
401 !value.exhausted,
402 "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
403 );
404
405 let (start, last) = value.into_inner();
406 RangeInclusive { start, last }
407 }
408}
409
410#[lang = "RangeFromCopy"]
435#[derive(Copy, Hash)]
436#[derive_const(Clone, PartialEq, Eq)]
437#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
438pub struct RangeFrom<Idx> {
439 #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
441 pub start: Idx,
442}
443
444#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
445impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
446 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
447 self.start.fmt(fmt)?;
448 write!(fmt, "..")?;
449 Ok(())
450 }
451}
452
453impl<Idx: Step> RangeFrom<Idx> {
454 #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
469 #[inline]
470 pub fn iter(&self) -> RangeFromIter<Idx> {
471 self.clone().into_iter()
472 }
473}
474
475impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
476 #[inline]
492 #[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
493 #[rustc_const_unstable(feature = "const_range", issue = "none")]
494 pub const fn contains<U>(&self, item: &U) -> bool
495 where
496 Idx: [const] PartialOrd<U>,
497 U: ?Sized + [const] PartialOrd<Idx>,
498 {
499 <Self as RangeBounds<Idx>>::contains(self, item)
500 }
501}
502
503#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
504#[rustc_const_unstable(feature = "const_range", issue = "none")]
505impl<T> const RangeBounds<T> for RangeFrom<T> {
506 fn start_bound(&self) -> Bound<&T> {
507 Included(&self.start)
508 }
509 fn end_bound(&self) -> Bound<&T> {
510 Unbounded
511 }
512}
513
514#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
521#[rustc_const_unstable(feature = "const_range", issue = "none")]
522impl<T> const RangeBounds<T> for RangeFrom<&T> {
523 fn start_bound(&self) -> Bound<&T> {
524 Included(self.start)
525 }
526 fn end_bound(&self) -> Bound<&T> {
527 Unbounded
528 }
529}
530
531#[unstable(feature = "range_into_bounds", issue = "136903")]
532#[rustc_const_unstable(feature = "const_range", issue = "none")]
533impl<T> const IntoBounds<T> for RangeFrom<T> {
534 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
535 (Included(self.start), Unbounded)
536 }
537}
538
539#[unstable(feature = "one_sided_range", issue = "69780")]
540#[rustc_const_unstable(feature = "const_range", issue = "none")]
541impl<T> const OneSidedRange<T> for RangeFrom<T>
542where
543 Self: RangeBounds<T>,
544{
545 fn bound(self) -> (OneSidedRangeBound, T) {
546 (OneSidedRangeBound::StartInclusive, self.start)
547 }
548}
549
550#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
551#[rustc_const_unstable(feature = "const_index", issue = "143775")]
552impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
553 #[inline]
554 fn from(value: RangeFrom<T>) -> Self {
555 Self { start: value.start }
556 }
557}
558#[stable(feature = "new_range_from_api", since = "CURRENT_RUSTC_VERSION")]
559#[rustc_const_unstable(feature = "const_index", issue = "143775")]
560impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
561 #[inline]
562 fn from(value: legacy::RangeFrom<T>) -> Self {
563 Self { start: value.start }
564 }
565}
566
567#[lang = "RangeToInclusiveCopy"]
607#[doc(alias = "..=")]
608#[derive(Copy, Clone, PartialEq, Eq, Hash)]
609#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
610pub struct RangeToInclusive<Idx> {
611 #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
613 pub last: Idx,
614}
615
616#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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 #[inline]
640 #[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
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#[stable(feature = "new_range_to_inclusive_api", since = "CURRENT_RUSTC_VERSION")]
679#[rustc_const_unstable(feature = "const_range", issue = "none")]
680impl<T> const RangeBounds<T> for RangeToInclusive<&T> {
681 fn start_bound(&self) -> Bound<&T> {
682 Unbounded
683 }
684 fn end_bound(&self) -> Bound<&T> {
685 Included(self.last)
686 }
687}
688
689#[unstable(feature = "range_into_bounds", issue = "136903")]
690#[rustc_const_unstable(feature = "const_range", issue = "none")]
691impl<T> const IntoBounds<T> for RangeToInclusive<T> {
692 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
693 (Unbounded, Included(self.last))
694 }
695}
696
697#[unstable(feature = "one_sided_range", issue = "69780")]
698#[rustc_const_unstable(feature = "const_range", issue = "none")]
699impl<T> const OneSidedRange<T> for RangeToInclusive<T>
700where
701 Self: RangeBounds<T>,
702{
703 fn bound(self) -> (OneSidedRangeBound, T) {
704 (OneSidedRangeBound::EndInclusive, self.last)
705 }
706}