@@ -100,6 +100,21 @@ pub fn size_of_shape_checked<D: Dimension>(dim: &D) -> Result<usize, ShapeError>
100
100
}
101
101
}
102
102
103
+ /// Select how aliasing is checked
104
+ ///
105
+ /// For owned or mutable data:
106
+ ///
107
+ /// The strides must not allow any element to be referenced by two different indices.
108
+ ///
109
+ #[ derive( Copy , Clone , PartialEq ) ]
110
+ pub ( crate ) enum CanIndexCheckMode
111
+ {
112
+ /// Owned or mutable: No aliasing
113
+ OwnedMutable ,
114
+ /// Aliasing
115
+ ReadOnly ,
116
+ }
117
+
103
118
/// Checks whether the given data and dimension meet the invariants of the
104
119
/// `ArrayBase` type, assuming the strides are created using
105
120
/// `dim.default_strides()` or `dim.fortran_strides()`.
@@ -125,12 +140,13 @@ pub fn size_of_shape_checked<D: Dimension>(dim: &D) -> Result<usize, ShapeError>
125
140
/// `A` and in units of bytes between the least address and greatest address
126
141
/// accessible by moving along all axes does not exceed `isize::MAX`.
127
142
pub ( crate ) fn can_index_slice_with_strides < A , D : Dimension > (
128
- data : & [ A ] , dim : & D , strides : & Strides < D > ,
143
+ data : & [ A ] , dim : & D , strides : & Strides < D > , mode : CanIndexCheckMode ,
129
144
) -> Result < ( ) , ShapeError >
130
145
{
131
146
if let Strides :: Custom ( strides) = strides {
132
- can_index_slice ( data, dim, strides)
147
+ can_index_slice ( data, dim, strides, mode )
133
148
} else {
149
+ // contiguous shapes: never aliasing, mode does not matter
134
150
can_index_slice_not_custom ( data. len ( ) , dim)
135
151
}
136
152
}
@@ -239,15 +255,19 @@ where D: Dimension
239
255
/// allocation. (In other words, the pointer to the first element of the array
240
256
/// must be computed using `offset_from_low_addr_ptr_to_logical_ptr` so that
241
257
/// negative strides are correctly handled.)
242
- pub ( crate ) fn can_index_slice < A , D : Dimension > ( data : & [ A ] , dim : & D , strides : & D ) -> Result < ( ) , ShapeError >
258
+ ///
259
+ /// Note, condition (4) is guaranteed to be checked last
260
+ pub ( crate ) fn can_index_slice < A , D : Dimension > (
261
+ data : & [ A ] , dim : & D , strides : & D , mode : CanIndexCheckMode ,
262
+ ) -> Result < ( ) , ShapeError >
243
263
{
244
264
// Check conditions 1 and 2 and calculate `max_offset`.
245
265
let max_offset = max_abs_offset_check_overflow :: < A , _ > ( dim, strides) ?;
246
- can_index_slice_impl ( max_offset, data. len ( ) , dim, strides)
266
+ can_index_slice_impl ( max_offset, data. len ( ) , dim, strides, mode )
247
267
}
248
268
249
269
fn can_index_slice_impl < D : Dimension > (
250
- max_offset : usize , data_len : usize , dim : & D , strides : & D ,
270
+ max_offset : usize , data_len : usize , dim : & D , strides : & D , mode : CanIndexCheckMode ,
251
271
) -> Result < ( ) , ShapeError >
252
272
{
253
273
// Check condition 3.
@@ -260,7 +280,7 @@ fn can_index_slice_impl<D: Dimension>(
260
280
}
261
281
262
282
// Check condition 4.
263
- if !is_empty && dim_stride_overlap ( dim, strides) {
283
+ if !is_empty && mode != CanIndexCheckMode :: ReadOnly && dim_stride_overlap ( dim, strides) {
264
284
return Err ( from_kind ( ErrorKind :: Unsupported ) ) ;
265
285
}
266
286
@@ -782,6 +802,7 @@ mod test
782
802
slice_min_max,
783
803
slices_intersect,
784
804
solve_linear_diophantine_eq,
805
+ CanIndexCheckMode ,
785
806
IntoDimension ,
786
807
} ;
787
808
use crate :: error:: { from_kind, ErrorKind } ;
@@ -796,11 +817,11 @@ mod test
796
817
let v: alloc:: vec:: Vec < _ > = ( 0 ..12 ) . collect ( ) ;
797
818
let dim = ( 2 , 3 , 2 ) . into_dimension ( ) ;
798
819
let strides = ( 1 , 2 , 6 ) . into_dimension ( ) ;
799
- assert ! ( super :: can_index_slice( & v, & dim, & strides) . is_ok( ) ) ;
820
+ assert ! ( super :: can_index_slice( & v, & dim, & strides, CanIndexCheckMode :: OwnedMutable ) . is_ok( ) ) ;
800
821
801
822
let strides = ( 2 , 4 , 12 ) . into_dimension ( ) ;
802
823
assert_eq ! (
803
- super :: can_index_slice( & v, & dim, & strides) ,
824
+ super :: can_index_slice( & v, & dim, & strides, CanIndexCheckMode :: OwnedMutable ) ,
804
825
Err ( from_kind( ErrorKind :: OutOfBounds ) )
805
826
) ;
806
827
}
@@ -848,71 +869,79 @@ mod test
848
869
#[ test]
849
870
fn can_index_slice_ix0 ( )
850
871
{
851
- can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix0 ( ) , & Ix0 ( ) ) . unwrap ( ) ;
852
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix0 ( ) , & Ix0 ( ) ) . unwrap_err ( ) ;
872
+ can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix0 ( ) , & Ix0 ( ) , CanIndexCheckMode :: OwnedMutable ) . unwrap ( ) ;
873
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix0 ( ) , & Ix0 ( ) , CanIndexCheckMode :: OwnedMutable ) . unwrap_err ( ) ;
853
874
}
854
875
855
876
#[ test]
856
877
fn can_index_slice_ix1 ( )
857
878
{
858
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 0 ) , & Ix1 ( 0 ) ) . unwrap ( ) ;
859
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 0 ) , & Ix1 ( 1 ) ) . unwrap ( ) ;
860
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 1 ) , & Ix1 ( 0 ) ) . unwrap_err ( ) ;
861
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 1 ) , & Ix1 ( 1 ) ) . unwrap_err ( ) ;
862
- can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 1 ) , & Ix1 ( 0 ) ) . unwrap ( ) ;
863
- can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 1 ) , & Ix1 ( 2 ) ) . unwrap ( ) ;
864
- can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 1 ) , & Ix1 ( -1isize as usize ) ) . unwrap ( ) ;
865
- can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) ) . unwrap_err ( ) ;
866
- can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix1 ( 2 ) , & Ix1 ( 0 ) ) . unwrap_err ( ) ;
867
- can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) ) . unwrap ( ) ;
868
- can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix1 ( 2 ) , & Ix1 ( -1isize as usize ) ) . unwrap ( ) ;
879
+ let mode = CanIndexCheckMode :: OwnedMutable ;
880
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 0 ) , & Ix1 ( 0 ) , mode) . unwrap ( ) ;
881
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 0 ) , & Ix1 ( 1 ) , mode) . unwrap ( ) ;
882
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 1 ) , & Ix1 ( 0 ) , mode) . unwrap_err ( ) ;
883
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix1 ( 1 ) , & Ix1 ( 1 ) , mode) . unwrap_err ( ) ;
884
+ can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 1 ) , & Ix1 ( 0 ) , mode) . unwrap ( ) ;
885
+ can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 1 ) , & Ix1 ( 2 ) , mode) . unwrap ( ) ;
886
+ can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 1 ) , & Ix1 ( -1isize as usize ) , mode) . unwrap ( ) ;
887
+ can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) , mode) . unwrap_err ( ) ;
888
+ can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix1 ( 2 ) , & Ix1 ( 0 ) , mode) . unwrap_err ( ) ;
889
+ can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) , mode) . unwrap ( ) ;
890
+ can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix1 ( 2 ) , & Ix1 ( -1isize as usize ) , mode) . unwrap ( ) ;
869
891
}
870
892
871
893
#[ test]
872
894
fn can_index_slice_ix2 ( )
873
895
{
874
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 0 ) , & Ix2 ( 0 , 0 ) ) . unwrap ( ) ;
875
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 0 ) , & Ix2 ( 2 , 1 ) ) . unwrap ( ) ;
876
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 1 ) , & Ix2 ( 0 , 0 ) ) . unwrap ( ) ;
877
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 1 ) , & Ix2 ( 2 , 1 ) ) . unwrap ( ) ;
878
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 0 , 0 ) ) . unwrap ( ) ;
879
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 2 , 1 ) ) . unwrap_err ( ) ;
880
- can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix2 ( 1 , 2 ) , & Ix2 ( 5 , 1 ) ) . unwrap_err ( ) ;
881
- can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix2 ( 1 , 2 ) , & Ix2 ( 5 , 1 ) ) . unwrap ( ) ;
882
- can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix2 ( 1 , 2 ) , & Ix2 ( 5 , 2 ) ) . unwrap_err ( ) ;
883
- can_index_slice :: < i32 , _ > ( & [ 1 , 2 , 3 , 4 , 5 ] , & Ix2 ( 2 , 2 ) , & Ix2 ( 3 , 1 ) ) . unwrap ( ) ;
884
- can_index_slice :: < i32 , _ > ( & [ 1 , 2 , 3 , 4 ] , & Ix2 ( 2 , 2 ) , & Ix2 ( 3 , 1 ) ) . unwrap_err ( ) ;
896
+ let mode = CanIndexCheckMode :: OwnedMutable ;
897
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 0 ) , & Ix2 ( 0 , 0 ) , mode) . unwrap ( ) ;
898
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 0 ) , & Ix2 ( 2 , 1 ) , mode) . unwrap ( ) ;
899
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 1 ) , & Ix2 ( 0 , 0 ) , mode) . unwrap ( ) ;
900
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 1 ) , & Ix2 ( 2 , 1 ) , mode) . unwrap ( ) ;
901
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 0 , 0 ) , mode) . unwrap ( ) ;
902
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 2 , 1 ) , mode) . unwrap_err ( ) ;
903
+ can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix2 ( 1 , 2 ) , & Ix2 ( 5 , 1 ) , mode) . unwrap_err ( ) ;
904
+ can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix2 ( 1 , 2 ) , & Ix2 ( 5 , 1 ) , mode) . unwrap ( ) ;
905
+ can_index_slice :: < i32 , _ > ( & [ 1 , 2 ] , & Ix2 ( 1 , 2 ) , & Ix2 ( 5 , 2 ) , mode) . unwrap_err ( ) ;
906
+ can_index_slice :: < i32 , _ > ( & [ 1 , 2 , 3 , 4 , 5 ] , & Ix2 ( 2 , 2 ) , & Ix2 ( 3 , 1 ) , mode) . unwrap ( ) ;
907
+ can_index_slice :: < i32 , _ > ( & [ 1 , 2 , 3 , 4 ] , & Ix2 ( 2 , 2 ) , & Ix2 ( 3 , 1 ) , mode) . unwrap_err ( ) ;
908
+
909
+ // aliasing strides: ok when readonly
910
+ can_index_slice :: < i32 , _ > ( & [ 0 ; 4 ] , & Ix2 ( 2 , 2 ) , & Ix2 ( 1 , 1 ) , CanIndexCheckMode :: OwnedMutable ) . unwrap_err ( ) ;
911
+ can_index_slice :: < i32 , _ > ( & [ 0 ; 4 ] , & Ix2 ( 2 , 2 ) , & Ix2 ( 1 , 1 ) , CanIndexCheckMode :: ReadOnly ) . unwrap ( ) ;
885
912
}
886
913
887
914
#[ test]
888
915
fn can_index_slice_ix3 ( )
889
916
{
890
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix3 ( 0 , 0 , 1 ) , & Ix3 ( 2 , 1 , 3 ) ) . unwrap ( ) ;
891
- can_index_slice :: < i32 , _ > ( & [ ] , & Ix3 ( 1 , 1 , 1 ) , & Ix3 ( 2 , 1 , 3 ) ) . unwrap_err ( ) ;
892
- can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix3 ( 1 , 1 , 1 ) , & Ix3 ( 2 , 1 , 3 ) ) . unwrap ( ) ;
893
- can_index_slice :: < i32 , _ > ( & [ 1 ; 11 ] , & Ix3 ( 2 , 2 , 3 ) , & Ix3 ( 6 , 3 , 1 ) ) . unwrap_err ( ) ;
894
- can_index_slice :: < i32 , _ > ( & [ 1 ; 12 ] , & Ix3 ( 2 , 2 , 3 ) , & Ix3 ( 6 , 3 , 1 ) ) . unwrap ( ) ;
917
+ let mode = CanIndexCheckMode :: OwnedMutable ;
918
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix3 ( 0 , 0 , 1 ) , & Ix3 ( 2 , 1 , 3 ) , mode) . unwrap ( ) ;
919
+ can_index_slice :: < i32 , _ > ( & [ ] , & Ix3 ( 1 , 1 , 1 ) , & Ix3 ( 2 , 1 , 3 ) , mode) . unwrap_err ( ) ;
920
+ can_index_slice :: < i32 , _ > ( & [ 1 ] , & Ix3 ( 1 , 1 , 1 ) , & Ix3 ( 2 , 1 , 3 ) , mode) . unwrap ( ) ;
921
+ can_index_slice :: < i32 , _ > ( & [ 1 ; 11 ] , & Ix3 ( 2 , 2 , 3 ) , & Ix3 ( 6 , 3 , 1 ) , mode) . unwrap_err ( ) ;
922
+ can_index_slice :: < i32 , _ > ( & [ 1 ; 12 ] , & Ix3 ( 2 , 2 , 3 ) , & Ix3 ( 6 , 3 , 1 ) , mode) . unwrap ( ) ;
895
923
}
896
924
897
925
#[ test]
898
926
fn can_index_slice_zero_size_elem ( )
899
927
{
900
- can_index_slice :: < ( ) , _ > ( & [ ] , & Ix1 ( 0 ) , & Ix1 ( 1 ) ) . unwrap ( ) ;
901
- can_index_slice :: < ( ) , _ > ( & [ ( ) ] , & Ix1 ( 1 ) , & Ix1 ( 1 ) ) . unwrap ( ) ;
902
- can_index_slice :: < ( ) , _ > ( & [ ( ) , ( ) ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) ) . unwrap ( ) ;
928
+ let mode = CanIndexCheckMode :: OwnedMutable ;
929
+ can_index_slice :: < ( ) , _ > ( & [ ] , & Ix1 ( 0 ) , & Ix1 ( 1 ) , mode) . unwrap ( ) ;
930
+ can_index_slice :: < ( ) , _ > ( & [ ( ) ] , & Ix1 ( 1 ) , & Ix1 ( 1 ) , mode) . unwrap ( ) ;
931
+ can_index_slice :: < ( ) , _ > ( & [ ( ) , ( ) ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) , mode) . unwrap ( ) ;
903
932
904
933
// These might seem okay because the element type is zero-sized, but
905
934
// there could be a zero-sized type such that the number of instances
906
935
// in existence are carefully controlled.
907
- can_index_slice :: < ( ) , _ > ( & [ ] , & Ix1 ( 1 ) , & Ix1 ( 1 ) ) . unwrap_err ( ) ;
908
- can_index_slice :: < ( ) , _ > ( & [ ( ) ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) ) . unwrap_err ( ) ;
936
+ can_index_slice :: < ( ) , _ > ( & [ ] , & Ix1 ( 1 ) , & Ix1 ( 1 ) , mode ) . unwrap_err ( ) ;
937
+ can_index_slice :: < ( ) , _ > ( & [ ( ) ] , & Ix1 ( 2 ) , & Ix1 ( 1 ) , mode ) . unwrap_err ( ) ;
909
938
910
- can_index_slice :: < ( ) , _ > ( & [ ( ) , ( ) ] , & Ix2 ( 2 , 1 ) , & Ix2 ( 1 , 0 ) ) . unwrap ( ) ;
911
- can_index_slice :: < ( ) , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 0 , 0 ) ) . unwrap ( ) ;
939
+ can_index_slice :: < ( ) , _ > ( & [ ( ) , ( ) ] , & Ix2 ( 2 , 1 ) , & Ix2 ( 1 , 0 ) , mode ) . unwrap ( ) ;
940
+ can_index_slice :: < ( ) , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 0 , 0 ) , mode ) . unwrap ( ) ;
912
941
913
942
// This case would be probably be sound, but that's not entirely clear
914
943
// and it's not worth the special case code.
915
- can_index_slice :: < ( ) , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 2 , 1 ) ) . unwrap_err ( ) ;
944
+ can_index_slice :: < ( ) , _ > ( & [ ] , & Ix2 ( 0 , 2 ) , & Ix2 ( 2 , 1 ) , mode ) . unwrap_err ( ) ;
916
945
}
917
946
918
947
quickcheck ! {
@@ -923,8 +952,8 @@ mod test
923
952
// Avoid overflow `dim.default_strides()` or `dim.fortran_strides()`.
924
953
result. is_err( )
925
954
} else {
926
- result == can_index_slice( & data, & dim, & dim. default_strides( ) ) &&
927
- result == can_index_slice( & data, & dim, & dim. fortran_strides( ) )
955
+ result == can_index_slice( & data, & dim, & dim. default_strides( ) , CanIndexCheckMode :: OwnedMutable ) &&
956
+ result == can_index_slice( & data, & dim, & dim. fortran_strides( ) , CanIndexCheckMode :: OwnedMutable )
928
957
}
929
958
}
930
959
}
0 commit comments