@@ -34,36 +34,41 @@ where
34
34
#[ cfg_attr( not( feature = "panic_immediate_abort" ) , inline( never) , cold) ]
35
35
#[ cfg_attr( feature = "panic_immediate_abort" , inline) ]
36
36
#[ 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
+ }
45
46
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
+ }
57
55
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`.
62
67
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}" ,
66
70
end: usize ,
71
+ len: usize ,
67
72
)
68
73
}
69
74
@@ -341,7 +346,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
341
346
// SAFETY: `self` is checked to be valid and in bounds above.
342
347
unsafe { & * get_offset_len_noubcheck ( slice, self . start ( ) , self . len ( ) ) }
343
348
} else {
344
- slice_end_index_len_fail ( self . end ( ) , slice. len ( ) )
349
+ slice_index_fail ( self . start ( ) , self . end ( ) , slice. len ( ) )
345
350
}
346
351
}
347
352
@@ -351,7 +356,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
351
356
// SAFETY: `self` is checked to be valid and in bounds above.
352
357
unsafe { & mut * get_offset_len_mut_noubcheck ( slice, self . start ( ) , self . len ( ) ) }
353
358
} else {
354
- slice_end_index_len_fail ( self . end ( ) , slice. len ( ) )
359
+ slice_index_fail ( self . start ( ) , self . end ( ) , slice. len ( ) )
355
360
}
356
361
}
357
362
}
@@ -436,26 +441,27 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
436
441
#[ inline( always) ]
437
442
fn index ( self , slice : & [ T ] ) -> & [ T ] {
438
443
// 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 ( ) )
444
451
}
445
- // SAFETY: `self` is checked to be valid and in bounds above.
446
- unsafe { & * get_offset_len_noubcheck ( slice, self . start , new_len) }
447
452
}
448
453
449
454
#[ inline]
450
455
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 ( ) )
456
464
}
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) }
459
465
}
460
466
}
461
467
@@ -567,7 +573,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
567
573
#[ inline]
568
574
fn index ( self , slice : & [ T ] ) -> & [ T ] {
569
575
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 ( ) )
571
577
}
572
578
// SAFETY: `self` is checked to be valid and in bounds above.
573
579
unsafe { & * self . get_unchecked ( slice) }
@@ -576,7 +582,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
576
582
#[ inline]
577
583
fn index_mut ( self , slice : & mut [ T ] ) -> & mut [ T ] {
578
584
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 ( ) )
580
586
}
581
587
// SAFETY: `self` is checked to be valid and in bounds above.
582
588
unsafe { & mut * self . get_unchecked_mut ( slice) }
@@ -690,16 +696,16 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
690
696
691
697
#[ inline]
692
698
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 ( ) )
695
701
}
696
702
self . into_slice_range ( ) . index ( slice)
697
703
}
698
704
699
705
#[ inline]
700
706
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 ( ) )
703
709
}
704
710
self . into_slice_range ( ) . index_mut ( slice)
705
711
}
@@ -861,19 +867,25 @@ where
861
867
} ;
862
868
863
869
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) ,
867
875
ops:: Bound :: Excluded ( & end) => end,
868
876
ops:: Bound :: Unbounded => len,
869
877
} ;
870
878
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
+ } ;
877
889
878
890
ops:: Range { start, end }
879
891
}
@@ -982,13 +994,26 @@ pub(crate) fn into_slice_range(
982
994
len : usize ,
983
995
( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
984
996
) -> 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
+
986
1008
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 ,
992
1017
} ;
993
1018
994
1019
let end = match end {
0 commit comments