From 4ee19d9e865ad619bbf790c01762cb66277016b6 Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Tue, 21 Oct 2025 13:21:06 +0300 Subject: [PATCH] Constify Range functions --- library/core/src/ops/index_range.rs | 9 +- library/core/src/ops/range.rs | 168 ++++++++++++++++++---------- library/core/src/range.rs | 73 +++++++----- library/core/src/slice/index.rs | 11 +- 4 files changed, 171 insertions(+), 90 deletions(-) diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index 507fa9460bea6..84395ddadf2b7 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -9,7 +9,8 @@ use crate::ub_checks; /// /// (Normal `Range` code needs to handle degenerate ranges like `10..0`, /// which takes extra checks compared to only handling the canonical form.) -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Debug)] +#[derive_const(Clone, Eq, PartialEq)] pub(crate) struct IndexRange { start: usize, end: usize, @@ -54,7 +55,7 @@ impl IndexRange { /// # Safety /// - Can only be called when `start < end`, aka when `len > 0`. #[inline] - unsafe fn next_unchecked(&mut self) -> usize { + const unsafe fn next_unchecked(&mut self) -> usize { debug_assert!(self.start < self.end); let value = self.start; @@ -66,7 +67,7 @@ impl IndexRange { /// # Safety /// - Can only be called when `start < end`, aka when `len > 0`. #[inline] - unsafe fn next_back_unchecked(&mut self) -> usize { + const unsafe fn next_back_unchecked(&mut self) -> usize { debug_assert!(self.start < self.end); // SAFETY: The range isn't empty, so this cannot overflow @@ -116,7 +117,7 @@ impl IndexRange { } #[inline] - fn assume_range(&self) { + const fn assume_range(&self) { // SAFETY: This is the type invariant unsafe { crate::hint::assert_unchecked(self.start <= self.end) } } diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 58a9431bd845d..d781f3f7ace4a 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::hash::Hash; - +use crate::marker::Destruct; /// An unbounded range (`..`). /// /// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`. @@ -38,7 +38,8 @@ use crate::hash::Hash; /// [slicing index]: crate::slice::SliceIndex #[lang = "RangeFull"] #[doc(alias = "..")] -#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)] +#[derive(Copy, Hash)] +#[derive_const(Clone, Default, Eq, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFull; @@ -75,7 +76,8 @@ impl fmt::Debug for RangeFull { /// ``` #[lang = "Range"] #[doc(alias = "..")] -#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Eq, Hash)] +#[derive_const(Clone, Default, PartialEq)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). @@ -117,10 +119,11 @@ impl> Range { /// ``` #[inline] #[stable(feature = "range_contains", since = "1.35.0")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -144,7 +147,11 @@ impl> Range { /// ``` #[inline] #[stable(feature = "range_is_empty", since = "1.47.0")] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn is_empty(&self) -> bool + where + Idx: [const] PartialOrd, + { !(self.start < self.end) } } @@ -184,7 +191,8 @@ impl> Range { /// ``` #[lang = "RangeFrom"] #[doc(alias = "..")] -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Eq, Hash)] +#[derive_const(Clone, PartialEq)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { /// The lower bound of the range (inclusive). @@ -217,10 +225,11 @@ impl> RangeFrom { /// ``` #[inline] #[stable(feature = "range_contains", since = "1.35.0")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -266,7 +275,8 @@ impl> RangeFrom { /// [slicing index]: crate::slice::SliceIndex #[lang = "RangeTo"] #[doc(alias = "..")] -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Eq, Hash)] +#[derive_const(Clone, PartialEq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeTo { /// The upper bound of the range (exclusive). @@ -299,10 +309,11 @@ impl> RangeTo { /// ``` #[inline] #[stable(feature = "range_contains", since = "1.35.0")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -340,7 +351,8 @@ impl> RangeTo { /// ``` #[lang = "RangeInclusive"] #[doc(alias = "..=")] -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, Hash)] +#[derive_const(Eq, PartialEq)] // not Copy -- see #27186 #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { // Note that the fields here are not public to allow changing the @@ -506,10 +518,11 @@ impl> RangeInclusive { /// ``` #[inline] #[stable(feature = "range_contains", since = "1.35.0")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -542,7 +555,11 @@ impl> RangeInclusive { /// ``` #[stable(feature = "range_is_empty", since = "1.47.0")] #[inline] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn is_empty(&self) -> bool + where + Idx: [const] PartialOrd, + { self.exhausted || !(self.start <= self.end) } } @@ -587,7 +604,8 @@ impl> RangeInclusive { /// [slicing index]: crate::slice::SliceIndex #[lang = "RangeToInclusive"] #[doc(alias = "..=")] -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Hash)] +#[derive(Clone, PartialEq, Eq)] #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeToInclusive { /// The upper bound of the range (inclusive) @@ -620,10 +638,11 @@ impl> RangeToInclusive { /// ``` #[inline] #[stable(feature = "range_contains", since = "1.35.0")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -668,7 +687,8 @@ impl> RangeToInclusive { /// /// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range #[stable(feature = "collections_bound", since = "1.17.0")] -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Debug, Hash)] +#[derive_const(Clone, Eq, PartialEq)] pub enum Bound { /// An inclusive bound. #[stable(feature = "collections_bound", since = "1.17.0")] @@ -685,7 +705,8 @@ impl Bound { /// Converts from `&Bound` to `Bound<&T>`. #[inline] #[stable(feature = "bound_as_ref_shared", since = "1.65.0")] - pub fn as_ref(&self) -> Bound<&T> { + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn as_ref(&self) -> Bound<&T> { match *self { Included(ref x) => Included(x), Excluded(ref x) => Excluded(x), @@ -696,7 +717,7 @@ impl Bound { /// Converts from `&mut Bound` to `Bound<&mut T>`. #[inline] #[unstable(feature = "bound_as_ref", issue = "80996")] - pub fn as_mut(&mut self) -> Bound<&mut T> { + pub const fn as_mut(&mut self) -> Bound<&mut T> { match *self { Included(ref mut x) => Included(x), Excluded(ref mut x) => Excluded(x), @@ -778,7 +799,11 @@ impl Bound<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "bound_cloned", since = "1.55.0")] - pub fn cloned(self) -> Bound { + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn cloned(self) -> Bound + where + T: [const] Clone, + { match self { Bound::Unbounded => Bound::Unbounded, Bound::Included(x) => Bound::Included(x.clone()), @@ -791,6 +816,8 @@ impl Bound<&T> { /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. #[stable(feature = "collections_range", since = "1.28.0")] #[rustc_diagnostic_item = "RangeBounds"] +#[const_trait] +#[rustc_const_unstable(feature = "const_range", issue = "none")] pub trait RangeBounds { /// Start index bound. /// @@ -841,8 +868,8 @@ pub trait RangeBounds { #[stable(feature = "range_contains", since = "1.35.0")] fn contains(&self, item: &U) -> bool where - T: PartialOrd, - U: ?Sized + PartialOrd, + T: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { (match self.start_bound() { Included(start) => start <= item, @@ -909,7 +936,7 @@ pub trait RangeBounds { #[unstable(feature = "range_bounds_is_empty", issue = "137300")] fn is_empty(&self) -> bool where - T: PartialOrd, + T: [const] PartialOrd, { !match (self.start_bound(), self.end_bound()) { (Unbounded, _) | (_, Unbounded) => true, @@ -927,7 +954,9 @@ pub trait RangeBounds { /// `IntoBounds` is implemented by Rust’s built-in range types, produced /// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`. #[unstable(feature = "range_into_bounds", issue = "136903")] -pub trait IntoBounds: RangeBounds { +#[const_trait] +#[rustc_const_unstable(feature = "const_range", issue = "none")] +pub trait IntoBounds: [const] RangeBounds { /// Convert this range into the start and end bounds. /// Returns `(start_bound, end_bound)`. /// @@ -973,8 +1002,8 @@ pub trait IntoBounds: RangeBounds { fn intersect(self, other: R) -> (Bound, Bound) where Self: Sized, - T: Ord, - R: Sized + IntoBounds, + T: [const] Ord + [const] Destruct, + R: Sized + [const] IntoBounds, { let (self_start, self_end) = IntoBounds::into_bounds(self); let (other_start, other_end) = IntoBounds::into_bounds(other); @@ -1017,7 +1046,8 @@ pub trait IntoBounds: RangeBounds { use self::Bound::{Excluded, Included, Unbounded}; #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeFull { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeFull { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -1027,14 +1057,16 @@ impl RangeBounds for RangeFull { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for RangeFull { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeFull { fn into_bounds(self) -> (Bound, Bound) { (Unbounded, Unbounded) } } #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeFrom { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeFrom { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -1044,14 +1076,16 @@ impl RangeBounds for RangeFrom { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for RangeFrom { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeFrom { fn into_bounds(self) -> (Bound, Bound) { (Included(self.start), Unbounded) } } #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeTo { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeTo { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -1061,14 +1095,16 @@ impl RangeBounds for RangeTo { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for RangeTo { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeTo { fn into_bounds(self) -> (Bound, Bound) { (Unbounded, Excluded(self.end)) } } #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for Range { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for Range { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -1078,14 +1114,16 @@ impl RangeBounds for Range { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for Range { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for Range { fn into_bounds(self) -> (Bound, Bound) { (Included(self.start), Excluded(self.end)) } } #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeInclusive { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -1101,7 +1139,8 @@ impl RangeBounds for RangeInclusive { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for RangeInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeInclusive { fn into_bounds(self) -> (Bound, Bound) { ( Included(self.start), @@ -1117,7 +1156,8 @@ impl IntoBounds for RangeInclusive { } #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeToInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeToInclusive { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -1127,14 +1167,16 @@ impl RangeBounds for RangeToInclusive { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for RangeToInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeToInclusive { fn into_bounds(self) -> (Bound, Bound) { (Unbounded, Included(self.end)) } } #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for (Bound, Bound) { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for (Bound, Bound) { fn start_bound(&self) -> Bound<&T> { match *self { (Included(ref start), _) => Included(start), @@ -1153,14 +1195,16 @@ impl RangeBounds for (Bound, Bound) { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for (Bound, Bound) { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for (Bound, Bound) { fn into_bounds(self) -> (Bound, Bound) { self } } #[stable(feature = "collections_range", since = "1.28.0")] -impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl<'a, T: ?Sized + 'a> const RangeBounds for (Bound<&'a T>, Bound<&'a T>) { fn start_bound(&self) -> Bound<&T> { self.0 } @@ -1177,7 +1221,8 @@ impl<'a, T: ?Sized + 'a> RangeBounds for (Bound<&'a T>, Bound<&'a T>) { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`. #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeFrom<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeFrom<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -1193,7 +1238,8 @@ impl RangeBounds for RangeFrom<&T> { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `..end` with `(Bound::Unbounded, Bound::Excluded(end))`. #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeTo<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeTo<&T> { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -1209,7 +1255,8 @@ impl RangeBounds for RangeTo<&T> { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`. #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for Range<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for Range<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -1225,7 +1272,8 @@ impl RangeBounds for Range<&T> { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`. #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeInclusive<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -1241,7 +1289,8 @@ impl RangeBounds for RangeInclusive<&T> { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `..=end` with `(Bound::Unbounded, Bound::Included(end))`. #[stable(feature = "collections_range", since = "1.28.0")] -impl RangeBounds for RangeToInclusive<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeToInclusive<&T> { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -1270,6 +1319,8 @@ pub enum OneSidedRangeBound { /// Types that implement `OneSidedRange` must return `Bound::Unbounded` /// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. #[unstable(feature = "one_sided_range", issue = "69780")] +#[const_trait] +#[rustc_const_unstable(feature = "const_range", issue = "none")] pub trait OneSidedRange: RangeBounds { /// An internal-only helper function for `split_off` and /// `split_off_mut` that returns the bound of the one-sided range. @@ -1277,7 +1328,8 @@ pub trait OneSidedRange: RangeBounds { } #[unstable(feature = "one_sided_range", issue = "69780")] -impl OneSidedRange for RangeTo +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const OneSidedRange for RangeTo where Self: RangeBounds, { @@ -1287,7 +1339,8 @@ where } #[unstable(feature = "one_sided_range", issue = "69780")] -impl OneSidedRange for RangeFrom +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const OneSidedRange for RangeFrom where Self: RangeBounds, { @@ -1297,7 +1350,8 @@ where } #[unstable(feature = "one_sided_range", issue = "69780")] -impl OneSidedRange for RangeToInclusive +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const OneSidedRange for RangeToInclusive where Self: RangeBounds, { diff --git a/library/core/src/range.rs b/library/core/src/range.rs index a096a8ceafc87..96c56e96b3ebe 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -118,10 +118,11 @@ impl> Range { /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -151,13 +152,18 @@ impl> Range { /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn is_empty(&self) -> bool + where + Idx: [const] PartialOrd, + { !(self.start < self.end) } } #[unstable(feature = "new_range_api", issue = "125687")] -impl RangeBounds for Range { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for Range { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -173,7 +179,8 @@ impl RangeBounds for Range { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`. #[unstable(feature = "new_range_api", issue = "125687")] -impl RangeBounds for Range<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for Range<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -184,7 +191,8 @@ impl RangeBounds for Range<&T> { // #[unstable(feature = "range_into_bounds", issue = "136903")] #[unstable(feature = "new_range_api", issue = "125687")] -impl IntoBounds for Range { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for Range { fn into_bounds(self) -> (Bound, Bound) { (Included(self.start), Excluded(self.end)) } @@ -271,10 +279,11 @@ impl> RangeInclusive { /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -304,7 +313,11 @@ impl> RangeInclusive { /// ``` #[unstable(feature = "new_range_api", issue = "125687")] #[inline] - pub fn is_empty(&self) -> bool { + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn is_empty(&self) -> bool + where + Idx: [const] PartialOrd, + { !(self.start <= self.last) } } @@ -342,7 +355,8 @@ impl RangeInclusive { } #[unstable(feature = "new_range_api", issue = "125687")] -impl RangeBounds for RangeInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeInclusive { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -358,7 +372,8 @@ impl RangeBounds for RangeInclusive { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`. #[unstable(feature = "new_range_api", issue = "125687")] -impl RangeBounds for RangeInclusive<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -369,7 +384,8 @@ impl RangeBounds for RangeInclusive<&T> { // #[unstable(feature = "range_into_bounds", issue = "136903")] #[unstable(feature = "new_range_api", issue = "125687")] -impl IntoBounds for RangeInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeInclusive { fn into_bounds(self) -> (Bound, Bound) { (Included(self.start), Included(self.last)) } @@ -485,17 +501,19 @@ impl> RangeFrom { /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } } #[unstable(feature = "new_range_api", issue = "125687")] -impl RangeBounds for RangeFrom { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeFrom { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } @@ -511,7 +529,8 @@ impl RangeBounds for RangeFrom { /// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound], /// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`. #[unstable(feature = "new_range_api", issue = "125687")] -impl RangeBounds for RangeFrom<&T> { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeFrom<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } @@ -522,7 +541,8 @@ impl RangeBounds for RangeFrom<&T> { // #[unstable(feature = "range_into_bounds", issue = "136903")] #[unstable(feature = "new_range_api", issue = "125687")] -impl IntoBounds for RangeFrom { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeFrom { fn into_bounds(self) -> (Bound, Bound) { (Included(self.start), Unbounded) } @@ -620,10 +640,11 @@ impl> RangeToInclusive { /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] - pub fn contains(&self, item: &U) -> bool + #[rustc_const_unstable(feature = "const_range", issue = "none")] + pub const fn contains(&self, item: &U) -> bool where - Idx: PartialOrd, - U: ?Sized + PartialOrd, + Idx: [const] PartialOrd, + U: ?Sized + [const] PartialOrd, { >::contains(self, item) } @@ -633,7 +654,8 @@ impl> RangeToInclusive { // because underflow would be possible with (..0).into() #[unstable(feature = "new_range_api", issue = "125687")] -impl RangeBounds for RangeToInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const RangeBounds for RangeToInclusive { fn start_bound(&self) -> Bound<&T> { Unbounded } @@ -643,7 +665,8 @@ impl RangeBounds for RangeToInclusive { } #[unstable(feature = "range_into_bounds", issue = "136903")] -impl IntoBounds for RangeToInclusive { +#[rustc_const_unstable(feature = "const_range", issue = "none")] +impl const IntoBounds for RangeToInclusive { fn into_bounds(self) -> (Bound, Bound) { (Unbounded, Included(self.last)) } diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index a9806060d3d81..aad046a7e5a94 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -1,6 +1,7 @@ //! Indexing implementations for `[T]`. use crate::intrinsics::slice_get_unchecked; +use crate::marker::Destruct; use crate::panic::const_panic; use crate::ub_checks::assert_unsafe_precondition; use crate::{ops, range}; @@ -899,9 +900,10 @@ unsafe impl const SliceIndex<[T]> for range::RangeToInclusive { #[track_caller] #[unstable(feature = "slice_range", issue = "76393")] #[must_use] -pub fn range(range: R, bounds: ops::RangeTo) -> ops::Range +#[rustc_const_unstable(feature = "const_range", issue = "none")] +pub const fn range(range: R, bounds: ops::RangeTo) -> ops::Range where - R: ops::RangeBounds, + R: [const] ops::RangeBounds + [const] Destruct, { let len = bounds.end; @@ -984,7 +986,7 @@ where /// Converts a pair of `ops::Bound`s into `ops::Range` without performing any /// bounds checking or (in debug) overflow checking. -pub(crate) fn into_range_unchecked( +pub(crate) const fn into_range_unchecked( len: usize, (start, end): (ops::Bound, ops::Bound), ) -> ops::Range { @@ -1004,7 +1006,8 @@ pub(crate) fn into_range_unchecked( /// Converts pair of `ops::Bound`s into `ops::Range`. /// Returns `None` on overflowing indices. -pub(crate) fn into_range( +#[rustc_const_unstable(feature = "const_range", issue = "none")] +pub(crate) const fn into_range( len: usize, (start, end): (ops::Bound, ops::Bound), ) -> Option> {