Skip to content

Document unsafety #280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/core_simd/src/elements/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,17 +202,20 @@ macro_rules! impl_trait {
#[inline]
fn to_bits(self) -> Simd<$bits_ty, LANES> {
assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>());
// Safety: transmuting between vector types is safe
unsafe { core::mem::transmute_copy(&self) }
}

#[inline]
fn from_bits(bits: Simd<$bits_ty, LANES>) -> Self {
assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>());
// Safety: transmuting between vector types is safe
unsafe { core::mem::transmute_copy(&bits) }
}

#[inline]
fn abs(self) -> Self {
// Safety: `self` is a float vector
unsafe { intrinsics::simd_fabs(self) }
}

Expand Down Expand Up @@ -283,11 +286,13 @@ macro_rules! impl_trait {

#[inline]
fn simd_min(self, other: Self) -> Self {
// Safety: `self` and `other` are float vectors
unsafe { intrinsics::simd_fmin(self, other) }
}

#[inline]
fn simd_max(self, other: Self) -> Self {
// Safety: `self` and `other` are floating point vectors
unsafe { intrinsics::simd_fmax(self, other) }
}

Expand Down
2 changes: 1 addition & 1 deletion crates/core_simd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#![cfg_attr(feature = "generic_const_exprs", feature(generic_const_exprs))]
#![cfg_attr(feature = "generic_const_exprs", allow(incomplete_features))]
#![warn(missing_docs)]
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)]
#![unstable(feature = "portable_simd", issue = "86656")]
//! Portable SIMD module.

Expand Down
1 change: 1 addition & 0 deletions crates/core_simd/src/masks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ macro_rules! impl_element {
const FALSE: Self = 0;
}

// Safety: this is a valid mask element type
unsafe impl MaskElement for $ty {}
}
}
Expand Down
32 changes: 12 additions & 20 deletions crates/core_simd/src/masks/to_bitmask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@ where
/// Converts masks to and from integer bitmasks.
///
/// Each bit of the bitmask corresponds to a mask lane, starting with the LSB.
///
/// # Safety
/// This trait is `unsafe` and sealed, since the `BitMask` type must match the number of lanes in
/// the mask.
pub unsafe trait ToBitMask: Sealed {
pub trait ToBitMask: Sealed {
/// The integer bitmask type.
type BitMask;

Expand All @@ -34,12 +30,8 @@ pub unsafe trait ToBitMask: Sealed {
/// Converts masks to and from byte array bitmasks.
///
/// Each bit of the bitmask corresponds to a mask lane, starting with the LSB of the first byte.
///
/// # Safety
/// This trait is `unsafe` and sealed, since the `BYTES` value must match the number of lanes in
/// the mask.
#[cfg(feature = "generic_const_exprs")]
pub unsafe trait ToBitMaskArray: Sealed {
pub trait ToBitMaskArray: Sealed {
/// The length of the bitmask array.
const BYTES: usize;

Expand All @@ -51,9 +43,9 @@ pub unsafe trait ToBitMaskArray: Sealed {
}

macro_rules! impl_integer_intrinsic {
{ $(unsafe impl ToBitMask<BitMask=$int:ty> for Mask<_, $lanes:literal>)* } => {
{ $(impl ToBitMask<BitMask=$int:ty> for Mask<_, $lanes:literal>)* } => {
$(
unsafe impl<T: MaskElement> ToBitMask for Mask<T, $lanes> {
impl<T: MaskElement> ToBitMask for Mask<T, $lanes> {
type BitMask = $int;

fn to_bitmask(self) -> $int {
Expand All @@ -69,13 +61,13 @@ macro_rules! impl_integer_intrinsic {
}

impl_integer_intrinsic! {
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 1>
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 2>
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 4>
unsafe impl ToBitMask<BitMask=u8> for Mask<_, 8>
unsafe impl ToBitMask<BitMask=u16> for Mask<_, 16>
unsafe impl ToBitMask<BitMask=u32> for Mask<_, 32>
unsafe impl ToBitMask<BitMask=u64> for Mask<_, 64>
impl ToBitMask<BitMask=u8> for Mask<_, 1>
impl ToBitMask<BitMask=u8> for Mask<_, 2>
impl ToBitMask<BitMask=u8> for Mask<_, 4>
impl ToBitMask<BitMask=u8> for Mask<_, 8>
impl ToBitMask<BitMask=u16> for Mask<_, 16>
impl ToBitMask<BitMask=u32> for Mask<_, 32>
impl ToBitMask<BitMask=u64> for Mask<_, 64>
}

/// Returns the minimum numnber of bytes in a bitmask with `lanes` lanes.
Expand All @@ -85,7 +77,7 @@ pub const fn bitmask_len(lanes: usize) -> usize {
}

#[cfg(feature = "generic_const_exprs")]
unsafe impl<T: MaskElement, const LANES: usize> ToBitMaskArray for Mask<T, LANES>
impl<T: MaskElement, const LANES: usize> ToBitMaskArray for Mask<T, LANES>
where
LaneCount<LANES>: SupportedLaneCount,
{
Expand Down
3 changes: 3 additions & 0 deletions crates/core_simd/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ where

macro_rules! unsafe_base {
($lhs:ident, $rhs:ident, {$simd_call:ident}, $($_:tt)*) => {
// Safety: $lhs and $rhs are vectors
unsafe { $crate::simd::intrinsics::$simd_call($lhs, $rhs) }
};
}
Expand All @@ -49,6 +50,7 @@ macro_rules! unsafe_base {
macro_rules! wrap_bitshift {
($lhs:ident, $rhs:ident, {$simd_call:ident}, $int:ident) => {
#[allow(clippy::suspicious_arithmetic_impl)]
// Safety: $lhs and the bitand result are vectors
unsafe {
$crate::simd::intrinsics::$simd_call(
$lhs,
Expand Down Expand Up @@ -91,6 +93,7 @@ macro_rules! int_divrem_guard {
// Nice base case to make it easy to const-fold away the other branch.
$rhs
};
// Safety: $lhs and rhs are vectors
unsafe { $crate::simd::intrinsics::$simd_call($lhs, rhs) }
}
};
Expand Down
1 change: 1 addition & 0 deletions crates/core_simd/src/ops/unary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ macro_rules! neg {
#[inline]
#[must_use = "operator returns a new vector without mutating the input"]
fn neg(self) -> Self::Output {
// Safety: `self` is a signed vector
unsafe { intrinsics::simd_neg(self) }
}
})*
Expand Down
2 changes: 2 additions & 0 deletions crates/core_simd/src/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ macro_rules! implement {
$type: FloatToInt<I>,
I: SimdElement,
{
// Safety: `self` is a vector, and `FloatToInt` ensures the type can be casted to
// an integer.
unsafe { intrinsics::simd_cast(self) }
}
}
Expand Down
26 changes: 25 additions & 1 deletion crates/core_simd/src/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ where
#[inline]
#[cfg(not(bootstrap))]
pub fn cast<U: SimdElement>(self) -> Simd<U, LANES> {
// Safety: The input argument is a vector of a known SIMD type.
// Safety: The input argument is a vector of a valid SIMD element type.
unsafe { intrinsics::simd_as(self) }
}

Expand Down Expand Up @@ -624,61 +624,85 @@ pub unsafe trait SimdElement: Sealed + Copy {
}

impl Sealed for u8 {}

// Safety: u8 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for u8 {
type Mask = i8;
}

impl Sealed for u16 {}

// Safety: u16 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for u16 {
type Mask = i16;
}

impl Sealed for u32 {}

// Safety: u32 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for u32 {
type Mask = i32;
}

impl Sealed for u64 {}

// Safety: u64 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for u64 {
type Mask = i64;
}

impl Sealed for usize {}

// Safety: usize is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for usize {
type Mask = isize;
}

impl Sealed for i8 {}

// Safety: i8 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for i8 {
type Mask = i8;
}

impl Sealed for i16 {}

// Safety: i16 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for i16 {
type Mask = i16;
}

impl Sealed for i32 {}

// Safety: i32 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for i32 {
type Mask = i32;
}

impl Sealed for i64 {}

// Safety: i64 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for i64 {
type Mask = i64;
}

impl Sealed for isize {}

// Safety: isize is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for isize {
type Mask = isize;
}

impl Sealed for f32 {}

// Safety: f32 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for f32 {
type Mask = i32;
}

impl Sealed for f64 {}

// Safety: f64 is a valid SIMD element type, and is supported by this API
unsafe impl SimdElement for f64 {
type Mask = i64;
}