@@ -34,53 +34,44 @@ 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
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
-
84
75
// The UbChecks are great for catching bugs in the unsafe methods, but including
85
76
// them in safe indexing is unnecessary and hurts inlining and debug runtime perf.
86
77
// Both the safe and unsafe public methods share these helpers,
@@ -341,7 +332,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
341
332
// SAFETY: `self` is checked to be valid and in bounds above.
342
333
unsafe { & * get_offset_len_noubcheck ( slice, self . start ( ) , self . len ( ) ) }
343
334
} else {
344
- slice_end_index_len_fail ( self . end ( ) , slice. len ( ) )
335
+ slice_index_fail ( self . start ( ) , self . end ( ) , slice. len ( ) )
345
336
}
346
337
}
347
338
@@ -351,7 +342,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
351
342
// SAFETY: `self` is checked to be valid and in bounds above.
352
343
unsafe { & mut * get_offset_len_mut_noubcheck ( slice, self . start ( ) , self . len ( ) ) }
353
344
} else {
354
- slice_end_index_len_fail ( self . end ( ) , slice. len ( ) )
345
+ slice_index_fail ( self . start ( ) , self . end ( ) , slice. len ( ) )
355
346
}
356
347
}
357
348
}
@@ -436,26 +427,27 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
436
427
#[ inline( always) ]
437
428
fn index ( self , slice : & [ T ] ) -> & [ T ] {
438
429
// 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 ( ) )
444
437
}
445
- // SAFETY: `self` is checked to be valid and in bounds above.
446
- unsafe { & * get_offset_len_noubcheck ( slice, self . start , new_len) }
447
438
}
448
439
449
440
#[ inline]
450
441
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 ( ) )
456
450
}
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
451
}
460
452
}
461
453
@@ -567,7 +559,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
567
559
#[ inline]
568
560
fn index ( self , slice : & [ T ] ) -> & [ T ] {
569
561
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 ( ) )
571
563
}
572
564
// SAFETY: `self` is checked to be valid and in bounds above.
573
565
unsafe { & * self . get_unchecked ( slice) }
@@ -576,7 +568,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
576
568
#[ inline]
577
569
fn index_mut ( self , slice : & mut [ T ] ) -> & mut [ T ] {
578
570
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 ( ) )
580
572
}
581
573
// SAFETY: `self` is checked to be valid and in bounds above.
582
574
unsafe { & mut * self . get_unchecked_mut ( slice) }
@@ -690,16 +682,16 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
690
682
691
683
#[ inline]
692
684
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 ( ) )
695
687
}
696
688
self . into_slice_range ( ) . index ( slice)
697
689
}
698
690
699
691
#[ inline]
700
692
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 ( ) )
703
695
}
704
696
self . into_slice_range ( ) . index_mut ( slice)
705
697
}
@@ -852,28 +844,26 @@ where
852
844
{
853
845
let len = bounds. end ;
854
846
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
-
863
847
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) ,
867
853
ops:: Bound :: Excluded ( & end) => end,
868
854
ops:: Bound :: Unbounded => len,
869
855
} ;
870
856
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
+ } ;
877
867
878
868
ops:: Range { start, end }
879
869
}
@@ -982,25 +972,27 @@ pub(crate) fn into_slice_range(
982
972
len : usize ,
983
973
( start, end) : ( ops:: Bound < usize > , ops:: Bound < usize > ) ,
984
974
) -> 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
-
994
975
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,
1000
984
} ;
1001
985
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
+ } ;
1004
996
1005
997
start..end
1006
998
}
0 commit comments