@@ -76,6 +76,11 @@ use crate::simd::{
76
76
/// [`read`]: pointer::read
77
77
/// [`write`]: pointer::write
78
78
/// [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.
79
84
#[ repr( simd) ]
80
85
pub struct Simd < T , const LANES : usize > ( [ T ; LANES ] )
81
86
where
@@ -135,22 +140,54 @@ where
135
140
/// assert_eq!(v.as_array(), &[0, 1, 2, 3]);
136
141
/// ```
137
142
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 ] ) }
139
150
}
140
151
141
152
/// Returns a mutable array reference containing the entire SIMD vector.
142
153
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 ] ) }
144
161
}
145
162
146
163
/// Converts an array to a SIMD vector.
147
164
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 ( ) }
149
176
}
150
177
151
178
/// Converts a SIMD vector to an array.
152
179
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 ( ) }
154
191
}
155
192
156
193
/// Converts a slice to a SIMD vector containing `slice[..LANES]`.
@@ -735,7 +772,7 @@ where
735
772
{
736
773
#[ inline]
737
774
fn as_ref ( & self ) -> & [ T ; LANES ] {
738
- & self . 0
775
+ self . as_array ( )
739
776
}
740
777
}
741
778
@@ -746,7 +783,7 @@ where
746
783
{
747
784
#[ inline]
748
785
fn as_mut ( & mut self ) -> & mut [ T ; LANES ] {
749
- & mut self . 0
786
+ self . as_mut_array ( )
750
787
}
751
788
}
752
789
@@ -758,7 +795,7 @@ where
758
795
{
759
796
#[ inline]
760
797
fn as_ref ( & self ) -> & [ T ] {
761
- & self . 0
798
+ self . as_array ( )
762
799
}
763
800
}
764
801
@@ -769,7 +806,7 @@ where
769
806
{
770
807
#[ inline]
771
808
fn as_mut ( & mut self ) -> & mut [ T ] {
772
- & mut self . 0
809
+ self . as_mut_array ( )
773
810
}
774
811
}
775
812
0 commit comments