@@ -76,6 +76,11 @@ use crate::simd::{
7676/// [`read`]: pointer::read
7777/// [`write`]: pointer::write
7878/// [as_simd]: slice::as_simd
79+ //
80+ // NOTE: Accessing the inner array directly in any way (e.g. by using the `.0` field syntax) or
81+ // directly constructing an instance of the type (i.e. `let vector = Simd(array)`) should be
82+ // avoided, as it will likely become illegal on `#[repr(simd)]` structs in the future. It also
83+ // causes rustc to emit illegal LLVM IR in some cases.
7984#[ repr( simd) ]
8085pub struct Simd < T , const LANES : usize > ( [ T ; LANES ] )
8186where
@@ -135,22 +140,54 @@ where
135140 /// assert_eq!(v.as_array(), &[0, 1, 2, 3]);
136141 /// ```
137142 pub const fn as_array ( & self ) -> & [ T ; LANES ] {
138- & self . 0
143+ // SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
144+ // is always valid and `Simd<T, LANES>` never has a lower alignment
145+ // than `[T; LANES]`.
146+ //
147+ // NOTE: This deliberately doesn't just use `&self.0`, see the comment
148+ // on the struct definition for details.
149+ unsafe { & * ( self as * const Self as * const [ T ; LANES ] ) }
139150 }
140151
141152 /// Returns a mutable array reference containing the entire SIMD vector.
142153 pub fn as_mut_array ( & mut self ) -> & mut [ T ; LANES ] {
143- & mut self . 0
154+ // SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
155+ // is always valid and `Simd<T, LANES>` never has a lower alignment
156+ // than `[T; LANES]`.
157+ //
158+ // NOTE: This deliberately doesn't just use `&mut self.0`, see the comment
159+ // on the struct definition for details.
160+ unsafe { & mut * ( self as * mut Self as * mut [ T ; LANES ] ) }
144161 }
145162
146163 /// Converts an array to a SIMD vector.
147164 pub const fn from_array ( array : [ T ; LANES ] ) -> Self {
148- Self ( array)
165+ // SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
166+ // is always valid. We need to use `read_unaligned` here, since
167+ // the array may have a lower alignment than the vector.
168+ //
169+ // FIXME: We currently use a pointer read instead of `transmute_copy` because
170+ // it results in better codegen with optimizations disabled, but we should
171+ // probably just use `transmute` once that works on const generic types.
172+ //
173+ // NOTE: This deliberately doesn't just use `Self(array)`, see the comment
174+ // on the struct definition for details.
175+ unsafe { ( & array as * const [ T ; LANES ] as * const Self ) . read_unaligned ( ) }
149176 }
150177
151178 /// Converts a SIMD vector to an array.
152179 pub const fn to_array ( self ) -> [ T ; LANES ] {
153- self . 0
180+ // SAFETY: Transmuting between `Simd<T, LANES>` and `[T; LANES]`
181+ // is always valid. No need to use `read_unaligned` here, since
182+ // the vector never has a lower alignment than the array.
183+ //
184+ // FIXME: We currently use a pointer read instead of `transmute_copy` because
185+ // it results in better codegen with optimizations disabled, but we should
186+ // probably just use `transmute` once that works on const generic types.
187+ //
188+ // NOTE: This deliberately doesn't just use `self.0`, see the comment
189+ // on the struct definition for details.
190+ unsafe { ( & self as * const Self as * const [ T ; LANES ] ) . read ( ) }
154191 }
155192
156193 /// Converts a slice to a SIMD vector containing `slice[..LANES]`.
@@ -735,7 +772,7 @@ where
735772{
736773 #[ inline]
737774 fn as_ref ( & self ) -> & [ T ; LANES ] {
738- & self . 0
775+ self . as_array ( )
739776 }
740777}
741778
@@ -746,7 +783,7 @@ where
746783{
747784 #[ inline]
748785 fn as_mut ( & mut self ) -> & mut [ T ; LANES ] {
749- & mut self . 0
786+ self . as_mut_array ( )
750787 }
751788}
752789
@@ -758,7 +795,7 @@ where
758795{
759796 #[ inline]
760797 fn as_ref ( & self ) -> & [ T ] {
761- & self . 0
798+ self . as_array ( )
762799 }
763800}
764801
@@ -769,7 +806,7 @@ where
769806{
770807 #[ inline]
771808 fn as_mut ( & mut self ) -> & mut [ T ] {
772- & mut self . 0
809+ self . as_mut_array ( )
773810 }
774811}
775812
0 commit comments