@@ -34,53 +34,44 @@ where
3434#[ cfg_attr( not( feature = "panic_immediate_abort" ) ,  inline( never) ,  cold) ]  
3535#[ cfg_attr( feature = "panic_immediate_abort" ,  inline) ]  
3636#[ track_caller]  
37- const  fn  slice_start_index_len_fail ( index :  usize ,  len :  usize )  -> ! { 
38-     const_panic ! ( 
39-         "slice start index is out of range for slice" , 
40-         "range start index {index} out of range for slice of length {len}" , 
41-         index:  usize , 
42-         len:  usize , 
43-     ) 
44- } 
37+ const  fn  slice_index_fail ( start :  usize ,  end :  usize ,  len :  usize )  -> ! { 
38+     if  start > len { 
39+         const_panic ! ( 
40+             "slice start index is out of range for slice" , 
41+             "range start index {start} out of range for slice of length {len}" , 
42+             start:  usize , 
43+             len:  usize , 
44+         ) 
45+     } 
4546
46- #[ cfg_attr( not( feature = "panic_immediate_abort" ) ,  inline( never) ,  cold) ]  
47- #[ cfg_attr( feature = "panic_immediate_abort" ,  inline) ]  
48- #[ track_caller]  
49- const  fn  slice_end_index_len_fail ( index :  usize ,  len :  usize )  -> ! { 
50-     const_panic ! ( 
51-         "slice end index is out of range for slice" , 
52-         "range end index {index} out of range for slice of length {len}" , 
53-         index:  usize , 
54-         len:  usize , 
55-     ) 
56- } 
47+     if  end > len { 
48+         const_panic ! ( 
49+             "slice end index is out of range for slice" , 
50+             "range end index {end} out of range for slice of length {len}" , 
51+             end:  usize , 
52+             len:  usize , 
53+         ) 
54+     } 
5755
58- #[ cfg_attr( not( feature = "panic_immediate_abort" ) ,  inline( never) ,  cold) ]  
59- #[ cfg_attr( feature = "panic_immediate_abort" ,  inline) ]  
60- #[ track_caller]  
61- const  fn  slice_index_order_fail ( index :  usize ,  end :  usize )  -> ! { 
56+     if  start > end { 
57+         const_panic ! ( 
58+             "slice index start is larger than end" , 
59+             "slice index starts at {start} but ends at {end}" , 
60+             start:  usize , 
61+             end:  usize , 
62+         ) 
63+     } 
64+ 
65+     // Only reachable if the range was a `RangeInclusive` or a 
66+     // `RangeToInclusive`, with `end == len`. 
6267    const_panic ! ( 
63-         "slice index start is larger than end" , 
64-         "slice index starts at {index} but ends at {end}" , 
65-         index:  usize , 
68+         "slice end index is out of range for slice" , 
69+         "range end index {end} out of range for slice of length {len}" , 
6670        end:  usize , 
71+         len:  usize , 
6772    ) 
6873} 
6974
70- #[ cfg_attr( not( feature = "panic_immediate_abort" ) ,  inline( never) ,  cold) ]  
71- #[ cfg_attr( feature = "panic_immediate_abort" ,  inline) ]  
72- #[ track_caller]  
73- const  fn  slice_start_index_overflow_fail ( )  -> ! { 
74-     panic ! ( "attempted to index slice from after maximum usize" ) ; 
75- } 
76- 
77- #[ cfg_attr( not( feature = "panic_immediate_abort" ) ,  inline( never) ,  cold) ]  
78- #[ cfg_attr( feature = "panic_immediate_abort" ,  inline) ]  
79- #[ track_caller]  
80- const  fn  slice_end_index_overflow_fail ( )  -> ! { 
81-     panic ! ( "attempted to index slice up to maximum usize" ) ; 
82- } 
83- 
8475// The UbChecks are great for catching bugs in the unsafe methods, but including 
8576// them in safe indexing is unnecessary and hurts inlining and debug runtime perf. 
8677// Both the safe and unsafe public methods share these helpers, 
@@ -341,7 +332,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
341332            // SAFETY: `self` is checked to be valid and in bounds above. 
342333            unsafe  {  & * get_offset_len_noubcheck ( slice,  self . start ( ) ,  self . len ( ) )  } 
343334        }  else  { 
344-             slice_end_index_len_fail ( self . end ( ) ,  slice. len ( ) ) 
335+             slice_index_fail ( self . start ( ) ,   self . end ( ) ,  slice. len ( ) ) 
345336        } 
346337    } 
347338
@@ -351,7 +342,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
351342            // SAFETY: `self` is checked to be valid and in bounds above. 
352343            unsafe  {  & mut  * get_offset_len_mut_noubcheck ( slice,  self . start ( ) ,  self . len ( ) )  } 
353344        }  else  { 
354-             slice_end_index_len_fail ( self . end ( ) ,  slice. len ( ) ) 
345+             slice_index_fail ( self . start ( ) ,   self . end ( ) ,  slice. len ( ) ) 
355346        } 
356347    } 
357348} 
@@ -436,26 +427,27 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
436427    #[ inline( always) ]  
437428    fn  index ( self ,  slice :  & [ T ] )  -> & [ T ]  { 
438429        // Using checked_sub is a safe way to get `SubUnchecked` in MIR 
439-         let  Some ( new_len)  = usize:: checked_sub ( self . end ,  self . start )  else  { 
440-             slice_index_order_fail ( self . start ,  self . end ) 
441-         } ; 
442-         if  self . end  > slice. len ( )  { 
443-             slice_end_index_len_fail ( self . end ,  slice. len ( ) ) ; 
430+         if  let  Some ( new_len)  = usize:: checked_sub ( self . end ,  self . start ) 
431+             && self . end  <= slice. len ( ) 
432+         { 
433+             // SAFETY: `self` is checked to be valid and in bounds above. 
434+             unsafe  {  & * get_offset_len_noubcheck ( slice,  self . start ,  new_len)  } 
435+         }  else  { 
436+             slice_index_fail ( self . start ,  self . end ,  slice. len ( ) ) 
444437        } 
445-         // SAFETY: `self` is checked to be valid and in bounds above. 
446-         unsafe  {  & * get_offset_len_noubcheck ( slice,  self . start ,  new_len)  } 
447438    } 
448439
449440    #[ inline]  
450441    fn  index_mut ( self ,  slice :  & mut  [ T ] )  -> & mut  [ T ]  { 
451-         let  Some ( new_len)  = usize:: checked_sub ( self . end ,  self . start )  else  { 
452-             slice_index_order_fail ( self . start ,  self . end ) 
453-         } ; 
454-         if  self . end  > slice. len ( )  { 
455-             slice_end_index_len_fail ( self . end ,  slice. len ( ) ) ; 
442+         // Using checked_sub is a safe way to get `SubUnchecked` in MIR 
443+         if  let  Some ( new_len)  = usize:: checked_sub ( self . end ,  self . start ) 
444+             && self . end  <= slice. len ( ) 
445+         { 
446+             // SAFETY: `self` is checked to be valid and in bounds above. 
447+             unsafe  {  & mut  * get_offset_len_mut_noubcheck ( slice,  self . start ,  new_len)  } 
448+         }  else  { 
449+             slice_index_fail ( self . start ,  self . end ,  slice. len ( ) ) 
456450        } 
457-         // SAFETY: `self` is checked to be valid and in bounds above. 
458-         unsafe  {  & mut  * get_offset_len_mut_noubcheck ( slice,  self . start ,  new_len)  } 
459451    } 
460452} 
461453
@@ -567,7 +559,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
567559    #[ inline]  
568560    fn  index ( self ,  slice :  & [ T ] )  -> & [ T ]  { 
569561        if  self . start  > slice. len ( )  { 
570-             slice_start_index_len_fail ( self . start ,  slice. len ( ) ) ; 
562+             slice_index_fail ( self . start ,  slice. len ( ) ,  slice . len ( ) ) 
571563        } 
572564        // SAFETY: `self` is checked to be valid and in bounds above. 
573565        unsafe  {  & * self . get_unchecked ( slice)  } 
@@ -576,7 +568,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
576568    #[ inline]  
577569    fn  index_mut ( self ,  slice :  & mut  [ T ] )  -> & mut  [ T ]  { 
578570        if  self . start  > slice. len ( )  { 
579-             slice_start_index_len_fail ( self . start ,  slice. len ( ) ) ; 
571+             slice_index_fail ( self . start ,  slice. len ( ) ,  slice . len ( ) ) 
580572        } 
581573        // SAFETY: `self` is checked to be valid and in bounds above. 
582574        unsafe  {  & mut  * self . get_unchecked_mut ( slice)  } 
@@ -690,16 +682,16 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
690682
691683    #[ inline]  
692684    fn  index ( self ,  slice :  & [ T ] )  -> & [ T ]  { 
693-         if  * self . end ( )  == usize :: MAX  { 
694-             slice_end_index_overflow_fail ( ) ; 
685+         if  * self . end ( )  >= slice . len ( )  { 
686+             slice_index_fail ( self . start ,   self . end ,  slice . len ( ) ) 
695687        } 
696688        self . into_slice_range ( ) . index ( slice) 
697689    } 
698690
699691    #[ inline]  
700692    fn  index_mut ( self ,  slice :  & mut  [ T ] )  -> & mut  [ T ]  { 
701-         if  * self . end ( )  == usize :: MAX  { 
702-             slice_end_index_overflow_fail ( ) ; 
693+         if  * self . end ( )  >= slice . len ( )  { 
694+             slice_index_fail ( self . start ,   self . end ,  slice . len ( ) ) 
703695        } 
704696        self . into_slice_range ( ) . index_mut ( slice) 
705697    } 
@@ -852,28 +844,26 @@ where
852844{ 
853845    let  len = bounds. end ; 
854846
855-     let  start = match  range. start_bound ( )  { 
856-         ops:: Bound :: Included ( & start)  => start, 
857-         ops:: Bound :: Excluded ( start)  => { 
858-             start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) ) 
859-         } 
860-         ops:: Bound :: Unbounded  => 0 , 
861-     } ; 
862- 
863847    let  end = match  range. end_bound ( )  { 
864-         ops:: Bound :: Included ( end)  => { 
865-             end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) ) 
866-         } 
848+         ops:: Bound :: Included ( & end)  if  end >= len => slice_index_fail ( 0 ,  end,  len) , 
849+         // Cannot overflow because `end < len` implies `end < usize::MAX`. 
850+         ops:: Bound :: Included ( & end)  => end + 1 , 
851+ 
852+         ops:: Bound :: Excluded ( & end)  if  end > len => slice_index_fail ( 0 ,  end,  len) , 
867853        ops:: Bound :: Excluded ( & end)  => end, 
868854        ops:: Bound :: Unbounded  => len, 
869855    } ; 
870856
871-     if  start > end { 
872-         slice_index_order_fail ( start,  end) ; 
873-     } 
874-     if  end > len { 
875-         slice_end_index_len_fail ( end,  len) ; 
876-     } 
857+     let  start = match  range. start_bound ( )  { 
858+         ops:: Bound :: Excluded ( & start)  if  start >= end => slice_index_fail ( start,  end,  len) , 
859+         // Cannot overflow because `start < end` implies `start < usize::MAX`. 
860+         ops:: Bound :: Excluded ( & start)  => start + 1 , 
861+ 
862+         ops:: Bound :: Included ( & start)  if  start > end => slice_index_fail ( start,  end,  len) , 
863+         ops:: Bound :: Included ( & start)  => start, 
864+ 
865+         ops:: Bound :: Unbounded  => 0 , 
866+     } ; 
877867
878868    ops:: Range  {  start,  end } 
879869} 
@@ -982,25 +972,27 @@ pub(crate) fn into_slice_range(
982972    len :  usize , 
983973    ( start,  end) :  ( ops:: Bound < usize > ,  ops:: Bound < usize > ) , 
984974)  -> ops:: Range < usize >  { 
985-     use  ops:: Bound ; 
986-     let  start = match  start { 
987-         Bound :: Included ( start)  => start, 
988-         Bound :: Excluded ( start)  => { 
989-             start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) ) 
990-         } 
991-         Bound :: Unbounded  => 0 , 
992-     } ; 
993- 
994975    let  end = match  end { 
995-         Bound :: Included ( end)  => { 
996-             end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) ) 
997-         } 
998-         Bound :: Excluded ( end)  => end, 
999-         Bound :: Unbounded  => len, 
976+         ops:: Bound :: Included ( end)  if  end >= len => slice_index_fail ( 0 ,  end,  len) , 
977+         // Cannot overflow because `end < len` implies `end < usize::MAX`. 
978+         ops:: Bound :: Included ( end)  => end + 1 , 
979+ 
980+         ops:: Bound :: Excluded ( end)  if  end > len => slice_index_fail ( 0 ,  end,  len) , 
981+         ops:: Bound :: Excluded ( end)  => end, 
982+ 
983+         ops:: Bound :: Unbounded  => len, 
1000984    } ; 
1001985
1002-     // Don't bother with checking `start < end` and `end <= len` 
1003-     // since these checks are handled by `Range` impls 
986+     let  start = match  start { 
987+         ops:: Bound :: Excluded ( start)  if  start >= end => slice_index_fail ( start,  end,  len) , 
988+         // Cannot overflow because `start < end` implies `start < usize::MAX`. 
989+         ops:: Bound :: Excluded ( start)  => start + 1 , 
990+ 
991+         ops:: Bound :: Included ( start)  if  start > end => slice_index_fail ( start,  end,  len) , 
992+         ops:: Bound :: Included ( start)  => start, 
993+ 
994+         ops:: Bound :: Unbounded  => 0 , 
995+     } ; 
1004996
1005997    start..end
1006998} 
0 commit comments