Skip to content

Commit dddfffc

Browse files
calebzulawskiworkingjubilee
authored andcommitted
Add some safety comments
1 parent 6143bde commit dddfffc

File tree

11 files changed

+57
-5
lines changed

11 files changed

+57
-5
lines changed

crates/core_simd/src/comparisons.rs

+12
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ where
1010
#[inline]
1111
#[must_use = "method returns a new mask and does not mutate the original value"]
1212
pub fn lanes_eq(self, other: Self) -> Mask<T::Mask, LANES> {
13+
// Safety: `self` is a vector, and the result of the comparison
14+
// is always a valid mask.
1315
unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) }
1416
}
1517

1618
/// Test if each lane is not equal to the corresponding lane in `other`.
1719
#[inline]
1820
#[must_use = "method returns a new mask and does not mutate the original value"]
1921
pub fn lanes_ne(self, other: Self) -> Mask<T::Mask, LANES> {
22+
// Safety: `self` is a vector, and the result of the comparison
23+
// is always a valid mask.
2024
unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) }
2125
}
2226
}
@@ -30,27 +34,35 @@ where
3034
#[inline]
3135
#[must_use = "method returns a new mask and does not mutate the original value"]
3236
pub fn lanes_lt(self, other: Self) -> Mask<T::Mask, LANES> {
37+
// Safety: `self` is a vector, and the result of the comparison
38+
// is always a valid mask.
3339
unsafe { Mask::from_int_unchecked(intrinsics::simd_lt(self, other)) }
3440
}
3541

3642
/// Test if each lane is greater than the corresponding lane in `other`.
3743
#[inline]
3844
#[must_use = "method returns a new mask and does not mutate the original value"]
3945
pub fn lanes_gt(self, other: Self) -> Mask<T::Mask, LANES> {
46+
// Safety: `self` is a vector, and the result of the comparison
47+
// is always a valid mask.
4048
unsafe { Mask::from_int_unchecked(intrinsics::simd_gt(self, other)) }
4149
}
4250

4351
/// Test if each lane is less than or equal to the corresponding lane in `other`.
4452
#[inline]
4553
#[must_use = "method returns a new mask and does not mutate the original value"]
4654
pub fn lanes_le(self, other: Self) -> Mask<T::Mask, LANES> {
55+
// Safety: `self` is a vector, and the result of the comparison
56+
// is always a valid mask.
4757
unsafe { Mask::from_int_unchecked(intrinsics::simd_le(self, other)) }
4858
}
4959

5060
/// Test if each lane is greater than or equal to the corresponding lane in `other`.
5161
#[inline]
5262
#[must_use = "method returns a new mask and does not mutate the original value"]
5363
pub fn lanes_ge(self, other: Self) -> Mask<T::Mask, LANES> {
64+
// Safety: `self` is a vector, and the result of the comparison
65+
// is always a valid mask.
5466
unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) }
5567
}
5668
}

crates/core_simd/src/masks.rs

+9
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ mod sealed {
4242
use sealed::Sealed;
4343

4444
/// Marker trait for types that may be used as SIMD mask elements.
45+
///
46+
/// # Safety
47+
/// Type must be a signed integer.
4548
pub unsafe trait MaskElement: SimdElement + Sealed {}
4649

4750
macro_rules! impl_element {
@@ -149,6 +152,7 @@ where
149152
#[inline]
150153
#[must_use = "method returns a new mask and does not mutate the original value"]
151154
pub unsafe fn from_int_unchecked(value: Simd<T, LANES>) -> Self {
155+
// Safety: the caller must confirm this invariant
152156
unsafe { Self(mask_impl::Mask::from_int_unchecked(value)) }
153157
}
154158

@@ -161,6 +165,7 @@ where
161165
#[must_use = "method returns a new mask and does not mutate the original value"]
162166
pub fn from_int(value: Simd<T, LANES>) -> Self {
163167
assert!(T::valid(value), "all values must be either 0 or -1",);
168+
// Safety: the validity has been checked
164169
unsafe { Self::from_int_unchecked(value) }
165170
}
166171

@@ -179,6 +184,7 @@ where
179184
#[inline]
180185
#[must_use = "method returns a new bool and does not mutate the original value"]
181186
pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
187+
// Safety: the caller must confirm this invariant
182188
unsafe { self.0.test_unchecked(lane) }
183189
}
184190

@@ -190,6 +196,7 @@ where
190196
#[must_use = "method returns a new bool and does not mutate the original value"]
191197
pub fn test(&self, lane: usize) -> bool {
192198
assert!(lane < LANES, "lane index out of range");
199+
// Safety: the lane index has been checked
193200
unsafe { self.test_unchecked(lane) }
194201
}
195202

@@ -199,6 +206,7 @@ where
199206
/// `lane` must be less than `LANES`.
200207
#[inline]
201208
pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
209+
// Safety: the caller must confirm this invariant
202210
unsafe {
203211
self.0.set_unchecked(lane, value);
204212
}
@@ -211,6 +219,7 @@ where
211219
#[inline]
212220
pub fn set(&mut self, lane: usize, value: bool) {
213221
assert!(lane < LANES, "lane index out of range");
222+
// Safety: the lane index has been checked
214223
unsafe {
215224
self.set_unchecked(lane, value);
216225
}

crates/core_simd/src/masks/bitmask.rs

+1
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ where
137137
where
138138
U: MaskElement,
139139
{
140+
// Safety: bitmask layout does not depend on the element width
140141
unsafe { core::mem::transmute_copy(&self) }
141142
}
142143

crates/core_simd/src/masks/full_masks.rs

+6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ where
106106
where
107107
U: MaskElement,
108108
{
109+
// Safety: masks are simply integer vectors of 0 and -1, and we can cast the element type.
109110
unsafe { Mask(intrinsics::simd_cast(self.0)) }
110111
}
111112

@@ -155,12 +156,14 @@ where
155156
#[inline]
156157
#[must_use = "method returns a new bool and does not mutate the original value"]
157158
pub fn any(self) -> bool {
159+
// Safety: use `self` as an integer vector
158160
unsafe { intrinsics::simd_reduce_any(self.to_int()) }
159161
}
160162

161163
#[inline]
162164
#[must_use = "method returns a new vector and does not mutate the original value"]
163165
pub fn all(self) -> bool {
166+
// Safety: use `self` as an integer vector
164167
unsafe { intrinsics::simd_reduce_all(self.to_int()) }
165168
}
166169
}
@@ -184,6 +187,7 @@ where
184187
#[inline]
185188
#[must_use = "method returns a new mask and does not mutate the original value"]
186189
fn bitand(self, rhs: Self) -> Self {
190+
// Safety: `self` is an integer vector
187191
unsafe { Self(intrinsics::simd_and(self.0, rhs.0)) }
188192
}
189193
}
@@ -197,6 +201,7 @@ where
197201
#[inline]
198202
#[must_use = "method returns a new mask and does not mutate the original value"]
199203
fn bitor(self, rhs: Self) -> Self {
204+
// Safety: `self` is an integer vector
200205
unsafe { Self(intrinsics::simd_or(self.0, rhs.0)) }
201206
}
202207
}
@@ -210,6 +215,7 @@ where
210215
#[inline]
211216
#[must_use = "method returns a new mask and does not mutate the original value"]
212217
fn bitxor(self, rhs: Self) -> Self {
218+
// Safety: `self` is an integer vector
213219
unsafe { Self(intrinsics::simd_xor(self.0, rhs.0)) }
214220
}
215221
}

crates/core_simd/src/math.rs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ macro_rules! impl_uint_arith {
2222
/// ```
2323
#[inline]
2424
pub fn saturating_add(self, second: Self) -> Self {
25+
// Safety: `self` is a vector
2526
unsafe { simd_saturating_add(self, second) }
2627
}
2728

@@ -41,6 +42,7 @@ macro_rules! impl_uint_arith {
4142
/// assert_eq!(sat, Simd::splat(0));
4243
#[inline]
4344
pub fn saturating_sub(self, second: Self) -> Self {
45+
// Safety: `self` is a vector
4446
unsafe { simd_saturating_sub(self, second) }
4547
}
4648
})+
@@ -68,6 +70,7 @@ macro_rules! impl_int_arith {
6870
/// ```
6971
#[inline]
7072
pub fn saturating_add(self, second: Self) -> Self {
73+
// Safety: `self` is a vector
7174
unsafe { simd_saturating_add(self, second) }
7275
}
7376

@@ -87,6 +90,7 @@ macro_rules! impl_int_arith {
8790
/// assert_eq!(sat, Simd::from_array([MIN, MIN, MIN, 0]));
8891
#[inline]
8992
pub fn saturating_sub(self, second: Self) -> Self {
93+
// Safety: `self` is a vector
9094
unsafe { simd_saturating_sub(self, second) }
9195
}
9296

crates/core_simd/src/reduction.rs

+8
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,28 @@ macro_rules! impl_integer_reductions {
1414
/// Horizontal wrapping add. Returns the sum of the lanes of the vector, with wrapping addition.
1515
#[inline]
1616
pub fn horizontal_sum(self) -> $scalar {
17+
// Safety: `self` is an integer vector
1718
unsafe { simd_reduce_add_ordered(self, 0) }
1819
}
1920

2021
/// Horizontal wrapping multiply. Returns the product of the lanes of the vector, with wrapping multiplication.
2122
#[inline]
2223
pub fn horizontal_product(self) -> $scalar {
24+
// Safety: `self` is an integer vector
2325
unsafe { simd_reduce_mul_ordered(self, 1) }
2426
}
2527

2628
/// Horizontal maximum. Returns the maximum lane in the vector.
2729
#[inline]
2830
pub fn horizontal_max(self) -> $scalar {
31+
// Safety: `self` is an integer vector
2932
unsafe { simd_reduce_max(self) }
3033
}
3134

3235
/// Horizontal minimum. Returns the minimum lane in the vector.
3336
#[inline]
3437
pub fn horizontal_min(self) -> $scalar {
38+
// Safety: `self` is an integer vector
3539
unsafe { simd_reduce_min(self) }
3640
}
3741
}
@@ -63,6 +67,7 @@ macro_rules! impl_float_reductions {
6367
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
6468
self.as_array().iter().sum()
6569
} else {
70+
// Safety: `self` is a float vector
6671
unsafe { simd_reduce_add_ordered(self, 0.) }
6772
}
6873
}
@@ -74,6 +79,7 @@ macro_rules! impl_float_reductions {
7479
if cfg!(all(target_arch = "x86", not(target_feature = "sse2"))) {
7580
self.as_array().iter().product()
7681
} else {
82+
// Safety: `self` is a float vector
7783
unsafe { simd_reduce_mul_ordered(self, 1.) }
7884
}
7985
}
@@ -84,6 +90,7 @@ macro_rules! impl_float_reductions {
8490
/// return either. This function will not return `NaN` unless all lanes are `NaN`.
8591
#[inline]
8692
pub fn horizontal_max(self) -> $scalar {
93+
// Safety: `self` is a float vector
8794
unsafe { simd_reduce_max(self) }
8895
}
8996

@@ -93,6 +100,7 @@ macro_rules! impl_float_reductions {
93100
/// return either. This function will not return `NaN` unless all lanes are `NaN`.
94101
#[inline]
95102
pub fn horizontal_min(self) -> $scalar {
103+
// Safety: `self` is a float vector
96104
unsafe { simd_reduce_min(self) }
97105
}
98106
}

crates/core_simd/src/swizzle.rs

+2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub trait Swizzle<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
9595
LaneCount<INPUT_LANES>: SupportedLaneCount,
9696
LaneCount<OUTPUT_LANES>: SupportedLaneCount,
9797
{
98+
// Safety: `vector` is a vector, and `INDEX_IMPL` is a const array of u32.
9899
unsafe { intrinsics::simd_shuffle(vector, vector, Self::INDEX_IMPL) }
99100
}
100101
}
@@ -119,6 +120,7 @@ pub trait Swizzle2<const INPUT_LANES: usize, const OUTPUT_LANES: usize> {
119120
LaneCount<INPUT_LANES>: SupportedLaneCount,
120121
LaneCount<OUTPUT_LANES>: SupportedLaneCount,
121122
{
123+
// Safety: `first` and `second` are vectors, and `INDEX_IMPL` is a const array of u32.
122124
unsafe { intrinsics::simd_shuffle(first, second, Self::INDEX_IMPL) }
123125
}
124126
}

crates/core_simd/src/to_bytes.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ macro_rules! impl_to_bytes {
88
/// Return the memory representation of this integer as a byte array in native byte
99
/// order.
1010
pub fn to_ne_bytes(self) -> crate::simd::Simd<u8, {{ $size * LANES }}> {
11+
// Safety: transmuting between vectors is safe
1112
unsafe { core::mem::transmute_copy(&self) }
1213
}
1314

1415
/// Create a native endian integer value from its memory representation as a byte array
1516
/// in native endianness.
1617
pub fn from_ne_bytes(bytes: crate::simd::Simd<u8, {{ $size * LANES }}>) -> Self {
18+
// Safety: transmuting between vectors is safe
1719
unsafe { core::mem::transmute_copy(&bytes) }
1820
}
1921
}

crates/core_simd/src/vector.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ where
206206
or: Self,
207207
) -> Self {
208208
let enable: Mask<isize, LANES> = enable & idxs.lanes_lt(Simd::splat(slice.len()));
209-
// SAFETY: We have masked-off out-of-bounds lanes.
209+
// Safety: We have masked-off out-of-bounds lanes.
210210
unsafe { Self::gather_select_unchecked(slice, enable, idxs, or) }
211211
}
212212

@@ -247,7 +247,7 @@ where
247247
let base_ptr = crate::simd::ptr::SimdConstPtr::splat(slice.as_ptr());
248248
// Ferris forgive me, I have done pointer arithmetic here.
249249
let ptrs = base_ptr.wrapping_add(idxs);
250-
// SAFETY: The ptrs have been bounds-masked to prevent memory-unsafe reads insha'allah
250+
// Safety: The ptrs have been bounds-masked to prevent memory-unsafe reads insha'allah
251251
unsafe { intrinsics::simd_gather(or, ptrs, enable.to_int()) }
252252
}
253253

@@ -299,7 +299,7 @@ where
299299
idxs: Simd<usize, LANES>,
300300
) {
301301
let enable: Mask<isize, LANES> = enable & idxs.lanes_lt(Simd::splat(slice.len()));
302-
// SAFETY: We have masked-off out-of-bounds lanes.
302+
// Safety: We have masked-off out-of-bounds lanes.
303303
unsafe { self.scatter_select_unchecked(slice, enable, idxs) }
304304
}
305305

@@ -338,7 +338,7 @@ where
338338
enable: Mask<isize, LANES>,
339339
idxs: Simd<usize, LANES>,
340340
) {
341-
// SAFETY: This block works with *mut T derived from &mut 'a [T],
341+
// Safety: This block works with *mut T derived from &mut 'a [T],
342342
// which means it is delicate in Rust's borrowing model, circa 2021:
343343
// &mut 'a [T] asserts uniqueness, so deriving &'a [T] invalidates live *mut Ts!
344344
// Even though this block is largely safe methods, it must be exactly this way
@@ -518,7 +518,9 @@ mod sealed {
518518
use sealed::Sealed;
519519

520520
/// Marker trait for types that may be used as SIMD vector elements.
521-
/// SAFETY: This trait, when implemented, asserts the compiler can monomorphize
521+
///
522+
/// # Safety
523+
/// This trait, when implemented, asserts the compiler can monomorphize
522524
/// `#[repr(simd)]` structs with the marked type as an element.
523525
/// Strictly, it is valid to impl if the vector will not be miscompiled.
524526
/// Practically, it is user-unfriendly to impl it if the vector won't compile,

crates/core_simd/src/vector/ptr.rs

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ where
2121
#[inline]
2222
#[must_use]
2323
pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
24+
// Safety: converting pointers to usize and vice-versa is safe
25+
// (even if using that pointer is not)
2426
unsafe {
2527
let x: Simd<usize, LANES> = mem::transmute_copy(&self);
2628
mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })
@@ -47,6 +49,8 @@ where
4749
#[inline]
4850
#[must_use]
4951
pub fn wrapping_add(self, addend: Simd<usize, LANES>) -> Self {
52+
// Safety: converting pointers to usize and vice-versa is safe
53+
// (even if using that pointer is not)
5054
unsafe {
5155
let x: Simd<usize, LANES> = mem::transmute_copy(&self);
5256
mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::<T>())) })

crates/core_simd/src/vendor.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ macro_rules! from_transmute {
99
impl core::convert::From<$from> for $to {
1010
#[inline]
1111
fn from(value: $from) -> $to {
12+
// Safety: transmuting between vectors is safe, but the caller of this macro
13+
// checks the invariants
1214
unsafe { core::mem::transmute(value) }
1315
}
1416
}

0 commit comments

Comments
 (0)