]> git.lizzy.rs Git - rust.git/blob - library/core/src/slice/index.rs
Rollup merge of #101967 - jmillikin:linux-abstract-socket-addr, r=joshtriplett
[rust.git] / library / core / src / slice / index.rs
1 //! Indexing implementations for `[T]`.
2
3 use crate::intrinsics::assert_unsafe_precondition;
4 use crate::intrinsics::const_eval_select;
5 use crate::ops;
6 use crate::ptr;
7
8 #[stable(feature = "rust1", since = "1.0.0")]
9 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
10 impl<T, I> const ops::Index<I> for [T]
11 where
12     I: ~const SliceIndex<[T]>,
13 {
14     type Output = I::Output;
15
16     #[inline]
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_slice_index", issue = "none")]
24 impl<T, I> const ops::IndexMut<I> for [T]
25 where
26     I: ~const SliceIndex<[T]>,
27 {
28     #[inline]
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))]
35 #[cfg_attr(feature = "panic_immediate_abort", inline)]
36 #[cold]
37 #[track_caller]
38 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
39 const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
40     // SAFETY: we are just panicking here
41     unsafe {
42         const_eval_select(
43             (index, len),
44             slice_start_index_len_fail_ct,
45             slice_start_index_len_fail_rt,
46         )
47     }
48 }
49
50 // FIXME const-hack
51 #[track_caller]
52 fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! {
53     panic!("range start index {index} out of range for slice of length {len}");
54 }
55
56 #[track_caller]
57 const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! {
58     panic!("slice start index is out of range for slice");
59 }
60
61 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
62 #[cfg_attr(feature = "panic_immediate_abort", inline)]
63 #[cold]
64 #[track_caller]
65 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
66 const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
67     // SAFETY: we are just panicking here
68     unsafe {
69         const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt)
70     }
71 }
72
73 // FIXME const-hack
74 #[track_caller]
75 fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! {
76     panic!("range end index {index} out of range for slice of length {len}");
77 }
78
79 #[track_caller]
80 const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! {
81     panic!("slice end index is out of range for slice");
82 }
83
84 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
85 #[cfg_attr(feature = "panic_immediate_abort", inline)]
86 #[cold]
87 #[track_caller]
88 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
89 const fn slice_index_order_fail(index: usize, end: usize) -> ! {
90     // SAFETY: we are just panicking here
91     unsafe { const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) }
92 }
93
94 // FIXME const-hack
95 #[track_caller]
96 fn slice_index_order_fail_rt(index: usize, end: usize) -> ! {
97     panic!("slice index starts at {index} but ends at {end}");
98 }
99
100 #[track_caller]
101 const fn slice_index_order_fail_ct(_: usize, _: usize) -> ! {
102     panic!("slice index start is larger than end");
103 }
104
105 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
106 #[cfg_attr(feature = "panic_immediate_abort", inline)]
107 #[cold]
108 #[track_caller]
109 const fn slice_start_index_overflow_fail() -> ! {
110     panic!("attempted to index slice from after maximum usize");
111 }
112
113 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
114 #[cfg_attr(feature = "panic_immediate_abort", inline)]
115 #[cold]
116 #[track_caller]
117 const fn slice_end_index_overflow_fail() -> ! {
118     panic!("attempted to index slice up to maximum usize");
119 }
120
121 mod private_slice_index {
122     use super::ops;
123     #[stable(feature = "slice_get_slice", since = "1.28.0")]
124     pub trait Sealed {}
125
126     #[stable(feature = "slice_get_slice", since = "1.28.0")]
127     impl Sealed for usize {}
128     #[stable(feature = "slice_get_slice", since = "1.28.0")]
129     impl Sealed for ops::Range<usize> {}
130     #[stable(feature = "slice_get_slice", since = "1.28.0")]
131     impl Sealed for ops::RangeTo<usize> {}
132     #[stable(feature = "slice_get_slice", since = "1.28.0")]
133     impl Sealed for ops::RangeFrom<usize> {}
134     #[stable(feature = "slice_get_slice", since = "1.28.0")]
135     impl Sealed for ops::RangeFull {}
136     #[stable(feature = "slice_get_slice", since = "1.28.0")]
137     impl Sealed for ops::RangeInclusive<usize> {}
138     #[stable(feature = "slice_get_slice", since = "1.28.0")]
139     impl Sealed for ops::RangeToInclusive<usize> {}
140     #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
141     impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
142
143     impl Sealed for ops::IndexRange {}
144 }
145
146 /// A helper trait used for indexing operations.
147 ///
148 /// Implementations of this trait have to promise that if the argument
149 /// to `get_unchecked(_mut)` is a safe reference, then so is the result.
150 #[stable(feature = "slice_get_slice", since = "1.28.0")]
151 #[rustc_diagnostic_item = "SliceIndex"]
152 #[rustc_on_unimplemented(
153     on(T = "str", label = "string indices are ranges of `usize`",),
154     on(
155         all(any(T = "str", T = "&str", T = "std::string::String"), _Self = "{integer}"),
156         note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
157                 for more information, see chapter 8 in The Book: \
158                 <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
159     ),
160     message = "the type `{T}` cannot be indexed by `{Self}`",
161     label = "slice indices are of type `usize` or ranges of `usize`"
162 )]
163 #[const_trait]
164 pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
165     /// The output type returned by methods.
166     #[stable(feature = "slice_get_slice", since = "1.28.0")]
167     type Output: ?Sized;
168
169     /// Returns a shared reference to the output at this location, if in
170     /// bounds.
171     #[unstable(feature = "slice_index_methods", issue = "none")]
172     fn get(self, slice: &T) -> Option<&Self::Output>;
173
174     /// Returns a mutable reference to the output at this location, if in
175     /// bounds.
176     #[unstable(feature = "slice_index_methods", issue = "none")]
177     fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
178
179     /// Returns a shared reference to the output at this location, without
180     /// performing any bounds checking.
181     /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
182     /// is *[undefined behavior]* even if the resulting reference is not used.
183     ///
184     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
185     #[unstable(feature = "slice_index_methods", issue = "none")]
186     unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
187
188     /// Returns a mutable reference to the output at this location, without
189     /// performing any bounds checking.
190     /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
191     /// is *[undefined behavior]* even if the resulting reference is not used.
192     ///
193     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
194     #[unstable(feature = "slice_index_methods", issue = "none")]
195     unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output;
196
197     /// Returns a shared 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(self, slice: &T) -> &Self::Output;
202
203     /// Returns a mutable reference to the output at this location, panicking
204     /// if out of bounds.
205     #[unstable(feature = "slice_index_methods", issue = "none")]
206     #[track_caller]
207     fn index_mut(self, slice: &mut T) -> &mut Self::Output;
208 }
209
210 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
211 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
212 unsafe impl<T> const SliceIndex<[T]> for usize {
213     type Output = T;
214
215     #[inline]
216     fn get(self, slice: &[T]) -> Option<&T> {
217         // SAFETY: `self` is checked to be in bounds.
218         if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None }
219     }
220
221     #[inline]
222     fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
223         // SAFETY: `self` is checked to be in bounds.
224         if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None }
225     }
226
227     #[inline]
228     unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
229         let this = self;
230         // SAFETY: the caller guarantees that `slice` is not dangling, so it
231         // cannot be longer than `isize::MAX`. They also guarantee that
232         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
233         // so the call to `add` is safe.
234         unsafe {
235             assert_unsafe_precondition!(
236                 "slice::get_unchecked requires that the index is within the slice",
237                 [T](this: usize, slice: *const [T]) => this < slice.len()
238             );
239             slice.as_ptr().add(self)
240         }
241     }
242
243     #[inline]
244     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
245         let this = self;
246         // SAFETY: see comments for `get_unchecked` above.
247         unsafe {
248             assert_unsafe_precondition!(
249                 "slice::get_unchecked_mut requires that the index is within the slice",
250                 [T](this: usize, slice: *mut [T]) => this < slice.len()
251             );
252             slice.as_mut_ptr().add(self)
253         }
254     }
255
256     #[inline]
257     fn index(self, slice: &[T]) -> &T {
258         // N.B., use intrinsic indexing
259         &(*slice)[self]
260     }
261
262     #[inline]
263     fn index_mut(self, slice: &mut [T]) -> &mut T {
264         // N.B., use intrinsic indexing
265         &mut (*slice)[self]
266     }
267 }
268
269 /// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
270 /// than there are for a general `Range<usize>` (which might be `100..3`).
271 #[rustc_const_unstable(feature = "const_index_range_slice_index", issue = "none")]
272 unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
273     type Output = [T];
274
275     #[inline]
276     fn get(self, slice: &[T]) -> Option<&[T]> {
277         if self.end() <= slice.len() {
278             // SAFETY: `self` is checked to be valid and in bounds above.
279             unsafe { Some(&*self.get_unchecked(slice)) }
280         } else {
281             None
282         }
283     }
284
285     #[inline]
286     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
287         if self.end() <= slice.len() {
288             // SAFETY: `self` is checked to be valid and in bounds above.
289             unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
290         } else {
291             None
292         }
293     }
294
295     #[inline]
296     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
297         let end = self.end();
298         // SAFETY: the caller guarantees that `slice` is not dangling, so it
299         // cannot be longer than `isize::MAX`. They also guarantee that
300         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
301         // so the call to `add` is safe.
302
303         unsafe {
304             assert_unsafe_precondition!(
305                 "slice::get_unchecked requires that the index is within the slice",
306                 [T](end: usize, slice: *const [T]) => end <= slice.len()
307             );
308             ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len())
309         }
310     }
311
312     #[inline]
313     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
314         let end = self.end();
315         // SAFETY: see comments for `get_unchecked` above.
316         unsafe {
317             assert_unsafe_precondition!(
318                 "slice::get_unchecked_mut requires that the index is within the slice",
319                 [T](end: usize, slice: *mut [T]) => end <= slice.len()
320             );
321             ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len())
322         }
323     }
324
325     #[inline]
326     fn index(self, slice: &[T]) -> &[T] {
327         if self.end() <= slice.len() {
328             // SAFETY: `self` is checked to be valid and in bounds above.
329             unsafe { &*self.get_unchecked(slice) }
330         } else {
331             slice_end_index_len_fail(self.end(), slice.len())
332         }
333     }
334
335     #[inline]
336     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
337         if self.end() <= slice.len() {
338             // SAFETY: `self` is checked to be valid and in bounds above.
339             unsafe { &mut *self.get_unchecked_mut(slice) }
340         } else {
341             slice_end_index_len_fail(self.end(), slice.len())
342         }
343     }
344 }
345
346 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
347 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
348 unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
349     type Output = [T];
350
351     #[inline]
352     fn get(self, slice: &[T]) -> Option<&[T]> {
353         if self.start > self.end || self.end > slice.len() {
354             None
355         } else {
356             // SAFETY: `self` is checked to be valid and in bounds above.
357             unsafe { Some(&*self.get_unchecked(slice)) }
358         }
359     }
360
361     #[inline]
362     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
363         if self.start > self.end || self.end > slice.len() {
364             None
365         } else {
366             // SAFETY: `self` is checked to be valid and in bounds above.
367             unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
368         }
369     }
370
371     #[inline]
372     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
373         let this = ops::Range { start: self.start, end: self.end };
374         // SAFETY: the caller guarantees that `slice` is not dangling, so it
375         // cannot be longer than `isize::MAX`. They also guarantee that
376         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
377         // so the call to `add` is safe.
378
379         unsafe {
380             assert_unsafe_precondition!(
381                 "slice::get_unchecked requires that the range is within the slice",
382                 [T](this: ops::Range<usize>, slice: *const [T]) =>
383                 this.end >= this.start && this.end <= slice.len()
384             );
385             ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start)
386         }
387     }
388
389     #[inline]
390     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
391         let this = ops::Range { start: self.start, end: self.end };
392         // SAFETY: see comments for `get_unchecked` above.
393         unsafe {
394             assert_unsafe_precondition!(
395                 "slice::get_unchecked_mut requires that the range is within the slice",
396                 [T](this: ops::Range<usize>, slice: *mut [T]) =>
397                 this.end >= this.start && this.end <= slice.len()
398             );
399             ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
400         }
401     }
402
403     #[inline]
404     fn index(self, slice: &[T]) -> &[T] {
405         if self.start > self.end {
406             slice_index_order_fail(self.start, self.end);
407         } else if self.end > slice.len() {
408             slice_end_index_len_fail(self.end, slice.len());
409         }
410         // SAFETY: `self` is checked to be valid and in bounds above.
411         unsafe { &*self.get_unchecked(slice) }
412     }
413
414     #[inline]
415     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
416         if self.start > self.end {
417             slice_index_order_fail(self.start, self.end);
418         } else if self.end > slice.len() {
419             slice_end_index_len_fail(self.end, slice.len());
420         }
421         // SAFETY: `self` is checked to be valid and in bounds above.
422         unsafe { &mut *self.get_unchecked_mut(slice) }
423     }
424 }
425
426 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
427 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
428 unsafe impl<T> const SliceIndex<[T]> for ops::RangeTo<usize> {
429     type Output = [T];
430
431     #[inline]
432     fn get(self, slice: &[T]) -> Option<&[T]> {
433         (0..self.end).get(slice)
434     }
435
436     #[inline]
437     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
438         (0..self.end).get_mut(slice)
439     }
440
441     #[inline]
442     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
443         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
444         unsafe { (0..self.end).get_unchecked(slice) }
445     }
446
447     #[inline]
448     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
449         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
450         unsafe { (0..self.end).get_unchecked_mut(slice) }
451     }
452
453     #[inline]
454     fn index(self, slice: &[T]) -> &[T] {
455         (0..self.end).index(slice)
456     }
457
458     #[inline]
459     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
460         (0..self.end).index_mut(slice)
461     }
462 }
463
464 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
465 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
466 unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
467     type Output = [T];
468
469     #[inline]
470     fn get(self, slice: &[T]) -> Option<&[T]> {
471         (self.start..slice.len()).get(slice)
472     }
473
474     #[inline]
475     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
476         (self.start..slice.len()).get_mut(slice)
477     }
478
479     #[inline]
480     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
481         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
482         unsafe { (self.start..slice.len()).get_unchecked(slice) }
483     }
484
485     #[inline]
486     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
487         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
488         unsafe { (self.start..slice.len()).get_unchecked_mut(slice) }
489     }
490
491     #[inline]
492     fn index(self, slice: &[T]) -> &[T] {
493         if self.start > slice.len() {
494             slice_start_index_len_fail(self.start, slice.len());
495         }
496         // SAFETY: `self` is checked to be valid and in bounds above.
497         unsafe { &*self.get_unchecked(slice) }
498     }
499
500     #[inline]
501     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
502         if self.start > slice.len() {
503             slice_start_index_len_fail(self.start, slice.len());
504         }
505         // SAFETY: `self` is checked to be valid and in bounds above.
506         unsafe { &mut *self.get_unchecked_mut(slice) }
507     }
508 }
509
510 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
511 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
512 unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull {
513     type Output = [T];
514
515     #[inline]
516     fn get(self, slice: &[T]) -> Option<&[T]> {
517         Some(slice)
518     }
519
520     #[inline]
521     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
522         Some(slice)
523     }
524
525     #[inline]
526     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
527         slice
528     }
529
530     #[inline]
531     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
532         slice
533     }
534
535     #[inline]
536     fn index(self, slice: &[T]) -> &[T] {
537         slice
538     }
539
540     #[inline]
541     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
542         slice
543     }
544 }
545
546 #[stable(feature = "inclusive_range", since = "1.26.0")]
547 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
548 unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
549     type Output = [T];
550
551     #[inline]
552     fn get(self, slice: &[T]) -> Option<&[T]> {
553         if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
554     }
555
556     #[inline]
557     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
558         if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
559     }
560
561     #[inline]
562     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
563         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
564         unsafe { self.into_slice_range().get_unchecked(slice) }
565     }
566
567     #[inline]
568     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
569         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
570         unsafe { self.into_slice_range().get_unchecked_mut(slice) }
571     }
572
573     #[inline]
574     fn index(self, slice: &[T]) -> &[T] {
575         if *self.end() == usize::MAX {
576             slice_end_index_overflow_fail();
577         }
578         self.into_slice_range().index(slice)
579     }
580
581     #[inline]
582     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
583         if *self.end() == usize::MAX {
584             slice_end_index_overflow_fail();
585         }
586         self.into_slice_range().index_mut(slice)
587     }
588 }
589
590 #[stable(feature = "inclusive_range", since = "1.26.0")]
591 #[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
592 unsafe impl<T> const SliceIndex<[T]> for ops::RangeToInclusive<usize> {
593     type Output = [T];
594
595     #[inline]
596     fn get(self, slice: &[T]) -> Option<&[T]> {
597         (0..=self.end).get(slice)
598     }
599
600     #[inline]
601     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
602         (0..=self.end).get_mut(slice)
603     }
604
605     #[inline]
606     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
607         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
608         unsafe { (0..=self.end).get_unchecked(slice) }
609     }
610
611     #[inline]
612     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
613         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
614         unsafe { (0..=self.end).get_unchecked_mut(slice) }
615     }
616
617     #[inline]
618     fn index(self, slice: &[T]) -> &[T] {
619         (0..=self.end).index(slice)
620     }
621
622     #[inline]
623     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
624         (0..=self.end).index_mut(slice)
625     }
626 }
627
628 /// Performs bounds-checking of a range.
629 ///
630 /// This method is similar to [`Index::index`] for slices, but it returns a
631 /// [`Range`] equivalent to `range`. You can use this method to turn any range
632 /// into `start` and `end` values.
633 ///
634 /// `bounds` is the range of the slice to use for bounds-checking. It should
635 /// be a [`RangeTo`] range that ends at the length of the slice.
636 ///
637 /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
638 /// [`slice::get_unchecked_mut`] for slices with the given range.
639 ///
640 /// [`Range`]: ops::Range
641 /// [`RangeTo`]: ops::RangeTo
642 /// [`slice::get_unchecked`]: slice::get_unchecked
643 /// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut
644 ///
645 /// # Panics
646 ///
647 /// Panics if `range` would be out of bounds.
648 ///
649 /// # Examples
650 ///
651 /// ```
652 /// #![feature(slice_range)]
653 ///
654 /// use std::slice;
655 ///
656 /// let v = [10, 40, 30];
657 /// assert_eq!(1..2, slice::range(1..2, ..v.len()));
658 /// assert_eq!(0..2, slice::range(..2, ..v.len()));
659 /// assert_eq!(1..3, slice::range(1.., ..v.len()));
660 /// ```
661 ///
662 /// Panics when [`Index::index`] would panic:
663 ///
664 /// ```should_panic
665 /// #![feature(slice_range)]
666 ///
667 /// use std::slice;
668 ///
669 /// let _ = slice::range(2..1, ..3);
670 /// ```
671 ///
672 /// ```should_panic
673 /// #![feature(slice_range)]
674 ///
675 /// use std::slice;
676 ///
677 /// let _ = slice::range(1..4, ..3);
678 /// ```
679 ///
680 /// ```should_panic
681 /// #![feature(slice_range)]
682 ///
683 /// use std::slice;
684 ///
685 /// let _ = slice::range(1..=usize::MAX, ..3);
686 /// ```
687 ///
688 /// [`Index::index`]: ops::Index::index
689 #[track_caller]
690 #[unstable(feature = "slice_range", issue = "76393")]
691 #[must_use]
692 pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
693 where
694     R: ops::RangeBounds<usize>,
695 {
696     let len = bounds.end;
697
698     let start: ops::Bound<&usize> = range.start_bound();
699     let start = match start {
700         ops::Bound::Included(&start) => start,
701         ops::Bound::Excluded(start) => {
702             start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
703         }
704         ops::Bound::Unbounded => 0,
705     };
706
707     let end: ops::Bound<&usize> = range.end_bound();
708     let end = match end {
709         ops::Bound::Included(end) => {
710             end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
711         }
712         ops::Bound::Excluded(&end) => end,
713         ops::Bound::Unbounded => len,
714     };
715
716     if start > end {
717         slice_index_order_fail(start, end);
718     }
719     if end > len {
720         slice_end_index_len_fail(end, len);
721     }
722
723     ops::Range { start, end }
724 }
725
726 /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
727 fn into_range_unchecked(
728     len: usize,
729     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
730 ) -> ops::Range<usize> {
731     use ops::Bound;
732     let start = match start {
733         Bound::Included(i) => i,
734         Bound::Excluded(i) => i + 1,
735         Bound::Unbounded => 0,
736     };
737     let end = match end {
738         Bound::Included(i) => i + 1,
739         Bound::Excluded(i) => i,
740         Bound::Unbounded => len,
741     };
742     start..end
743 }
744
745 /// Convert pair of `ops::Bound`s into `ops::Range`.
746 /// Returns `None` on overflowing indices.
747 fn into_range(
748     len: usize,
749     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
750 ) -> Option<ops::Range<usize>> {
751     use ops::Bound;
752     let start = match start {
753         Bound::Included(start) => start,
754         Bound::Excluded(start) => start.checked_add(1)?,
755         Bound::Unbounded => 0,
756     };
757
758     let end = match end {
759         Bound::Included(end) => end.checked_add(1)?,
760         Bound::Excluded(end) => end,
761         Bound::Unbounded => len,
762     };
763
764     // Don't bother with checking `start < end` and `end <= len`
765     // since these checks are handled by `Range` impls
766
767     Some(start..end)
768 }
769
770 /// Convert pair of `ops::Bound`s into `ops::Range`.
771 /// Panics on overflowing indices.
772 fn into_slice_range(
773     len: usize,
774     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
775 ) -> ops::Range<usize> {
776     use ops::Bound;
777     let start = match start {
778         Bound::Included(start) => start,
779         Bound::Excluded(start) => {
780             start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
781         }
782         Bound::Unbounded => 0,
783     };
784
785     let end = match end {
786         Bound::Included(end) => {
787             end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
788         }
789         Bound::Excluded(end) => end,
790         Bound::Unbounded => len,
791     };
792
793     // Don't bother with checking `start < end` and `end <= len`
794     // since these checks are handled by `Range` impls
795
796     start..end
797 }
798
799 #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
800 unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) {
801     type Output = [T];
802
803     #[inline]
804     fn get(self, slice: &[T]) -> Option<&Self::Output> {
805         into_range(slice.len(), self)?.get(slice)
806     }
807
808     #[inline]
809     fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
810         into_range(slice.len(), self)?.get_mut(slice)
811     }
812
813     #[inline]
814     unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
815         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
816         unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) }
817     }
818
819     #[inline]
820     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
821         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
822         unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) }
823     }
824
825     #[inline]
826     fn index(self, slice: &[T]) -> &Self::Output {
827         into_slice_range(slice.len(), self).index(slice)
828     }
829
830     #[inline]
831     fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
832         into_slice_range(slice.len(), self).index_mut(slice)
833     }
834 }