From 78d8ce7301ef5dd562ea0e06e2b316f1a8d04bf2 Mon Sep 17 00:00:00 2001 From: Jeremy Smart Date: Sat, 6 Sep 2025 01:14:31 -0400 Subject: [PATCH] add SliceIndex wrapper types Last and Clamp --- library/core/src/index.rs | 472 +++++++++++++++++++++++++++++++ library/core/src/lib.rs | 1 + library/core/src/range.rs | 12 + library/core/src/slice/index.rs | 5 + library/coretests/tests/index.rs | 83 ++++++ library/coretests/tests/lib.rs | 4 + 6 files changed, 577 insertions(+) create mode 100644 library/core/src/index.rs create mode 100644 library/coretests/tests/index.rs diff --git a/library/core/src/index.rs b/library/core/src/index.rs new file mode 100644 index 0000000000000..3baefdf10cecb --- /dev/null +++ b/library/core/src/index.rs @@ -0,0 +1,472 @@ +#![unstable(feature = "sliceindex_wrappers", issue = "146179")] + +//! Helper types for indexing slices. + +use crate::intrinsics::slice_get_unchecked; +use crate::slice::SliceIndex; +use crate::{cmp, ops, range}; + +/// Clamps an index, guaranteeing that it will only access valid elements of the slice. +/// +/// # Examples +/// +/// ``` +/// #![feature(sliceindex_wrappers)] +/// +/// use core::index::Clamp; +/// +/// let s: &[usize] = &[0, 1, 2, 3]; +/// +/// assert_eq!(&3, &s[Clamp(6)]); +/// assert_eq!(&[1, 2, 3], &s[Clamp(1..6)]); +/// assert_eq!(&[] as &[usize], &s[Clamp(5..6)]); +/// assert_eq!(&[0, 1, 2, 3], &s[Clamp(..6)]); +/// assert_eq!(&[0, 1, 2, 3], &s[Clamp(..=6)]); +/// assert_eq!(&[] as &[usize], &s[Clamp(6..)]); +/// ``` +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +#[derive(Debug)] +pub struct Clamp(pub Idx); + +/// Always accesses the last element of the slice. +/// +/// # Examples +/// +/// ``` +/// #![feature(sliceindex_wrappers)] +/// #![feature(slice_index_methods)] +/// +/// use core::index::Last; +/// use core::slice::SliceIndex; +/// +/// let s = &[0, 1, 2, 3]; +/// +/// assert_eq!(&3, &s[Last]); +/// assert_eq!(None, Last.get(&[] as &[usize])); +/// +/// ``` +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +#[derive(Debug)] +pub struct Last; + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp { + type Output = T; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + slice.get(cmp::min(self.0, slice.len() - 1)) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + slice.get_mut(cmp::min(self.0, slice.len() - 1)) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { slice_get_unchecked(slice, cmp::min(self.0, slice.len() - 1)) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { slice_get_unchecked(slice, cmp::min(self.0, slice.len() - 1)) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + &(*slice)[cmp::min(self.0, slice.len() - 1)] + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + &mut (*slice)[cmp::min(self.0, slice.len() - 1)] + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + // SAFETY: a range ending before len is always valid + unsafe { (start..end).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + // SAFETY: a range ending before len is always valid + unsafe { (start..end).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + // SAFETY: a range ending before len is always valid + unsafe { (start..end).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + // SAFETY: a range ending before len is always valid + unsafe { (start..end).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + let start = cmp::min(self.0.start, slice.len()); + let end = cmp::min(self.0.end, slice.len()); + (start..end).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.last, slice.len() - 1); + (start..=end).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.last, slice.len() - 1); + (start..=end).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.last, slice.len() - 1); + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (start..=end).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.last, slice.len() - 1); + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (start..=end).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.last, slice.len() - 1); + (start..=end).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.last, slice.len() - 1); + (start..=end).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.end, slice.len() - 1); + (start..=end).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.end, slice.len() - 1); + (start..=end).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.end, slice.len() - 1); + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (start..=end).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.end, slice.len() - 1); + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (start..=end).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.end, slice.len() - 1); + (start..=end).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + let start = cmp::min(self.0.start, slice.len() - 1); + let end = cmp::min(self.0.end, slice.len() - 1); + (start..=end).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + (cmp::min(self.0.start, slice.len())..).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + (cmp::min(self.0.start, slice.len())..).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: a range starting at len is valid + unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: a range starting at len is valid + unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + (cmp::min(self.0.start, slice.len())..).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + (cmp::min(self.0.start, slice.len())..).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + (cmp::min(self.0.start, slice.len())..).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + (cmp::min(self.0.start, slice.len())..).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: a range starting at len is valid + unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: a range starting at len is valid + unsafe { (cmp::min(self.0.start, slice.len())..).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + (cmp::min(self.0.start, slice.len())..).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + (cmp::min(self.0.start, slice.len())..).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + (..cmp::min(self.0.end, slice.len())).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + (..cmp::min(self.0.end, slice.len())).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: a range ending before len is always valid + unsafe { (..cmp::min(self.0.end, slice.len())).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: a range ending before len is always valid + unsafe { (..cmp::min(self.0.end, slice.len())).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + (..cmp::min(self.0.end, slice.len())).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + (..cmp::min(self.0.end, slice.len())).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + (..=cmp::min(self.0.last, slice.len() - 1)).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + (..=cmp::min(self.0.last, slice.len() - 1)).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (..=cmp::min(self.0.last, slice.len() - 1)).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (..=cmp::min(self.0.last, slice.len() - 1)).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + (..=cmp::min(self.0.last, slice.len() - 1)).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + (..=cmp::min(self.0.last, slice.len() - 1)).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp> { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + (..=cmp::min(self.0.end, slice.len() - 1)).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + (..=cmp::min(self.0.end, slice.len() - 1)).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (..=cmp::min(self.0.end, slice.len() - 1)).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { (..=cmp::min(self.0.end, slice.len() - 1)).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + (..=cmp::min(self.0.end, slice.len() - 1)).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + (..=cmp::min(self.0.end, slice.len() - 1)).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Clamp { + type Output = [T]; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + (..).get(slice) + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + (..).get_mut(slice) + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: RangeFull just returns `slice` here + unsafe { (..).get_unchecked(slice) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: RangeFull just returns `slice` here + unsafe { (..).get_unchecked_mut(slice) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + (..).index(slice) + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + (..).index_mut(slice) + } +} + +#[unstable(feature = "sliceindex_wrappers", issue = "146179")] +unsafe impl SliceIndex<[T]> for Last { + type Output = T; + + fn get(self, slice: &[T]) -> Option<&Self::Output> { + slice.last() + } + + fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> { + slice.last_mut() + } + + unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { slice_get_unchecked(slice, slice.len() - 1) } + } + + unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output { + // SAFETY: the caller ensures that the slice isn't empty + unsafe { slice_get_unchecked(slice, slice.len() - 1) } + } + + fn index(self, slice: &[T]) -> &Self::Output { + // N.B., use intrinsic indexing + &(*slice)[slice.len() - 1] + } + + fn index_mut(self, slice: &mut [T]) -> &mut Self::Output { + // N.B., use intrinsic indexing + &mut (*slice)[slice.len() - 1] + } +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 86a68e18b0af4..db059b86a8c84 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -292,6 +292,7 @@ pub mod cmp; pub mod convert; pub mod default; pub mod error; +pub mod index; pub mod marker; pub mod ops; diff --git a/library/core/src/range.rs b/library/core/src/range.rs index a096a8ceafc87..ee8252c177652 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -629,6 +629,18 @@ impl> RangeToInclusive { } } +impl From> for RangeToInclusive { + fn from(value: legacy::RangeToInclusive) -> Self { + Self { last: value.end } + } +} + +impl From> for legacy::RangeToInclusive { + fn from(value: RangeToInclusive) -> Self { + Self { end: value.last } + } +} + // RangeToInclusive cannot impl From> // because underflow would be possible with (..0).into() diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index a8147d745f3ab..40baff3f4465e 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -134,6 +134,11 @@ mod private_slice_index { impl Sealed for range::RangeFrom {} impl Sealed for ops::IndexRange {} + + #[unstable(feature = "sliceindex_wrappers", issue = "146179")] + impl Sealed for crate::index::Last {} + #[unstable(feature = "sliceindex_wrappers", issue = "146179")] + impl Sealed for crate::index::Clamp where T: Sealed {} } /// A helper trait used for indexing operations. diff --git a/library/coretests/tests/index.rs b/library/coretests/tests/index.rs new file mode 100644 index 0000000000000..68e4c841e3226 --- /dev/null +++ b/library/coretests/tests/index.rs @@ -0,0 +1,83 @@ +use core::index::Clamp; +use core::range; +use core::slice::SliceIndex; + +macro_rules! test_clamp { + ($range:expr, $(($slice:expr, $other:expr)),+) => { + $( + assert_eq!(Clamp($range.clone()).get(&$slice as &[_]), $other.get(&$slice as &[_])); + assert_eq!(Clamp($range.clone()).get_mut(&mut $slice as &mut [_]), $other.get_mut(&mut $slice as &mut [_])); + unsafe { + assert_eq!(&*Clamp($range.clone()).get_unchecked(&$slice as &[_]), &*$other.get_unchecked(&$slice as &[_])); + assert_eq!(&*Clamp($range.clone()).get_unchecked_mut(&mut $slice as &mut [_]), &*$other.get_unchecked_mut(&mut $slice as &mut [_])); + } + assert_eq!(Clamp($range.clone()).index(&$slice as &[_]), $other.index(&$slice as &[_])); + assert_eq!(Clamp($range.clone()).index_mut(&mut $slice as &mut [_]), $other.index_mut(&mut $slice as &mut [_])); + )+ + }; +} + +#[test] +fn test_clamp_usize() { + test_clamp!(2, ([0, 1], 1), ([0, 1, 2], 2)); +} + +#[test] +fn test_clamp_range_range() { + test_clamp!(range::Range::from(1..4), ([0, 1], 1..2), ([0, 1, 2, 3, 4], 1..4), ([0], 1..1)); +} + +#[test] +fn test_clamp_ops_range() { + test_clamp!(1..4, ([0, 1], 1..2), ([0, 1, 2, 3, 4], 1..4), ([0], 1..1)); +} + +#[test] +fn test_clamp_range_range_inclusive() { + test_clamp!( + range::RangeInclusive::from(1..=3), + ([0, 1], 1..=1), + ([0, 1, 2, 3, 4], 1..=3), + ([0], 0..=0) + ); +} + +#[test] +fn test_clamp_ops_range_inclusive() { + test_clamp!(1..=3, ([0, 1], 1..=1), ([0, 1, 2, 3, 4], 1..=3), ([0], 0..=0)); +} + +#[test] +fn test_clamp_range_range_from() { + test_clamp!(range::RangeFrom::from(1..), ([0, 1], 1..), ([0, 1, 2, 3, 4], 1..), ([0], 1..)); +} + +#[test] +fn test_clamp_ops_range_from() { + test_clamp!(1.., ([0, 1], 1..), ([0, 1, 2, 3, 4], 1..), ([0], 1..)); +} + +#[test] +fn test_clamp_range_to() { + test_clamp!(..4, ([0, 1], ..2), ([0, 1, 2, 3, 4], ..4), ([0], ..1)); +} + +#[test] +fn test_clamp_range_range_to_inclusive() { + test_clamp!( + range::RangeToInclusive::from(..=4), + ([0, 1], ..=1), + ([0, 1, 2, 3, 4], ..=4), + ([0], ..=0) + ); +} + +#[test] +fn test_clamp_ops_range_to_inclusive() { + test_clamp!(..=4, ([0, 1], ..=1), ([0, 1, 2, 3, 4], ..=4), ([0], ..=0)); +} + +#[test] +fn test_clamp_range_full() { + test_clamp!(.., ([0, 1], ..), ([0, 1, 2, 3, 4], ..), ([0], ..)); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 5c519f3a499d2..4d0a7780fe8de 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -81,6 +81,7 @@ #![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] #![feature(never_type)] +#![feature(new_range_api)] #![feature(next_index)] #![feature(non_exhaustive_omitted_patterns_lint)] #![feature(numfmt)] @@ -93,9 +94,11 @@ #![feature(ptr_metadata)] #![feature(result_option_map_or_default)] #![feature(slice_from_ptr_range)] +#![feature(slice_index_methods)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] #![feature(slice_split_once)] +#![feature(sliceindex_wrappers)] #![feature(split_array)] #![feature(split_as_slice)] #![feature(std_internals)] @@ -173,6 +176,7 @@ mod fmt; mod future; mod hash; mod hint; +mod index; mod intrinsics; mod io; mod iter;