@@ -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,
@@ -853,28 +839,27 @@ where
853839{
854840 let len = bounds. end ;
855841
856- let start = match range. start_bound ( ) {
857- ops:: Bound :: Included ( & start) => start,
858- ops:: Bound :: Excluded ( start) => {
859- start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
860- }
861- ops:: Bound :: Unbounded => 0 ,
862- } ;
863-
864842 let end = match range. end_bound ( ) {
865- ops:: Bound :: Included ( end) => {
866- end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
867- }
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) ,
868848 ops:: Bound :: Excluded ( & end) => end,
849+
869850 ops:: Bound :: Unbounded => len,
870851 } ;
871852
872- if start > end {
873- slice_index_order_fail ( start, end) ;
874- }
875- if end > len {
876- slice_end_index_len_fail ( end, len) ;
877- }
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+ } ;
878863
879864 ops:: Range { start, end }
880865}
@@ -917,19 +902,29 @@ where
917902{
918903 let len = bounds. end ;
919904
920- let start = match range. start_bound ( ) {
921- ops:: Bound :: Included ( & start) => start,
922- ops:: Bound :: Excluded ( start) => start. checked_add ( 1 ) ?,
923- ops:: Bound :: Unbounded => 0 ,
924- } ;
925-
926905 let end = match range. end_bound ( ) {
927- 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 ,
928911 ops:: Bound :: Excluded ( & end) => end,
912+
929913 ops:: Bound :: Unbounded => len,
930914 } ;
931915
932- 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 } )
933928}
934929
935930/// Converts a pair of `ops::Bound`s into `ops::Range` without performing any
@@ -958,21 +953,27 @@ pub(crate) fn into_range(
958953 len : usize ,
959954 ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
960955) -> Option < ops:: Range < usize > > {
961- use ops:: Bound ;
962- let start = match start {
963- Bound :: Included ( start) => start,
964- Bound :: Excluded ( start) => start. checked_add ( 1 ) ?,
965- Bound :: Unbounded => 0 ,
966- } ;
967-
968956 let end = match end {
969- Bound :: Included ( end) => end. checked_add ( 1 ) ?,
970- Bound :: Excluded ( end) => end,
971- 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,
972965 } ;
973966
974- // Don't bother with checking `start < end` and `end <= len`
975- // 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+ } ;
976977
977978 Some ( start..end)
978979}
@@ -983,25 +984,27 @@ pub(crate) fn into_slice_range(
983984 len : usize ,
984985 ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
985986) -> ops:: Range < usize > {
986- use ops:: Bound ;
987- let start = match start {
988- Bound :: Included ( start) => start,
989- Bound :: Excluded ( start) => {
990- start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
991- }
992- Bound :: Unbounded => 0 ,
993- } ;
994-
995987 let end = match end {
996- Bound :: Included ( end) => {
997- end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
998- }
999- Bound :: Excluded ( end) => end,
1000- 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,
1001996 } ;
1002997
1003- // Don't bother with checking `start < end` and `end <= len`
1004- // 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+ } ;
10051008
10061009 start..end
10071010}
0 commit comments