index.rs - source (original) (raw)

core/slice/

index.rs

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