@@ -9,7 +9,7 @@ use error::{ShapeError, ErrorKind};
99use std:: ops:: { Deref , Range , RangeFrom , RangeFull , RangeInclusive , RangeTo , RangeToInclusive } ;
1010use std:: fmt;
1111use std:: marker:: PhantomData ;
12- use super :: Dimension ;
12+ use crate :: { ArrayView , ArrayViewMut , Dimension , RawArrayViewMut } ;
1313
1414/// A slice (range with step size).
1515///
@@ -624,6 +624,32 @@ macro_rules! s(
624624 } ;
625625) ;
626626
627+ /// Returns a ZST representing the lifetime of the mutable view.
628+ #[ doc( hidden) ]
629+ pub fn life_of_view_mut < ' a , A , D : Dimension > (
630+ _view : & ArrayViewMut < ' a , A , D >
631+ ) -> PhantomData < & ' a mut A > {
632+ PhantomData
633+ }
634+
635+ /// Derefs the raw mutable view into a view, using the given lifetime.
636+ #[ doc( hidden) ]
637+ pub unsafe fn deref_raw_view_mut_into_view_with_life < ' a , A , D : Dimension > (
638+ raw : RawArrayViewMut < A , D > ,
639+ _life : PhantomData < & ' a mut A > ,
640+ ) -> ArrayView < ' a , A , D > {
641+ raw. deref_into_view ( )
642+ }
643+
644+ /// Derefs the raw mutable view into a mutable view, using the given lifetime.
645+ #[ doc( hidden) ]
646+ pub unsafe fn deref_raw_view_mut_into_view_mut_with_life < ' a , A , D : Dimension > (
647+ raw : RawArrayViewMut < A , D > ,
648+ _life : PhantomData < & ' a mut A > ,
649+ ) -> ArrayViewMut < ' a , A , D > {
650+ raw. deref_into_view_mut ( )
651+ }
652+
627653/// Take multiple slices simultaneously.
628654///
629655/// This macro makes it possible to take multiple slices of the same array, as
@@ -706,110 +732,124 @@ macro_rules! s(
706732/// ```
707733#[ macro_export]
708734macro_rules! multislice(
709- (
710- @check $view: expr,
711- $info: expr,
712- ( )
713- ) => { } ;
735+ ( @check $view: expr, $info: expr, ( ) ) => { } ;
714736 // Check that $info doesn't intersect $other.
715- (
716- @check $view: expr,
717- $info: expr,
718- ( $other: expr, )
719- ) => {
737+ ( @check $view: expr, $info: expr, ( $other: expr, ) ) => {
720738 assert!(
721739 !$crate:: slices_intersect( & $view. raw_dim( ) , $info, $other) ,
722740 "Slice {:?} must not intersect slice {:?}" , $info, $other
723741 )
724742 } ;
725743 // Check that $info doesn't intersect any of the other info in the tuple.
726- (
727- @check $view: expr,
728- $info: expr,
729- ( $other: expr, $( $more: tt) * )
730- ) => {
744+ ( @check $view: expr, $info: expr, ( $other: expr, $( $more: tt) * ) ) => {
731745 {
732746 multislice!( @check $view, $info, ( $other, ) ) ;
733747 multislice!( @check $view, $info, ( $( $more) * ) ) ;
734748 }
735749 } ;
750+ // Create the (mutable) slice.
751+ ( @slice $view: expr, $life: expr, mut $info: expr) => {
752+ #[ allow( unsafe_code) ]
753+ unsafe {
754+ $crate:: deref_raw_view_mut_into_view_mut_with_life(
755+ $view. clone( ) . slice_move( $info) ,
756+ $life,
757+ )
758+ }
759+ } ;
760+ // Create the (read-only) slice.
761+ ( @slice $view: expr, $life: expr, $info: expr) => {
762+ #[ allow( unsafe_code) ]
763+ unsafe {
764+ $crate:: deref_raw_view_mut_into_view_with_life(
765+ $view. clone( ) . slice_move( $info) ,
766+ $life,
767+ )
768+ }
769+ } ;
736770 // Parse last slice (mutable), no trailing comma.
737771 (
738- @parse $view: expr,
772+ @parse $view: expr, $life : expr ,
739773 ( $( $sliced: tt) * ) ,
740774 ( $( $mut_info: tt) * ) ,
741775 ( $( $immut_info: tt) * ) ,
742776 ( mut $info: expr)
743777 ) => {
744- match $info {
745- info => {
746- multislice!( @check $view, info, ( $( $mut_info) * ) ) ;
747- multislice!( @check $view, info, ( $( $immut_info) * ) ) ;
748- ( $( $sliced) * unsafe { $view. aliasing_view_mut( ) } . slice_move( info) )
749- }
750- }
778+ // Add trailing comma.
779+ multislice!(
780+ @parse $view, $life,
781+ ( $( $sliced) * ) ,
782+ ( $( $mut_info) * ) ,
783+ ( $( $immut_info) * ) ,
784+ ( mut $info, )
785+ )
751786 } ;
752787 // Parse last slice (read-only), no trailing comma.
753788 (
754- @parse $view: expr,
789+ @parse $view: expr, $life : expr ,
755790 ( $( $sliced: tt) * ) ,
756791 ( $( $mut_info: tt) * ) ,
757792 ( $( $immut_info: tt) * ) ,
758793 ( $info: expr)
759794 ) => {
760- match $info {
761- info => {
762- multislice!( @check $view, info, ( $( $mut_info) * ) ) ;
763- ( $( $sliced) * unsafe { $view. aliasing_view( ) } . slice_move( info) )
764- }
765- }
795+ // Add trailing comma.
796+ multislice!(
797+ @parse $view, $life,
798+ ( $( $sliced) * ) ,
799+ ( $( $mut_info) * ) ,
800+ ( $( $immut_info) * ) ,
801+ ( $info, )
802+ )
766803 } ;
767804 // Parse last slice (mutable), with trailing comma.
768805 (
769- @parse $view: expr,
806+ @parse $view: expr, $life : expr ,
770807 ( $( $sliced: tt) * ) ,
771808 ( $( $mut_info: tt) * ) ,
772809 ( $( $immut_info: tt) * ) ,
773810 ( mut $info: expr, )
774811 ) => {
775812 match $info {
776813 info => {
814+ // Check for overlap with all previous mutable and immutable slices.
777815 multislice!( @check $view, info, ( $( $mut_info) * ) ) ;
778816 multislice!( @check $view, info, ( $( $immut_info) * ) ) ;
779- ( $( $sliced) * unsafe { $view. aliasing_view_mut ( ) } . slice_move ( info) )
817+ ( $( $sliced) * multislice! ( @slice $view, $life , mut info) , )
780818 }
781819 }
782820 } ;
783821 // Parse last slice (read-only), with trailing comma.
784822 (
785- @parse $view: expr,
823+ @parse $view: expr, $life : expr ,
786824 ( $( $sliced: tt) * ) ,
787825 ( $( $mut_info: tt) * ) ,
788826 ( $( $immut_info: tt) * ) ,
789827 ( $info: expr, )
790828 ) => {
791829 match $info {
792830 info => {
831+ // Check for overlap with all previous mutable slices.
793832 multislice!( @check $view, info, ( $( $mut_info) * ) ) ;
794- ( $( $sliced) * unsafe { $view. aliasing_view ( ) } . slice_move ( info) )
833+ ( $( $sliced) * multislice! ( @slice $view, $life , info) , )
795834 }
796835 }
797836 } ;
798837 // Parse a mutable slice.
799838 (
800- @parse $view: expr,
839+ @parse $view: expr, $life : expr ,
801840 ( $( $sliced: tt) * ) ,
802841 ( $( $mut_info: tt) * ) ,
803842 ( $( $immut_info: tt) * ) ,
804843 ( mut $info: expr, $( $t: tt) * )
805844 ) => {
806845 match $info {
807846 info => {
847+ // Check for overlap with all previous mutable and immutable slices.
808848 multislice!( @check $view, info, ( $( $mut_info) * ) ) ;
809849 multislice!( @check $view, info, ( $( $immut_info) * ) ) ;
810850 multislice!(
811- @parse $view,
812- ( $( $sliced) * unsafe { $view. aliasing_view_mut ( ) } . slice_move ( info) , ) ,
851+ @parse $view, $life ,
852+ ( $( $sliced) * multislice! ( @slice $view, $life , mut info) , ) ,
813853 ( $( $mut_info) * info, ) ,
814854 ( $( $immut_info) * ) ,
815855 ( $( $t) * )
@@ -819,18 +859,19 @@ macro_rules! multislice(
819859 } ;
820860 // Parse a read-only slice.
821861 (
822- @parse $view: expr,
862+ @parse $view: expr, $life : expr ,
823863 ( $( $sliced: tt) * ) ,
824864 ( $( $mut_info: tt) * ) ,
825865 ( $( $immut_info: tt) * ) ,
826866 ( $info: expr, $( $t: tt) * )
827867 ) => {
828868 match $info {
829869 info => {
870+ // Check for overlap with all previous mutable slices.
830871 multislice!( @check $view, info, ( $( $mut_info) * ) ) ;
831872 multislice!(
832- @parse $view,
833- ( $( $sliced) * unsafe { $view. aliasing_view ( ) } . slice_move ( info) , ) ,
873+ @parse $view, $life ,
874+ ( $( $sliced) * multislice! ( @slice $view, $life , info) , ) ,
834875 ( $( $mut_info) * ) ,
835876 ( $( $immut_info) * info, ) ,
836877 ( $( $t) * )
@@ -841,8 +882,11 @@ macro_rules! multislice(
841882 // Entry point.
842883 ( $arr: expr, ( $( $t: tt) * ) ) => {
843884 {
844- let view = $crate:: ArrayBase :: view_mut( & mut $arr) ;
845- multislice!( @parse view, ( ) , ( ) , ( ) , ( $( $t) * ) )
885+ let ( life, raw_view) = {
886+ let mut view = $crate:: ArrayBase :: view_mut( & mut $arr) ;
887+ ( $crate:: life_of_view_mut( & view) , view. raw_view_mut( ) )
888+ } ;
889+ multislice!( @parse raw_view, life, ( ) , ( ) , ( ) , ( $( $t) * ) )
846890 }
847891 } ;
848892) ;
0 commit comments