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