diff --git a/src/lib.rs b/src/lib.rs index 334b8682e..62a40f397 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -126,10 +126,7 @@ pub use crate::dimension::IxDynImpl; pub use crate::dimension::NdIndex; pub use crate::error::{ErrorKind, ShapeError}; pub use crate::indexes::{indices, indices_of}; -pub use crate::slice::{ - deref_raw_view_mut_into_view_mut_with_life, deref_raw_view_mut_into_view_with_life, - life_of_view_mut, Slice, SliceInfo, SliceNextDim, SliceOrIndex, -}; +pub use crate::slice::{Slice, SliceInfo, SliceNextDim, SliceOrIndex}; use crate::iterators::Baseiter; use crate::iterators::{ElementsBase, ElementsBaseMut, Iter, IterMut, Lanes, LanesMut}; diff --git a/src/slice.rs b/src/slice.rs index 045480d8f..575b60783 100644 --- a/src/slice.rs +++ b/src/slice.rs @@ -7,7 +7,7 @@ // except according to those terms. use crate::dimension::slices_intersect; use crate::error::{ErrorKind, ShapeError}; -use crate::{ArrayView, ArrayViewMut, Dimension, RawArrayViewMut}; +use crate::{ArrayViewMut, Dimension, RawArrayViewMut}; use std::fmt; use std::marker::PhantomData; use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; @@ -631,380 +631,6 @@ macro_rules! s( }; ); -/// Returns a ZST representing the lifetime of the mutable view. -#[doc(hidden)] -pub fn life_of_view_mut<'a, A, D: Dimension>( - _view: &ArrayViewMut<'a, A, D>, -) -> PhantomData<&'a mut A> { - PhantomData -} - -/// Derefs the raw mutable view into a view, using the given lifetime. -#[doc(hidden)] -pub unsafe fn deref_raw_view_mut_into_view_with_life<'a, A, D: Dimension>( - raw: RawArrayViewMut, - _life: PhantomData<&'a mut A>, -) -> ArrayView<'a, A, D> { - raw.deref_into_view() -} - -/// Derefs the raw mutable view into a mutable view, using the given lifetime. -#[doc(hidden)] -pub unsafe fn deref_raw_view_mut_into_view_mut_with_life<'a, A, D: Dimension>( - raw: RawArrayViewMut, - _life: PhantomData<&'a mut A>, -) -> ArrayViewMut<'a, A, D> { - raw.deref_into_view_mut() -} - -/// Take multiple slices simultaneously. -/// -/// This macro makes it possible to take multiple slices of the same array, as -/// long as Rust's aliasing rules are followed for *elements* in the slices. -/// For example, it's possible to take two disjoint, mutable slices of an -/// array, with one referencing the even-index elements and the other -/// referencing the odd-index elements. If you tried to achieve this by calling -/// `.slice_mut()` twice, the borrow checker would complain about mutably -/// borrowing the array twice (even though it's safe as long as the slices are -/// disjoint). -/// -/// The syntax is `multislice!(` *expression, pattern [, pattern [, …]]* `)`, -/// where *expression* evaluates to a mutable array, and each *pattern* is -/// either -/// -/// * `mut` *s-args-or-expr*: creates an `ArrayViewMut` or -/// * *s-args-or-expr*: creates an `ArrayView` -/// -/// where *s-args-or-expr* is either (1) arguments enclosed in `[]` to pass to -/// the [`s!`] macro to create a `&SliceInfo` instance or (2) an expression -/// that evaluates to a `&SliceInfo` instance. -/// -/// **Note** that this macro always mutably borrows the array even if there are -/// no `mut` patterns. If all you want to do is take read-only slices, you -/// don't need `multislice!()`; just call -/// [`.slice()`](struct.ArrayBase.html#method.slice) multiple times instead. -/// -/// `multislice!()` evaluates to a tuple of `ArrayView` and/or `ArrayViewMut` -/// instances. It checks Rust's aliasing rules: -/// -/// * An `ArrayViewMut` and `ArrayView` cannot reference the same element. -/// * Two `ArrayViewMut` cannot reference the same element. -/// * Two `ArrayView` can reference the same element. -/// -/// **Panics** at runtime if any of the aliasing rules is violated. -/// -/// See also [*Slicing*](struct.ArrayBase.html#slicing). -/// -/// # Examples -/// -/// In this example, there are two overlapping read-only slices, and two -/// disjoint mutable slices. Neither of the mutable slices intersects any of -/// the other slices. -/// -/// ``` -/// extern crate ndarray; -/// -/// use ndarray::multislice; -/// use ndarray::prelude::*; -/// -/// # fn main() { -/// let mut arr: Array1<_> = (0..12).collect(); -/// let (a, b, c, d) = multislice!(arr, [0..5], mut [6..;2], [1..6], mut [7..;2]); -/// assert_eq!(a, array![0, 1, 2, 3, 4]); -/// assert_eq!(b, array![6, 8, 10]); -/// assert_eq!(c, array![1, 2, 3, 4, 5]); -/// assert_eq!(d, array![7, 9, 11]); -/// # } -/// ``` -/// -/// These examples panic because they don't follow the aliasing rules: -/// -/// * `ArrayViewMut` and `ArrayView` cannot reference the same element. -/// -/// ```should_panic -/// # extern crate ndarray; -/// # use ndarray::multislice; -/// # use ndarray::prelude::*; -/// # fn main() { -/// let mut arr: Array1<_> = (0..12).collect(); -/// multislice!(arr, [0..5], mut [1..;2]); // panic! -/// # } -/// ``` -/// -/// * Two `ArrayViewMut` cannot reference the same element. -/// -/// ```should_panic -/// # extern crate ndarray; -/// # use ndarray::multislice; -/// # use ndarray::prelude::*; -/// # fn main() { -/// let mut arr: Array1<_> = (0..12).collect(); -/// multislice!(arr, mut [0..5], mut [1..;2]); // panic! -/// # } -/// ``` -#[macro_export] -macro_rules! multislice( - (@check $view:expr, $info:expr, ()) => {}; - // Check that $info doesn't intersect $other. - (@check $view:expr, $info:expr, ($other:expr,)) => { - assert!( - !$crate::slices_intersect(&$view.raw_dim(), $info, $other), - "Slice {:?} must not intersect slice {:?}", $info, $other - ) - }; - // Check that $info doesn't intersect any of the other info in the tuple. - (@check $view:expr, $info:expr, ($other:expr, $($more:tt)*)) => { - { - $crate::multislice!(@check $view, $info, ($other,)); - $crate::multislice!(@check $view, $info, ($($more)*)); - } - }; - // Create the (mutable) slice. - (@slice $view:expr, $life:expr, mut $info:expr) => { - #[allow(unsafe_code)] - unsafe { - $crate::deref_raw_view_mut_into_view_mut_with_life( - $view.clone().slice_move($info), - $life, - ) - } - }; - // Create the (read-only) slice. - (@slice $view:expr, $life:expr, $info:expr) => { - #[allow(unsafe_code)] - unsafe { - $crate::deref_raw_view_mut_into_view_with_life( - $view.clone().slice_move($info), - $life, - ) - } - }; - // Parse last slice (mutable), no trailing comma, applying `s![]` macro. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - (mut [$($info:tt)*]) - ) => { - // Apply `s![]` macro to info. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - (mut $crate::s![$($info)*],) - ) - }; - // Parse last slice (read-only), no trailing comma, applying `s![]` macro. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - ([$($info:tt)*]) - ) => { - // Apply `s![]` macro to info. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - ($crate::s![$($info)*],) - ) - }; - // Parse last slice (mutable), with trailing comma, applying `s![]` macro. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - (mut [$($info:tt)*],) - ) => { - // Apply `s![]` macro to info. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - (mut $crate::s![$($info)*],) - ) - }; - // Parse last slice (read-only), with trailing comma, applying `s![]` macro. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - ([$($info:tt)*],) - ) => { - // Apply `s![]` macro to info. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - ($crate::s![$($info)*],) - ) - }; - // Parse a mutable slice, applying `s![]` macro. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - (mut [$($info:tt)*], $($t:tt)*) - ) => { - // Apply `s![]` macro to info. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - (mut $crate::s![$($info)*], $($t)*) - ) - }; - // Parse a read-only slice, applying `s![]` macro. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - ([$($info:tt)*], $($t:tt)*) - ) => { - // Apply `s![]` macro to info. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - ($crate::s![$($info)*], $($t)*) - ) - }; - // Parse last slice (mutable), no trailing comma. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - (mut $info:expr) - ) => { - // Add trailing comma. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - (mut $info,) - ) - }; - // Parse last slice (read-only), no trailing comma. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - ($info:expr) - ) => { - // Add trailing comma. - $crate::multislice!( - @parse $view, $life, - ($($sliced)*), - ($($mut_info)*), - ($($immut_info)*), - ($info,) - ) - }; - // Parse last slice (mutable), with trailing comma. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - (mut $info:expr,) - ) => { - match $info { - info => { - // Check for overlap with all previous mutable and immutable slices. - $crate::multislice!(@check $view, info, ($($mut_info)*)); - $crate::multislice!(@check $view, info, ($($immut_info)*)); - ($($sliced)* $crate::multislice!(@slice $view, $life, mut info),) - } - } - }; - // Parse last slice (read-only), with trailing comma. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - ($info:expr,) - ) => { - match $info { - info => { - // Check for overlap with all previous mutable slices. - $crate::multislice!(@check $view, info, ($($mut_info)*)); - ($($sliced)* $crate::multislice!(@slice $view, $life, info),) - } - } - }; - // Parse a mutable slice. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - (mut $info:expr, $($t:tt)*) - ) => { - match $info { - info => { - // Check for overlap with all previous mutable and immutable slices. - $crate::multislice!(@check $view, info, ($($mut_info)*)); - $crate::multislice!(@check $view, info, ($($immut_info)*)); - $crate::multislice!( - @parse $view, $life, - ($($sliced)* $crate::multislice!(@slice $view, $life, mut info),), - ($($mut_info)* info,), - ($($immut_info)*), - ($($t)*) - ) - } - } - }; - // Parse a read-only slice. - ( - @parse $view:expr, $life:expr, - ($($sliced:tt)*), - ($($mut_info:tt)*), - ($($immut_info:tt)*), - ($info:expr, $($t:tt)*) - ) => { - match $info { - info => { - // Check for overlap with all previous mutable slices. - $crate::multislice!(@check $view, info, ($($mut_info)*)); - $crate::multislice!( - @parse $view, $life, - ($($sliced)* $crate::multislice!(@slice $view, $life, info),), - ($($mut_info)*), - ($($immut_info)* info,), - ($($t)*) - ) - } - } - }; - // Entry point. - ($arr:expr, $($t:tt)*) => { - { - let (life, raw_view) = { - let mut view = $crate::ArrayBase::view_mut(&mut $arr); - ($crate::life_of_view_mut(&view), view.raw_view_mut()) - }; - $crate::multislice!(@parse raw_view, life, (), (), (), ($($t)*)) - } - }; -); - /// Slicing information describing multiple mutable, disjoint slices. /// /// It's unfortunate that we need `'out` and `A` to be parameters of the trait, diff --git a/tests/array.rs b/tests/array.rs index 722fe488b..ef70e5c0e 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -11,7 +11,7 @@ use defmac::defmac; use itertools::{enumerate, zip, Itertools}; use ndarray::indices; use ndarray::prelude::*; -use ndarray::{arr3, multislice, rcarr2}; +use ndarray::{arr3, rcarr2}; use ndarray::{Slice, SliceInfo, SliceOrIndex}; use std::iter::FromIterator;