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