@@ -30,7 +30,7 @@ use crate::intrinsics::{assume, exact_div, is_aligned_and_not_null, unchecked_su
3030use crate :: iter:: * ;
3131use crate :: marker:: { self , Copy , Send , Sized , Sync } ;
3232use crate :: mem;
33- use crate :: ops:: { self , FnMut , Range } ;
33+ use crate :: ops:: { self , Bound , FnMut , Range , RangeBounds } ;
3434use crate :: option:: Option ;
3535use crate :: option:: Option :: { None , Some } ;
3636use crate :: ptr:: { self , NonNull } ;
@@ -350,6 +350,80 @@ impl<T> [T] {
350350 unsafe { & mut * index. get_unchecked_mut ( self ) }
351351 }
352352
353+ /// Converts a range over this slice to [`Range`].
354+ ///
355+ /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
356+ ///
357+ /// [`get_unchecked`]: #method.get_unchecked
358+ /// [`get_unchecked_mut`]: #method.get_unchecked_mut
359+ /// [`Range`]: ../ops/struct.Range.html
360+ ///
361+ /// # Panics
362+ ///
363+ /// Panics if the range is out of bounds.
364+ ///
365+ /// # Examples
366+ ///
367+ /// ```
368+ /// #![feature(slice_check_range)]
369+ ///
370+ /// let v = [10, 40, 30];
371+ /// assert_eq!(1..2, v.check_range(1..2));
372+ /// assert_eq!(0..2, v.check_range(..2));
373+ /// assert_eq!(1..3, v.check_range(1..));
374+ /// ```
375+ ///
376+ /// Panics when [`Index::index`] would panic:
377+ ///
378+ /// ```should_panic
379+ /// #![feature(slice_check_range)]
380+ ///
381+ /// [10, 40, 30].check_range(2..1);
382+ /// ```
383+ ///
384+ /// ```should_panic
385+ /// #![feature(slice_check_range)]
386+ ///
387+ /// [10, 40, 30].check_range(1..4);
388+ /// ```
389+ ///
390+ /// ```should_panic
391+ /// #![feature(slice_check_range)]
392+ ///
393+ /// [10, 40, 30].check_range(1..=usize::MAX);
394+ /// ```
395+ ///
396+ /// [`Index::index`]: ../ops/trait.Index.html#tymethod.index
397+ #[ track_caller]
398+ #[ unstable( feature = "slice_check_range" , issue = "none" ) ]
399+ pub fn check_range < R : RangeBounds < usize > > ( & self , range : R ) -> Range < usize > {
400+ let start = match range. start_bound ( ) {
401+ Bound :: Included ( & start) => start,
402+ Bound :: Excluded ( start) => {
403+ start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
404+ }
405+ Bound :: Unbounded => 0 ,
406+ } ;
407+
408+ let len = self . len ( ) ;
409+ let end = match range. end_bound ( ) {
410+ Bound :: Included ( end) => {
411+ end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
412+ }
413+ Bound :: Excluded ( & end) => end,
414+ Bound :: Unbounded => len,
415+ } ;
416+
417+ if start > end {
418+ slice_index_order_fail ( start, end) ;
419+ }
420+ if end > len {
421+ slice_end_index_len_fail ( end, len) ;
422+ }
423+
424+ Range { start, end }
425+ }
426+
353427 /// Returns a raw pointer to the slice's buffer.
354428 ///
355429 /// The caller must ensure that the slice outlives the pointer this
@@ -2445,13 +2519,13 @@ impl<T> [T] {
24452519 let src_start = match src. start_bound ( ) {
24462520 ops:: Bound :: Included ( & n) => n,
24472521 ops:: Bound :: Excluded ( & n) => {
2448- n. checked_add ( 1 ) . unwrap_or_else ( || slice_index_overflow_fail ( ) )
2522+ n. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
24492523 }
24502524 ops:: Bound :: Unbounded => 0 ,
24512525 } ;
24522526 let src_end = match src. end_bound ( ) {
24532527 ops:: Bound :: Included ( & n) => {
2454- n. checked_add ( 1 ) . unwrap_or_else ( || slice_index_overflow_fail ( ) )
2528+ n. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
24552529 }
24562530 ops:: Bound :: Excluded ( & n) => n,
24572531 ops:: Bound :: Unbounded => self . len ( ) ,
@@ -3034,7 +3108,14 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! {
30343108#[ inline( never) ]
30353109#[ cold]
30363110#[ track_caller]
3037- fn slice_index_overflow_fail ( ) -> ! {
3111+ fn slice_start_index_overflow_fail ( ) -> ! {
3112+ panic ! ( "attempted to index slice from after maximum usize" ) ;
3113+ }
3114+
3115+ #[ inline( never) ]
3116+ #[ cold]
3117+ #[ track_caller]
3118+ fn slice_end_index_overflow_fail ( ) -> ! {
30383119 panic ! ( "attempted to index slice up to maximum usize" ) ;
30393120}
30403121
@@ -3370,15 +3451,15 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
33703451 #[ inline]
33713452 fn index ( self , slice : & [ T ] ) -> & [ T ] {
33723453 if * self . end ( ) == usize:: MAX {
3373- slice_index_overflow_fail ( ) ;
3454+ slice_end_index_overflow_fail ( ) ;
33743455 }
33753456 ( * self . start ( ) ..self . end ( ) + 1 ) . index ( slice)
33763457 }
33773458
33783459 #[ inline]
33793460 fn index_mut ( self , slice : & mut [ T ] ) -> & mut [ T ] {
33803461 if * self . end ( ) == usize:: MAX {
3381- slice_index_overflow_fail ( ) ;
3462+ slice_end_index_overflow_fail ( ) ;
33823463 }
33833464 ( * self . start ( ) ..self . end ( ) + 1 ) . index_mut ( slice)
33843465 }
0 commit comments