Skip to main content

core/slice/
index.rs

1//! Indexing implementations for `[T]`.
2
3use crate::intrinsics::slice_get_unchecked;
4use crate::marker::Destruct;
5use crate::panic::const_panic;
6use crate::ub_checks::assert_unsafe_precondition;
7use crate::{ops, range};
8
9#[stable(feature = "rust1", since = "1.0.0")]
10#[rustc_const_unstable(feature = "const_index", issue = "143775")]
11const impl<T, I> ops::Index<I> for [T]
12where
13    I: [const] SliceIndex<[T]>,
14{
15    type Output = I::Output;
16
17    #[inline(always)]
18    fn index(&self, index: I) -> &I::Output {
19        index.index(self)
20    }
21}
22
23#[stable(feature = "rust1", since = "1.0.0")]
24#[rustc_const_unstable(feature = "const_index", issue = "143775")]
25const impl<T, I> ops::IndexMut<I> for [T]
26where
27    I: [const] SliceIndex<[T]>,
28{
29    #[inline(always)]
30    fn index_mut(&mut self, index: I) -> &mut I::Output {
31        index.index_mut(self)
32    }
33}
34
35#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
36#[cfg_attr(panic = "immediate-abort", inline)]
37#[track_caller]
38const fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
39    if start > len {
40        const_panic!(
41            "slice start index is out of range for slice",
42            "range start index {start} out of range for slice of length {len}",
43            start: usize,
44            len: usize,
45        )
46    }
47
48    if end > len {
49        const_panic!(
50            "slice end index is out of range for slice",
51            "range end index {end} out of range for slice of length {len}",
52            end: usize,
53            len: usize,
54        )
55    }
56
57    if start > end {
58        const_panic!(
59            "slice index start is larger than end",
60            "slice index starts at {start} but ends at {end}",
61            start: usize,
62            end: usize,
63        )
64    }
65
66    // Only reachable if the range was a `RangeInclusive` or a
67    // `RangeToInclusive`, with `end == len`.
68    const_panic!(
69        "slice end index is out of range for slice",
70        "range end index {end} out of range for slice of length {len}",
71        end: usize,
72        len: usize,
73    )
74}
75
76// The UbChecks are great for catching bugs in the unsafe methods, but including
77// them in safe indexing is unnecessary and hurts inlining and debug runtime perf.
78// Both the safe and unsafe public methods share these helpers,
79// which use intrinsics directly to get *no* extra checks.
80
81#[inline(always)]
82const unsafe fn get_offset_len_noubcheck<T>(
83    ptr: *const [T],
84    offset: usize,
85    len: usize,
86) -> *const [T] {
87    let ptr = ptr as *const T;
88    // SAFETY: The caller already checked these preconditions
89    let ptr = unsafe { crate::intrinsics::offset(ptr, offset) };
90    crate::intrinsics::aggregate_raw_ptr(ptr, len)
91}
92
93#[inline(always)]
94const unsafe fn get_offset_len_mut_noubcheck<T>(
95    ptr: *mut [T],
96    offset: usize,
97    len: usize,
98) -> *mut [T] {
99    let ptr = ptr as *mut T;
100    // SAFETY: The caller already checked these preconditions
101    let ptr = unsafe { crate::intrinsics::offset(ptr, offset) };
102    crate::intrinsics::aggregate_raw_ptr(ptr, len)
103}
104
105/// A helper trait used for indexing operations.
106///
107/// Implementations of this trait have to promise that if the argument
108/// to `get_unchecked(_mut)` is a safe reference, then so is the result.
109#[stable(feature = "slice_get_slice", since = "1.28.0")]
110#[rustc_diagnostic_item = "SliceIndex"]
111#[rustc_on_unimplemented(
112    on(T = "str", label = "string indices are ranges of `usize`",),
113    on(
114        all(any(T = "str", T = "&str", T = "alloc::string::String"), Self = "{integer}"),
115        note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
116                for more information, see chapter 8 in The Book: \
117                <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
118    ),
119    message = "the type `{T}` cannot be indexed by `{Self}`",
120    label = "slice indices are of type `usize` or ranges of `usize`"
121)]
122#[rustc_const_unstable(feature = "const_index", issue = "143775")]
123pub impl(crate) const unsafe trait SliceIndex<T: ?Sized> {
124    /// The output type returned by methods.
125    #[stable(feature = "slice_get_slice", since = "1.28.0")]
126    type Output: ?Sized;
127
128    /// Returns a shared reference to the output at this location, if in
129    /// bounds.
130    #[unstable(feature = "slice_index_methods", issue = "none")]
131    fn get(self, slice: &T) -> Option<&Self::Output>;
132
133    /// Returns a mutable reference to the output at this location, if in
134    /// bounds.
135    #[unstable(feature = "slice_index_methods", issue = "none")]
136    fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
137
138    /// Returns a pointer to the output at this location, without
139    /// performing any bounds checking.
140    ///
141    /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
142    /// is *[undefined behavior]* even if the resulting pointer is not used.
143    ///
144    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
145    #[unstable(feature = "slice_index_methods", issue = "none")]
146    unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
147
148    /// Returns a mutable pointer to the output at this location, without
149    /// performing any bounds checking.
150    ///
151    /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
152    /// is *[undefined behavior]* even if the resulting pointer is not used.
153    ///
154    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
155    #[unstable(feature = "slice_index_methods", issue = "none")]
156    unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output;
157
158    /// Returns a shared reference to the output at this location, panicking
159    /// if out of bounds.
160    #[unstable(feature = "slice_index_methods", issue = "none")]
161    #[track_caller]
162    fn index(self, slice: &T) -> &Self::Output;
163
164    /// Returns a mutable reference to the output at this location, panicking
165    /// if out of bounds.
166    #[unstable(feature = "slice_index_methods", issue = "none")]
167    #[track_caller]
168    fn index_mut(self, slice: &mut T) -> &mut Self::Output;
169}
170
171/// The methods `index` and `index_mut` panic if the index is out of bounds.
172#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
173#[rustc_const_unstable(feature = "const_index", issue = "143775")]
174const unsafe impl<T> SliceIndex<[T]> for usize {
175    type Output = T;
176
177    #[inline]
178    fn get(self, slice: &[T]) -> Option<&T> {
179        if self < slice.len() {
180            // SAFETY: `self` is checked to be in bounds.
181            unsafe { Some(slice_get_unchecked(slice, self)) }
182        } else {
183            None
184        }
185    }
186
187    #[inline]
188    fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
189        if self < slice.len() {
190            // SAFETY: `self` is checked to be in bounds.
191            unsafe { Some(slice_get_unchecked(slice, self)) }
192        } else {
193            None
194        }
195    }
196
197    #[inline]
198    #[track_caller]
199    unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
200        assert_unsafe_precondition!(
201            check_language_ub, // okay because of the `assume` below
202            "slice::get_unchecked requires that the index is within the slice",
203            (this: usize = self, len: usize = slice.len()) => this < len
204        );
205        // SAFETY: the caller guarantees that `slice` is not dangling, so it
206        // cannot be longer than `isize::MAX`. They also guarantee that
207        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
208        // so the call to `add` is safe.
209        unsafe {
210            // Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the
211            // precondition of this function twice.
212            crate::intrinsics::assume(self < slice.len());
213            slice_get_unchecked(slice, self)
214        }
215    }
216
217    #[inline]
218    #[track_caller]
219    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
220        assert_unsafe_precondition!(
221            check_library_ub,
222            "slice::get_unchecked_mut requires that the index is within the slice",
223            (this: usize = self, len: usize = slice.len()) => this < len
224        );
225        // SAFETY: see comments for `get_unchecked` above.
226        unsafe { slice_get_unchecked(slice, self) }
227    }
228
229    #[inline]
230    fn index(self, slice: &[T]) -> &T {
231        // N.B., use intrinsic indexing
232        &(*slice)[self]
233    }
234
235    #[inline]
236    fn index_mut(self, slice: &mut [T]) -> &mut T {
237        // N.B., use intrinsic indexing
238        &mut (*slice)[self]
239    }
240}
241
242/// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
243/// than there are for a general `Range<usize>` (which might be `100..3`).
244#[rustc_const_unstable(feature = "const_index", issue = "143775")]
245const unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
246    type Output = [T];
247
248    #[inline]
249    fn get(self, slice: &[T]) -> Option<&[T]> {
250        if self.end() <= slice.len() {
251            // SAFETY: `self` is checked to be valid and in bounds above.
252            unsafe { Some(&*get_offset_len_noubcheck(slice, self.start(), self.len())) }
253        } else {
254            None
255        }
256    }
257
258    #[inline]
259    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
260        if self.end() <= slice.len() {
261            // SAFETY: `self` is checked to be valid and in bounds above.
262            unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len())) }
263        } else {
264            None
265        }
266    }
267
268    #[inline]
269    #[track_caller]
270    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
271        assert_unsafe_precondition!(
272            check_library_ub,
273            "slice::get_unchecked requires that the index is within the slice",
274            (end: usize = self.end(), len: usize = slice.len()) => end <= len
275        );
276        // SAFETY: the caller guarantees that `slice` is not dangling, so it
277        // cannot be longer than `isize::MAX`. They also guarantee that
278        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
279        // so the call to `add` is safe.
280        unsafe { get_offset_len_noubcheck(slice, self.start(), self.len()) }
281    }
282
283    #[inline]
284    #[track_caller]
285    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
286        assert_unsafe_precondition!(
287            check_library_ub,
288            "slice::get_unchecked_mut requires that the index is within the slice",
289            (end: usize = self.end(), len: usize = slice.len()) => end <= len
290        );
291
292        // SAFETY: see comments for `get_unchecked` above.
293        unsafe { get_offset_len_mut_noubcheck(slice, self.start(), self.len()) }
294    }
295
296    #[inline]
297    fn index(self, slice: &[T]) -> &[T] {
298        if self.end() <= slice.len() {
299            // SAFETY: `self` is checked to be valid and in bounds above.
300            unsafe { &*get_offset_len_noubcheck(slice, self.start(), self.len()) }
301        } else {
302            slice_index_fail(self.start(), self.end(), slice.len())
303        }
304    }
305
306    #[inline]
307    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
308        if self.end() <= slice.len() {
309            // SAFETY: `self` is checked to be valid and in bounds above.
310            unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len()) }
311        } else {
312            slice_index_fail(self.start(), self.end(), slice.len())
313        }
314    }
315}
316
317/// The methods `index` and `index_mut` panic if:
318/// - the start of the range is greater than the end of the range or
319/// - the end of the range is out of bounds.
320#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
321#[rustc_const_unstable(feature = "const_index", issue = "143775")]
322const unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
323    type Output = [T];
324
325    #[inline]
326    fn get(self, slice: &[T]) -> Option<&[T]> {
327        // Using checked_sub is a safe way to get `SubUnchecked` in MIR
328        if let Some(new_len) = usize::checked_sub(self.end, self.start)
329            && self.end <= slice.len()
330        {
331            // SAFETY: `self` is checked to be valid and in bounds above.
332            unsafe { Some(&*get_offset_len_noubcheck(slice, self.start, new_len)) }
333        } else {
334            None
335        }
336    }
337
338    #[inline]
339    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
340        if let Some(new_len) = usize::checked_sub(self.end, self.start)
341            && self.end <= slice.len()
342        {
343            // SAFETY: `self` is checked to be valid and in bounds above.
344            unsafe { Some(&mut *get_offset_len_mut_noubcheck(slice, self.start, new_len)) }
345        } else {
346            None
347        }
348    }
349
350    #[inline]
351    #[track_caller]
352    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
353        assert_unsafe_precondition!(
354            check_library_ub,
355            "slice::get_unchecked requires that the range is within the slice",
356            (
357                start: usize = self.start,
358                end: usize = self.end,
359                len: usize = slice.len()
360            ) => end >= start && end <= len
361        );
362
363        // SAFETY: the caller guarantees that `slice` is not dangling, so it
364        // cannot be longer than `isize::MAX`. They also guarantee that
365        // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
366        // so the call to `add` is safe and the length calculation cannot overflow.
367        unsafe {
368            // Using the intrinsic avoids a superfluous UB check,
369            // since the one on this method already checked `end >= start`.
370            let new_len = crate::intrinsics::unchecked_sub(self.end, self.start);
371            get_offset_len_noubcheck(slice, self.start, new_len)
372        }
373    }
374
375    #[inline]
376    #[track_caller]
377    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
378        assert_unsafe_precondition!(
379            check_library_ub,
380            "slice::get_unchecked_mut requires that the range is within the slice",
381            (
382                start: usize = self.start,
383                end: usize = self.end,
384                len: usize = slice.len()
385            ) => end >= start && end <= len
386        );
387        // SAFETY: see comments for `get_unchecked` above.
388        unsafe {
389            let new_len = crate::intrinsics::unchecked_sub(self.end, self.start);
390            get_offset_len_mut_noubcheck(slice, self.start, new_len)
391        }
392    }
393
394    #[inline(always)]
395    fn index(self, slice: &[T]) -> &[T] {
396        // Using checked_sub is a safe way to get `SubUnchecked` in MIR
397        if let Some(new_len) = usize::checked_sub(self.end, self.start)
398            && self.end <= slice.len()
399        {
400            // SAFETY: `self` is checked to be valid and in bounds above.
401            unsafe { &*get_offset_len_noubcheck(slice, self.start, new_len) }
402        } else {
403            slice_index_fail(self.start, self.end, slice.len())
404        }
405    }
406
407    #[inline]
408    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
409        // Using checked_sub is a safe way to get `SubUnchecked` in MIR
410        if let Some(new_len) = usize::checked_sub(self.end, self.start)
411            && self.end <= slice.len()
412        {
413            // SAFETY: `self` is checked to be valid and in bounds above.
414            unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start, new_len) }
415        } else {
416            slice_index_fail(self.start, self.end, slice.len())
417        }
418    }
419}
420
421#[stable(feature = "new_range_api", since = "1.96.0")]
422#[rustc_const_unstable(feature = "const_index", issue = "143775")]
423const unsafe impl<T> SliceIndex<[T]> for range::Range<usize> {
424    type Output = [T];
425
426    #[inline]
427    fn get(self, slice: &[T]) -> Option<&[T]> {
428        ops::Range::from(self).get(slice)
429    }
430
431    #[inline]
432    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
433        ops::Range::from(self).get_mut(slice)
434    }
435
436    #[inline]
437    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
438        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
439        unsafe { ops::Range::from(self).get_unchecked(slice) }
440    }
441
442    #[inline]
443    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
444        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
445        unsafe { ops::Range::from(self).get_unchecked_mut(slice) }
446    }
447
448    #[inline(always)]
449    fn index(self, slice: &[T]) -> &[T] {
450        ops::Range::from(self).index(slice)
451    }
452
453    #[inline]
454    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
455        ops::Range::from(self).index_mut(slice)
456    }
457}
458
459/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
460#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
461#[rustc_const_unstable(feature = "const_index", issue = "143775")]
462const unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
463    type Output = [T];
464
465    #[inline]
466    fn get(self, slice: &[T]) -> Option<&[T]> {
467        (0..self.end).get(slice)
468    }
469
470    #[inline]
471    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
472        (0..self.end).get_mut(slice)
473    }
474
475    #[inline]
476    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
477        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
478        unsafe { (0..self.end).get_unchecked(slice) }
479    }
480
481    #[inline]
482    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
483        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
484        unsafe { (0..self.end).get_unchecked_mut(slice) }
485    }
486
487    #[inline(always)]
488    fn index(self, slice: &[T]) -> &[T] {
489        (0..self.end).index(slice)
490    }
491
492    #[inline]
493    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
494        (0..self.end).index_mut(slice)
495    }
496}
497
498/// The methods `index` and `index_mut` panic if the start of the range is out of bounds.
499#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
500#[rustc_const_unstable(feature = "const_index", issue = "143775")]
501const unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
502    type Output = [T];
503
504    #[inline]
505    fn get(self, slice: &[T]) -> Option<&[T]> {
506        (self.start..slice.len()).get(slice)
507    }
508
509    #[inline]
510    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
511        (self.start..slice.len()).get_mut(slice)
512    }
513
514    #[inline]
515    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
516        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
517        unsafe { (self.start..slice.len()).get_unchecked(slice) }
518    }
519
520    #[inline]
521    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
522        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
523        unsafe { (self.start..slice.len()).get_unchecked_mut(slice) }
524    }
525
526    #[inline]
527    fn index(self, slice: &[T]) -> &[T] {
528        if self.start > slice.len() {
529            slice_index_fail(self.start, slice.len(), slice.len())
530        }
531        // SAFETY: `self` is checked to be valid and in bounds above.
532        unsafe {
533            let new_len = crate::intrinsics::unchecked_sub(slice.len(), self.start);
534            &*get_offset_len_noubcheck(slice, self.start, new_len)
535        }
536    }
537
538    #[inline]
539    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
540        if self.start > slice.len() {
541            slice_index_fail(self.start, slice.len(), slice.len())
542        }
543        // SAFETY: `self` is checked to be valid and in bounds above.
544        unsafe {
545            let new_len = crate::intrinsics::unchecked_sub(slice.len(), self.start);
546            &mut *get_offset_len_mut_noubcheck(slice, self.start, new_len)
547        }
548    }
549}
550
551#[stable(feature = "new_range_from_api", since = "1.96.0")]
552#[rustc_const_unstable(feature = "const_index", issue = "143775")]
553const unsafe impl<T> SliceIndex<[T]> for range::RangeFrom<usize> {
554    type Output = [T];
555
556    #[inline]
557    fn get(self, slice: &[T]) -> Option<&[T]> {
558        ops::RangeFrom::from(self).get(slice)
559    }
560
561    #[inline]
562    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
563        ops::RangeFrom::from(self).get_mut(slice)
564    }
565
566    #[inline]
567    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
568        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
569        unsafe { ops::RangeFrom::from(self).get_unchecked(slice) }
570    }
571
572    #[inline]
573    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
574        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
575        unsafe { ops::RangeFrom::from(self).get_unchecked_mut(slice) }
576    }
577
578    #[inline]
579    fn index(self, slice: &[T]) -> &[T] {
580        ops::RangeFrom::from(self).index(slice)
581    }
582
583    #[inline]
584    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
585        ops::RangeFrom::from(self).index_mut(slice)
586    }
587}
588
589#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
590#[rustc_const_unstable(feature = "const_index", issue = "143775")]
591const unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
592    type Output = [T];
593
594    #[inline]
595    fn get(self, slice: &[T]) -> Option<&[T]> {
596        Some(slice)
597    }
598
599    #[inline]
600    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
601        Some(slice)
602    }
603
604    #[inline]
605    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
606        slice
607    }
608
609    #[inline]
610    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
611        slice
612    }
613
614    #[inline]
615    fn index(self, slice: &[T]) -> &[T] {
616        slice
617    }
618
619    #[inline]
620    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
621        slice
622    }
623}
624
625/// The methods `index` and `index_mut` panic if:
626/// - the start of the range is greater than the end of the range or
627/// - the end of the range is out of bounds.
628#[stable(feature = "inclusive_range", since = "1.26.0")]
629#[rustc_const_unstable(feature = "const_index", issue = "143775")]
630const unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
631    type Output = [T];
632
633    #[inline]
634    fn get(self, slice: &[T]) -> Option<&[T]> {
635        if *self.end() >= slice.len() { None } else { self.into_slice_range().get(slice) }
636    }
637
638    #[inline]
639    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
640        if *self.end() >= slice.len() { None } else { self.into_slice_range().get_mut(slice) }
641    }
642
643    #[inline]
644    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
645        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
646        unsafe { self.into_slice_range().get_unchecked(slice) }
647    }
648
649    #[inline]
650    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
651        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
652        unsafe { self.into_slice_range().get_unchecked_mut(slice) }
653    }
654
655    #[inline]
656    fn index(self, slice: &[T]) -> &[T] {
657        let Self { mut start, mut end, exhausted } = self;
658        let len = slice.len();
659        if end < len {
660            end = end + 1;
661            start = if exhausted { end } else { start };
662            if let Some(new_len) = usize::checked_sub(end, start) {
663                // SAFETY: `self` is checked to be valid and in bounds above.
664                unsafe { return &*get_offset_len_noubcheck(slice, start, new_len) }
665            }
666        }
667        slice_index_fail(start, end, slice.len())
668    }
669
670    #[inline]
671    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
672        let Self { mut start, mut end, exhausted } = self;
673        let len = slice.len();
674        if end < len {
675            end = end + 1;
676            start = if exhausted { end } else { start };
677            if let Some(new_len) = usize::checked_sub(end, start) {
678                // SAFETY: `self` is checked to be valid and in bounds above.
679                unsafe { return &mut *get_offset_len_mut_noubcheck(slice, start, new_len) }
680            }
681        }
682        slice_index_fail(start, end, slice.len())
683    }
684}
685
686#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
687#[rustc_const_unstable(feature = "const_index", issue = "143775")]
688const unsafe impl<T> SliceIndex<[T]> for range::RangeInclusive<usize> {
689    type Output = [T];
690
691    #[inline]
692    fn get(self, slice: &[T]) -> Option<&[T]> {
693        ops::RangeInclusive::from(self).get(slice)
694    }
695
696    #[inline]
697    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
698        ops::RangeInclusive::from(self).get_mut(slice)
699    }
700
701    #[inline]
702    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
703        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
704        unsafe { ops::RangeInclusive::from(self).get_unchecked(slice) }
705    }
706
707    #[inline]
708    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
709        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
710        unsafe { ops::RangeInclusive::from(self).get_unchecked_mut(slice) }
711    }
712
713    #[inline]
714    fn index(self, slice: &[T]) -> &[T] {
715        ops::RangeInclusive::from(self).index(slice)
716    }
717
718    #[inline]
719    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
720        ops::RangeInclusive::from(self).index_mut(slice)
721    }
722}
723
724/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
725#[stable(feature = "inclusive_range", since = "1.26.0")]
726#[rustc_const_unstable(feature = "const_index", issue = "143775")]
727const unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
728    type Output = [T];
729
730    #[inline]
731    fn get(self, slice: &[T]) -> Option<&[T]> {
732        (0..=self.end).get(slice)
733    }
734
735    #[inline]
736    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
737        (0..=self.end).get_mut(slice)
738    }
739
740    #[inline]
741    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
742        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
743        unsafe { (0..=self.end).get_unchecked(slice) }
744    }
745
746    #[inline]
747    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
748        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
749        unsafe { (0..=self.end).get_unchecked_mut(slice) }
750    }
751
752    #[inline]
753    fn index(self, slice: &[T]) -> &[T] {
754        (0..=self.end).index(slice)
755    }
756
757    #[inline]
758    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
759        (0..=self.end).index_mut(slice)
760    }
761}
762
763/// The methods `index` and `index_mut` panic if the end of the range is out of bounds.
764#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
765#[rustc_const_unstable(feature = "const_index", issue = "143775")]
766const unsafe impl<T> SliceIndex<[T]> for range::RangeToInclusive<usize> {
767    type Output = [T];
768
769    #[inline]
770    fn get(self, slice: &[T]) -> Option<&[T]> {
771        (0..=self.last).get(slice)
772    }
773
774    #[inline]
775    fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
776        (0..=self.last).get_mut(slice)
777    }
778
779    #[inline]
780    unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
781        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
782        unsafe { (0..=self.last).get_unchecked(slice) }
783    }
784
785    #[inline]
786    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
787        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
788        unsafe { (0..=self.last).get_unchecked_mut(slice) }
789    }
790
791    #[inline]
792    fn index(self, slice: &[T]) -> &[T] {
793        (0..=self.last).index(slice)
794    }
795
796    #[inline]
797    fn index_mut(self, slice: &mut [T]) -> &mut [T] {
798        (0..=self.last).index_mut(slice)
799    }
800}
801
802/// Performs bounds checking of a range.
803///
804/// This method is similar to [`Index::index`] for slices, but it returns a
805/// [`Range`] equivalent to `range`. You can use this method to turn any range
806/// into `start` and `end` values.
807///
808/// `bounds` is the range of the slice to use for bounds checking. It should
809/// be a [`RangeTo`] range that ends at the length of the slice.
810///
811/// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
812/// [`slice::get_unchecked_mut`] for slices with the given range.
813///
814/// [`Range`]: ops::Range
815/// [`RangeTo`]: ops::RangeTo
816/// [`slice::get_unchecked`]: slice::get_unchecked
817/// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut
818///
819/// # Panics
820///
821/// Panics if `range` would be out of bounds.
822///
823/// # Examples
824///
825/// ```
826/// #![feature(slice_range)]
827///
828/// use std::slice;
829///
830/// let v = [10, 40, 30];
831/// assert_eq!(1..2, slice::range(1..2, ..v.len()));
832/// assert_eq!(0..2, slice::range(..2, ..v.len()));
833/// assert_eq!(1..3, slice::range(1.., ..v.len()));
834/// ```
835///
836/// Panics when [`Index::index`] would panic:
837///
838/// ```should_panic
839/// #![feature(slice_range)]
840///
841/// use std::slice;
842///
843/// let _ = slice::range(2..1, ..3);
844/// ```
845///
846/// ```should_panic
847/// #![feature(slice_range)]
848///
849/// use std::slice;
850///
851/// let _ = slice::range(1..4, ..3);
852/// ```
853///
854/// ```should_panic
855/// #![feature(slice_range)]
856///
857/// use std::slice;
858///
859/// let _ = slice::range(1..=usize::MAX, ..3);
860/// ```
861///
862/// [`Index::index`]: ops::Index::index
863#[track_caller]
864#[unstable(feature = "slice_range", issue = "76393")]
865#[must_use]
866#[rustc_const_unstable(feature = "const_range", issue = "none")]
867pub const fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
868where
869    R: [const] ops::RangeBounds<usize> + [const] Destruct,
870{
871    let len = bounds.end;
872    into_slice_range(len, (range.start_bound().copied(), range.end_bound().copied()))
873}
874
875/// Performs bounds checking of a range without panicking.
876///
877/// This is a version of [`range()`] that returns [`None`] instead of panicking.
878///
879/// # Examples
880///
881/// ```
882/// #![feature(slice_range)]
883///
884/// use std::slice;
885///
886/// let v = [10, 40, 30];
887/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len()));
888/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len()));
889/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len()));
890/// ```
891///
892/// Returns [`None`] when [`Index::index`] would panic:
893///
894/// ```
895/// #![feature(slice_range)]
896///
897/// use std::slice;
898///
899/// assert_eq!(None, slice::try_range(2..1, ..3));
900/// assert_eq!(None, slice::try_range(1..4, ..3));
901/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3));
902/// ```
903///
904/// [`Index::index`]: ops::Index::index
905#[unstable(feature = "slice_range", issue = "76393")]
906#[must_use]
907pub fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<usize>>
908where
909    R: ops::RangeBounds<usize>,
910{
911    let len = bounds.end;
912    try_into_slice_range(len, (range.start_bound().copied(), range.end_bound().copied()))
913}
914
915/// Converts a pair of `ops::Bound`s into `ops::Range` without performing any
916/// bounds checking or (in debug) overflow checking.
917pub(crate) const fn into_range_unchecked(
918    len: usize,
919    (start, end): (ops::Bound<usize>, ops::Bound<usize>),
920) -> ops::Range<usize> {
921    use ops::Bound;
922    let start = match start {
923        Bound::Included(i) => i,
924        Bound::Excluded(i) => i + 1,
925        Bound::Unbounded => 0,
926    };
927    let end = match end {
928        Bound::Included(i) => i + 1,
929        Bound::Excluded(i) => i,
930        Bound::Unbounded => len,
931    };
932    start..end
933}
934
935/// Converts pair of `ops::Bound`s into `ops::Range`.
936/// Returns `None` on overflowing indices.
937#[rustc_const_unstable(feature = "const_range", issue = "none")]
938#[inline]
939pub(crate) const fn try_into_slice_range(
940    len: usize,
941    (start, end): (ops::Bound<usize>, ops::Bound<usize>),
942) -> Option<ops::Range<usize>> {
943    let end = match end {
944        ops::Bound::Included(end) if end >= len => return None,
945        // Cannot overflow because `end < len` implies `end < usize::MAX`.
946        ops::Bound::Included(end) => end + 1,
947
948        ops::Bound::Excluded(end) if end > len => return None,
949        ops::Bound::Excluded(end) => end,
950
951        ops::Bound::Unbounded => len,
952    };
953
954    let start = match start {
955        ops::Bound::Excluded(start) if start >= end => return None,
956        // Cannot overflow because `start < end` implies `start < usize::MAX`.
957        ops::Bound::Excluded(start) => start + 1,
958
959        ops::Bound::Included(start) if start > end => return None,
960        ops::Bound::Included(start) => start,
961
962        ops::Bound::Unbounded => 0,
963    };
964
965    Some(start..end)
966}
967
968/// Converts pair of `ops::Bound`s into `ops::Range`.
969/// Panics on overflowing indices.
970#[inline]
971pub(crate) const fn into_slice_range(
972    len: usize,
973    (start, end): (ops::Bound<usize>, ops::Bound<usize>),
974) -> ops::Range<usize> {
975    let end = match end {
976        ops::Bound::Included(end) if end >= len => slice_index_fail(0, end, len),
977        // Cannot overflow because `end < len` implies `end < usize::MAX`.
978        ops::Bound::Included(end) => end + 1,
979
980        ops::Bound::Excluded(end) if end > len => slice_index_fail(0, end, len),
981        ops::Bound::Excluded(end) => end,
982
983        ops::Bound::Unbounded => len,
984    };
985
986    let start = match start {
987        ops::Bound::Excluded(start) if start >= end => slice_index_fail(start, end, len),
988        // Cannot overflow because `start < end` implies `start < usize::MAX`.
989        ops::Bound::Excluded(start) => start + 1,
990
991        ops::Bound::Included(start) if start > end => slice_index_fail(start, end, len),
992        ops::Bound::Included(start) => start,
993
994        ops::Bound::Unbounded => 0,
995    };
996
997    start..end
998}
999
1000#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
1001unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) {
1002    type Output = [T];
1003
1004    #[inline]
1005    fn get(self, slice: &[T]) -> Option<&Self::Output> {
1006        try_into_slice_range(slice.len(), self)?.get(slice)
1007    }
1008
1009    #[inline]
1010    fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
1011        try_into_slice_range(slice.len(), self)?.get_mut(slice)
1012    }
1013
1014    #[inline]
1015    unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
1016        // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
1017        unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) }
1018    }
1019
1020    #[inline]
1021    unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
1022        // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
1023        unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) }
1024    }
1025
1026    #[inline]
1027    fn index(self, slice: &[T]) -> &Self::Output {
1028        into_slice_range(slice.len(), self).index(slice)
1029    }
1030
1031    #[inline]
1032    fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
1033        into_slice_range(slice.len(), self).index_mut(slice)
1034    }
1035}