Skip to content
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

[WIP] Add Self: Read bound to is_bit_valid #1912

Open
wants to merge 3 commits into
base: I7af68cdaa5ea47ab245a942d1cbd8bc5e6407223
Choose a base branch
from
Open
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
86 changes: 45 additions & 41 deletions src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,13 +443,13 @@ mod atomics {
use super::*;

macro_rules! impl_traits_for_atomics {
($($atomics:ident),* $(,)?) => {
($($atomics:ident[$repr:ty]),* $(,)?) => {
$(
impl_known_layout!($atomics);
impl_for_transparent_wrapper!(=> TryFromBytes for $atomics);
impl_for_transparent_wrapper!(=> FromZeros for $atomics);
impl_for_transparent_wrapper!(=> FromBytes for $atomics);
impl_for_transparent_wrapper!(=> IntoBytes for $atomics);
impl_for_transmute_from!(=> TryFromBytes for $atomics[UnsafeCell<$repr>]);
impl_for_transmute_from!(=> FromZeros for $atomics[UnsafeCell<$repr>]);
impl_for_transmute_from!(=> FromBytes for $atomics[UnsafeCell<$repr>]);
impl_for_transmute_from!(=> IntoBytes for $atomics[UnsafeCell<$repr>]);
)*
};
}
Expand All @@ -461,13 +461,13 @@ mod atomics {

use super::*;

impl_traits_for_atomics!(AtomicU8, AtomicI8);
impl_traits_for_atomics!(AtomicU8[u8], AtomicI8[i8]);

impl_known_layout!(AtomicBool);

impl_for_transparent_wrapper!(=> TryFromBytes for AtomicBool);
impl_for_transparent_wrapper!(=> FromZeros for AtomicBool);
impl_for_transparent_wrapper!(=> IntoBytes for AtomicBool);
impl_for_transmute_from!(=> TryFromBytes for AtomicBool[UnsafeCell<bool>]);
impl_for_transmute_from!(=> FromZeros for AtomicBool[UnsafeCell<bool>]);
impl_for_transmute_from!(=> IntoBytes for AtomicBool[UnsafeCell<bool>]);

safety_comment! {
/// SAFETY:
Expand Down Expand Up @@ -497,7 +497,7 @@ mod atomics {
/// SAFETY:
/// All of these pass an atomic type and that type's native equivalent, as
/// required by the macro safety preconditions.
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU8 [u8], AtomicI8 [i8], AtomicBool [bool]);
unsafe_impl_transmute_from_for_atomic!(AtomicU8 [u8], AtomicI8 [i8], AtomicBool [bool]);
}
}

Expand All @@ -508,13 +508,13 @@ mod atomics {

use super::*;

impl_traits_for_atomics!(AtomicU16, AtomicI16);
impl_traits_for_atomics!(AtomicU16[u16], AtomicI16[i16]);

safety_comment! {
/// SAFETY:
/// All of these pass an atomic type and that type's native equivalent, as
/// required by the macro safety preconditions.
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU16 [u16], AtomicI16 [i16]);
unsafe_impl_transmute_from_for_atomic!(AtomicU16 [u16], AtomicI16 [i16]);
}
}

Expand All @@ -525,13 +525,13 @@ mod atomics {

use super::*;

impl_traits_for_atomics!(AtomicU32, AtomicI32);
impl_traits_for_atomics!(AtomicU32[u32], AtomicI32[i32]);

safety_comment! {
/// SAFETY:
/// All of these pass an atomic type and that type's native equivalent, as
/// required by the macro safety preconditions.
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU32 [u32], AtomicI32 [i32]);
unsafe_impl_transmute_from_for_atomic!(AtomicU32 [u32], AtomicI32 [i32]);
}
}

Expand All @@ -542,13 +542,13 @@ mod atomics {

use super::*;

impl_traits_for_atomics!(AtomicU64, AtomicI64);
impl_traits_for_atomics!(AtomicU64[u64], AtomicI64[i64]);

safety_comment! {
/// SAFETY:
/// All of these pass an atomic type and that type's native equivalent, as
/// required by the macro safety preconditions.
unsafe_impl_transparent_wrapper_for_atomic!(AtomicU64 [u64], AtomicI64 [i64]);
unsafe_impl_transmute_from_for_atomic!(AtomicU64 [u64], AtomicI64 [i64]);
}
}

Expand All @@ -559,21 +559,21 @@ mod atomics {

use super::*;

impl_traits_for_atomics!(AtomicUsize, AtomicIsize);
impl_traits_for_atomics!(AtomicUsize[usize], AtomicIsize[isize]);

impl_known_layout!(T => AtomicPtr<T>);

// TODO(#170): Implement `FromBytes` and `IntoBytes` once we implement
// those traits for `*mut T`.
impl_for_transparent_wrapper!(T => TryFromBytes for AtomicPtr<T>);
impl_for_transparent_wrapper!(T => FromZeros for AtomicPtr<T>);
impl_for_transmute_from!(T => TryFromBytes for AtomicPtr<T>[UnsafeCell<*mut T>]);
impl_for_transmute_from!(T => FromZeros for AtomicPtr<T>[UnsafeCell<*mut T>]);

safety_comment! {
/// SAFETY:
/// This passes an atomic type and that type's native equivalent, as
/// required by the macro safety preconditions.
unsafe_impl_transparent_wrapper_for_atomic!(AtomicUsize [usize], AtomicIsize [isize]);
unsafe_impl_transparent_wrapper_for_atomic!(T => AtomicPtr<T> [*mut T]);
unsafe_impl_transmute_from_for_atomic!(AtomicUsize [usize], AtomicIsize [isize]);
unsafe_impl_transmute_from_for_atomic!(T => AtomicPtr<T> [*mut T]);
}
}
}
Expand Down Expand Up @@ -603,12 +603,12 @@ safety_comment! {
assert_unaligned!(PhantomData<()>, PhantomData<u8>, PhantomData<u64>);
}

impl_for_transparent_wrapper!(T: Immutable => Immutable for Wrapping<T>);
impl_for_transparent_wrapper!(T: TryFromBytes => TryFromBytes for Wrapping<T>);
impl_for_transparent_wrapper!(T: FromZeros => FromZeros for Wrapping<T>);
impl_for_transparent_wrapper!(T: FromBytes => FromBytes for Wrapping<T>);
impl_for_transparent_wrapper!(T: IntoBytes => IntoBytes for Wrapping<T>);
impl_for_transparent_wrapper!(T: Unaligned => Unaligned for Wrapping<T>);
impl_for_transmute_from!(T: Immutable => Immutable for Wrapping<T>[T]);
impl_for_transmute_from!(T: TryFromBytes => TryFromBytes for Wrapping<T>[T]);
impl_for_transmute_from!(T: FromZeros => FromZeros for Wrapping<T>[T]);
impl_for_transmute_from!(T: FromBytes => FromBytes for Wrapping<T>[T]);
impl_for_transmute_from!(T: IntoBytes => IntoBytes for Wrapping<T>[T]);
impl_for_transmute_from!(T: Unaligned => Unaligned for Wrapping<T>[T]);
assert_unaligned!(Wrapping<()>, Wrapping<u8>);

safety_comment! {
Expand All @@ -620,22 +620,22 @@ safety_comment! {
unsafe_impl!(T => FromBytes for MaybeUninit<T>);
}

impl_for_transparent_wrapper!(T: Immutable => Immutable for MaybeUninit<T>);
impl_for_transparent_wrapper!(T: Unaligned => Unaligned for MaybeUninit<T>);
impl_for_transmute_from!(T: Immutable => Immutable for MaybeUninit<T>[T]);
impl_for_transmute_from!(T: Unaligned => Unaligned for MaybeUninit<T>[T]);
assert_unaligned!(MaybeUninit<()>, MaybeUninit<u8>);

impl_for_transparent_wrapper!(T: ?Sized + Immutable => Immutable for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>);
impl_for_transparent_wrapper!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>);
impl_for_transmute_from!(T: ?Sized + Immutable => Immutable for ManuallyDrop<T>[T]);
impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop<T>[T]);
impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop<T>[T]);
impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>[T]);
impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>[T]);
impl_for_transmute_from!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>[T]);
assert_unaligned!(ManuallyDrop<()>, ManuallyDrop<u8>);

impl_for_transparent_wrapper!(T: ?Sized + FromZeros => FromZeros for UnsafeCell<T>);
impl_for_transparent_wrapper!(T: ?Sized + FromBytes => FromBytes for UnsafeCell<T>);
impl_for_transparent_wrapper!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell<T>);
impl_for_transparent_wrapper!(T: ?Sized + Unaligned => Unaligned for UnsafeCell<T>);
impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for UnsafeCell<T>[T]);
impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for UnsafeCell<T>[T]);
impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for UnsafeCell<T>[T]);
impl_for_transmute_from!(T: ?Sized + Unaligned => Unaligned for UnsafeCell<T>[T]);
assert_unaligned!(UnsafeCell<()>, UnsafeCell<u8>);

// SAFETY: See safety comment in `is_bit_valid` impl.
Expand All @@ -648,7 +648,10 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
}

#[inline]
fn is_bit_valid<A: invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool {
fn is_bit_valid<A: invariant::Reference, R>(candidate: Maybe<'_, Self, A>) -> bool
where
Self: invariant::Read<A, R>,
{
// The only way to implement this function is using an exclusive-aliased
// pointer. `UnsafeCell`s cannot be read via shared-aliased pointers
// (other than by using `unsafe` code, which we can't use since we can't
Expand Down Expand Up @@ -700,11 +703,12 @@ safety_comment! {
/// [1] https://doc.rust-lang.org/1.81.0/reference/type-layout.html#array-layout
unsafe_impl!(const N: usize, T: Immutable => Immutable for [T; N]);
unsafe_impl!(const N: usize, T: TryFromBytes => TryFromBytes for [T; N]; |c: Maybe<[T; N]>| {
use invariant::*;
// Note that this call may panic, but it would still be sound even if it
// did. `is_bit_valid` does not promise that it will not panic (in fact,
// it explicitly warns that it's a possibility), and we have not
// violated any safety invariants that we must fix before returning.
<[T] as TryFromBytes>::is_bit_valid(c.as_slice())
<[T] as TryFromBytes>::is_bit_valid::<AA, BecauseSliceElem<BecauseArray<R, N>>>(c.as_slice())
});
unsafe_impl!(const N: usize, T: FromZeros => FromZeros for [T; N]);
unsafe_impl!(const N: usize, T: FromBytes => FromBytes for [T; N]);
Expand Down
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1321,7 +1321,9 @@ pub unsafe trait TryFromBytes {
/// [`UnsafeCell`]: core::cell::UnsafeCell
/// [`Shared`]: invariant::Shared
#[doc(hidden)]
fn is_bit_valid<A: invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool;
fn is_bit_valid<A: invariant::Reference, R: ?Sized>(candidate: Maybe<'_, Self, A>) -> bool
where
Self: invariant::Read<A, R>;

/// Attempts to interpret the given `source` as a `&Self`.
///
Expand Down Expand Up @@ -2718,7 +2720,7 @@ unsafe fn try_read_from<S, T: TryFromBytes>(
// We use `from_mut` despite not mutating via `c_ptr` so that we don't need
// to add a `T: Immutable` bound.
let c_ptr = Ptr::from_mut(&mut candidate);
let c_ptr = c_ptr.transparent_wrapper_into_inner();
let c_ptr = c_ptr.transmute();
// SAFETY: `c_ptr` has no uninitialized sub-ranges because it derived from
// `candidate`, which the caller promises is entirely initialized.
let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
Expand Down
Loading
Loading