@@ -10,10 +10,10 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less};
10
10
use crate :: intrinsics:: { exact_div, select_unpredictable, unchecked_sub} ;
11
11
use crate :: mem:: { self , SizedTypeProperties } ;
12
12
use crate :: num:: NonZero ;
13
- use crate :: ops:: { Bound , OneSidedRange , Range , RangeBounds } ;
13
+ use crate :: ops:: { Bound , OneSidedRange , Range , RangeBounds , RangeInclusive } ;
14
14
use crate :: simd:: { self , Simd } ;
15
15
use crate :: ub_checks:: assert_unsafe_precondition;
16
- use crate :: { fmt, hint, ptr, slice} ;
16
+ use crate :: { fmt, hint, ptr, range , slice} ;
17
17
18
18
#[ unstable(
19
19
feature = "slice_internals" ,
@@ -4467,6 +4467,12 @@ impl<T> [T] {
4467
4467
4468
4468
/// Returns mutable references to many indices at once, without doing any checks.
4469
4469
///
4470
+ /// An index can be either a `usize` or a [`Range`] or a [`RangeInclusive`] (note
4471
+ /// that this method takes an array, so all indices must be of the same type.
4472
+ /// This restriction may be lifted in the future). If passed an array of `usize`s
4473
+ /// this method gives back an array of mutable references to single elements, while
4474
+ /// if passed an array of ranges it gives back an array of mutable references to slices.
4475
+ ///
4470
4476
/// For a safe alternative see [`get_many_mut`].
4471
4477
///
4472
4478
/// # Safety
@@ -4487,39 +4493,68 @@ impl<T> [T] {
4487
4493
/// *b *= 100;
4488
4494
/// }
4489
4495
/// assert_eq!(x, &[10, 2, 400]);
4496
+ ///
4497
+ /// unsafe {
4498
+ /// let [a, b] = x.get_many_unchecked_mut([0..1, 1..3]);
4499
+ /// a[0] = 8;
4500
+ /// b[0] = 88;
4501
+ /// b[1] = 888;
4502
+ /// }
4503
+ /// assert_eq!(x, &[8, 88, 888]);
4504
+ ///
4505
+ /// unsafe {
4506
+ /// let [a, b] = x.get_many_unchecked_mut([1..=2, 0..=0]);
4507
+ /// a[0] = 11;
4508
+ /// a[1] = 111;
4509
+ /// b[0] = 1;
4510
+ /// }
4511
+ /// assert_eq!(x, &[1, 11, 111]);
4490
4512
/// ```
4491
4513
///
4492
4514
/// [`get_many_mut`]: slice::get_many_mut
4493
4515
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
4494
4516
#[ unstable( feature = "get_many_mut" , issue = "104642" ) ]
4495
4517
#[ inline]
4496
- pub unsafe fn get_many_unchecked_mut < const N : usize > (
4518
+ pub unsafe fn get_many_unchecked_mut < I , const N : usize > (
4497
4519
& mut self ,
4498
- indices : [ usize ; N ] ,
4499
- ) -> [ & mut T ; N ] {
4520
+ indices : [ I ; N ] ,
4521
+ ) -> [ & mut I :: Output ; N ]
4522
+ where
4523
+ I : GetManyMutIndex + SliceIndex < Self > ,
4524
+ {
4500
4525
// NB: This implementation is written as it is because any variation of
4501
4526
// `indices.map(|i| self.get_unchecked_mut(i))` would make miri unhappy,
4502
4527
// or generate worse code otherwise. This is also why we need to go
4503
4528
// through a raw pointer here.
4504
4529
let slice: * mut [ T ] = self ;
4505
- let mut arr: mem:: MaybeUninit < [ & mut T ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
4530
+ let mut arr: mem:: MaybeUninit < [ & mut I :: Output ; N ] > = mem:: MaybeUninit :: uninit ( ) ;
4506
4531
let arr_ptr = arr. as_mut_ptr ( ) ;
4507
4532
4508
4533
// SAFETY: We expect `indices` to contain disjunct values that are
4509
4534
// in bounds of `self`.
4510
4535
unsafe {
4511
4536
for i in 0 ..N {
4512
- let idx = * indices. get_unchecked ( i) ;
4513
- * ( * arr_ptr) . get_unchecked_mut ( i) = & mut * slice. get_unchecked_mut ( idx) ;
4537
+ let idx = indices. get_unchecked ( i) . clone ( ) ;
4538
+ arr_ptr. cast :: < & mut I :: Output > ( ) . add ( i) . write ( & mut * slice. get_unchecked_mut ( idx) ) ;
4514
4539
}
4515
4540
arr. assume_init ( )
4516
4541
}
4517
4542
}
4518
4543
4519
4544
/// Returns mutable references to many indices at once.
4520
4545
///
4521
- /// Returns an error if any index is out-of-bounds, or if the same index was
4522
- /// passed more than once.
4546
+ /// An index can be either a `usize` or a [`Range`] or a [`RangeInclusive`] (note
4547
+ /// that this method takes an array, so all indices must be of the same type.
4548
+ /// This restriction may be lifted in the future). If passed an array of `usize`s
4549
+ /// this method gives back an array of mutable references to single elements, while
4550
+ /// if passed an array of ranges it gives back an array of mutable references to slices.
4551
+ ///
4552
+ /// Returns an error if any index is out-of-bounds, or if there are overlapping indices.
4553
+ /// An empty range is not considered to overlap if it is located at the beginning or at
4554
+ /// the end of another range, but is considered to overlap if it is located in the middle.
4555
+ ///
4556
+ /// This method does a O(n^2) check to check that there are no overlapping indices, so be careful
4557
+ /// when passing many indices.
4523
4558
///
4524
4559
/// # Examples
4525
4560
///
@@ -4532,13 +4567,30 @@ impl<T> [T] {
4532
4567
/// *b = 612;
4533
4568
/// }
4534
4569
/// assert_eq!(v, &[413, 2, 612]);
4570
+ ///
4571
+ /// if let Ok([a, b]) = v.get_many_mut([0..1, 1..3]) {
4572
+ /// a[0] = 8;
4573
+ /// b[0] = 88;
4574
+ /// b[1] = 888;
4575
+ /// }
4576
+ /// assert_eq!(v, &[8, 88, 888]);
4577
+ ///
4578
+ /// if let Ok([a, b]) = v.get_many_mut([1..=2, 0..=0]) {
4579
+ /// a[0] = 11;
4580
+ /// a[1] = 111;
4581
+ /// b[0] = 1;
4582
+ /// }
4583
+ /// assert_eq!(v, &[1, 11, 111]);
4535
4584
/// ```
4536
4585
#[ unstable( feature = "get_many_mut" , issue = "104642" ) ]
4537
4586
#[ inline]
4538
- pub fn get_many_mut < const N : usize > (
4587
+ pub fn get_many_mut < I , const N : usize > (
4539
4588
& mut self ,
4540
- indices : [ usize ; N ] ,
4541
- ) -> Result < [ & mut T ; N ] , GetManyMutError < N > > {
4589
+ indices : [ I ; N ] ,
4590
+ ) -> Result < [ & mut I :: Output ; N ] , GetManyMutError < N > >
4591
+ where
4592
+ I : GetManyMutIndex + SliceIndex < Self > ,
4593
+ {
4542
4594
if !get_many_check_valid ( & indices, self . len ( ) ) {
4543
4595
return Err ( GetManyMutError { _private : ( ) } ) ;
4544
4596
}
@@ -4883,14 +4935,15 @@ impl<T, const N: usize> SlicePattern for [T; N] {
4883
4935
///
4884
4936
/// This will do `binomial(N + 1, 2) = N * (N + 1) / 2 = 0, 1, 3, 6, 10, ..`
4885
4937
/// comparison operations.
4886
- fn get_many_check_valid < const N : usize > ( indices : & [ usize ; N ] , len : usize ) -> bool {
4938
+ #[ inline]
4939
+ fn get_many_check_valid < I : GetManyMutIndex , const N : usize > ( indices : & [ I ; N ] , len : usize ) -> bool {
4887
4940
// NB: The optimizer should inline the loops into a sequence
4888
4941
// of instructions without additional branching.
4889
4942
let mut valid = true ;
4890
- for ( i, & idx) in indices. iter ( ) . enumerate ( ) {
4891
- valid &= idx < len;
4892
- for & idx2 in & indices[ ..i] {
4893
- valid &= idx != idx2;
4943
+ for ( i, idx) in indices. iter ( ) . enumerate ( ) {
4944
+ valid &= idx. is_in_bounds ( len) ;
4945
+ for idx2 in & indices[ ..i] {
4946
+ valid &= !idx . is_overlapping ( idx2) ;
4894
4947
}
4895
4948
}
4896
4949
valid
@@ -4914,6 +4967,7 @@ fn get_many_check_valid<const N: usize>(indices: &[usize; N], len: usize) -> boo
4914
4967
#[ unstable( feature = "get_many_mut" , issue = "104642" ) ]
4915
4968
// NB: The N here is there to be forward-compatible with adding more details
4916
4969
// to the error type at a later point
4970
+ #[ derive( Clone , PartialEq , Eq ) ]
4917
4971
pub struct GetManyMutError < const N : usize > {
4918
4972
_private : ( ) ,
4919
4973
}
@@ -4931,3 +4985,93 @@ impl<const N: usize> fmt::Display for GetManyMutError<N> {
4931
4985
fmt:: Display :: fmt ( "an index is out of bounds or appeared multiple times in the array" , f)
4932
4986
}
4933
4987
}
4988
+
4989
+ /// A helper trait for `<[T]>::get_many_mut()`.
4990
+ ///
4991
+ /// # Safety
4992
+ ///
4993
+ /// If `is_in_bounds()` returns `true` and `is_overlapping()` returns `false`,
4994
+ /// it must be safe to index the slice with the indices.
4995
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
4996
+ pub unsafe trait GetManyMutIndex : Clone {
4997
+ /// Returns `true` if `self` is in bounds for `len` slice elements.
4998
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
4999
+ fn is_in_bounds ( & self , len : usize ) -> bool ;
5000
+
5001
+ /// Returns `true` if `self` overlaps with `other`.
5002
+ ///
5003
+ /// Note that we don't consider zero-length ranges to overlap at the beginning or the end,
5004
+ /// but do consider them to overlap in the middle.
5005
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
5006
+ fn is_overlapping ( & self , other : & Self ) -> bool ;
5007
+ }
5008
+
5009
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
5010
+ // SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly.
5011
+ unsafe impl GetManyMutIndex for usize {
5012
+ #[ inline]
5013
+ fn is_in_bounds ( & self , len : usize ) -> bool {
5014
+ * self < len
5015
+ }
5016
+
5017
+ #[ inline]
5018
+ fn is_overlapping ( & self , other : & Self ) -> bool {
5019
+ * self == * other
5020
+ }
5021
+ }
5022
+
5023
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
5024
+ // SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly.
5025
+ unsafe impl GetManyMutIndex for Range < usize > {
5026
+ #[ inline]
5027
+ fn is_in_bounds ( & self , len : usize ) -> bool {
5028
+ ( self . start <= self . end ) & ( self . end <= len)
5029
+ }
5030
+
5031
+ #[ inline]
5032
+ fn is_overlapping ( & self , other : & Self ) -> bool {
5033
+ ( self . start < other. end ) & ( other. start < self . end )
5034
+ }
5035
+ }
5036
+
5037
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
5038
+ // SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly.
5039
+ unsafe impl GetManyMutIndex for RangeInclusive < usize > {
5040
+ #[ inline]
5041
+ fn is_in_bounds ( & self , len : usize ) -> bool {
5042
+ ( self . start <= self . end ) & ( self . end < len)
5043
+ }
5044
+
5045
+ #[ inline]
5046
+ fn is_overlapping ( & self , other : & Self ) -> bool {
5047
+ ( self . start <= other. end ) & ( other. start <= self . end )
5048
+ }
5049
+ }
5050
+
5051
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
5052
+ // SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly.
5053
+ unsafe impl GetManyMutIndex for range:: Range < usize > {
5054
+ #[ inline]
5055
+ fn is_in_bounds ( & self , len : usize ) -> bool {
5056
+ Range :: from ( * self ) . is_in_bounds ( len)
5057
+ }
5058
+
5059
+ #[ inline]
5060
+ fn is_overlapping ( & self , other : & Self ) -> bool {
5061
+ Range :: from ( * self ) . is_overlapping ( & Range :: from ( * other) )
5062
+ }
5063
+ }
5064
+
5065
+ #[ unstable( feature = "get_many_mut_helpers" , issue = "none" ) ]
5066
+ // SAFETY: We implement `is_in_bounds()` and `is_overlapping()` correctly.
5067
+ unsafe impl GetManyMutIndex for range:: RangeInclusive < usize > {
5068
+ #[ inline]
5069
+ fn is_in_bounds ( & self , len : usize ) -> bool {
5070
+ RangeInclusive :: from ( * self ) . is_in_bounds ( len)
5071
+ }
5072
+
5073
+ #[ inline]
5074
+ fn is_overlapping ( & self , other : & Self ) -> bool {
5075
+ RangeInclusive :: from ( * self ) . is_overlapping ( & RangeInclusive :: from ( * other) )
5076
+ }
5077
+ }
0 commit comments