]> git.lizzy.rs Git - rust.git/blob - library/core/src/slice/index.rs
Bump slice_index_with_ops_bound_pair to 1.53.0
[rust.git] / library / core / src / slice / index.rs
1 //! Indexing implementations for `[T]`.
2
3 use crate::ops;
4 use crate::ptr;
5
6 #[stable(feature = "rust1", since = "1.0.0")]
7 impl<T, I> ops::Index<I> for [T]
8 where
9     I: SliceIndex<[T]>,
10 {
11     type Output = I::Output;
12
13     #[inline]
14     fn index(&self, index: I) -> &I::Output {
15         index.index(self)
16     }
17 }
18
19 #[stable(feature = "rust1", since = "1.0.0")]
20 impl<T, I> ops::IndexMut<I> for [T]
21 where
22     I: SliceIndex<[T]>,
23 {
24     #[inline]
25     fn index_mut(&mut self, index: I) -> &mut I::Output {
26         index.index_mut(self)
27     }
28 }
29
30 #[inline(never)]
31 #[cold]
32 #[track_caller]
33 fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
34     panic!("range start index {} out of range for slice of length {}", index, len);
35 }
36
37 #[inline(never)]
38 #[cold]
39 #[track_caller]
40 fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
41     panic!("range end index {} out of range for slice of length {}", index, len);
42 }
43
44 #[inline(never)]
45 #[cold]
46 #[track_caller]
47 fn slice_index_order_fail(index: usize, end: usize) -> ! {
48     panic!("slice index starts at {} but ends at {}", index, end);
49 }
50
51 #[inline(never)]
52 #[cold]
53 #[track_caller]
54 fn slice_start_index_overflow_fail() -> ! {
55     panic!("attempted to index slice from after maximum usize");
56 }
57
58 #[inline(never)]
59 #[cold]
60 #[track_caller]
61 fn slice_end_index_overflow_fail() -> ! {
62     panic!("attempted to index slice up to maximum usize");
63 }
64
65 mod private_slice_index {
66     use super::ops;
67     #[stable(feature = "slice_get_slice", since = "1.28.0")]
68     pub trait Sealed {}
69
70     #[stable(feature = "slice_get_slice", since = "1.28.0")]
71     impl Sealed for usize {}
72     #[stable(feature = "slice_get_slice", since = "1.28.0")]
73     impl Sealed for ops::Range<usize> {}
74     #[stable(feature = "slice_get_slice", since = "1.28.0")]
75     impl Sealed for ops::RangeTo<usize> {}
76     #[stable(feature = "slice_get_slice", since = "1.28.0")]
77     impl Sealed for ops::RangeFrom<usize> {}
78     #[stable(feature = "slice_get_slice", since = "1.28.0")]
79     impl Sealed for ops::RangeFull {}
80     #[stable(feature = "slice_get_slice", since = "1.28.0")]
81     impl Sealed for ops::RangeInclusive<usize> {}
82     #[stable(feature = "slice_get_slice", since = "1.28.0")]
83     impl Sealed for ops::RangeToInclusive<usize> {}
84     #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
85     impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
86 }
87
88 /// A helper trait used for indexing operations.
89 ///
90 /// Implementations of this trait have to promise that if the argument
91 /// to `get_(mut_)unchecked` is a safe reference, then so is the result.
92 #[stable(feature = "slice_get_slice", since = "1.28.0")]
93 #[rustc_on_unimplemented(
94     on(T = "str", label = "string indices are ranges of `usize`",),
95     on(
96         all(any(T = "str", T = "&str", T = "std::string::String"), _Self = "{integer}"),
97         note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
98                 for more information, see chapter 8 in The Book: \
99                 <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
100     ),
101     message = "the type `{T}` cannot be indexed by `{Self}`",
102     label = "slice indices are of type `usize` or ranges of `usize`"
103 )]
104 pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
105     /// The output type returned by methods.
106     #[stable(feature = "slice_get_slice", since = "1.28.0")]
107     type Output: ?Sized;
108
109     /// Returns a shared reference to the output at this location, if in
110     /// bounds.
111     #[unstable(feature = "slice_index_methods", issue = "none")]
112     fn get(self, slice: &T) -> Option<&Self::Output>;
113
114     /// Returns a mutable reference to the output at this location, if in
115     /// bounds.
116     #[unstable(feature = "slice_index_methods", issue = "none")]
117     fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
118
119     /// Returns a shared reference to the output at this location, without
120     /// performing any bounds checking.
121     /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
122     /// is *[undefined behavior]* even if the resulting reference is not used.
123     ///
124     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
125     #[unstable(feature = "slice_index_methods", issue = "none")]
126     unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
127
128     /// Returns a mutable reference to the output at this location, without
129     /// performing any bounds checking.
130     /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
131     /// is *[undefined behavior]* even if the resulting reference is not used.
132     ///
133     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
134     #[unstable(feature = "slice_index_methods", issue = "none")]
135     unsafe fn get_unchecked_mut(self, slice: *mut T) -> *mut Self::Output;
136
137     /// Returns a shared reference to the output at this location, panicking
138     /// if out of bounds.
139     #[unstable(feature = "slice_index_methods", issue = "none")]
140     #[track_caller]
141     fn index(self, slice: &T) -> &Self::Output;
142
143     /// Returns a mutable reference to the output at this location, panicking
144     /// if out of bounds.
145     #[unstable(feature = "slice_index_methods", issue = "none")]
146     #[track_caller]
147     fn index_mut(self, slice: &mut T) -> &mut Self::Output;
148 }
149
150 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
151 unsafe impl<T> SliceIndex<[T]> for usize {
152     type Output = T;
153
154     #[inline]
155     fn get(self, slice: &[T]) -> Option<&T> {
156         // SAFETY: `self` is checked to be in bounds.
157         if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None }
158     }
159
160     #[inline]
161     fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
162         // SAFETY: `self` is checked to be in bounds.
163         if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None }
164     }
165
166     #[inline]
167     unsafe fn get_unchecked(self, slice: *const [T]) -> *const T {
168         // SAFETY: the caller guarantees that `slice` is not dangling, so it
169         // cannot be longer than `isize::MAX`. They also guarantee that
170         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
171         // so the call to `add` is safe.
172         unsafe { slice.as_ptr().add(self) }
173     }
174
175     #[inline]
176     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut T {
177         // SAFETY: see comments for `get_unchecked` above.
178         unsafe { slice.as_mut_ptr().add(self) }
179     }
180
181     #[inline]
182     fn index(self, slice: &[T]) -> &T {
183         // N.B., use intrinsic indexing
184         &(*slice)[self]
185     }
186
187     #[inline]
188     fn index_mut(self, slice: &mut [T]) -> &mut T {
189         // N.B., use intrinsic indexing
190         &mut (*slice)[self]
191     }
192 }
193
194 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
195 unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
196     type Output = [T];
197
198     #[inline]
199     fn get(self, slice: &[T]) -> Option<&[T]> {
200         if self.start > self.end || self.end > slice.len() {
201             None
202         } else {
203             // SAFETY: `self` is checked to be valid and in bounds above.
204             unsafe { Some(&*self.get_unchecked(slice)) }
205         }
206     }
207
208     #[inline]
209     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
210         if self.start > self.end || self.end > slice.len() {
211             None
212         } else {
213             // SAFETY: `self` is checked to be valid and in bounds above.
214             unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
215         }
216     }
217
218     #[inline]
219     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
220         // SAFETY: the caller guarantees that `slice` is not dangling, so it
221         // cannot be longer than `isize::MAX`. They also guarantee that
222         // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
223         // so the call to `add` is safe.
224         unsafe { ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start) }
225     }
226
227     #[inline]
228     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
229         // SAFETY: see comments for `get_unchecked` above.
230         unsafe {
231             ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
232         }
233     }
234
235     #[inline]
236     fn index(self, slice: &[T]) -> &[T] {
237         if self.start > self.end {
238             slice_index_order_fail(self.start, self.end);
239         } else if self.end > slice.len() {
240             slice_end_index_len_fail(self.end, slice.len());
241         }
242         // SAFETY: `self` is checked to be valid and in bounds above.
243         unsafe { &*self.get_unchecked(slice) }
244     }
245
246     #[inline]
247     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
248         if self.start > self.end {
249             slice_index_order_fail(self.start, self.end);
250         } else if self.end > slice.len() {
251             slice_end_index_len_fail(self.end, slice.len());
252         }
253         // SAFETY: `self` is checked to be valid and in bounds above.
254         unsafe { &mut *self.get_unchecked_mut(slice) }
255     }
256 }
257
258 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
259 unsafe impl<T> SliceIndex<[T]> for ops::RangeTo<usize> {
260     type Output = [T];
261
262     #[inline]
263     fn get(self, slice: &[T]) -> Option<&[T]> {
264         (0..self.end).get(slice)
265     }
266
267     #[inline]
268     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
269         (0..self.end).get_mut(slice)
270     }
271
272     #[inline]
273     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
274         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
275         unsafe { (0..self.end).get_unchecked(slice) }
276     }
277
278     #[inline]
279     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
280         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
281         unsafe { (0..self.end).get_unchecked_mut(slice) }
282     }
283
284     #[inline]
285     fn index(self, slice: &[T]) -> &[T] {
286         (0..self.end).index(slice)
287     }
288
289     #[inline]
290     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
291         (0..self.end).index_mut(slice)
292     }
293 }
294
295 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
296 unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
297     type Output = [T];
298
299     #[inline]
300     fn get(self, slice: &[T]) -> Option<&[T]> {
301         (self.start..slice.len()).get(slice)
302     }
303
304     #[inline]
305     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
306         (self.start..slice.len()).get_mut(slice)
307     }
308
309     #[inline]
310     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
311         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
312         unsafe { (self.start..slice.len()).get_unchecked(slice) }
313     }
314
315     #[inline]
316     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
317         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
318         unsafe { (self.start..slice.len()).get_unchecked_mut(slice) }
319     }
320
321     #[inline]
322     fn index(self, slice: &[T]) -> &[T] {
323         if self.start > slice.len() {
324             slice_start_index_len_fail(self.start, slice.len());
325         }
326         // SAFETY: `self` is checked to be valid and in bounds above.
327         unsafe { &*self.get_unchecked(slice) }
328     }
329
330     #[inline]
331     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
332         if self.start > slice.len() {
333             slice_start_index_len_fail(self.start, slice.len());
334         }
335         // SAFETY: `self` is checked to be valid and in bounds above.
336         unsafe { &mut *self.get_unchecked_mut(slice) }
337     }
338 }
339
340 #[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
341 unsafe impl<T> SliceIndex<[T]> for ops::RangeFull {
342     type Output = [T];
343
344     #[inline]
345     fn get(self, slice: &[T]) -> Option<&[T]> {
346         Some(slice)
347     }
348
349     #[inline]
350     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
351         Some(slice)
352     }
353
354     #[inline]
355     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
356         slice
357     }
358
359     #[inline]
360     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
361         slice
362     }
363
364     #[inline]
365     fn index(self, slice: &[T]) -> &[T] {
366         slice
367     }
368
369     #[inline]
370     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
371         slice
372     }
373 }
374
375 #[stable(feature = "inclusive_range", since = "1.26.0")]
376 unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
377     type Output = [T];
378
379     #[inline]
380     fn get(self, slice: &[T]) -> Option<&[T]> {
381         if *self.end() == usize::MAX { None } else { self.into_slice_range().get(slice) }
382     }
383
384     #[inline]
385     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
386         if *self.end() == usize::MAX { None } else { self.into_slice_range().get_mut(slice) }
387     }
388
389     #[inline]
390     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
391         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
392         unsafe { self.into_slice_range().get_unchecked(slice) }
393     }
394
395     #[inline]
396     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
397         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
398         unsafe { self.into_slice_range().get_unchecked_mut(slice) }
399     }
400
401     #[inline]
402     fn index(self, slice: &[T]) -> &[T] {
403         if *self.end() == usize::MAX {
404             slice_end_index_overflow_fail();
405         }
406         self.into_slice_range().index(slice)
407     }
408
409     #[inline]
410     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
411         if *self.end() == usize::MAX {
412             slice_end_index_overflow_fail();
413         }
414         self.into_slice_range().index_mut(slice)
415     }
416 }
417
418 #[stable(feature = "inclusive_range", since = "1.26.0")]
419 unsafe impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
420     type Output = [T];
421
422     #[inline]
423     fn get(self, slice: &[T]) -> Option<&[T]> {
424         (0..=self.end).get(slice)
425     }
426
427     #[inline]
428     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
429         (0..=self.end).get_mut(slice)
430     }
431
432     #[inline]
433     unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
434         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
435         unsafe { (0..=self.end).get_unchecked(slice) }
436     }
437
438     #[inline]
439     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
440         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
441         unsafe { (0..=self.end).get_unchecked_mut(slice) }
442     }
443
444     #[inline]
445     fn index(self, slice: &[T]) -> &[T] {
446         (0..=self.end).index(slice)
447     }
448
449     #[inline]
450     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
451         (0..=self.end).index_mut(slice)
452     }
453 }
454
455 /// Performs bounds-checking of a range.
456 ///
457 /// This method is similar to [`Index::index`] for slices, but it returns a
458 /// [`Range`] equivalent to `range`. You can use this method to turn any range
459 /// into `start` and `end` values.
460 ///
461 /// `bounds` is the range of the slice to use for bounds-checking. It should
462 /// be a [`RangeTo`] range that ends at the length of the slice.
463 ///
464 /// The returned [`Range`] is safe to pass to [`slice::get_unchecked`] and
465 /// [`slice::get_unchecked_mut`] for slices with the given range.
466 ///
467 /// [`Range`]: ops::Range
468 /// [`RangeTo`]: ops::RangeTo
469 /// [`slice::get_unchecked`]: slice::get_unchecked
470 /// [`slice::get_unchecked_mut`]: slice::get_unchecked_mut
471 ///
472 /// # Panics
473 ///
474 /// Panics if `range` would be out of bounds.
475 ///
476 /// # Examples
477 ///
478 /// ```
479 /// #![feature(slice_range)]
480 ///
481 /// use std::slice;
482 ///
483 /// let v = [10, 40, 30];
484 /// assert_eq!(1..2, slice::range(1..2, ..v.len()));
485 /// assert_eq!(0..2, slice::range(..2, ..v.len()));
486 /// assert_eq!(1..3, slice::range(1.., ..v.len()));
487 /// ```
488 ///
489 /// Panics when [`Index::index`] would panic:
490 ///
491 /// ```should_panic
492 /// #![feature(slice_range)]
493 ///
494 /// use std::slice;
495 ///
496 /// slice::range(2..1, ..3);
497 /// ```
498 ///
499 /// ```should_panic
500 /// #![feature(slice_range)]
501 ///
502 /// use std::slice;
503 ///
504 /// slice::range(1..4, ..3);
505 /// ```
506 ///
507 /// ```should_panic
508 /// #![feature(slice_range)]
509 ///
510 /// use std::slice;
511 ///
512 /// slice::range(1..=usize::MAX, ..3);
513 /// ```
514 ///
515 /// [`Index::index`]: ops::Index::index
516 #[track_caller]
517 #[unstable(feature = "slice_range", issue = "76393")]
518 pub fn range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
519 where
520     R: ops::RangeBounds<usize>,
521 {
522     let len = bounds.end;
523
524     let start: ops::Bound<&usize> = range.start_bound();
525     let start = match start {
526         ops::Bound::Included(&start) => start,
527         ops::Bound::Excluded(start) => {
528             start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
529         }
530         ops::Bound::Unbounded => 0,
531     };
532
533     let end: ops::Bound<&usize> = range.end_bound();
534     let end = match end {
535         ops::Bound::Included(end) => {
536             end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
537         }
538         ops::Bound::Excluded(&end) => end,
539         ops::Bound::Unbounded => len,
540     };
541
542     if start > end {
543         slice_index_order_fail(start, end);
544     }
545     if end > len {
546         slice_end_index_len_fail(end, len);
547     }
548
549     ops::Range { start, end }
550 }
551
552 /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
553 fn into_range_unchecked(
554     len: usize,
555     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
556 ) -> ops::Range<usize> {
557     use ops::Bound;
558     let start = match start {
559         Bound::Included(i) => i,
560         Bound::Excluded(i) => i + 1,
561         Bound::Unbounded => 0,
562     };
563     let end = match end {
564         Bound::Included(i) => i + 1,
565         Bound::Excluded(i) => i,
566         Bound::Unbounded => len,
567     };
568     start..end
569 }
570
571 /// Convert pair of `ops::Bound`s into `ops::Range`.
572 /// Returns `None` on overflowing indices.
573 fn into_range(
574     len: usize,
575     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
576 ) -> Option<ops::Range<usize>> {
577     use ops::Bound;
578     let start = match start {
579         Bound::Included(start) => start,
580         Bound::Excluded(start) => start.checked_add(1)?,
581         Bound::Unbounded => 0,
582     };
583
584     let end = match end {
585         Bound::Included(end) => end.checked_add(1)?,
586         Bound::Excluded(end) => end,
587         Bound::Unbounded => len,
588     };
589
590     // Don't bother with checking `start < end` and `end <= len`
591     // since these checks are handled by `Range` impls
592
593     Some(start..end)
594 }
595
596 /// Convert pair of `ops::Bound`s into `ops::Range`.
597 /// Panics on overflowing indices.
598 fn into_slice_range(
599     len: usize,
600     (start, end): (ops::Bound<usize>, ops::Bound<usize>),
601 ) -> ops::Range<usize> {
602     use ops::Bound;
603     let start = match start {
604         Bound::Included(start) => start,
605         Bound::Excluded(start) => {
606             start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
607         }
608         Bound::Unbounded => 0,
609     };
610
611     let end = match end {
612         Bound::Included(end) => {
613             end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
614         }
615         Bound::Excluded(end) => end,
616         Bound::Unbounded => len,
617     };
618
619     // Don't bother with checking `start < end` and `end <= len`
620     // since these checks are handled by `Range` impls
621
622     start..end
623 }
624
625 #[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
626 unsafe impl<T> SliceIndex<[T]> for (ops::Bound<usize>, ops::Bound<usize>) {
627     type Output = [T];
628
629     #[inline]
630     fn get(self, slice: &[T]) -> Option<&Self::Output> {
631         into_range(slice.len(), self)?.get(slice)
632     }
633
634     #[inline]
635     fn get_mut(self, slice: &mut [T]) -> Option<&mut Self::Output> {
636         into_range(slice.len(), self)?.get_mut(slice)
637     }
638
639     #[inline]
640     unsafe fn get_unchecked(self, slice: *const [T]) -> *const Self::Output {
641         // SAFETY: the caller has to uphold the safety contract for `get_unchecked`.
642         unsafe { into_range_unchecked(slice.len(), self).get_unchecked(slice) }
643     }
644
645     #[inline]
646     unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut Self::Output {
647         // SAFETY: the caller has to uphold the safety contract for `get_unchecked_mut`.
648         unsafe { into_range_unchecked(slice.len(), self).get_unchecked_mut(slice) }
649     }
650
651     #[inline]
652     fn index(self, slice: &[T]) -> &Self::Output {
653         into_slice_range(slice.len(), self).index(slice)
654     }
655
656     #[inline]
657     fn index_mut(self, slice: &mut [T]) -> &mut Self::Output {
658         into_slice_range(slice.len(), self).index_mut(slice)
659     }
660 }