core\slice/
index.rs

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