@@ -34,36 +34,41 @@ 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
@@ -341,7 +346,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
341346 // SAFETY: `self` is checked to be valid and in bounds above.
342347 unsafe { & * get_offset_len_noubcheck ( slice, self . start ( ) , self . len ( ) ) }
343348 } else {
344- slice_end_index_len_fail ( self . end ( ) , slice. len ( ) )
349+ slice_index_fail ( self . start ( ) , self . end ( ) , slice. len ( ) )
345350 }
346351 }
347352
@@ -351,7 +356,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
351356 // SAFETY: `self` is checked to be valid and in bounds above.
352357 unsafe { & mut * get_offset_len_mut_noubcheck ( slice, self . start ( ) , self . len ( ) ) }
353358 } else {
354- slice_end_index_len_fail ( self . end ( ) , slice. len ( ) )
359+ slice_index_fail ( self . start ( ) , self . end ( ) , slice. len ( ) )
355360 }
356361 }
357362}
@@ -436,26 +441,27 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
436441 #[ inline( always) ]
437442 fn index ( self , slice : & [ T ] ) -> & [ T ] {
438443 // 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 ( ) ) ;
444+ if let Some ( new_len) = usize:: checked_sub ( self . end , self . start )
445+ && self . end <= slice. len ( )
446+ {
447+ // SAFETY: `self` is checked to be valid and in bounds above.
448+ unsafe { & * get_offset_len_noubcheck ( slice, self . start , new_len) }
449+ } else {
450+ slice_index_fail ( self . start , self . end , slice. len ( ) )
444451 }
445- // SAFETY: `self` is checked to be valid and in bounds above.
446- unsafe { & * get_offset_len_noubcheck ( slice, self . start , new_len) }
447452 }
448453
449454 #[ inline]
450455 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 ( ) ) ;
456+ // Using checked_sub is a safe way to get `SubUnchecked` in MIR
457+ if let Some ( new_len) = usize:: checked_sub ( self . end , self . start )
458+ && self . end <= slice. len ( )
459+ {
460+ // SAFETY: `self` is checked to be valid and in bounds above.
461+ unsafe { & mut * get_offset_len_mut_noubcheck ( slice, self . start , new_len) }
462+ } else {
463+ slice_index_fail ( self . start , self . end , slice. len ( ) )
456464 }
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) }
459465 }
460466}
461467
@@ -567,7 +573,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
567573 #[ inline]
568574 fn index ( self , slice : & [ T ] ) -> & [ T ] {
569575 if self . start > slice. len ( ) {
570- slice_start_index_len_fail ( self . start , slice. len ( ) ) ;
576+ slice_index_fail ( self . start , slice. len ( ) , slice . len ( ) )
571577 }
572578 // SAFETY: `self` is checked to be valid and in bounds above.
573579 unsafe { & * self . get_unchecked ( slice) }
@@ -576,7 +582,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
576582 #[ inline]
577583 fn index_mut ( self , slice : & mut [ T ] ) -> & mut [ T ] {
578584 if self . start > slice. len ( ) {
579- slice_start_index_len_fail ( self . start , slice. len ( ) ) ;
585+ slice_index_fail ( self . start , slice. len ( ) , slice . len ( ) )
580586 }
581587 // SAFETY: `self` is checked to be valid and in bounds above.
582588 unsafe { & mut * self . get_unchecked_mut ( slice) }
@@ -690,16 +696,16 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
690696
691697 #[ inline]
692698 fn index ( self , slice : & [ T ] ) -> & [ T ] {
693- if * self . end ( ) == usize :: MAX {
694- slice_end_index_overflow_fail ( ) ;
699+ if * self . end ( ) >= slice . len ( ) {
700+ slice_index_fail ( self . start , self . end , slice . len ( ) )
695701 }
696702 self . into_slice_range ( ) . index ( slice)
697703 }
698704
699705 #[ inline]
700706 fn index_mut ( self , slice : & mut [ T ] ) -> & mut [ T ] {
701- if * self . end ( ) == usize :: MAX {
702- slice_end_index_overflow_fail ( ) ;
707+ if * self . end ( ) >= slice . len ( ) {
708+ slice_index_fail ( self . start , self . end , slice . len ( ) )
703709 }
704710 self . into_slice_range ( ) . index_mut ( slice)
705711 }
@@ -861,19 +867,25 @@ where
861867 } ;
862868
863869 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- }
870+ ops:: Bound :: Included ( & end) if end >= len => slice_index_fail ( 0 , end, len) ,
871+ // Cannot overflow because `end < len` implies `end < usize::MAX`.
872+ ops:: Bound :: Included ( & end) => end + 1 ,
873+
874+ ops:: Bound :: Excluded ( & end) if end > len => slice_index_fail ( 0 , end, len) ,
867875 ops:: Bound :: Excluded ( & end) => end,
868876 ops:: Bound :: Unbounded => len,
869877 } ;
870878
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- }
879+ let start = match range. start_bound ( ) {
880+ ops:: Bound :: Excluded ( & start) if start >= end => slice_index_fail ( start, end, len) ,
881+ // Cannot overflow because `start < end` implies `start < usize::MAX`.
882+ ops:: Bound :: Excluded ( & start) => start + 1 ,
883+
884+ ops:: Bound :: Included ( & start) if start > end => slice_index_fail ( start, end, len) ,
885+ ops:: Bound :: Included ( & start) => start,
886+
887+ ops:: Bound :: Unbounded => 0 ,
888+ } ;
877889
878890 ops:: Range { start, end }
879891}
@@ -982,13 +994,26 @@ pub(crate) fn into_slice_range(
982994 len : usize ,
983995 ( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
984996) -> ops:: Range < usize > {
985- use ops:: Bound ;
997+ let end = match end {
998+ ops:: Bound :: Included ( end) if end >= len => slice_index_fail ( 0 , end, len) ,
999+ // Cannot overflow because `end < len` implies `end < usize::MAX`.
1000+ ops:: Bound :: Included ( end) => end + 1 ,
1001+
1002+ ops:: Bound :: Excluded ( end) if end > len => slice_index_fail ( 0 , end, len) ,
1003+ ops:: Bound :: Excluded ( end) => end,
1004+
1005+ ops:: Bound :: Unbounded => len,
1006+ } ;
1007+
9861008 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 ,
1009+ ops:: Bound :: Excluded ( start) if start >= end => slice_index_fail ( start, end, len) ,
1010+ // Cannot overflow because `start < end` implies `start < usize::MAX`.
1011+ ops:: Bound :: Excluded ( start) => start + 1 ,
1012+
1013+ ops:: Bound :: Included ( start) if start > end => slice_index_fail ( start, end, len) ,
1014+ ops:: Bound :: Included ( start) => start,
1015+
1016+ ops:: Bound :: Unbounded => 0 ,
9921017 } ;
9931018
9941019 let end = match end {
0 commit comments