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