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