Skip to content

Commit

Permalink
FromZeroes for Option<T> where T is subject to NPO
Browse files Browse the repository at this point in the history
For thin pointer types, `P` (`Box<T>`, `&T`, `&mut T`, and `NonNull<T>`
where `T: Sized`), implement `FromZeroes` for `Option<P>`.

Release 0.7.25.

Closes #293
  • Loading branch information
joshlf committed Nov 4, 2023
1 parent c9772d9 commit 94f00d7
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 9 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Expand Up @@ -15,7 +15,7 @@
[package]
edition = "2018"
name = "zerocopy"
version = "0.7.24"
version = "0.7.25"
authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
description = "Utilities for zero-copy parsing and serialization"
license = "BSD-2-Clause OR Apache-2.0 OR MIT"
Expand Down Expand Up @@ -49,7 +49,7 @@ simd-nightly = ["simd"]
__internal_use_only_features_that_work_on_stable = ["alloc", "derive", "simd"]

[dependencies]
zerocopy-derive = { version = "=0.7.24", path = "zerocopy-derive", optional = true }
zerocopy-derive = { version = "=0.7.25", path = "zerocopy-derive", optional = true }

[dependencies.byteorder]
version = "1.3"
Expand All @@ -60,7 +60,7 @@ optional = true
# zerocopy-derive remain equal, even if the 'derive' feature isn't used.
# See: https://github.com/matklad/macro-dep-test
[target.'cfg(any())'.dependencies]
zerocopy-derive = { version = "=0.7.24", path = "zerocopy-derive" }
zerocopy-derive = { version = "=0.7.25", path = "zerocopy-derive" }

[dev-dependencies]
assert_matches = "1.5"
Expand All @@ -75,6 +75,6 @@ testutil = { path = "testutil" }
# CI test failures.
trybuild = { version = "=1.0.85", features = ["diff"] }
# In tests, unlike in production, zerocopy-derive is not optional
zerocopy-derive = { version = "=0.7.24", path = "zerocopy-derive" }
zerocopy-derive = { version = "=0.7.25", path = "zerocopy-derive" }
# TODO(#381) Remove this dependency once we have our own layout gadgets.
elain = "0.3.0"
43 changes: 42 additions & 1 deletion src/lib.rs
Expand Up @@ -1880,6 +1880,37 @@ safety_comment! {
unsafe_impl!(Option<NonZeroIsize>: FromZeroes, FromBytes, AsBytes);
}

safety_comment! {
/// SAFETY:
/// The following types can be transmuted from `[0u8; size_of::<T>()]`. [1]
/// None of them contain `UnsafeCell`s, and so they all soundly implement
/// `FromZeroes`.
///
/// [1] Per
/// https://doc.rust-lang.org/nightly/core/option/index.html#representation:
///
/// Rust guarantees to optimize the following types `T` such that
/// [`Option<T>`] has the same size and alignment as `T`. In some of these
/// cases, Rust further guarantees that `transmute::<_, Option<T>>([0u8;
/// size_of::<T>()])` is sound and produces `Option::<T>::None`. These
/// cases are identified by the second column:
///
/// | `T` | `transmute::<_, Option<T>>([0u8; size_of::<T>()])` sound? |
/// |---------------------|-----------------------------------------------------------|
/// | [`Box<U>`] | when `U: Sized` |
/// | `&U` | when `U: Sized` |
/// | `&mut U` | when `U: Sized` |
/// | [`ptr::NonNull<U>`] | when `U: Sized` |
///
/// TODO(#429), TODO(https://github.com/rust-lang/rust/pull/115333): Cite
/// the Stable docs once they're available.
#[cfg(feature = "alloc")]
unsafe_impl!(T => FromZeroes for Option<Box<T>>);
unsafe_impl!(T => FromZeroes for Option<&'_ T>);
unsafe_impl!(T => FromZeroes for Option<&'_ mut T>);
unsafe_impl!(T => FromZeroes for Option<NonNull<T>>);
}

safety_comment! {
/// SAFETY:
/// For all `T`, `PhantomData<T>` has size 0 and alignment 1. [1]
Expand Down Expand Up @@ -3820,7 +3851,7 @@ pub use alloc_support::*;
mod tests {
#![allow(clippy::unreadable_literal)]

use core::{convert::TryInto as _, ops::Deref};
use core::{cell::UnsafeCell, convert::TryInto as _, ops::Deref};

use static_assertions::assert_impl_all;

Expand Down Expand Up @@ -5515,6 +5546,16 @@ mod tests {
// Implements none of the ZC traits.
struct NotZerocopy;

#[cfg(feature = "alloc")]
assert_impls!(Option<Box<UnsafeCell<NotZerocopy>>>: KnownLayout, FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Option<Box<[UnsafeCell<NotZerocopy>]>>: KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Option<&'static UnsafeCell<NotZerocopy>>: KnownLayout, FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Option<&'static [UnsafeCell<NotZerocopy>]>: KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Option<&'static mut UnsafeCell<NotZerocopy>>: KnownLayout, FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Option<&'static mut [UnsafeCell<NotZerocopy>]>: KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Option<NonNull<UnsafeCell<NotZerocopy>>>: KnownLayout, FromZeroes, !FromBytes, !AsBytes, !Unaligned);
assert_impls!(Option<NonNull<[UnsafeCell<NotZerocopy>]>>: KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned);

assert_impls!(PhantomData<NotZerocopy>: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned);
assert_impls!(PhantomData<[u8]>: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned);

Expand Down
6 changes: 3 additions & 3 deletions src/macros.rs
Expand Up @@ -26,9 +26,9 @@
/// The macro invocations are emitted, each decorated with the following
/// attribute: `#[allow(clippy::undocumented_unsafe_blocks)]`.
macro_rules! safety_comment {
(#[doc = r" SAFETY:"] $($(#[doc = $_doc:literal])* $macro:ident!$args:tt;)*) => {
#[allow(clippy::undocumented_unsafe_blocks)]
const _: () = { $($macro!$args;)* };
(#[doc = r" SAFETY:"] $($(#[$attr:meta])* $macro:ident!$args:tt;)*) => {
#[allow(clippy::undocumented_unsafe_blocks, unused_attributes)]
const _: () = { $($(#[$attr])* $macro!$args;)* };
}
}

Expand Down
2 changes: 1 addition & 1 deletion zerocopy-derive/Cargo.toml
Expand Up @@ -9,7 +9,7 @@
[package]
edition = "2018"
name = "zerocopy-derive"
version = "0.7.24"
version = "0.7.25"
authors = ["Joshua Liebow-Feeser <joshlf@google.com>"]
description = "Custom derive for traits from the zerocopy crate"
license = "BSD-2-Clause OR Apache-2.0 OR MIT"
Expand Down

0 comments on commit 94f00d7

Please sign in to comment.