@@ -67,20 +67,6 @@ const fn slice_index_order_fail(index: usize, end: usize) -> ! {
6767 )
6868}
6969
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-
8470// The UbChecks are great for catching bugs in the unsafe methods, but including
8571// them in safe indexing is unnecessary and hurts inlining and debug runtime perf.
8672// Both the safe and unsafe public methods share these helpers,
@@ -658,7 +644,6 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFull {
658644}
659645
660646/// The methods `index` and `index_mut` panic if:
661- /// - the end of the range is `usize::MAX` or
662647/// - the start of the range is greater than the end of the range or
663648/// - the end of the range is out of bounds.
664649#[ stable( feature = "inclusive_range" , since = "1.26.0" ) ]
@@ -668,12 +653,14 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
668653
669654 #[ inline]
670655 fn get ( self , slice : & [ T ] ) -> Option < & [ T ] > {
671- if * self . end ( ) == usize:: MAX { None } else { self . into_slice_range ( ) . get ( slice) }
656+ // `self.into_slice_range()` cannot overflow, because `*self.end() <
657+ // slice.len()` implies `*self.end() < usize::MAX`.
658+ if * self . end ( ) >= slice. len ( ) { None } else { self . into_slice_range ( ) . get ( slice) }
672659 }
673660
674661 #[ inline]
675662 fn get_mut ( self , slice : & mut [ T ] ) -> Option < & mut [ T ] > {
676- if * self . end ( ) == usize :: MAX { None } else { self . into_slice_range ( ) . get_mut ( slice) }
663+ if * self . end ( ) >= slice . len ( ) { None } else { self . into_slice_range ( ) . get_mut ( slice) }
677664 }
678665
679666 #[ inline]
@@ -690,16 +677,16 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
690677
691678 #[ inline]
692679 fn index ( self , slice : & [ T ] ) -> & [ T ] {
693- if * self . end ( ) == usize :: MAX {
694- slice_end_index_overflow_fail ( ) ;
680+ if * self . end ( ) >= slice . len ( ) {
681+ slice_end_index_len_fail ( * self . end ( ) , slice . len ( ) ) ;
695682 }
696683 self . into_slice_range ( ) . index ( slice)
697684 }
698685
699686 #[ inline]
700687 fn index_mut ( self , slice : & mut [ T ] ) -> & mut [ T ] {
701- if * self . end ( ) == usize :: MAX {
702- slice_end_index_overflow_fail ( ) ;
688+ if * self . end ( ) >= slice . len ( ) {
689+ slice_end_index_len_fail ( * self . end ( ) , slice . len ( ) ) ;
703690 }
704691 self . into_slice_range ( ) . index_mut ( slice)
705692 }
@@ -852,28 +839,27 @@ where
852839{
853840 let len = bounds. end ;
854841
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-
863842 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- }
843+ ops:: Bound :: Included ( & end) if end >= len => slice_end_index_len_fail ( end, len) ,
844+ // Cannot overflow because `end < len` implies `end < usize::MAX`.
845+ ops:: Bound :: Included ( & end) => end + 1 ,
846+
847+ ops:: Bound :: Excluded ( & end) if end > len => slice_end_index_len_fail ( end, len) ,
867848 ops:: Bound :: Excluded ( & end) => end,
849+
868850 ops:: Bound :: Unbounded => len,
869851 } ;
870852
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- }
853+ let start = match range. start_bound ( ) {
854+ ops:: Bound :: Excluded ( & start) if start >= end => slice_index_order_fail ( start, end) ,
855+ // Cannot overflow because `start < end` implies `start < usize::MAX`.
856+ ops:: Bound :: Excluded ( & start) => start + 1 ,
857+
858+ ops:: Bound :: Included ( & start) if start > end => slice_index_order_fail ( start, end) ,
859+ ops:: Bound :: Included ( & start) => start,
860+
861+ ops:: Bound :: Unbounded => 0 ,
862+ } ;
877863
878864 ops:: Range { start, end }
879865}
@@ -916,19 +902,29 @@ where
916902{
917903 let len = bounds. end ;
918904
919- let start = match range. start_bound ( ) {
920- ops:: Bound :: Included ( & start) => start,
921- ops:: Bound :: Excluded ( start) => start. checked_add ( 1 ) ?,
922- ops:: Bound :: Unbounded => 0 ,
923- } ;
924-
925905 let end = match range. end_bound ( ) {
926- ops:: Bound :: Included ( end) => end. checked_add ( 1 ) ?,
906+ ops:: Bound :: Included ( & end) if end >= len => return None ,
907+ // Cannot overflow because `end < len` implies `end < usize::MAX`.
908+ ops:: Bound :: Included ( end) => end + 1 ,
909+
910+ ops:: Bound :: Excluded ( & end) if end > len => return None ,
927911 ops:: Bound :: Excluded ( & end) => end,
912+
928913 ops:: Bound :: Unbounded => len,
929914 } ;
930915
931- if start > end || end > len { None } else { Some ( ops:: Range { start, end } ) }
916+ let start = match range. start_bound ( ) {
917+ ops:: Bound :: Excluded ( & start) if start >= end => return None ,
918+ // Cannot overflow because `start < end` implies `start < usize::MAX`.
919+ ops:: Bound :: Excluded ( & start) => start + 1 ,
920+
921+ ops:: Bound :: Included ( & start) if start > end => return None ,
922+ ops:: Bound :: Included ( & start) => start,
923+
924+ ops:: Bound :: Unbounded => 0 ,
925+ } ;
926+
927+ Some ( ops:: Range { start, end } )
932928}
933929
934930/// Converts a pair of `ops::Bound`s into `ops::Range` without performing any
@@ -957,21 +953,27 @@ pub(crate) fn into_range(
957953 len : usize ,
958954 ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
959955) -> Option < ops:: Range < usize > > {
960- use ops:: Bound ;
961- let start = match start {
962- Bound :: Included ( start) => start,
963- Bound :: Excluded ( start) => start. checked_add ( 1 ) ?,
964- Bound :: Unbounded => 0 ,
965- } ;
966-
967956 let end = match end {
968- Bound :: Included ( end) => end. checked_add ( 1 ) ?,
969- Bound :: Excluded ( end) => end,
970- Bound :: Unbounded => len,
957+ ops:: Bound :: Included ( end) if end >= len => return None ,
958+ // Cannot overflow because `end < len` implies `end < usize::MAX`.
959+ ops:: Bound :: Included ( end) => end + 1 ,
960+
961+ ops:: Bound :: Excluded ( end) if end > len => return None ,
962+ ops:: Bound :: Excluded ( end) => end,
963+
964+ ops:: Bound :: Unbounded => len,
971965 } ;
972966
973- // Don't bother with checking `start < end` and `end <= len`
974- // since these checks are handled by `Range` impls
967+ let start = match start {
968+ ops:: Bound :: Excluded ( start) if start >= end => return None ,
969+ // Cannot overflow because `start < end` implies `start < usize::MAX`.
970+ ops:: Bound :: Excluded ( start) => start + 1 ,
971+
972+ ops:: Bound :: Included ( start) if start > end => return None ,
973+ ops:: Bound :: Included ( start) => start,
974+
975+ ops:: Bound :: Unbounded => 0 ,
976+ } ;
975977
976978 Some ( start..end)
977979}
@@ -982,25 +984,27 @@ pub(crate) fn into_slice_range(
982984 len : usize ,
983985 ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
984986) -> 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-
994987 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,
988+ ops:: Bound :: Included ( end) if end >= len => slice_end_index_len_fail ( end, len) ,
989+ // Cannot overflow because `end < len` implies `end < usize::MAX`.
990+ ops:: Bound :: Included ( end) => end + 1 ,
991+
992+ ops:: Bound :: Excluded ( end) if end > len => slice_end_index_len_fail ( end, len) ,
993+ ops:: Bound :: Excluded ( end) => end,
994+
995+ ops:: Bound :: Unbounded => len,
1000996 } ;
1001997
1002- // Don't bother with checking `start < end` and `end <= len`
1003- // since these checks are handled by `Range` impls
998+ let start = match start {
999+ ops:: Bound :: Excluded ( start) if start >= end => slice_index_order_fail ( start, end) ,
1000+ // Cannot overflow because `start < end` implies `start < usize::MAX`.
1001+ ops:: Bound :: Excluded ( start) => start + 1 ,
1002+
1003+ ops:: Bound :: Included ( start) if start > end => slice_index_order_fail ( start, end) ,
1004+ ops:: Bound :: Included ( start) => start,
1005+
1006+ ops:: Bound :: Unbounded => 0 ,
1007+ } ;
10041008
10051009 start..end
10061010}
0 commit comments