run cargo fmt (#120)

This commit is contained in:
Waffle Maybe 2022-07-24 19:27:49 +04:00 committed by GitHub
parent d75942c484
commit 331762b014
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 176 additions and 140 deletions

View File

@ -93,11 +93,13 @@ pub fn zeroed_box<T: Zeroable>() -> Box<T> {
try_zeroed_box().unwrap()
}
/// Allocates a `Vec<T>` of length and capacity exactly equal to `length` and all elements zeroed.
///
/// Allocates a `Vec<T>` of length and capacity exactly equal to `length` and
/// all elements zeroed.
///
/// ## Failure
///
/// This fails if the allocation fails, or if a layout cannot be calculated for the allocation.
/// This fails if the allocation fails, or if a layout cannot be calculated for
/// the allocation.
pub fn try_zeroed_vec<T: Zeroable>(length: usize) -> Result<Vec<T>, ()> {
if length == 0 {
Ok(Vec::new())
@ -121,7 +123,8 @@ pub fn zeroed_vec<T: Zeroable>(length: usize) -> Vec<T> {
///
/// ## Failure
///
/// This fails if the allocation fails, or if a layout cannot be calculated for the allocation.
/// This fails if the allocation fails, or if a layout cannot be calculated for
/// the allocation.
#[inline]
pub fn try_zeroed_slice_box<T: Zeroable>(
length: usize,
@ -145,7 +148,7 @@ pub fn try_zeroed_slice_box<T: Zeroable>(
let slice =
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
Ok(unsafe { Box::<[T]>::from_raw(slice) })
}
}
}
/// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you.
@ -313,12 +316,14 @@ pub fn pod_collect_to_vec<
}
/// An extension trait for `TransparentWrapper` and alloc types.
pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
pub trait TransparentWrapperAlloc<Inner: ?Sized>:
TransparentWrapper<Inner>
{
/// Convert a vec of the inner type into a vec of the wrapper type.
fn wrap_vec(s: Vec<Inner>) -> Vec<Self>
where
Self: Sized,
Inner: Sized
Inner: Sized,
{
let mut s = core::mem::ManuallyDrop::new(s);
@ -331,11 +336,7 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
// * ptr comes from Vec (and will not be double-dropped)
// * the two types have the identical representation
// * the len and capacity fields are valid
Vec::from_raw_parts(
ptr as *mut Self,
length,
capacity
)
Vec::from_raw_parts(ptr as *mut Self, length, capacity)
}
}
@ -350,12 +351,12 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
//
// SAFETY:
// * The unsafe contract requires that pointers to Inner and Self
// have identical representations
// * Box is guaranteed to have representation identical to a
// (non-null) pointer
// * The pointer comes from a box (and thus satisfies all safety
// SAFETY:
// * The unsafe contract requires that pointers to Inner and Self have
// identical representations
// * Box is guaranteed to have representation identical to a (non-null)
// pointer
// * The pointer comes from a box (and thus satisfies all safety
// requirements of Box)
let inner_ptr: *mut Inner = Box::into_raw(s);
let wrapper_ptr: *mut Self = transmute!(inner_ptr);
@ -367,7 +368,7 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
fn peel_vec(s: Vec<Self>) -> Vec<Inner>
where
Self: Sized,
Inner: Sized
Inner: Sized,
{
let mut s = core::mem::ManuallyDrop::new(s);
@ -380,11 +381,7 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
// * ptr comes from Vec (and will not be double-dropped)
// * the two types have the identical representation
// * the len and capacity fields are valid
Vec::from_raw_parts(
ptr as *mut Inner,
length,
capacity
)
Vec::from_raw_parts(ptr as *mut Inner, length, capacity)
}
}
@ -399,12 +396,12 @@ pub trait TransparentWrapperAlloc<Inner: ?Sized>: TransparentWrapper<Inner> {
// the vtables match (because of the `?Sized` restriction relaxation).
// A `transmute` doesn't work because the sizes are unspecified.
//
// SAFETY:
// * The unsafe contract requires that pointers to Inner and Self
// have identical representations
// * Box is guaranteed to have representation identical to a
// (non-null) pointer
// * The pointer comes from a box (and thus satisfies all safety
// SAFETY:
// * The unsafe contract requires that pointers to Inner and Self have
// identical representations
// * Box is guaranteed to have representation identical to a (non-null)
// pointer
// * The pointer comes from a box (and thus satisfies all safety
// requirements of Box)
let wrapper_ptr: *mut Self = Box::into_raw(s);
let inner_ptr: *mut Inner = transmute!(wrapper_ptr);

View File

@ -5,46 +5,52 @@ use crate::{Pod, Zeroable};
/// The requirements for this is very similar to [`Pod`],
/// except that the type can allow uninit (or padding) bytes.
/// This limits what you can do with a type of this kind, but also broadens the
/// included types to `repr(C)` `struct`s that contain padding as well as `union`s. Notably, you can only cast
/// *immutable* references and *owned* values into [`AnyBitPattern`] types, not
/// *mutable* references.
/// included types to `repr(C)` `struct`s that contain padding as well as
/// `union`s. Notably, you can only cast *immutable* references and *owned*
/// values into [`AnyBitPattern`] types, not *mutable* references.
///
/// [`Pod`] is a subset of [`AnyBitPattern`], meaning that any `T: Pod` is also
/// [`AnyBitPattern`] but any `T: AnyBitPattern` is not necessarily [`Pod`].
///
/// [`AnyBitPattern`] is a subset of [`Zeroable`], meaning that any `T: AnyBitPattern`
/// is also [`Zeroable`], but any `T: Zeroable` is not necessarily [`AnyBitPattern ]
/// [`AnyBitPattern`] is a subset of [`Zeroable`], meaning that any `T:
/// AnyBitPattern` is also [`Zeroable`], but any `T: Zeroable` is not
/// necessarily [`AnyBitPattern ]
///
/// # Derive
///
/// A `#[derive(AnyBitPattern)]` macro is provided under the `derive` feature flag which will
/// automatically validate the requirements of this trait and implement the
/// trait for you for both structs and enums. This is the recommended method for
/// implementing the trait, however it's also possible to do manually. If you
/// implement it manually, you *must* carefully follow the below safety rules.
/// A `#[derive(AnyBitPattern)]` macro is provided under the `derive` feature
/// flag which will automatically validate the requirements of this trait and
/// implement the trait for you for both structs and enums. This is the
/// recommended method for implementing the trait, however it's also possible to
/// do manually. If you implement it manually, you *must* carefully follow the
/// below safety rules.
///
/// * *NOTE: even `C-style`, fieldless enums are intentionally **excluded** from
/// this trait, since it is **unsound** for an enum to have a discriminant value
/// that is not one of its defined variants.
///
///
/// # Safety
///
/// Similar to [`Pod`] except we disregard the rule about it must not contain uninit bytes.
/// Still, this is a quite strong guarantee about a type, so *be careful* when
/// implementing it manually.
/// Similar to [`Pod`] except we disregard the rule about it must not contain
/// uninit bytes. Still, this is a quite strong guarantee about a type, so *be
/// careful* when implementing it manually.
///
/// * The type must be inhabited (eg: no
/// [Infallible](core::convert::Infallible)).
/// * The type must be valid for any bit pattern of its backing memory.
/// * Structs need to have all fields also be `AnyBitPattern`.
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`, atomics, and any
/// other forms of interior mutability.
/// * More precisely: A shared reference to the type must allow reads, and *only* reads. RustBelt's
/// separation logic is based on the notion that a type is allowed to define a sharing predicate,
/// its own invariant that must hold for shared references, and this predicate is the reasoning
/// that allow it to deal with atomic and cells etc. We require the sharing predicate to be
/// trivial and permit only read-only access.
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`,
/// atomics, and any other forms of interior mutability.
/// * More precisely: A shared reference to the type must allow reads, and
/// *only* reads. RustBelt's separation logic is based on the notion that a
/// type is allowed to define a sharing predicate, its own invariant that must
/// hold for shared references, and this predicate is the reasoning that allow
/// it to deal with atomic and cells etc. We require the sharing predicate to
/// be trivial and permit only read-only access.
/// * There's probably more, don't mess it up (I mean it).
pub unsafe trait AnyBitPattern: Zeroable + Sized + Copy + 'static {}
pub unsafe trait AnyBitPattern:
Zeroable + Sized + Copy + 'static
{
}
unsafe impl<T: Pod> AnyBitPattern for T {}

View File

@ -1,32 +1,40 @@
//! Checked versions of the casting functions exposed in crate root
//! that support [`CheckedBitPattern`] types.
use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
use crate::{
internal::{self, something_went_wrong},
AnyBitPattern, NoUninit,
};
/// A marker trait that allows types that have some invalid bit patterns to be used
/// in places that otherwise require [`AnyBitPattern`] or [`Pod`] types by performing
/// a runtime check on a perticular set of bits. This is particularly
/// useful for types like fieldless ('C-style') enums, [`char`], bool, and structs containing them.
/// A marker trait that allows types that have some invalid bit patterns to be
/// used in places that otherwise require [`AnyBitPattern`] or [`Pod`] types by
/// performing a runtime check on a perticular set of bits. This is particularly
/// useful for types like fieldless ('C-style') enums, [`char`], bool, and
/// structs containing them.
///
/// To do this, we define a `Bits` type which is a type with equivalent layout
/// to `Self` other than the invalid bit patterns which disallow `Self` from
/// being [`AnyBitPattern`]. This `Bits` type must itself implement [`AnyBitPattern`].
/// Then, we implement a function that checks wheter a certain instance
/// of the `Bits` is also a valid bit pattern of `Self`. If this check passes, then we
/// can allow casting from the `Bits` to `Self` (and therefore, any type which
/// is able to be cast to `Bits` is also able to be cast to `Self`).
/// being [`AnyBitPattern`]. This `Bits` type must itself implement
/// [`AnyBitPattern`]. Then, we implement a function that checks wheter a
/// certain instance of the `Bits` is also a valid bit pattern of `Self`. If
/// this check passes, then we can allow casting from the `Bits` to `Self` (and
/// therefore, any type which is able to be cast to `Bits` is also able to be
/// cast to `Self`).
///
/// [`AnyBitPattern`] is a subset of [`CheckedBitPattern`], meaning that any `T: AnyBitPattern` is also
/// [`CheckedBitPattern`]. This means you can also use any [`AnyBitPattern`] type in the checked versions
/// of casting functions in this module. If it's possible, prefer implementing [`AnyBitPattern`] for your
/// type directly instead of [`CheckedBitPattern`] as it gives greater flexibility.
/// [`AnyBitPattern`] is a subset of [`CheckedBitPattern`], meaning that any `T:
/// AnyBitPattern` is also [`CheckedBitPattern`]. This means you can also use
/// any [`AnyBitPattern`] type in the checked versions of casting functions in
/// this module. If it's possible, prefer implementing [`AnyBitPattern`] for
/// your type directly instead of [`CheckedBitPattern`] as it gives greater
/// flexibility.
///
/// # Derive
///
/// A `#[derive(CheckedBitPattern)]` macro is provided under the `derive` feature flag which will
/// automatically validate the requirements of this trait and implement the
/// trait for you for both enums and structs. This is the recommended method for
/// implementing the trait, however it's also possible to do manually.
/// A `#[derive(CheckedBitPattern)]` macro is provided under the `derive`
/// feature flag which will automatically validate the requirements of this
/// trait and implement the trait for you for both enums and structs. This is
/// the recommended method for implementing the trait, however it's also
/// possible to do manually.
///
/// # Example
///
@ -53,7 +61,7 @@ use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
/// }
/// }
/// }
///
///
/// // It is often useful to also implement `NoUninit` on our `CheckedBitPattern` types.
/// // This will allow us to do casting of mutable references (and mutable slices).
/// // It is not always possible to do so, but in this case we have no padding so it is.
@ -92,7 +100,7 @@ use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
/// let bytes = bytes_of(&100u32);
/// let result = checked::try_from_bytes::<MyEnum>(bytes);
/// assert!(result.is_err());
///
///
/// // Since we implemented NoUninit, we can also cast mutably from an original type
/// // that is `NoUninit + AnyBitPattern`:
/// let mut my_u32 = 2u32;
@ -107,25 +115,28 @@ use crate::{internal::{self, something_went_wrong}, NoUninit, AnyBitPattern};
/// # Safety
///
/// * `Self` *must* have the same layout as the specified `Bits` except for
/// the possible invalid bit patterns being checked during [`is_valid_bit_pattern`].
/// the possible invalid bit patterns being checked during
/// [`is_valid_bit_pattern`].
/// * This almost certainly means your type must be `#[repr(C)]` or a similar
/// specified repr, but if you think you know better, you probably don't. If you
/// still think you know better, be careful and have fun. And don't mess it up
/// (I mean it).
/// * If [`is_valid_bit_pattern`] returns true, then the bit pattern contained in
/// `bits` must also be valid for an instance of `Self`.
/// specified repr, but if you think you know better, you probably don't. If
/// you still think you know better, be careful and have fun. And don't mess
/// it up (I mean it).
/// * If [`is_valid_bit_pattern`] returns true, then the bit pattern contained
/// in `bits` must also be valid for an instance of `Self`.
/// * Probably more, don't mess it up (I mean it 2.0)
///
/// [`is_valid_bit_pattern`]: CheckedBitPattern::is_valid_bit_pattern
/// [`Pod`]: crate::Pod
pub unsafe trait CheckedBitPattern: Copy {
/// `Self` *must* have the same layout as the specified `Bits` except for
/// the possible invalid bit patterns being checked during [`is_valid_bit_pattern`].
/// the possible invalid bit patterns being checked during
/// [`is_valid_bit_pattern`].
///
/// [`is_valid_bit_pattern`]: CheckedBitPattern::is_valid_bit_pattern
type Bits: AnyBitPattern;
/// If this function returns true, then it must be valid to reinterpret `bits` as `&Self`.
/// If this function returns true, then it must be valid to reinterpret `bits`
/// as `&Self`.
fn is_valid_bit_pattern(bits: &Self::Bits) -> bool;
}
@ -159,15 +170,16 @@ unsafe impl CheckedBitPattern for bool {
}
}
/// The things that can go wrong when casting between [`CheckedBitPattern`] data forms.
/// The things that can go wrong when casting between [`CheckedBitPattern`] data
/// forms.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CheckedCastError {
/// An error occurred during a true-[`Pod`] cast
PodCastError(crate::PodCastError),
/// When casting to a [`CheckedBitPattern`] type, it is possible that the original
/// data contains an invalid bit pattern. If so, the cast will fail and
/// this error will be returned. Will never happen on casts between
/// [`Pod`] types.
/// When casting to a [`CheckedBitPattern`] type, it is possible that the
/// original data contains an invalid bit pattern. If so, the cast will
/// fail and this error will be returned. Will never happen on casts
/// between [`Pod`] types.
InvalidBitPattern,
}
@ -232,7 +244,9 @@ pub fn try_from_bytes_mut<T: CheckedBitPattern + NoUninit>(
/// * If the `bytes` length is not equal to `size_of::<T>()`.
/// * If the slice contains an invalid bit pattern for `T`
#[inline]
pub fn try_pod_read_unaligned<T: CheckedBitPattern>(bytes: &[u8]) -> Result<T, CheckedCastError> {
pub fn try_pod_read_unaligned<T: CheckedBitPattern>(
bytes: &[u8],
) -> Result<T, CheckedCastError> {
let pod = unsafe { internal::try_pod_read_unaligned(bytes) }?;
if <T as CheckedBitPattern>::is_valid_bit_pattern(pod) {
@ -290,7 +304,10 @@ pub fn try_cast_ref<A: NoUninit, B: CheckedBitPattern>(
///
/// As [`checked_cast_ref`], but `mut`.
#[inline]
pub fn try_cast_mut<A: NoUninit + AnyBitPattern, B: CheckedBitPattern + NoUninit>(
pub fn try_cast_mut<
A: NoUninit + AnyBitPattern,
B: CheckedBitPattern + NoUninit,
>(
a: &mut A,
) -> Result<&mut B, CheckedCastError> {
let pod = unsafe { internal::try_cast_mut(a) }?;
@ -317,7 +334,8 @@ pub fn try_cast_mut<A: NoUninit + AnyBitPattern, B: CheckedBitPattern + NoUninit
/// that's a failure).
/// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
/// and a non-ZST.
/// * If any element of the converted slice would contain an invalid bit pattern for `B` this fails.
/// * If any element of the converted slice would contain an invalid bit pattern
/// for `B` this fails.
#[inline]
pub fn try_cast_slice<A: NoUninit, B: CheckedBitPattern>(
a: &[A],
@ -338,7 +356,10 @@ pub fn try_cast_slice<A: NoUninit, B: CheckedBitPattern>(
///
/// As [`checked_cast_slice`], but `&mut`.
#[inline]
pub fn try_cast_slice_mut<A: NoUninit + AnyBitPattern, B: CheckedBitPattern + NoUninit>(
pub fn try_cast_slice_mut<
A: NoUninit + AnyBitPattern,
B: CheckedBitPattern + NoUninit,
>(
a: &mut [A],
) -> Result<&mut [B], CheckedCastError> {
let pod = unsafe { internal::try_cast_slice_mut(a) }?;
@ -409,7 +430,12 @@ pub fn cast<A: NoUninit, B: CheckedBitPattern>(a: A) -> B {
///
/// This is [`try_cast_mut`] but will panic on error.
#[inline]
pub fn cast_mut<A: NoUninit + AnyBitPattern, B: NoUninit + CheckedBitPattern>(a: &mut A) -> &mut B {
pub fn cast_mut<
A: NoUninit + AnyBitPattern,
B: NoUninit + CheckedBitPattern,
>(
a: &mut A,
) -> &mut B {
match try_cast_mut(a) {
Ok(t) => t,
Err(e) => something_went_wrong("cast_mut", e),
@ -448,9 +474,14 @@ pub fn cast_slice<A: NoUninit, B: CheckedBitPattern>(a: &[A]) -> &[B] {
///
/// This is [`try_cast_slice_mut`] but will panic on error.
#[inline]
pub fn cast_slice_mut<A: NoUninit + AnyBitPattern, B: NoUninit + CheckedBitPattern>(a: &mut [A]) -> &mut [B] {
pub fn cast_slice_mut<
A: NoUninit + AnyBitPattern,
B: NoUninit + CheckedBitPattern,
>(
a: &mut [A],
) -> &mut [B] {
match try_cast_slice_mut(a) {
Ok(t) => t,
Err(e) => something_went_wrong("cast_slice_mut", e),
}
}
}

View File

@ -1,7 +1,7 @@
//! Internal implementation of casting functions not bound by marker traits
//! and therefore marked as unsafe. This is used so that we don't need to duplicate
//! the business logic contained in these functions between the versions exported in
//! the crate root, `checked`, and `relaxed` modules.
//! and therefore marked as unsafe. This is used so that we don't need to
//! duplicate the business logic contained in these functions between the
//! versions exported in the crate root, `checked`, and `relaxed` modules.
#![allow(unused_unsafe)]
use crate::PodCastError;
@ -22,7 +22,9 @@ possibility code branch.
/// Immediately panics.
#[cold]
#[inline(never)]
pub(crate) fn something_went_wrong<D: core::fmt::Display>(_src: &str, _err: D) -> ! {
pub(crate) fn something_went_wrong<D: core::fmt::Display>(
_src: &str, _err: D,
) -> ! {
// Note(Lokathor): Keeping the panic here makes the panic _formatting_ go
// here too, which helps assembly readability and also helps keep down
// the inline pressure.
@ -100,7 +102,9 @@ pub(crate) unsafe fn from_bytes_mut<T: Copy>(s: &mut [u8]) -> &mut T {
/// ## Failure
/// * If the `bytes` length is not equal to `size_of::<T>()`.
#[inline]
pub(crate) unsafe fn try_pod_read_unaligned<T: Copy>(bytes: &[u8]) -> Result<T, PodCastError> {
pub(crate) unsafe fn try_pod_read_unaligned<T: Copy>(
bytes: &[u8],
) -> Result<T, PodCastError> {
if bytes.len() != size_of::<T>() {
Err(PodCastError::SizeMismatch)
} else {

View File

@ -1,68 +1,62 @@
use crate::Pod;
use core::num::{
NonZeroU8,
NonZeroI8,
NonZeroU16,
NonZeroI16,
NonZeroU32,
NonZeroI32,
NonZeroU64,
NonZeroI64,
NonZeroU128,
NonZeroI128,
NonZeroUsize,
NonZeroIsize,
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize,
NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
};
/// Marker trait for "plain old data" types with no uninit (or padding) bytes.
///
/// The requirements for this is very similar to [`Pod`],
/// except that it doesn't require that all bit patterns of the type are valid, i.e.
/// it does not require the type to be [`Zeroable`][crate::Zeroable].
/// except that it doesn't require that all bit patterns of the type are valid,
/// i.e. it does not require the type to be [`Zeroable`][crate::Zeroable].
/// This limits what you can do with a type of this kind, but also broadens the
/// included types to things like C-style enums. Notably, you can only cast from
/// *immutable* references to a [`NoUninit`] type into *immutable* references of any other
/// type, no casting of mutable references or mutable references to slices etc.
/// *immutable* references to a [`NoUninit`] type into *immutable* references of
/// any other type, no casting of mutable references or mutable references to
/// slices etc.
///
/// [`Pod`] is a subset of [`NoUninit`], meaning that any `T: Pod` is also
/// [`NoUninit`] but any `T: NoUninit` is not necessarily [`Pod`]. If possible,
/// prefer implementing [`Pod`] directly. To get more [`Pod`]-like functionality for
/// a type that is only [`NoUninit`], consider also implementing [`CheckedBitPattern`][crate::CheckedBitPattern].
/// prefer implementing [`Pod`] directly. To get more [`Pod`]-like functionality
/// for a type that is only [`NoUninit`], consider also implementing
/// [`CheckedBitPattern`][crate::CheckedBitPattern].
///
/// # Derive
///
/// A `#[derive(NoUninit)]` macro is provided under the `derive` feature flag which will
/// automatically validate the requirements of this trait and implement the
/// trait for you for both enums and structs. This is the recommended method for
/// implementing the trait, however it's also possible to do manually. If you
/// implement it manually, you *must* carefully follow the below safety rules.
/// A `#[derive(NoUninit)]` macro is provided under the `derive` feature flag
/// which will automatically validate the requirements of this trait and
/// implement the trait for you for both enums and structs. This is the
/// recommended method for implementing the trait, however it's also possible to
/// do manually. If you implement it manually, you *must* carefully follow the
/// below safety rules.
///
/// # Safety
///
/// The same as [`Pod`] except we disregard the rule about it must
/// allow any bit pattern (i.e. it does not need to be [`Zeroable`][crate::Zeroable]).
/// Still, this is a quite strong guarantee about a type, so *be careful* whem
/// implementing it manually.
/// allow any bit pattern (i.e. it does not need to be
/// [`Zeroable`][crate::Zeroable]). Still, this is a quite strong guarantee
/// about a type, so *be careful* whem implementing it manually.
///
/// * The type must be inhabited (eg: no
/// [Infallible](core::convert::Infallible)).
/// * The type must not contain any uninit (or padding) bytes, either in the middle or on
/// the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has padding in the
/// middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which has padding on
/// the end).
/// * The type must not contain any uninit (or padding) bytes, either in the
/// middle or on the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has
/// padding in the middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which
/// has padding on the end).
/// * Structs need to have all fields also be `NoUninit`.
/// * Structs need to be `repr(C)` or `repr(transparent)`. In the case of
/// `repr(C)`, the `packed` and `align` repr modifiers can be used as long as
/// all other rules end up being followed.
/// * Enums need to have an explicit `#[repr(Int)]`
/// * Enums must have only fieldless variants
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`, atomics, and any
/// other forms of interior mutability.
/// * More precisely: A shared reference to the type must allow reads, and *only* reads. RustBelt's
/// separation logic is based on the notion that a type is allowed to define a sharing predicate,
/// its own invariant that must hold for shared references, and this predicate is the reasoning
/// that allow it to deal with atomic and cells etc. We require the sharing predicate to be
/// trivial and permit only read-only access.
/// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`,
/// atomics, and any other forms of interior mutability.
/// * More precisely: A shared reference to the type must allow reads, and
/// *only* reads. RustBelt's separation logic is based on the notion that a
/// type is allowed to define a sharing predicate, its own invariant that must
/// hold for shared references, and this predicate is the reasoning that allow
/// it to deal with atomic and cells etc. We require the sharing predicate to
/// be trivial and permit only read-only access.
/// * There's probably more, don't mess it up (I mean it).
pub unsafe trait NoUninit: Sized + Copy + 'static {}
@ -83,4 +77,4 @@ unsafe impl NoUninit for NonZeroI64 {}
unsafe impl NoUninit for NonZeroU128 {}
unsafe impl NoUninit for NonZeroI128 {}
unsafe impl NoUninit for NonZeroUsize {}
unsafe impl NoUninit for NonZeroIsize {}
unsafe impl NoUninit for NonZeroIsize {}

View File

@ -21,11 +21,15 @@ fn test_transparent_wrapper() {
unsafe impl bytemuck::Pod for Wrapper {}
impl PartialEq<u8> for Foreign {
fn eq(&self, &other: &u8) -> bool { self.0 == other }
fn eq(&self, &other: &u8) -> bool {
self.0 == other
}
}
impl PartialEq<u8> for Wrapper {
fn eq(&self, &other: &u8) -> bool { self.0 == other }
fn eq(&self, &other: &u8) -> bool {
self.0 == other
}
}
let _: u8 = bytemuck::cast(Wrapper::wrap(Foreign::default()));
@ -75,7 +79,7 @@ fn test_transparent_wrapper() {
use bytemuck::allocation::TransparentWrapperAlloc;
let a: Vec<Foreign> = vec![Foreign::default(); 2];
let b: Vec<Wrapper> = Wrapper::wrap_vec(a);
assert_eq!(b, [0, 0]);
@ -83,7 +87,7 @@ fn test_transparent_wrapper() {
assert_eq!(c, [0, 0]);
let d: Box<Foreign> = Box::new(Foreign::default());
let e: Box<Wrapper> = Wrapper::wrap_box(d);
assert_eq!(&*e, &0);
let f: Box<Foreign> = Wrapper::peel_box(e);