Skip to content

Commit b5da8e0

Browse files
committed
Limit MultiSlice impls to flat tuples
1 parent 0b663a9 commit b5da8e0

File tree

4 files changed

+81
-135
lines changed

4 files changed

+81
-135
lines changed

src/impl_methods.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ where
381381
M: MultiSlice<'a, A, D>,
382382
S: DataMut,
383383
{
384-
unsafe { info.slice_and_deref(self.raw_view_mut()) }
384+
info.multi_slice_move(self.view_mut())
385385
}
386386

387387
/// Slice the array, possibly changing the number of dimensions.

src/impl_views/splitting.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@ where
129129
/// * if any of the views would intersect (i.e. if any element would appear in multiple slices)
130130
/// * if an index is out of bounds or step size is zero
131131
/// * if `D` is `IxDyn` and `info` does not match the number of array axes
132-
pub fn multi_slice_move<M>(mut self, info: M) -> M::Output
132+
pub fn multi_slice_move<M>(self, info: M) -> M::Output
133133
where
134134
M: MultiSlice<'a, A, D>,
135135
{
136-
unsafe { info.slice_and_deref(self.raw_view_mut()) }
136+
info.multi_slice_move(self)
137137
}
138138
}

src/slice.rs

+77-131
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// except according to those terms.
88
use crate::dimension::slices_intersect;
99
use crate::error::{ErrorKind, ShapeError};
10-
use crate::{ArrayViewMut, Dimension, RawArrayViewMut};
10+
use crate::{ArrayViewMut, Dimension};
1111
use std::fmt;
1212
use std::marker::PhantomData;
1313
use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
@@ -633,188 +633,134 @@ macro_rules! s(
633633

634634
/// Slicing information describing multiple mutable, disjoint slices.
635635
///
636-
/// It's unfortunate that we need `'out` and `A` to be parameters of the trait,
636+
/// It's unfortunate that we need `'a` and `A` to be parameters of the trait,
637637
/// but they're necessary until Rust supports generic associated types.
638-
///
639-
/// # Safety
640-
///
641-
/// Implementers of this trait must ensure that:
642-
///
643-
/// * `.slice_and_deref()` panics or aborts if the slices would intersect, and
644-
///
645-
/// * the `.intersects_self()`, `.intersects_indices()`, and
646-
/// `.intersects_other()` implementations are correct.
647-
pub unsafe trait MultiSlice<'out, A, D>
638+
pub trait MultiSlice<'a, A, D>
648639
where
649-
A: 'out,
640+
A: 'a,
650641
D: Dimension,
651642
{
652-
/// The type of the slices created by `.slice_and_deref()`.
643+
/// The type of the slices created by `.multi_slice_move()`.
653644
type Output;
654645

655646
/// Slice the raw view into multiple raw views, and dereference them.
656647
///
657648
/// **Panics** if performing any individual slice panics or if the slices
658649
/// are not disjoint (i.e. if they intersect).
659-
///
660-
/// # Safety
661-
///
662-
/// The caller must ensure that it is safe to mutably dereference the view
663-
/// using the lifetime `'out`.
664-
unsafe fn slice_and_deref(&self, view: RawArrayViewMut<A, D>) -> Self::Output;
665-
666-
/// Returns `true` if slicing an array of the specified `shape` with `self`
667-
/// would result in intersecting slices.
668-
///
669-
/// If `self.intersects_self(&view.raw_dim())` is `true`, then
670-
/// `self.slice_and_deref(view)` must panic.
671-
fn intersects_self(&self, shape: &D) -> bool;
672-
673-
/// Returns `true` if any slices created by slicing an array of the
674-
/// specified `shape` with `self` would intersect with the specified
675-
/// indices.
676-
///
677-
/// Note that even if this returns `false`, `self.intersects_self(shape)`
678-
/// may still return `true`. (`.intersects_indices()` doesn't check for
679-
/// intersections within `self`; it only checks for intersections between
680-
/// `self` and `indices`.)
681-
fn intersects_indices(&self, shape: &D, indices: &D::SliceArg) -> bool;
682-
683-
/// Returns `true` if any slices created by slicing an array of the
684-
/// specified `shape` with `self` would intersect any slices created by
685-
/// slicing the array with `other`.
686-
///
687-
/// Note that even if this returns `false`, `self.intersects_self(shape)`
688-
/// or `other.intersects_self(shape)` may still return `true`.
689-
/// (`.intersects_other()` doesn't check for intersections within `self` or
690-
/// within `other`; it only checks for intersections between `self` and
691-
/// `other`.)
692-
fn intersects_other(&self, shape: &D, other: impl MultiSlice<'out, A, D>) -> bool;
650+
fn multi_slice_move(&self, view: ArrayViewMut<'a, A, D>) -> Self::Output;
693651
}
694652

695-
unsafe impl<'out, A, D, Do> MultiSlice<'out, A, D> for SliceInfo<D::SliceArg, Do>
653+
impl<'a, A, D> MultiSlice<'a, A, D> for ()
696654
where
697-
A: 'out,
655+
A: 'a,
698656
D: Dimension,
699-
Do: Dimension,
700657
{
701-
type Output = ArrayViewMut<'out, A, Do>;
702-
703-
unsafe fn slice_and_deref(&self, view: RawArrayViewMut<A, D>) -> Self::Output {
704-
view.slice_move(self).deref_into_view_mut()
705-
}
706-
707-
fn intersects_self(&self, _shape: &D) -> bool {
708-
false
709-
}
710-
711-
fn intersects_indices(&self, shape: &D, indices: &D::SliceArg) -> bool {
712-
slices_intersect(shape, &*self, indices)
713-
}
658+
type Output = ();
714659

715-
fn intersects_other(&self, shape: &D, other: impl MultiSlice<'out, A, D>) -> bool {
716-
other.intersects_indices(shape, &*self)
660+
fn multi_slice_move(&self, _view: ArrayViewMut<'a, A, D>) -> Self::Output {
661+
()
717662
}
718663
}
719664

720-
unsafe impl<'out, A, D> MultiSlice<'out, A, D> for ()
665+
impl<'a, A, D, Do0> MultiSlice<'a, A, D> for (SliceInfo<D::SliceArg, Do0>,)
721666
where
722-
A: 'out,
667+
A: 'a,
723668
D: Dimension,
669+
D::SliceArg: Sized,
670+
Do0: Dimension,
724671
{
725-
type Output = ();
726-
727-
unsafe fn slice_and_deref(&self, _view: RawArrayViewMut<A, D>) -> Self::Output {
728-
()
729-
}
672+
type Output = (ArrayViewMut<'a, A, Do0>,);
730673

731-
fn intersects_self(&self, _shape: &D) -> bool {
732-
false
674+
fn multi_slice_move(&self, view: ArrayViewMut<'a, A, D>) -> Self::Output {
675+
(view.slice_move(&self.0),)
733676
}
677+
}
734678

735-
fn intersects_indices(&self, _shape: &D, _indices: &D::SliceArg) -> bool {
736-
false
737-
}
679+
impl<'a, A, D, Do0> MultiSlice<'a, A, D> for (&SliceInfo<D::SliceArg, Do0>,)
680+
where
681+
A: 'a,
682+
D: Dimension,
683+
Do0: Dimension,
684+
{
685+
type Output = (ArrayViewMut<'a, A, Do0>,);
738686

739-
fn intersects_other(&self, _shape: &D, _other: impl MultiSlice<'out, A, D>) -> bool {
740-
false
687+
fn multi_slice_move(&self, view: ArrayViewMut<'a, A, D>) -> Self::Output {
688+
(view.slice_move(self.0),)
741689
}
742690
}
743691

744692
macro_rules! impl_multislice_tuple {
745-
($($T:ident,)*) => {
746-
unsafe impl<'out, A, D, $($T,)*> MultiSlice<'out, A, D> for ($($T,)*)
693+
($($Do:ident,)*) => {
694+
impl<'a, A, D, $($Do,)*> MultiSlice<'a, A, D> for ($(SliceInfo<D::SliceArg, $Do>,)*)
747695
where
748-
A: 'out,
696+
A: 'a,
749697
D: Dimension,
750-
$($T: MultiSlice<'out, A, D>,)*
698+
D::SliceArg: Sized,
699+
$($Do: Dimension,)*
751700
{
752-
type Output = ($($T::Output,)*);
753-
754-
unsafe fn slice_and_deref(&self, view: RawArrayViewMut<A, D>) -> Self::Output {
755-
assert!(!self.intersects_self(&view.raw_dim()));
701+
type Output = ($(ArrayViewMut<'a, A, $Do>,)*);
756702

703+
fn multi_slice_move(&self, view: ArrayViewMut<'a, A, D>) -> Self::Output {
757704
#[allow(non_snake_case)]
758-
let ($($T,)*) = self;
759-
($($T.slice_and_deref(view.clone()),)*)
760-
}
705+
let ($($Do,)*) = self;
761706

762-
fn intersects_self(&self, shape: &D) -> bool {
763-
#[allow(non_snake_case)]
764-
let ($($T,)*) = self;
765-
impl_multislice_tuple!(@intersects_self shape, ($($T,)*))
766-
}
707+
let shape = view.raw_dim();
708+
assert!(!impl_multislice_tuple!(@intersects_self &shape, ($(&$Do,)*)));
767709

768-
fn intersects_indices(&self, shape: &D, indices: &D::SliceArg) -> bool {
769-
#[allow(non_snake_case)]
770-
let ($($T,)*) = self;
771-
$($T.intersects_indices(shape, indices)) ||*
710+
let raw_view = view.into_raw_view_mut();
711+
unsafe {
712+
($(raw_view.clone().slice_move(&$Do).deref_into_view_mut(),)*)
713+
}
772714
}
715+
}
716+
717+
impl<'a, A, D, $($Do,)*> MultiSlice<'a, A, D> for ($(&SliceInfo<D::SliceArg, $Do>,)*)
718+
where
719+
A: 'a,
720+
D: Dimension,
721+
$($Do: Dimension,)*
722+
{
723+
type Output = ($(ArrayViewMut<'a, A, $Do>,)*);
773724

774-
fn intersects_other(&self, shape: &D, other: impl MultiSlice<'out, A, D>) -> bool {
725+
fn multi_slice_move(&self, view: ArrayViewMut<'a, A, D>) -> Self::Output {
775726
#[allow(non_snake_case)]
776-
let ($($T,)*) = self;
777-
$($T.intersects_other(shape, &other)) ||*
727+
let ($($Do,)*) = self;
728+
729+
let shape = view.raw_dim();
730+
assert!(!impl_multislice_tuple!(@intersects_self &shape, ($($Do,)*)));
731+
732+
let raw_view = view.into_raw_view_mut();
733+
unsafe {
734+
($(raw_view.clone().slice_move($Do).deref_into_view_mut(),)*)
735+
}
778736
}
779737
}
780738
};
739+
781740
(@intersects_self $shape:expr, ($head:expr,)) => {
782-
$head.intersects_self($shape)
741+
false
783742
};
784743
(@intersects_self $shape:expr, ($head:expr, $($tail:expr,)*)) => {
785-
$head.intersects_self($shape) ||
786-
$($head.intersects_other($shape, &$tail)) ||* ||
787-
impl_multislice_tuple!(@intersects_self $shape, ($($tail,)*))
744+
$(slices_intersect($shape, $head, $tail)) ||*
745+
|| impl_multislice_tuple!(@intersects_self $shape, ($($tail,)*))
788746
};
789747
}
790-
impl_multislice_tuple!(T0,);
791-
impl_multislice_tuple!(T0, T1,);
792-
impl_multislice_tuple!(T0, T1, T2,);
793-
impl_multislice_tuple!(T0, T1, T2, T3,);
794-
impl_multislice_tuple!(T0, T1, T2, T3, T4,);
795-
impl_multislice_tuple!(T0, T1, T2, T3, T4, T5,);
796-
797-
unsafe impl<'out, A, D, T> MultiSlice<'out, A, D> for &'_ T
748+
749+
impl_multislice_tuple!(Do0, Do1,);
750+
impl_multislice_tuple!(Do0, Do1, Do2,);
751+
impl_multislice_tuple!(Do0, Do1, Do2, Do3,);
752+
impl_multislice_tuple!(Do0, Do1, Do2, Do3, Do4,);
753+
impl_multislice_tuple!(Do0, Do1, Do2, Do3, Do4, Do5,);
754+
755+
impl<'a, A, D, T> MultiSlice<'a, A, D> for &T
798756
where
799-
A: 'out,
757+
A: 'a,
800758
D: Dimension,
801-
T: MultiSlice<'out, A, D>,
759+
T: MultiSlice<'a, A, D>,
802760
{
803761
type Output = T::Output;
804762

805-
unsafe fn slice_and_deref(&self, view: RawArrayViewMut<A, D>) -> Self::Output {
806-
T::slice_and_deref(self, view)
807-
}
808-
809-
fn intersects_self(&self, shape: &D) -> bool {
810-
T::intersects_self(self, shape)
811-
}
812-
813-
fn intersects_indices(&self, shape: &D, indices: &D::SliceArg) -> bool {
814-
T::intersects_indices(self, shape, indices)
815-
}
816-
817-
fn intersects_other(&self, shape: &D, other: impl MultiSlice<'out, A, D>) -> bool {
818-
T::intersects_other(self, shape, other)
763+
fn multi_slice_move(&self, view: ArrayViewMut<'a, A, D>) -> Self::Output {
764+
T::multi_slice_move(self, view)
819765
}
820766
}

tests/array.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ fn test_multislice() {
354354
});
355355
let mut arr = Array1::from_iter(0..48).into_shape((8, 6)).unwrap();
356356

357-
assert_eq!(arr.clone().view(), arr.multi_slice_mut(s![.., ..]));
357+
assert_eq!((arr.clone().view_mut(),), arr.multi_slice_mut((s![.., ..],)));
358358
test_multislice!(&mut arr, s![0, ..], s![1, ..]);
359359
test_multislice!(&mut arr, s![0, ..], s![-1, ..]);
360360
test_multislice!(&mut arr, s![0, ..], s![1.., ..]);

0 commit comments

Comments
 (0)