Repository: rust-ndarray/ndarray (rust)

Issue:
Add/remove aliasing checks in constructors
- [ ] `ArrayViewMut::from_shape_ptr` should make sure that elements don't alias (with at least a debug assertion). #1413
- [x] `ArrayView::from_shape` should not check aliasing. #1410

Pull request:
Check for aliasing in `RawViewMut::from_shape_ptr` with a debug assertion
It should deny overlapping indexes. Because it's an unsafe function and we only do these checks on best-effort basis (caller has to ensure they are correct), it's a debug assertion.

Removed the small addition to a doc comment that was done in a previous PR (it was an unfinished idea).

Similar to pr #1410
Finishes and closes #919

Patch:
diff --git a/src/dimension/mod.rs b/src/dimension/mod.rs
index 2ae851d1..601f0dc4 100644
--- a/src/dimension/mod.rs
+++ b/src/dimension/mod.rs
@@ -55,7 +55,7 @@ pub fn stride_offset(n: Ix, stride: Ix) -> isize
 /// There is overlap if, when iterating through the dimensions in order of
 /// increasing stride, the current stride is less than or equal to the maximum
 /// possible offset along the preceding axes. (Axes of length ≤1 are ignored.)
-pub fn dim_stride_overlap<D: Dimension>(dim: &D, strides: &D) -> bool
+pub(crate) fn dim_stride_overlap<D: Dimension>(dim: &D, strides: &D) -> bool
 {
     let order = strides._fastest_varying_stride_order();
     let mut sum_prev_offsets = 0;
@@ -255,8 +255,6 @@ where D: Dimension
 /// allocation. (In other words, the pointer to the first element of the array
 /// must be computed using `offset_from_low_addr_ptr_to_logical_ptr` so that
 /// negative strides are correctly handled.)
-///
-/// Note, condition (4) is guaranteed to be checked last
 pub(crate) fn can_index_slice<A, D: Dimension>(
     data: &[A], dim: &D, strides: &D, mode: CanIndexCheckMode,
 ) -> Result<(), ShapeError>
diff --git a/src/impl_raw_views.rs b/src/impl_raw_views.rs
index fca5e7de..5132b115 100644
--- a/src/impl_raw_views.rs
+++ b/src/impl_raw_views.rs
@@ -294,6 +294,8 @@ where D: Dimension
             if let Strides::Custom(strides) = &shape.strides {
                 dimension::strides_non_negative(strides).unwrap();
                 dimension::max_abs_offset_check_overflow::<A, _>(&dim, strides).unwrap();
+                assert!(!dimension::dim_stride_overlap(&dim, strides),
+                        "The strides must not allow any element to be referenced by two different indices");
             } else {
                 dimension::size_of_shape_checked(&dim).unwrap();
             }


Test patch:
diff --git a/tests/array.rs b/tests/array.rs
index 4de22794..696904da 100644
--- a/tests/array.rs
+++ b/tests/array.rs
@@ -2281,6 +2281,29 @@ fn test_raw_view_mut_from_shape_ptr_deny_neg_strides()
     let _view = unsafe { RawArrayViewMut::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_mut_ptr()) };
 }
 
+#[test]
+fn test_raw_view_from_shape_allow_overlap()
+{
+    let data = [0, 1, 2];
+    let view;
+    unsafe {
+        let raw_view = RawArrayView::from_shape_ptr((2, 3).strides((0, 1)), data.as_ptr());
+        view = raw_view.deref_into_view();
+    }
+    assert_eq!(view, aview2(&[data, data]));
+}
+
+#[should_panic(expected = "strides must not allow any element")]
+#[cfg(debug_assertions)]
+#[test]
+fn test_raw_view_mut_from_shape_deny_overlap()
+{
+    let mut data = [0, 1, 2];
+    unsafe {
+        RawArrayViewMut::from_shape_ptr((2, 3).strides((0, 1)), data.as_mut_ptr());
+    }
+}
+
 #[test]
 fn test_default()
 {