Skip to main content

core/slice/
index.rs

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