Skip to content

Constify Index traits #143921

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,10 @@ impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] {
}

#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
impl<T, I, const N: usize> Index<I> for [T; N]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T, I, const N: usize> const Index<I> for [T; N]
where
[T]: Index<I>,
[T]: ~const Index<I>,
{
type Output = <[T] as Index<I>>::Output;

Expand All @@ -387,9 +388,10 @@ where
}

#[stable(feature = "index_trait_on_arrays", since = "1.50.0")]
impl<T, I, const N: usize> IndexMut<I> for [T; N]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T, I, const N: usize> const IndexMut<I> for [T; N]
where
[T]: IndexMut<I>,
[T]: ~const IndexMut<I>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
Expand Down
6 changes: 5 additions & 1 deletion library/core/src/ops/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
#[doc(alias = "]")]
#[doc(alias = "[")]
#[doc(alias = "[]")]
#[const_trait]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
pub trait Index<Idx: ?Sized> {
/// The returned type after indexing.
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -165,7 +167,9 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
#[doc(alias = "[")]
#[doc(alias = "]")]
#[doc(alias = "[]")]
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
#[const_trait]
pub trait IndexMut<Idx: ?Sized>: ~const Index<Idx> {
/// Performs the mutable indexing (`container[index]`) operation.
///
/// # Panics
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1524,10 +1524,11 @@ impl<T> *const [T] {
/// }
/// ```
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
#[inline]
pub unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
pub const unsafe fn get_unchecked<I>(self, index: I) -> *const I::Output
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
// SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds.
unsafe { index.get_unchecked(self) }
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1881,10 +1881,11 @@ impl<T> *mut [T] {
/// }
/// ```
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
#[inline(always)]
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> *mut I::Output
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
// SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds.
unsafe { index.get_unchecked_mut(self) }
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1597,10 +1597,11 @@ impl<T> NonNull<[T]> {
/// }
/// ```
#[unstable(feature = "slice_ptr_get", issue = "74265")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
#[inline]
pub unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output>
pub const unsafe fn get_unchecked_mut<I>(self, index: I) -> NonNull<I::Output>
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
// SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds.
// As a consequence, the resulting pointer cannot be null.
Expand Down
16 changes: 11 additions & 5 deletions library/core/src/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,17 @@ impl<T> IntoBounds<T> for Range<T> {
}

#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<Range<T>> for legacy::Range<T> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T> const From<Range<T>> for legacy::Range<T> {
#[inline]
fn from(value: Range<T>) -> Self {
Self { start: value.start, end: value.end }
}
}

#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<legacy::Range<T>> for Range<T> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T> const From<legacy::Range<T>> for Range<T> {
#[inline]
fn from(value: legacy::Range<T>) -> Self {
Self { start: value.start, end: value.end }
Expand Down Expand Up @@ -362,7 +365,8 @@ impl<T> IntoBounds<T> for RangeInclusive<T> {
}

#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
#[inline]
fn from(value: RangeInclusive<T>) -> Self {
Self::new(value.start, value.end)
Expand Down Expand Up @@ -506,14 +510,16 @@ impl<T> IntoBounds<T> for RangeFrom<T> {
}

#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
#[inline]
fn from(value: RangeFrom<T>) -> Self {
Self { start: value.start }
}
}
#[unstable(feature = "new_range_api", issue = "125687")]
impl<T> From<legacy::RangeFrom<T>> for RangeFrom<T> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
#[inline]
fn from(value: legacy::RangeFrom<T>) -> Self {
Self { start: value.start }
Expand Down
45 changes: 30 additions & 15 deletions library/core/src/slice/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ use crate::ub_checks::assert_unsafe_precondition;
use crate::{ops, range};

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, I> ops::Index<I> for [T]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T, I> const ops::Index<I> for [T]
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
type Output = I::Output;

Expand All @@ -19,9 +20,10 @@ where
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T, I> ops::IndexMut<I> for [T]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
impl<T, I> const ops::IndexMut<I> for [T]
where
I: SliceIndex<[T]>,
I: ~const SliceIndex<[T]>,
{
#[inline(always)]
fn index_mut(&mut self, index: I) -> &mut I::Output {
Expand Down Expand Up @@ -158,6 +160,8 @@ mod private_slice_index {
message = "the type `{T}` cannot be indexed by `{Self}`",
label = "slice indices are of type `usize` or ranges of `usize`"
)]
#[const_trait]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
/// The output type returned by methods.
#[stable(feature = "slice_get_slice", since = "1.28.0")]
Expand Down Expand Up @@ -208,7 +212,8 @@ pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {

/// The methods `index` and `index_mut` panic if the index is out of bounds.
#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for usize {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for usize {
type Output = T;

#[inline]
Expand Down Expand Up @@ -278,7 +283,8 @@ unsafe impl<T> SliceIndex<[T]> for usize {

/// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
/// than there are for a general `Range<usize>` (which might be `100..3`).
unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -354,7 +360,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
/// - the start of the range is greater than the end of the range or
/// - the end of the range is out of bounds.
#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -453,7 +460,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
}

#[unstable(feature = "new_range_api", issue = "125687")]
unsafe impl<T> SliceIndex<[T]> for range::Range<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for range::Range<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -491,7 +499,8 @@ unsafe impl<T> SliceIndex<[T]> for range::Range<usize> {

/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeTo<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -529,7 +538,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {

/// The methods `index` and `index_mut` panic if the start of the range is out of bounds.
#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -574,7 +584,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
}

#[unstable(feature = "new_range_api", issue = "125687")]
unsafe impl<T> SliceIndex<[T]> for range::RangeFrom<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for range::RangeFrom<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -611,7 +622,8 @@ unsafe impl<T> SliceIndex<[T]> for range::RangeFrom<usize> {
}

#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -650,7 +662,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
/// - the start of the range is greater than the end of the range or
/// - the end of the range is out of bounds.
#[stable(feature = "inclusive_range", since = "1.26.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -693,7 +706,8 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
}

#[unstable(feature = "new_range_api", issue = "125687")]
unsafe impl<T> SliceIndex<[T]> for range::RangeInclusive<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for range::RangeInclusive<usize> {
type Output = [T];

#[inline]
Expand Down Expand Up @@ -731,7 +745,8 @@ unsafe impl<T> SliceIndex<[T]> for range::RangeInclusive<usize> {

/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
#[stable(feature = "inclusive_range", since = "1.26.0")]
unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
type Output = [T];

#[inline]
Expand Down
20 changes: 12 additions & 8 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,9 +568,10 @@ impl<T> [T] {
#[rustc_no_implicit_autorefs]
#[inline]
#[must_use]
pub fn get<I>(&self, index: I) -> Option<&I::Output>
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
pub const fn get<I>(&self, index: I) -> Option<&I::Output>
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
index.get(self)
}
Expand All @@ -594,9 +595,10 @@ impl<T> [T] {
#[rustc_no_implicit_autorefs]
#[inline]
#[must_use]
pub fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
pub const fn get_mut<I>(&mut self, index: I) -> Option<&mut I::Output>
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
index.get_mut(self)
}
Expand Down Expand Up @@ -633,9 +635,10 @@ impl<T> [T] {
#[inline]
#[must_use]
#[track_caller]
pub unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
pub const unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
// SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`;
// the slice is dereferenceable because `self` is a safe reference.
Expand Down Expand Up @@ -677,9 +680,10 @@ impl<T> [T] {
#[inline]
#[must_use]
#[track_caller]
pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
pub const unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
where
I: SliceIndex<Self>,
I: ~const SliceIndex<Self>,
{
// SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`;
// the slice is dereferenceable because `self` is a safe reference.
Expand Down
6 changes: 4 additions & 2 deletions library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,8 +589,9 @@ impl str {
/// assert!(v.get(..42).is_none());
/// ```
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
#[inline]
pub fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
pub const fn get<I: ~const SliceIndex<str>>(&self, i: I) -> Option<&I::Output> {
i.get(self)
}

Expand Down Expand Up @@ -621,8 +622,9 @@ impl str {
/// assert_eq!("HEllo", v);
/// ```
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
#[inline]
pub fn get_mut<I: SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
pub const fn get_mut<I: ~const SliceIndex<str>>(&mut self, i: I) -> Option<&mut I::Output> {
i.get_mut(self)
}

Expand Down
Loading
Loading