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