@@ -30,7 +30,7 @@ use crate::intrinsics::{assume, exact_div, is_aligned_and_not_null, unchecked_su
30
30
use crate :: iter:: * ;
31
31
use crate :: marker:: { self , Copy , Send , Sized , Sync } ;
32
32
use crate :: mem;
33
- use crate :: ops:: { self , FnMut , Range } ;
33
+ use crate :: ops:: { self , Bound , FnMut , Range , RangeBounds } ;
34
34
use crate :: option:: Option ;
35
35
use crate :: option:: Option :: { None , Some } ;
36
36
use crate :: ptr:: { self , NonNull } ;
@@ -350,6 +350,80 @@ impl<T> [T] {
350
350
unsafe { & mut * index. get_unchecked_mut ( self ) }
351
351
}
352
352
353
+ /// Converts a range over this slice to [`Range`].
354
+ ///
355
+ /// The returned range is safe to pass to [`get_unchecked`] and [`get_unchecked_mut`].
356
+ ///
357
+ /// [`get_unchecked`]: #method.get_unchecked
358
+ /// [`get_unchecked_mut`]: #method.get_unchecked_mut
359
+ /// [`Range`]: ../ops/struct.Range.html
360
+ ///
361
+ /// # Panics
362
+ ///
363
+ /// Panics if the range is out of bounds.
364
+ ///
365
+ /// # Examples
366
+ ///
367
+ /// ```
368
+ /// #![feature(slice_check_range)]
369
+ ///
370
+ /// let v = [10, 40, 30];
371
+ /// assert_eq!(1..2, v.check_range(1..2));
372
+ /// assert_eq!(0..2, v.check_range(..2));
373
+ /// assert_eq!(1..3, v.check_range(1..));
374
+ /// ```
375
+ ///
376
+ /// Panics when [`Index::index`] would panic:
377
+ ///
378
+ /// ```should_panic
379
+ /// #![feature(slice_check_range)]
380
+ ///
381
+ /// [10, 40, 30].check_range(2..1);
382
+ /// ```
383
+ ///
384
+ /// ```should_panic
385
+ /// #![feature(slice_check_range)]
386
+ ///
387
+ /// [10, 40, 30].check_range(1..4);
388
+ /// ```
389
+ ///
390
+ /// ```should_panic
391
+ /// #![feature(slice_check_range)]
392
+ ///
393
+ /// [10, 40, 30].check_range(1..=usize::MAX);
394
+ /// ```
395
+ ///
396
+ /// [`Index::index`]: ../ops/trait.Index.html#tymethod.index
397
+ #[ track_caller]
398
+ #[ unstable( feature = "slice_check_range" , issue = "none" ) ]
399
+ pub fn check_range < R : RangeBounds < usize > > ( & self , range : R ) -> Range < usize > {
400
+ let start = match range. start_bound ( ) {
401
+ Bound :: Included ( & start) => start,
402
+ Bound :: Excluded ( start) => {
403
+ start. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
404
+ }
405
+ Bound :: Unbounded => 0 ,
406
+ } ;
407
+
408
+ let len = self . len ( ) ;
409
+ let end = match range. end_bound ( ) {
410
+ Bound :: Included ( end) => {
411
+ end. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
412
+ }
413
+ Bound :: Excluded ( & end) => end,
414
+ Bound :: Unbounded => len,
415
+ } ;
416
+
417
+ if start > end {
418
+ slice_index_order_fail ( start, end) ;
419
+ }
420
+ if end > len {
421
+ slice_end_index_len_fail ( end, len) ;
422
+ }
423
+
424
+ Range { start, end }
425
+ }
426
+
353
427
/// Returns a raw pointer to the slice's buffer.
354
428
///
355
429
/// The caller must ensure that the slice outlives the pointer this
@@ -2445,13 +2519,13 @@ impl<T> [T] {
2445
2519
let src_start = match src. start_bound ( ) {
2446
2520
ops:: Bound :: Included ( & n) => n,
2447
2521
ops:: Bound :: Excluded ( & n) => {
2448
- n. checked_add ( 1 ) . unwrap_or_else ( || slice_index_overflow_fail ( ) )
2522
+ n. checked_add ( 1 ) . unwrap_or_else ( || slice_start_index_overflow_fail ( ) )
2449
2523
}
2450
2524
ops:: Bound :: Unbounded => 0 ,
2451
2525
} ;
2452
2526
let src_end = match src. end_bound ( ) {
2453
2527
ops:: Bound :: Included ( & n) => {
2454
- n. checked_add ( 1 ) . unwrap_or_else ( || slice_index_overflow_fail ( ) )
2528
+ n. checked_add ( 1 ) . unwrap_or_else ( || slice_end_index_overflow_fail ( ) )
2455
2529
}
2456
2530
ops:: Bound :: Excluded ( & n) => n,
2457
2531
ops:: Bound :: Unbounded => self . len ( ) ,
@@ -3034,7 +3108,14 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! {
3034
3108
#[ inline( never) ]
3035
3109
#[ cold]
3036
3110
#[ track_caller]
3037
- fn slice_index_overflow_fail ( ) -> ! {
3111
+ fn slice_start_index_overflow_fail ( ) -> ! {
3112
+ panic ! ( "attempted to index slice from after maximum usize" ) ;
3113
+ }
3114
+
3115
+ #[ inline( never) ]
3116
+ #[ cold]
3117
+ #[ track_caller]
3118
+ fn slice_end_index_overflow_fail ( ) -> ! {
3038
3119
panic ! ( "attempted to index slice up to maximum usize" ) ;
3039
3120
}
3040
3121
@@ -3370,15 +3451,15 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
3370
3451
#[ inline]
3371
3452
fn index ( self , slice : & [ T ] ) -> & [ T ] {
3372
3453
if * self . end ( ) == usize:: MAX {
3373
- slice_index_overflow_fail ( ) ;
3454
+ slice_end_index_overflow_fail ( ) ;
3374
3455
}
3375
3456
( * self . start ( ) ..self . end ( ) + 1 ) . index ( slice)
3376
3457
}
3377
3458
3378
3459
#[ inline]
3379
3460
fn index_mut ( self , slice : & mut [ T ] ) -> & mut [ T ] {
3380
3461
if * self . end ( ) == usize:: MAX {
3381
- slice_index_overflow_fail ( ) ;
3462
+ slice_end_index_overflow_fail ( ) ;
3382
3463
}
3383
3464
( * self . start ( ) ..self . end ( ) + 1 ) . index_mut ( slice)
3384
3465
}
0 commit comments