Skip to content

Commit c017b47

Browse files
calebzulawskiworkingjubilee
authored andcommitted
Add some safety comments
1 parent 533f0fc commit c017b47

File tree

14 files changed

+79
-5
lines changed

14 files changed

+79
-5
lines changed

crates/core_simd/src/comparisons.rs

Lines changed: 12 additions & 0 deletions
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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ mod sealed {
4141
use sealed::Sealed;
4242

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

4649
macro_rules! impl_element {
@@ -131,6 +134,7 @@ where
131134
#[inline]
132135
#[must_use = "method returns a new mask and does not mutate the original value"]
133136
pub unsafe fn from_int_unchecked(value: Simd<T, LANES>) -> Self {
137+
// Safety: the caller must confirm this invariant
134138
unsafe { Self(mask_impl::Mask::from_int_unchecked(value)) }
135139
}
136140

@@ -143,6 +147,7 @@ where
143147
#[must_use = "method returns a new mask and does not mutate the original value"]
144148
pub fn from_int(value: Simd<T, LANES>) -> Self {
145149
assert!(T::valid(value), "all values must be either 0 or -1",);
150+
// Safety: the validity has been checked
146151
unsafe { Self::from_int_unchecked(value) }
147152
}
148153

@@ -161,6 +166,7 @@ where
161166
#[inline]
162167
#[must_use = "method returns a new bool and does not mutate the original value"]
163168
pub unsafe fn test_unchecked(&self, lane: usize) -> bool {
169+
// Safety: the caller must confirm this invariant
164170
unsafe { self.0.test_unchecked(lane) }
165171
}
166172

@@ -172,6 +178,7 @@ where
172178
#[must_use = "method returns a new bool and does not mutate the original value"]
173179
pub fn test(&self, lane: usize) -> bool {
174180
assert!(lane < LANES, "lane index out of range");
181+
// Safety: the lane index has been checked
175182
unsafe { self.test_unchecked(lane) }
176183
}
177184

@@ -181,6 +188,7 @@ where
181188
/// `lane` must be less than `LANES`.
182189
#[inline]
183190
pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) {
191+
// Safety: the caller must confirm this invariant
184192
unsafe {
185193
self.0.set_unchecked(lane, value);
186194
}
@@ -193,6 +201,7 @@ where
193201
#[inline]
194202
pub fn set(&mut self, lane: usize, value: bool) {
195203
assert!(lane < LANES, "lane index out of range");
204+
// Safety: the lane index has been checked
196205
unsafe {
197206
self.set_unchecked(lane, value);
198207
}

crates/core_simd/src/masks/bitmask.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,15 @@ 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

112113
#[cfg(feature = "generic_const_exprs")]
113114
#[inline]
114115
#[must_use = "method returns a new array and does not mutate the original value"]
115116
pub fn to_bitmask(self) -> [u8; LaneCount::<LANES>::BITMASK_LEN] {
117+
// Safety: IntBitMask is the integer equivalent of the return type.
116118
unsafe {
117119
let mut bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN] =
118120
intrinsics::simd_bitmask(self.0);
@@ -134,6 +136,7 @@ where
134136
#[inline]
135137
#[must_use = "method returns a new mask and does not mutate the original value"]
136138
pub fn from_bitmask(mut bitmask: [u8; LaneCount::<LANES>::BITMASK_LEN]) -> Self {
139+
// Safety: IntBitMask is the integer equivalent of the input type.
137140
unsafe {
138141
// There is a bug where LLVM appears to implement this operation with the wrong
139142
// bit order.
@@ -155,12 +158,14 @@ where
155158
#[inline]
156159
#[must_use = "method returns a new bool and does not mutate the original value"]
157160
pub fn any(self) -> bool {
161+
// Safety: use `self` as an integer vector
158162
unsafe { intrinsics::simd_reduce_any(self.to_int()) }
159163
}
160164

161165
#[inline]
162166
#[must_use = "method returns a new vector and does not mutate the original value"]
163167
pub fn all(self) -> bool {
168+
// Safety: use `self` as an integer vector
164169
unsafe { intrinsics::simd_reduce_all(self.to_int()) }
165170
}
166171
}
@@ -184,6 +189,7 @@ where
184189
#[inline]
185190
#[must_use = "method returns a new mask and does not mutate the original value"]
186191
fn bitand(self, rhs: Self) -> Self {
192+
// Safety: `self` is an integer vector
187193
unsafe { Self(intrinsics::simd_and(self.0, rhs.0)) }
188194
}
189195
}
@@ -197,6 +203,7 @@ where
197203
#[inline]
198204
#[must_use = "method returns a new mask and does not mutate the original value"]
199205
fn bitor(self, rhs: Self) -> Self {
206+
// Safety: `self` is an integer vector
200207
unsafe { Self(intrinsics::simd_or(self.0, rhs.0)) }
201208
}
202209
}
@@ -210,6 +217,7 @@ where
210217
#[inline]
211218
#[must_use = "method returns a new mask and does not mutate the original value"]
212219
fn bitxor(self, rhs: Self) -> Self {
220+
// Safety: `self` is an integer vector
213221
unsafe { Self(intrinsics::simd_xor(self.0, rhs.0)) }
214222
}
215223
}

crates/core_simd/src/math.rs

Lines changed: 4 additions & 0 deletions
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/ops.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ macro_rules! impl_op {
112112

113113
#[inline]
114114
fn $trait_fn(self, rhs: Self) -> Self::Output {
115+
// Safety: `self` is a vector
115116
unsafe {
116117
intrinsics::$intrinsic(self, rhs)
117118
}
@@ -169,6 +170,8 @@ macro_rules! impl_unsigned_int_ops {
169170
.any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
170171
panic!("attempt to divide with overflow");
171172
}
173+
// Safety: `self` is a vector, and the lanes have been checked for
174+
// division by zero and overflow
172175
unsafe { intrinsics::simd_div(self, rhs) }
173176
}
174177
}
@@ -198,6 +201,8 @@ macro_rules! impl_unsigned_int_ops {
198201
.any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
199202
panic!("attempt to calculate the remainder with overflow");
200203
}
204+
// Safety: `self` is a vector, and the lanes have been checked for
205+
// division by zero and overflow
201206
unsafe { intrinsics::simd_rem(self, rhs) }
202207
}
203208
}
@@ -221,6 +226,8 @@ macro_rules! impl_unsigned_int_ops {
221226
{
222227
panic!("attempt to shift left with overflow");
223228
}
229+
// Safety: `self` is a vector, and the shift argument has been checked for
230+
// overflow
224231
unsafe { intrinsics::simd_shl(self, rhs) }
225232
}
226233
}
@@ -243,6 +250,8 @@ macro_rules! impl_unsigned_int_ops {
243250
{
244251
panic!("attempt to shift with overflow");
245252
}
253+
// Safety: `self` is a vector, and the shift argument has been checked for
254+
// overflow
246255
unsafe { intrinsics::simd_shr(self, rhs) }
247256
}
248257
}

crates/core_simd/src/reduction.rs

Lines changed: 8 additions & 0 deletions
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/round.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,31 @@ macro_rules! implement {
1414
#[must_use = "method returns a new vector and does not mutate the original value"]
1515
#[inline]
1616
pub fn ceil(self) -> Self {
17+
// Safety: `self` is a vector
1718
unsafe { intrinsics::simd_ceil(self) }
1819
}
1920

2021
/// Returns the largest integer value less than or equal to each lane.
2122
#[must_use = "method returns a new vector and does not mutate the original value"]
2223
#[inline]
2324
pub fn floor(self) -> Self {
25+
// Safety: `self` is a vector
2426
unsafe { intrinsics::simd_floor(self) }
2527
}
2628

2729
/// Rounds to the nearest integer value. Ties round toward zero.
2830
#[must_use = "method returns a new vector and does not mutate the original value"]
2931
#[inline]
3032
pub fn round(self) -> Self {
33+
// Safety: `self` is a vector
3134
unsafe { intrinsics::simd_round(self) }
3235
}
3336

3437
/// Returns the floating point's integer value, with its fractional part removed.
3538
#[must_use = "method returns a new vector and does not mutate the original value"]
3639
#[inline]
3740
pub fn trunc(self) -> Self {
41+
// Safety: `self` is a vector
3842
unsafe { intrinsics::simd_trunc(self) }
3943
}
4044

@@ -61,13 +65,15 @@ macro_rules! implement {
6165
/// * Be representable in the return type, after truncating off its fractional part
6266
#[inline]
6367
pub unsafe fn to_int_unchecked(self) -> Simd<$int_type, LANES> {
68+
// Safety: the caller must check the invariants
6469
unsafe { intrinsics::simd_cast(self) }
6570
}
6671

6772
/// Creates a floating-point vector from an integer vector. Rounds values that are
6873
/// not exactly representable.
6974
#[inline]
7075
pub fn round_from_int(value: Simd<$int_type, LANES>) -> Self {
76+
// Safety: conversion from integer to float vectors is safe
7177
unsafe { intrinsics::simd_cast(value) }
7278
}
7379
}

crates/core_simd/src/swizzle.rs

Lines changed: 2 additions & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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
}

0 commit comments

Comments
 (0)