From b82bd97de1e78e63513cf0c24275be97dec4c9b2 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Fri, 1 Dec 2023 15:25:45 +0000 Subject: [PATCH] [derive] Support `derive(TryFromBytes)` for structs Supersedes #370. Makes progress on #5. Co-authored-by: Joshua Liebow-Feeser --- src/lib.rs | 9 +- src/macros.rs | 12 +- src/util.rs | 69 ++++++++- .../invalid-impls/invalid-impls.stderr | 96 ++++++++---- .../ui-nightly/invalid-impls/invalid-impls.rs | 3 +- .../invalid-impls/invalid-impls.stderr | 91 +++++++---- .../invalid-impls/invalid-impls.stderr | 91 +++++++---- zerocopy-derive/src/ext.rs | 56 +++++-- zerocopy-derive/src/lib.rs | 102 ++++++++++-- .../tests/struct_try_from_bytes.rs | 143 +++++++++++++++++ .../tests/ui-msrv/derive_transparent.stderr | 79 +++------- zerocopy-derive/tests/ui-msrv/enum.stderr | 139 ++++++++++++++++- .../tests/ui-msrv/late_compile_pass.stderr | 37 +++-- zerocopy-derive/tests/ui-msrv/struct.stderr | 100 +++++++----- .../tests/ui-nightly/derive_transparent.rs | 3 +- .../ui-nightly/derive_transparent.stderr | 124 ++++----------- zerocopy-derive/tests/ui-nightly/enum.rs | 30 ++-- zerocopy-derive/tests/ui-nightly/enum.stderr | 139 ++++++++++++++++- .../tests/ui-nightly/late_compile_pass.rs | 9 ++ .../tests/ui-nightly/late_compile_pass.stderr | 48 ++++-- zerocopy-derive/tests/ui-nightly/struct.rs | 28 ++++ .../tests/ui-nightly/struct.stderr | 146 +++++++++++++----- .../tests/ui-stable/derive_transparent.stderr | 124 ++++----------- zerocopy-derive/tests/ui-stable/enum.stderr | 139 ++++++++++++++++- .../tests/ui-stable/late_compile_pass.stderr | 47 ++++-- zerocopy-derive/tests/ui-stable/struct.stderr | 96 +++++++----- zerocopy-derive/tests/util.rs | 4 +- 27 files changed, 1407 insertions(+), 557 deletions(-) create mode 100644 zerocopy-derive/tests/struct_try_from_bytes.rs diff --git a/src/lib.rs b/src/lib.rs index 705e9d28ff0..676bed02cf5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -254,7 +254,7 @@ pub use crate::wrappers::*; #[cfg(any(feature = "derive", test))] #[cfg_attr(doc_cfg, doc(cfg(feature = "derive")))] -pub use zerocopy_derive::Unaligned; +pub use zerocopy_derive::{TryFromBytes, Unaligned}; // `pub use` separately here so that we can mark it `#[doc(hidden)]`. // @@ -1193,6 +1193,13 @@ pub unsafe trait NoCell { // TODO(#5): Update `try_from_ref` doc link once it exists #[doc(hidden)] pub unsafe trait TryFromBytes { + // The `Self: Sized` bound makes it so that `TryFromBytes` is still object + // safe. + #[doc(hidden)] + fn only_derive_is_allowed_to_implement_this_trait() + where + Self: Sized; + /// Does a given memory range contain a valid instance of `Self`? /// /// # Safety diff --git a/src/macros.rs b/src/macros.rs index 2da78af7df8..833ae387a7e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -133,6 +133,9 @@ macro_rules! unsafe_impl { }; (@method TryFromBytes ; |$candidate:ident: &$repr:ty| $is_bit_valid:expr) => { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() {} + #[inline] unsafe fn is_bit_valid(candidate: Ptr<'_, Self>) -> bool { // SAFETY: @@ -160,6 +163,9 @@ macro_rules! unsafe_impl { } }; (@method TryFromBytes ; |$candidate:ident: Ptr<$repr:ty>| $is_bit_valid:expr) => { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() {} + #[inline] unsafe fn is_bit_valid(candidate: Ptr<'_, Self>) -> bool { // SAFETY: @@ -174,7 +180,11 @@ macro_rules! unsafe_impl { $is_bit_valid } }; - (@method TryFromBytes) => { #[inline(always)] unsafe fn is_bit_valid(_: Ptr<'_, Self>) -> bool { true } }; + (@method TryFromBytes) => { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() {} + #[inline(always)] unsafe fn is_bit_valid(_: Ptr<'_, Self>) -> bool { true } + }; (@method $trait:ident) => { #[allow(clippy::missing_inline_in_public_items)] fn only_derive_is_allowed_to_implement_this_trait() {} diff --git a/src/util.rs b/src/util.rs index 23520f3e85d..ae8556ef0fa 100644 --- a/src/util.rs +++ b/src/util.rs @@ -110,7 +110,8 @@ pub(crate) mod ptr { /// than or equal to the size of the object referenced by `self`. /// - The alignment of `U` is less than or equal to the alignment of /// `T`. - pub(crate) unsafe fn cast_unsized *mut U>( + #[doc(hidden)] + pub unsafe fn cast_unsized *mut U>( self, cast: F, ) -> Ptr<'a, U> { @@ -139,6 +140,72 @@ pub(crate) mod ptr { // - `U: 'a` Ptr { ptr, _lifetime: PhantomData } } + + /// Projects a field from `self`. + /// + /// # Safety + /// + /// ## Preconditions + /// + /// The caller promises that `projector` projects a well-aligned field + /// of its argument. Its argument will be `self` casted to a raw + /// pointer. + /// + /// ## Postconditions + /// + /// If the preconditions of this function are met, this function will + /// return a `Ptr` to the field projected from `self` by `projector`. + #[doc(hidden)] + #[inline] + pub unsafe fn project( + self, + projector: impl FnOnce(*mut T) -> *mut U, + ) -> Ptr<'a, U> { + // SAFETY: `projector` is provided with `self` casted to a raw + // pointer. + let field = projector(self.ptr.as_ptr()); + + // SAFETY: We promise that `projector` is provided with `self` + // casted to a raw pointer, and the caller promises that `projector` + // is a field projection of its argument. By invariant on `Ptr`, + // `self` is non-null, and by contract on `projector`, so too will + // its return value. + // + // Note that field projection cannot wrap around the address space + // to null. + // + // TODO(https://github.com/rust-lang/rust/pull/116675): Cite + // documentation that allocated objects do not wrap around the + // address space. + let field = unsafe { NonNull::new_unchecked(field) }; + + // SAFETY: The safety invariants of `Ptr` (see definition) are + // satisfied: + // 1. `field` is derived from a valid Rust allocation, because + // `self` is derived from a valid Rust allocation, by invariant + // on `Ptr`, and `projector` (by contract) is a field projection + // through `self`. + // 2. `field` has the same provenance as `self`, because it derived + // from `self` using a series of provenance-preserving + // operations. + // 3. `field` is entirely contained in the allocation of `self`, + // because it is derived by `projector`, which is (by contract) a + // field projection through `self`. + // 4. `field` addresses a byte range whose length fits in an + // `isize`, because it is a field projection through `self` and + // thus is entirely contained by `self`, which satisfies this + // invariant. + // 5. `field` addresses a byte range which does not wrap around the + // address space (see above). + // 6. `field` is validly-aligned for `U`, by contract on + // `projector`. + // 7. The allocation of `field` is guaranteed to live for at least + // `'a`, because `field` is entirely contained in `self`, which + // lives for at least `'a` by invariant on `Ptr`. + // 8. `U: 'a`, because `field` is an element within `T`, and `T: 'a` + // by invariant on `Ptr`. + Ptr { ptr: field, _lifetime: PhantomData } + } } impl<'a> Ptr<'a, [u8]> { diff --git a/tests/ui-msrv/invalid-impls/invalid-impls.stderr b/tests/ui-msrv/invalid-impls/invalid-impls.stderr index c1de466ecef..d5b0b84e66c 100644 --- a/tests/ui-msrv/invalid-impls/invalid-impls.stderr +++ b/tests/ui-msrv/invalid-impls/invalid-impls.stderr @@ -1,33 +1,65 @@ +error[E0277]: the trait bound `T: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-msrv/invalid-impls/../../../src/macros.rs + | + | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} + | ^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `T` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1 + | +26 | impl_or_verify!(T => TryFromBytes for Foo); + | --------------------------------------------- in this macro invocation + | +note: required because of the requirements on the impl of `zerocopy::TryFromBytes` for `Foo` + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^^^^ +note: required by a bound in `_::Subtrait` + --> tests/ui-msrv/invalid-impls/../../../src/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `_::Subtrait` + | + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1 + | +26 | impl_or_verify!(T => TryFromBytes for Foo); + | --------------------------------------------- in this macro invocation + = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +26 | impl_or_verify!(T: zerocopy::TryFromBytes => TryFromBytes for Foo); + | ++++++++++++++++++++++++ + error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied --> tests/ui-msrv/invalid-impls/../../../src/macros.rs | | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} | ^^^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1 | -26 | impl_or_verify!(T => FromZeroes for Foo); +27 | impl_or_verify!(T => FromZeroes for Foo); | ------------------------------------------- in this macro invocation | note: required because of the requirements on the impl of `zerocopy::FromZeroes` for `Foo` - --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:10 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:24 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^^ +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1 | -26 | impl_or_verify!(T => FromZeroes for Foo); +27 | impl_or_verify!(T => FromZeroes for Foo); | ------------------------------------------- in this macro invocation = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -26 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); +27 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); | ++++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied @@ -36,30 +68,30 @@ error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} | ^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1 | -27 | impl_or_verify!(T => FromBytes for Foo); +28 | impl_or_verify!(T => FromBytes for Foo); | ------------------------------------------ in this macro invocation | note: required because of the requirements on the impl of `zerocopy::FromBytes` for `Foo` - --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:22 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:36 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^ +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1 | -27 | impl_or_verify!(T => FromBytes for Foo); +28 | impl_or_verify!(T => FromBytes for Foo); | ------------------------------------------ in this macro invocation = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -27 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); +28 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); | +++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied @@ -68,30 +100,30 @@ error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} | ^^^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `T` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1 | -28 | impl_or_verify!(T => AsBytes for Foo); +29 | impl_or_verify!(T => AsBytes for Foo); | ---------------------------------------- in this macro invocation | note: required because of the requirements on the impl of `zerocopy::AsBytes` for `Foo` - --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:33 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:47 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^ +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1 | -28 | impl_or_verify!(T => AsBytes for Foo); +29 | impl_or_verify!(T => AsBytes for Foo); | ---------------------------------------- in this macro invocation = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -28 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); +29 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); | +++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied @@ -100,28 +132,28 @@ error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} | ^^^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:30:1 | -29 | impl_or_verify!(T => Unaligned for Foo); +30 | impl_or_verify!(T => Unaligned for Foo); | ------------------------------------------ in this macro invocation | note: required because of the requirements on the impl of `zerocopy::Unaligned` for `Foo` - --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:42 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:56 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^ +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:30:1 | -29 | impl_or_verify!(T => Unaligned for Foo); +30 | impl_or_verify!(T => Unaligned for Foo); | ------------------------------------------ in this macro invocation = note: this error originates in the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); +30 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); | +++++++++++++++++++++ diff --git a/tests/ui-nightly/invalid-impls/invalid-impls.rs b/tests/ui-nightly/invalid-impls/invalid-impls.rs index ea963907df7..b008ec5de8e 100644 --- a/tests/ui-nightly/invalid-impls/invalid-impls.rs +++ b/tests/ui-nightly/invalid-impls/invalid-impls.rs @@ -19,10 +19,11 @@ use zerocopy_derive::*; fn main() {} -#[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +#[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] #[repr(transparent)] struct Foo(T); +impl_or_verify!(T => TryFromBytes for Foo); impl_or_verify!(T => FromZeroes for Foo); impl_or_verify!(T => FromBytes for Foo); impl_or_verify!(T => AsBytes for Foo); diff --git a/tests/ui-nightly/invalid-impls/invalid-impls.stderr b/tests/ui-nightly/invalid-impls/invalid-impls.stderr index e5651d169e0..b4ebd273805 100644 --- a/tests/ui-nightly/invalid-impls/invalid-impls.stderr +++ b/tests/ui-nightly/invalid-impls/invalid-impls.stderr @@ -1,107 +1,134 @@ +error[E0277]: the trait bound `T: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:26:39 + | +26 | impl_or_verify!(T => TryFromBytes for Foo); + | ^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `T` + | +note: required for `Foo` to implement `zerocopy::TryFromBytes` + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-nightly/invalid-impls/../../../src/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:26:1 + | +26 | impl_or_verify!(T => TryFromBytes for Foo); + | --------------------------------------------- in this macro invocation + = note: this error originates in the derive macro `TryFromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +26 | impl_or_verify!(T: zerocopy::TryFromBytes => TryFromBytes for Foo); + | ++++++++++++++++++++++++ + error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:26:37 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:27:37 | -26 | impl_or_verify!(T => FromZeroes for Foo); +27 | impl_or_verify!(T => FromZeroes for Foo); | ^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::FromZeroes` - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:10 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:24 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-nightly/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:26:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:27:1 | -26 | impl_or_verify!(T => FromZeroes for Foo); +27 | impl_or_verify!(T => FromZeroes for Foo); | ------------------------------------------- in this macro invocation = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -26 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); +27 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); | ++++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:27:36 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:28:36 | -27 | impl_or_verify!(T => FromBytes for Foo); +28 | impl_or_verify!(T => FromBytes for Foo); | ^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::FromBytes` - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:22 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:36 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-nightly/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:27:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:28:1 | -27 | impl_or_verify!(T => FromBytes for Foo); +28 | impl_or_verify!(T => FromBytes for Foo); | ------------------------------------------ in this macro invocation = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -27 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); +28 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); | +++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:28:34 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:29:34 | -28 | impl_or_verify!(T => AsBytes for Foo); +29 | impl_or_verify!(T => AsBytes for Foo); | ^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::AsBytes` - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:33 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:47 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-nightly/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:28:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:29:1 | -28 | impl_or_verify!(T => AsBytes for Foo); +29 | impl_or_verify!(T => AsBytes for Foo); | ---------------------------------------- in this macro invocation = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -28 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); +29 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); | +++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:29:36 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:30:36 | -29 | impl_or_verify!(T => Unaligned for Foo); +30 | impl_or_verify!(T => Unaligned for Foo); | ^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::Unaligned` - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:42 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:56 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-nightly/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:29:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:30:1 | -29 | impl_or_verify!(T => Unaligned for Foo); +30 | impl_or_verify!(T => Unaligned for Foo); | ------------------------------------------ in this macro invocation = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); +30 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); | +++++++++++++++++++++ diff --git a/tests/ui-stable/invalid-impls/invalid-impls.stderr b/tests/ui-stable/invalid-impls/invalid-impls.stderr index 7737d67175e..4489712b318 100644 --- a/tests/ui-stable/invalid-impls/invalid-impls.stderr +++ b/tests/ui-stable/invalid-impls/invalid-impls.stderr @@ -1,107 +1,134 @@ +error[E0277]: the trait bound `T: zerocopy::TryFromBytes` is not satisfied + --> tests/ui-stable/invalid-impls/invalid-impls.rs:26:39 + | +26 | impl_or_verify!(T => TryFromBytes for Foo); + | ^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `T` + | +note: required for `Foo` to implement `zerocopy::TryFromBytes` + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:10 + | +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `_::Subtrait` + --> tests/ui-stable/invalid-impls/../../../src/macros.rs + | + | trait Subtrait: $trait {} + | ^^^^^^ required by this bound in `Subtrait` + | + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:26:1 + | +26 | impl_or_verify!(T => TryFromBytes for Foo); + | --------------------------------------------- in this macro invocation + = note: this error originates in the derive macro `TryFromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider restricting type parameter `T` + | +26 | impl_or_verify!(T: zerocopy::TryFromBytes => TryFromBytes for Foo); + | ++++++++++++++++++++++++ + error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied - --> tests/ui-stable/invalid-impls/invalid-impls.rs:26:37 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:27:37 | -26 | impl_or_verify!(T => FromZeroes for Foo); +27 | impl_or_verify!(T => FromZeroes for Foo); | ^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::FromZeroes` - --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:10 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:24 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-stable/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:26:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:27:1 | -26 | impl_or_verify!(T => FromZeroes for Foo); +27 | impl_or_verify!(T => FromZeroes for Foo); | ------------------------------------------- in this macro invocation = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -26 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); +27 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); | ++++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied - --> tests/ui-stable/invalid-impls/invalid-impls.rs:27:36 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:28:36 | -27 | impl_or_verify!(T => FromBytes for Foo); +28 | impl_or_verify!(T => FromBytes for Foo); | ^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::FromBytes` - --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:22 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:36 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-stable/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:27:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:28:1 | -27 | impl_or_verify!(T => FromBytes for Foo); +28 | impl_or_verify!(T => FromBytes for Foo); | ------------------------------------------ in this macro invocation = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -27 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); +28 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); | +++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied - --> tests/ui-stable/invalid-impls/invalid-impls.rs:28:34 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:29:34 | -28 | impl_or_verify!(T => AsBytes for Foo); +29 | impl_or_verify!(T => AsBytes for Foo); | ^^^^^^ the trait `zerocopy::AsBytes` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::AsBytes` - --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:33 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:47 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-stable/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:28:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:29:1 | -28 | impl_or_verify!(T => AsBytes for Foo); +29 | impl_or_verify!(T => AsBytes for Foo); | ---------------------------------------- in this macro invocation = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -28 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); +29 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); | +++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied - --> tests/ui-stable/invalid-impls/invalid-impls.rs:29:36 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:30:36 | -29 | impl_or_verify!(T => Unaligned for Foo); +30 | impl_or_verify!(T => Unaligned for Foo); | ^^^^^^ the trait `zerocopy::Unaligned` is not implemented for `T` | note: required for `Foo` to implement `zerocopy::Unaligned` - --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:42 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:56 | -22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +22 | #[derive(TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `_::Subtrait` --> tests/ui-stable/invalid-impls/../../../src/macros.rs | | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:29:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:30:1 | -29 | impl_or_verify!(T => Unaligned for Foo); +30 | impl_or_verify!(T => Unaligned for Foo); | ------------------------------------------ in this macro invocation = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `impl_or_verify` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | -29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); +30 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); | +++++++++++++++++++++ diff --git a/zerocopy-derive/src/ext.rs b/zerocopy-derive/src/ext.rs index 87cf838f883..3f15a3cbdef 100644 --- a/zerocopy-derive/src/ext.rs +++ b/zerocopy-derive/src/ext.rs @@ -6,48 +6,74 @@ // This file may not be copied, modified, or distributed except according to // those terms. -use syn::{Data, DataEnum, DataStruct, DataUnion, Type}; +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{Data, DataEnum, DataStruct, DataUnion, Field, Index, Type}; pub trait DataExt { - /// Extract the types of all fields. For enums, extract the types of fields - /// from each variant. - fn field_types(&self) -> Vec<&Type>; + /// Extracts the names and types of all fields. For enums, extracts the names + /// and types of fields from each variant. For tuple structs, the names are + /// the indices used to index into the struct (ie, `0`, `1`, etc). + /// + /// TODO: Extracting field names for enums doesn't really make sense. Types + /// makes sense because we don't care about where they live - we just care + /// about transitive ownership. But for field names, we'd only use them when + /// generating is_bit_valid, which cares about where they live. + fn fields(&self) -> Vec<(TokenStream, &Type)>; } impl DataExt for Data { - fn field_types(&self) -> Vec<&Type> { + fn fields(&self) -> Vec<(TokenStream, &Type)> { match self { - Data::Struct(strc) => strc.field_types(), - Data::Enum(enm) => enm.field_types(), - Data::Union(un) => un.field_types(), + Data::Struct(strc) => strc.fields(), + Data::Enum(enm) => enm.fields(), + Data::Union(un) => un.fields(), } } } impl DataExt for DataStruct { - fn field_types(&self) -> Vec<&Type> { - self.fields.iter().map(|f| &f.ty).collect() + fn fields(&self) -> Vec<(TokenStream, &Type)> { + map_fields(&self.fields) } } impl DataExt for DataEnum { - fn field_types(&self) -> Vec<&Type> { - self.variants.iter().flat_map(|var| &var.fields).map(|f| &f.ty).collect() + fn fields(&self) -> Vec<(TokenStream, &Type)> { + map_fields(self.variants.iter().flat_map(|var| &var.fields)) } } impl DataExt for DataUnion { - fn field_types(&self) -> Vec<&Type> { - self.fields.named.iter().map(|f| &f.ty).collect() + fn fields(&self) -> Vec<(TokenStream, &Type)> { + map_fields(&self.fields.named) } } +fn map_fields<'a>( + fields: impl 'a + IntoIterator, +) -> Vec<(TokenStream, &'a Type)> { + fields + .into_iter() + .enumerate() + .map(|(idx, f)| { + ( + f.ident + .as_ref() + .map(ToTokens::to_token_stream) + .unwrap_or_else(|| Index::from(idx).to_token_stream()), + &f.ty, + ) + }) + .collect() +} + pub trait EnumExt { fn is_c_like(&self) -> bool; } impl EnumExt for DataEnum { fn is_c_like(&self) -> bool { - self.field_types().is_empty() + self.fields().is_empty() } } diff --git a/zerocopy-derive/src/lib.rs b/zerocopy-derive/src/lib.rs index a54cc112687..04dbbc0b07c 100644 --- a/zerocopy-derive/src/lib.rs +++ b/zerocopy-derive/src/lib.rs @@ -86,13 +86,16 @@ pub fn derive_known_layout(ts: proc_macro::TokenStream) -> proc_macro::TokenStre Data::Enum(..) | Data::Union(..) => None, }; - let fields = ast.data.field_types(); + let fields = ast.data.fields(); let (require_self_sized, extras) = if let ( Some(reprs), Some((trailing_field, leading_fields)), ) = (is_repr_c_struct, fields.split_last()) { + let (_name, trailing_field_ty) = trailing_field; + let leading_fields_tys = leading_fields.iter().map(|(_name, ty)| ty); + let repr_align = reprs .iter() .find_map( @@ -142,8 +145,8 @@ pub fn derive_known_layout(ts: proc_macro::TokenStream) -> proc_macro::TokenStre let repr_packed = #repr_packed; DstLayout::new_zst(repr_align) - #(.extend(DstLayout::for_type::<#leading_fields>(), repr_packed))* - .extend(<#trailing_field as KnownLayout>::LAYOUT, repr_packed) + #(.extend(DstLayout::for_type::<#leading_fields_tys>(), repr_packed))* + .extend(<#trailing_field_ty as KnownLayout>::LAYOUT, repr_packed) .pad_to_align() }; @@ -157,7 +160,7 @@ pub fn derive_known_layout(ts: proc_macro::TokenStream) -> proc_macro::TokenStre elems: usize, ) -> ::zerocopy::macro_util::core_reexport::ptr::NonNull { use ::zerocopy::{KnownLayout}; - let trailing = <#trailing_field as KnownLayout>::raw_from_ptr_len(bytes, elems); + let trailing = <#trailing_field_ty as KnownLayout>::raw_from_ptr_len(bytes, elems); let slf = trailing.as_ptr() as *mut Self; // SAFETY: Constructed from `trailing`, which is non-null. unsafe { ::zerocopy::macro_util::core_reexport::ptr::NonNull::new_unchecked(slf) } @@ -260,6 +263,21 @@ pub fn derive_no_cell(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { .into() } +#[proc_macro_derive(TryFromBytes)] +pub fn derive_try_from_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + let ast = syn::parse_macro_input!(ts as DeriveInput); + match &ast.data { + Data::Struct(strct) => derive_try_from_bytes_struct(&ast, strct), + Data::Enum(_) => { + Error::new_spanned(&ast, "TryFromBytes not supported on enum types").to_compile_error() + } + Data::Union(_) => { + Error::new_spanned(&ast, "TryFromBytes not supported on union types").to_compile_error() + } + } + .into() +} + #[proc_macro_derive(FromZeroes)] pub fn derive_from_zeroes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { let ast = syn::parse_macro_input!(ts as DeriveInput); @@ -304,6 +322,69 @@ pub fn derive_unaligned(ts: proc_macro::TokenStream) -> proc_macro::TokenStream .into() } +// A struct is `TryFromBytes` if: +// - all fields are `TryFromBytes` +// - the struct is NOT `repr(packed)` or `repr(packed(N))` + +fn derive_try_from_bytes_struct(ast: &DeriveInput, strct: &DataStruct) -> proc_macro2::TokenStream { + let reprs = try_or_print!(repr::reprs::(&ast.attrs)); + + for (meta, repr) in reprs { + if matches!(repr, Repr::Packed | Repr::PackedN(_)) { + try_or_print!(Err(vec![Error::new_spanned( + meta, + "cannot derive TryFromBytes with repr(packed)", + )])); + } + } + + let extras = Some({ + let fields = strct.fields(); + let field_names = fields.iter().map(|(name, _ty)| name); + let field_tys = fields.iter().map(|(_name, ty)| ty); + quote!( + // SAFETY: We use `is_bit_valid` to validate that each field is + // bit-valid, and only return `true` if all of them are. The bit + // validity of a struct is just the composition of the bit + // validities of its fields, so this is a sound implementation of + // `is_bit_valid`. + unsafe fn is_bit_valid(candidate: zerocopy::Ptr) -> bool { + true #(&& { + let project = |slf: *mut Self| ::core::ptr::addr_of_mut!((*slf).#field_names); + + // SAFETY: `project` is a field projection of `candidate`. + // The projected field will be well-aligned because this + // derive rejects packed types. + let field_candidate = unsafe { candidate.project(project) }; + + // SAFETY: The below invocation of `is_bit_valid` satisfies + // the safety preconditions of `is_bit_valid`: + // - The memory referenced by `field_candidate` is only + // accessed via reads for the duration of this method + // call. This is ensured by contract on the caller of the + // surrounding `is_bit_valid`. + // - `field_candidate` may not refer to a valid instance of + // its corresponding field type, but it will only have + // `UnsafeCell`s at the offsets at which they may occur in + // that field type. This is ensured both by contract on + // the caller of the surrounding `is_bit_valid`, and by + // the construction of `field_candidiate`, i.e., via + // projection through `candidate`. + // + // Note that it's possible that this call will panic - + // `is_bit_valid` does not promise that it doesn't panic, + // and in practice, we support user-defined validators, + // which could panic. This is sound because we haven't + // violated any safety invariants which we would need to fix + // before returning. + <#field_tys as zerocopy::TryFromBytes>::is_bit_valid(field_candidate) + })* + } + ) + }); + impl_block(ast, strct, Trait::TryFromBytes, RequireBoundedFields::Yes, false, None, extras) +} + const STRUCT_UNION_ALLOWED_REPR_COMBINATIONS: &[&[StructRepr]] = &[ &[StructRepr::C], &[StructRepr::Transparent], @@ -655,6 +736,7 @@ impl PaddingCheck { enum Trait { KnownLayout, NoCell, + TryFromBytes, FromZeroes, FromBytes, AsBytes, @@ -752,19 +834,19 @@ fn impl_block( let type_ident = &input.ident; let trait_ident = trt.ident(); - let field_types = data.field_types(); + let fields = data.fields(); let bound_tt = |ty| parse_quote!(#ty: ::zerocopy::#trait_ident); - let field_type_bounds: Vec<_> = match (require_trait_bound_on_field_types, &field_types[..]) { - (RequireBoundedFields::Yes, _) => field_types.iter().map(bound_tt).collect(), + let field_type_bounds: Vec<_> = match (require_trait_bound_on_field_types, &fields[..]) { + (RequireBoundedFields::Yes, _) => fields.iter().map(|(_name, ty)| bound_tt(ty)).collect(), (RequireBoundedFields::No, _) | (RequireBoundedFields::Trailing, []) => vec![], - (RequireBoundedFields::Trailing, [.., last]) => vec![bound_tt(last)], + (RequireBoundedFields::Trailing, [.., last]) => vec![bound_tt(&last.1)], }; // Don't bother emitting a padding check if there are no fields. #[allow(unstable_name_collisions)] // See `BoolExt` below - let padding_check_bound = padding_check.and_then(|check| (!field_types.is_empty()).then_some(check)).map(|check| { - let fields = field_types.iter(); + let padding_check_bound = padding_check.and_then(|check| (!fields.is_empty()).then_some(check)).map(|check| { + let fields = fields.iter().map(|(_name, ty)| ty); let validator_macro = check.validator_macro_ident(); parse_quote!( ::zerocopy::macro_util::HasPadding<#type_ident, {::zerocopy::#validator_macro!(#type_ident, #(#fields),*)}>: diff --git a/zerocopy-derive/tests/struct_try_from_bytes.rs b/zerocopy-derive/tests/struct_try_from_bytes.rs new file mode 100644 index 00000000000..904cd6f7781 --- /dev/null +++ b/zerocopy-derive/tests/struct_try_from_bytes.rs @@ -0,0 +1,143 @@ +// Copyright 2023 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#![allow(warnings)] + +mod util; + +use std::{marker::PhantomData, option::IntoIter}; + +use { + static_assertions::assert_impl_all, + zerocopy::{FromBytes, FromZeroes, TryFromBytes}, +}; + +use crate::util::AU16; + +// A struct is `TryFromBytes` if: +// - all fields are `TryFromBytes` + +#[derive(TryFromBytes, FromZeroes, FromBytes)] +struct Zst; + +assert_impl_all!(Zst: TryFromBytes); + +#[test] +fn zst() { + // TODO(#5): Use `try_transmute` in this test once it's available. + let candidate = zerocopy::Ptr::from(&Zst); + // SAFETY: `candidate` is derived from the tested type, so it will contain + // `UnsafeCell`s at the same offsets as the tested type. + let is_bit_valid = unsafe { Zst::is_bit_valid(candidate) }; + assert!(is_bit_valid); +} + +#[derive(TryFromBytes, FromZeroes, FromBytes)] +struct One { + a: u8, +} + +assert_impl_all!(One: TryFromBytes); + +#[test] +fn one() { + // TODO(#5): Use `try_transmute` in this test once it's available. + let candidate = zerocopy::Ptr::from(&One { a: 42 }); + // SAFETY: `candidate` is derived from the tested type, so it will contain + // `UnsafeCell`s at the same offsets as the tested type. + let is_bit_valid = unsafe { One::is_bit_valid(candidate) }; + assert!(is_bit_valid); +} + +#[derive(TryFromBytes, FromZeroes)] +struct Two { + a: bool, + b: Zst, +} + +assert_impl_all!(Two: TryFromBytes); + +#[test] +fn two() { + // TODO(#5): Use `try_transmute` in this test once it's available. + let candidate = zerocopy::Ptr::from(&Two { a: false, b: Zst }); + // SAFETY: `candidate` is derived from the tested type, so it will contain + // `UnsafeCell`s at the same offsets as the tested type. + let is_bit_valid = unsafe { Two::is_bit_valid(candidate) }; + assert!(is_bit_valid); +} + +#[test] +fn two_bad() { + // TODO(#5): Use `try_transmute` in this test once it's available. + let candidate = zerocopy::Ptr::from(&[2][..]); + // SAFETY: + // - The cast `cast(p)` is implemented exactly as follows: `|p: *mut T| p as + // *mut U`. + // - The size of the object referenced by the resulting pointer is equal to + // the size of the object referenced by `self`. + // - The alignment of `Unsized` is equal to the alignment of `[u8]`. + let candidate = unsafe { candidate.cast_unsized(|p| p as *mut Two) }; + // SAFETY: `candidate` is derived from the tested type, so it will contain + // `UnsafeCell`s at the same offsets as the tested type. + let is_bit_valid = unsafe { Two::is_bit_valid(candidate) }; + assert!(!is_bit_valid); +} + +#[derive(TryFromBytes, FromZeroes, FromBytes)] +struct Unsized { + a: [u8], +} + +assert_impl_all!(Unsized: TryFromBytes); + +#[test] +fn un_sized() { + // TODO(#5): Use `try_transmute` in this test once it's available. + let candidate = zerocopy::Ptr::from(&[16, 12, 42][..]); + // SAFETY: + // - The cast `cast(p)` is implemented exactly as follows: `|p: *mut T| p as + // *mut U`. + // - The size of the object referenced by the resulting pointer is equal to + // the size of the object referenced by `self`. + // - The alignment of `Unsized` is equal to the alignment of `[u8]`. + let candidate = unsafe { candidate.cast_unsized(|p| p as *mut Unsized) }; + // SAFETY: `candidate` is derived from the tested type, so it will contain + // `UnsafeCell`s at the same offsets as the tested type. + let is_bit_valid = unsafe { Unsized::is_bit_valid(candidate) }; + assert!(is_bit_valid); +} + +#[derive(TryFromBytes, FromZeroes, FromBytes)] +struct TypeParams<'a, T: ?Sized, I: Iterator> { + a: I::Item, + b: u8, + c: PhantomData<&'a [u8]>, + d: PhantomData<&'static str>, + e: PhantomData, + f: T, +} + +assert_impl_all!(TypeParams<'static, (), IntoIter<()>>: TryFromBytes); +assert_impl_all!(TypeParams<'static, AU16, IntoIter<()>>: TryFromBytes); +assert_impl_all!(TypeParams<'static, [AU16], IntoIter<()>>: TryFromBytes); + +// Deriving `TryFromBytes` should work if the struct has bounded parameters. + +#[derive(TryFromBytes, FromZeroes, FromBytes)] +#[repr(transparent)] +struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + TryFromBytes>( + PhantomData<&'a &'b ()>, + [T], +) +where + 'a: 'b, + 'b: 'a, + T: 'a + 'b + TryFromBytes; + +assert_impl_all!(WithParams<'static, 'static, 42, u8>: TryFromBytes); diff --git a/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr b/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr index 3b228b1551f..5b7df7f5e77 100644 --- a/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr @@ -1,71 +1,34 @@ -error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied - --> tests/ui-msrv/derive_transparent.rs:37:1 - | -37 | assert_impl_all!(TransparentStruct: FromZeroes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` - | -note: required because of the requirements on the impl of `FromZeroes` for `TransparentStruct` +error: cannot find derive macro `TryFromBytes` in this scope --> tests/ui-msrv/derive_transparent.rs:27:19 | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^^ -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-msrv/derive_transparent.rs:37:1 - | -37 | assert_impl_all!(TransparentStruct: FromZeroes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` - = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied - --> tests/ui-msrv/derive_transparent.rs:38:1 +27 | #[derive(AsBytes, TryFromBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^^^^ help: a derive macro with a similar name exists: `FromBytes` | -38 | assert_impl_all!(TransparentStruct: FromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + ::: src/lib.rs | -note: required because of the requirements on the impl of `FromBytes` for `TransparentStruct` - --> tests/ui-msrv/derive_transparent.rs:27:31 + | pub fn derive_from_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + | -------------------------------------------------------------------------------- similarly named derive macro `FromBytes` defined here | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^ -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-msrv/derive_transparent.rs:38:1 - | -38 | assert_impl_all!(TransparentStruct: FromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` - = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: consider importing one of these items: + zerocopy::TryFromBytes + zerocopy_derive::TryFromBytes -error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied - --> tests/ui-msrv/derive_transparent.rs:39:1 - | -39 | assert_impl_all!(TransparentStruct: AsBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` +error[E0405]: cannot find trait `TryFromBytes` in this scope + --> tests/ui-msrv/derive_transparent.rs:37:50 | -note: required because of the requirements on the impl of `AsBytes` for `TransparentStruct` - --> tests/ui-msrv/derive_transparent.rs:27:10 +37 | assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^ | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^ -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-msrv/derive_transparent.rs:39:1 + ::: $WORKSPACE/src/lib.rs | -39 | assert_impl_all!(TransparentStruct: AsBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` - = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied - --> tests/ui-msrv/derive_transparent.rs:40:1 + | pub unsafe trait FromBytes: FromZeroes { + | -------------------------------------- similarly named trait `FromBytes` defined here | -40 | assert_impl_all!(TransparentStruct: Unaligned); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy` +help: a trait with a similar name exists | -note: required because of the requirements on the impl of `Unaligned` for `TransparentStruct` - --> tests/ui-msrv/derive_transparent.rs:27:42 +37 | assert_impl_all!(TransparentStruct: FromBytes); + | ~~~~~~~~~ +help: consider importing this trait | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^ -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-msrv/derive_transparent.rs:40:1 +14 | use zerocopy::TryFromBytes; | -40 | assert_impl_all!(TransparentStruct: Unaligned); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_::{closure#0}::assert_impl_all` - = note: this error originates in the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/ui-msrv/enum.stderr b/zerocopy-derive/tests/ui-msrv/enum.stderr index fd2935baa8d..e3738f274a2 100644 --- a/zerocopy-derive/tests/ui-msrv/enum.stderr +++ b/zerocopy-derive/tests/ui-msrv/enum.stderr @@ -1,35 +1,87 @@ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:19:1 + | +19 | / #[repr("foo")] +20 | | enum Generic1 { +21 | | A, +22 | | } + | |_^ + error: unrecognized representation hint --> tests/ui-msrv/enum.rs:19:8 | 19 | #[repr("foo")] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:25:1 + | +25 | / #[repr(foo)] +26 | | enum Generic2 { +27 | | A, +28 | | } + | |_^ + error: unrecognized representation hint --> tests/ui-msrv/enum.rs:25:8 | 25 | #[repr(foo)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:31:1 + | +31 | / #[repr(transparent)] +32 | | enum Generic3 { +33 | | A, +34 | | } + | |_^ + error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum --> tests/ui-msrv/enum.rs:31:8 | 31 | #[repr(transparent)] | ^^^^^^^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:37:1 + | +37 | / #[repr(u8, u16)] +38 | | enum Generic4 { +39 | | A, +40 | | } + | |_^ + error: conflicting representation hints --> tests/ui-msrv/enum.rs:37:1 | 37 | #[repr(u8, u16)] | ^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:43:1 + | +43 | / enum Generic5 { +44 | | A, +45 | | } + | |_^ + error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout - --> tests/ui-msrv/enum.rs:42:22 + --> tests/ui-msrv/enum.rs:42:36 | -42 | #[derive(FromZeroes, FromBytes)] - | ^^^^^^^^^ +42 | #[derive(TryFromBytes, FromZeroes, FromBytes)] + | ^^^^^^^^^ | = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:70:1 + | +70 | / enum FromZeroes1 { +71 | | A(u8), +72 | | } + | |_^ + error: only C-like enums can implement FromZeroes --> tests/ui-msrv/enum.rs:70:1 | @@ -38,6 +90,15 @@ error: only C-like enums can implement FromZeroes 72 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:75:1 + | +75 | / enum FromZeroes2 { +76 | | A, +77 | | B(u8), +78 | | } + | |_^ + error: only C-like enums can implement FromZeroes --> tests/ui-msrv/enum.rs:75:1 | @@ -47,6 +108,15 @@ error: only C-like enums can implement FromZeroes 78 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:81:1 + | +81 | / enum FromZeroes3 { +82 | | A = 1, +83 | | B, +84 | | } + | |_^ + error: FromZeroes only supported on enums with a variant that has a discriminant of `0` --> tests/ui-msrv/enum.rs:81:1 | @@ -56,42 +126,105 @@ error: FromZeroes only supported on enums with a variant that has a discriminant 84 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:91:1 + | +91 | / #[repr(C)] +92 | | enum FromBytes1 { +93 | | A, +94 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-msrv/enum.rs:91:8 | 91 | #[repr(C)] | ^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:97:1 + | +97 | / #[repr(usize)] +98 | | enum FromBytes2 { +99 | | A, +100 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-msrv/enum.rs:97:8 | 97 | #[repr(usize)] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:103:1 + | +103 | / #[repr(isize)] +104 | | enum FromBytes3 { +105 | | A, +106 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-msrv/enum.rs:103:8 | 103 | #[repr(isize)] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:109:1 + | +109 | / #[repr(u32)] +110 | | enum FromBytes4 { +111 | | A, +112 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-msrv/enum.rs:109:8 | 109 | #[repr(u32)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:115:1 + | +115 | / #[repr(i32)] +116 | | enum FromBytes5 { +117 | | A, +118 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-msrv/enum.rs:115:8 | 115 | #[repr(i32)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:121:1 + | +121 | / #[repr(u64)] +122 | | enum FromBytes6 { +123 | | A, +124 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-msrv/enum.rs:121:8 | 121 | #[repr(u64)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-msrv/enum.rs:127:1 + | +127 | / #[repr(i64)] +128 | | enum FromBytes7 { +129 | | A, +130 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-msrv/enum.rs:127:8 | diff --git a/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr b/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr index 39dbcd18660..99bba567064 100644 --- a/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr @@ -6,28 +6,37 @@ warning: unused import: `zerocopy::KnownLayout` | = note: `#[warn(unused_imports)]` on by default -error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied --> tests/ui-msrv/late_compile_pass.rs:28:10 | -28 | #[derive(FromZeroes)] +28 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-msrv/late_compile_pass.rs:37:10 + | +37 | #[derive(FromZeroes)] | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` | = help: see issue #48214 = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:37:10 + --> tests/ui-msrv/late_compile_pass.rs:46:10 | -37 | #[derive(FromBytes)] +46 | #[derive(FromBytes)] | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` | = help: see issue #48214 = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:37:10 + --> tests/ui-msrv/late_compile_pass.rs:46:10 | -37 | #[derive(FromBytes)] +46 | #[derive(FromBytes)] | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1` | note: required by a bound in `FromBytes` @@ -38,36 +47,36 @@ note: required by a bound in `FromBytes` = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:46:10 + --> tests/ui-msrv/late_compile_pass.rs:55:10 | -46 | #[derive(AsBytes)] +55 | #[derive(AsBytes)] | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` | = help: see issue #48214 = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:56:10 + --> tests/ui-msrv/late_compile_pass.rs:65:10 | -56 | #[derive(Unaligned)] +65 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:64:10 + --> tests/ui-msrv/late_compile_pass.rs:73:10 | -64 | #[derive(Unaligned)] +73 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: see issue #48214 = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-msrv/late_compile_pass.rs:71:10 + --> tests/ui-msrv/late_compile_pass.rs:80:10 | -71 | #[derive(Unaligned)] +80 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: see issue #48214 diff --git a/zerocopy-derive/tests/ui-msrv/struct.stderr b/zerocopy-derive/tests/ui-msrv/struct.stderr index 3201f11ae4a..c7845b72857 100644 --- a/zerocopy-derive/tests/ui-msrv/struct.stderr +++ b/zerocopy-derive/tests/ui-msrv/struct.stderr @@ -1,46 +1,70 @@ +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-msrv/struct.rs:70:8 + | +70 | #[repr(packed)] + | ^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-msrv/struct.rs:76:8 + | +76 | #[repr(packed(1))] + | ^^^^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-msrv/struct.rs:82:11 + | +82 | #[repr(C, packed)] + | ^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-msrv/struct.rs:88:11 + | +88 | #[repr(C, packed(1))] + | ^^^^^^^^^ + error: unsupported on generic structs that are not repr(transparent) or repr(packed) - --> tests/ui-msrv/struct.rs:69:10 + --> tests/ui-msrv/struct.rs:97:10 | -69 | #[derive(AsBytes)] +97 | #[derive(AsBytes)] | ^^^^^^^ | = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:94:11 - | -94 | #[repr(C, align(2))] - | ^^^^^^^^ + --> tests/ui-msrv/struct.rs:122:11 + | +122 | #[repr(C, align(2))] + | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:98:21 - | -98 | #[repr(transparent, align(2))] - | ^^^^^^^^ + --> tests/ui-msrv/struct.rs:126:21 + | +126 | #[repr(transparent, align(2))] + | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:104:16 + --> tests/ui-msrv/struct.rs:132:16 | -104 | #[repr(packed, align(2))] +132 | #[repr(packed, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:108:18 + --> tests/ui-msrv/struct.rs:136:18 | -108 | #[repr(align(1), align(2))] +136 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-msrv/struct.rs:112:8 + --> tests/ui-msrv/struct.rs:140:8 | -112 | #[repr(align(2), align(4))] +140 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0692]: transparent struct cannot have other repr hints - --> tests/ui-msrv/struct.rs:98:8 - | -98 | #[repr(transparent, align(2))] - | ^^^^^^^^^^^ ^^^^^^^^ + --> tests/ui-msrv/struct.rs:126:8 + | +126 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> tests/ui-msrv/struct.rs:31:10 @@ -110,23 +134,23 @@ error[E0277]: the trait bound `UnsafeCell: NoCell` is not satisfied = note: this error originates in the derive macro `NoCell` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `HasPadding: ShouldBe` is not satisfied - --> tests/ui-msrv/struct.rs:73:10 - | -73 | #[derive(AsBytes)] - | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` - | - = help: the following implementations were found: - as ShouldBe> - = help: see issue #48214 - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui-msrv/struct.rs:101:10 + | +101 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` + | + = help: the following implementations were found: + as ShouldBe> + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `HasPadding: ShouldBe` is not satisfied - --> tests/ui-msrv/struct.rs:80:10 - | -80 | #[derive(AsBytes)] - | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` - | - = help: the following implementations were found: - as ShouldBe> - = help: see issue #48214 - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui-msrv/struct.rs:108:10 + | +108 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` + | + = help: the following implementations were found: + as ShouldBe> + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/ui-nightly/derive_transparent.rs b/zerocopy-derive/tests/ui-nightly/derive_transparent.rs index 2084d921bfd..f51db0a7738 100644 --- a/zerocopy-derive/tests/ui-nightly/derive_transparent.rs +++ b/zerocopy-derive/tests/ui-nightly/derive_transparent.rs @@ -24,7 +24,7 @@ fn main() {} // Test generic transparent structs -#[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] +#[derive(AsBytes, TryFromBytes, FromZeroes, FromBytes, Unaligned)] #[repr(transparent)] struct TransparentStruct { inner: T, @@ -34,6 +34,7 @@ struct TransparentStruct { // It should be legal to derive these traits on a transparent struct, but it // must also ensure the traits are only implemented when the inner type // implements them. +assert_impl_all!(TransparentStruct: TryFromBytes); assert_impl_all!(TransparentStruct: FromZeroes); assert_impl_all!(TransparentStruct: FromBytes); assert_impl_all!(TransparentStruct: AsBytes); diff --git a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr index f214877dfb5..55ca3575cd9 100644 --- a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr @@ -1,111 +1,41 @@ -error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied - --> tests/ui-nightly/derive_transparent.rs:37:18 - | -37 | assert_impl_all!(TransparentStruct: FromZeroes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` - | - = help: the following other types implement trait `FromZeroes`: - bool - char - isize - i8 - i16 - i32 - i64 - i128 - and $N others -note: required for `TransparentStruct` to implement `FromZeroes` +error: cannot find derive macro `TryFromBytes` in this scope --> tests/ui-nightly/derive_transparent.rs:27:19 | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-nightly/derive_transparent.rs:37:1 +27 | #[derive(AsBytes, TryFromBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^^^^ | -37 | assert_impl_all!(TransparentStruct: FromZeroes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied - --> tests/ui-nightly/derive_transparent.rs:38:18 + ::: src/lib.rs | -38 | assert_impl_all!(TransparentStruct: FromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | pub fn derive_from_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + | -------------------------------------------------------------------------------- similarly named derive macro `FromBytes` defined here | - = help: the following other types implement trait `FromBytes`: - isize - i8 - i16 - i32 - i64 - i128 - usize - u8 - and $N others -note: required for `TransparentStruct` to implement `FromBytes` - --> tests/ui-nightly/derive_transparent.rs:27:31 +help: a derive macro with a similar name exists | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-nightly/derive_transparent.rs:38:1 +27 | #[derive(AsBytes, FromBytes, FromZeroes, FromBytes, Unaligned)] + | ~~~~~~~~~ +help: consider importing one of these items | -38 | assert_impl_all!(TransparentStruct: FromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) +14 + use zerocopy::TryFromBytes; + | +14 + use zerocopy_derive::TryFromBytes; + | -error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied - --> tests/ui-nightly/derive_transparent.rs:39:18 +error[E0405]: cannot find trait `TryFromBytes` in this scope + --> tests/ui-nightly/derive_transparent.rs:37:50 | -39 | assert_impl_all!(TransparentStruct: AsBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` +37 | assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^ | - = help: the following other types implement trait `AsBytes`: - bool - char - isize - i8 - i16 - i32 - i64 - i128 - and $N others -note: required for `TransparentStruct` to implement `AsBytes` - --> tests/ui-nightly/derive_transparent.rs:27:10 - | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-nightly/derive_transparent.rs:39:1 - | -39 | assert_impl_all!(TransparentStruct: AsBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied - --> tests/ui-nightly/derive_transparent.rs:40:18 + ::: $WORKSPACE/src/lib.rs | -40 | assert_impl_all!(TransparentStruct: Unaligned); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy` + | pub unsafe trait FromBytes: FromZeroes { + | -------------------------------------- similarly named trait `FromBytes` defined here | - = help: the following other types implement trait `Unaligned`: - bool - i8 - u8 - TransparentStruct - U16 - U32 - U64 - U128 - and $N others -note: required for `TransparentStruct` to implement `Unaligned` - --> tests/ui-nightly/derive_transparent.rs:27:42 +help: a trait with a similar name exists | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-nightly/derive_transparent.rs:40:1 +37 | assert_impl_all!(TransparentStruct: FromBytes); + | ~~~~~~~~~ +help: consider importing this trait | -40 | assert_impl_all!(TransparentStruct: Unaligned); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) +14 + use zerocopy::TryFromBytes; + | diff --git a/zerocopy-derive/tests/ui-nightly/enum.rs b/zerocopy-derive/tests/ui-nightly/enum.rs index f9f9149e08b..e96e8a0f105 100644 --- a/zerocopy-derive/tests/ui-nightly/enum.rs +++ b/zerocopy-derive/tests/ui-nightly/enum.rs @@ -15,31 +15,31 @@ fn main() {} // Generic errors // -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr("foo")] enum Generic1 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(foo)] enum Generic2 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(transparent)] enum Generic3 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(u8, u16)] enum Generic4 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] enum Generic5 { A, } @@ -66,18 +66,18 @@ enum NoCell2 { // FromZeroes errors // -#[derive(FromZeroes)] +#[derive(TryFromBytes, FromZeroes)] enum FromZeroes1 { A(u8), } -#[derive(FromZeroes)] +#[derive(TryFromBytes, FromZeroes)] enum FromZeroes2 { A, B(u8), } -#[derive(FromZeroes)] +#[derive(TryFromBytes, FromZeroes)] enum FromZeroes3 { A = 1, B, @@ -87,43 +87,43 @@ enum FromZeroes3 { // FromBytes errors // -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(C)] enum FromBytes1 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(usize)] enum FromBytes2 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(isize)] enum FromBytes3 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(u32)] enum FromBytes4 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(i32)] enum FromBytes5 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(u64)] enum FromBytes6 { A, } -#[derive(FromZeroes, FromBytes)] +#[derive(TryFromBytes, FromZeroes, FromBytes)] #[repr(i64)] enum FromBytes7 { A, diff --git a/zerocopy-derive/tests/ui-nightly/enum.stderr b/zerocopy-derive/tests/ui-nightly/enum.stderr index 3fe3c7b2785..2b8fa047342 100644 --- a/zerocopy-derive/tests/ui-nightly/enum.stderr +++ b/zerocopy-derive/tests/ui-nightly/enum.stderr @@ -1,35 +1,87 @@ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:19:1 + | +19 | / #[repr("foo")] +20 | | enum Generic1 { +21 | | A, +22 | | } + | |_^ + error: unrecognized representation hint --> tests/ui-nightly/enum.rs:19:8 | 19 | #[repr("foo")] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:25:1 + | +25 | / #[repr(foo)] +26 | | enum Generic2 { +27 | | A, +28 | | } + | |_^ + error: unrecognized representation hint --> tests/ui-nightly/enum.rs:25:8 | 25 | #[repr(foo)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:31:1 + | +31 | / #[repr(transparent)] +32 | | enum Generic3 { +33 | | A, +34 | | } + | |_^ + error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum --> tests/ui-nightly/enum.rs:31:8 | 31 | #[repr(transparent)] | ^^^^^^^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:37:1 + | +37 | / #[repr(u8, u16)] +38 | | enum Generic4 { +39 | | A, +40 | | } + | |_^ + error: conflicting representation hints --> tests/ui-nightly/enum.rs:37:8 | 37 | #[repr(u8, u16)] | ^^^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:43:1 + | +43 | / enum Generic5 { +44 | | A, +45 | | } + | |_^ + error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout - --> tests/ui-nightly/enum.rs:42:22 + --> tests/ui-nightly/enum.rs:42:36 | -42 | #[derive(FromZeroes, FromBytes)] - | ^^^^^^^^^ +42 | #[derive(TryFromBytes, FromZeroes, FromBytes)] + | ^^^^^^^^^ | = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:70:1 + | +70 | / enum FromZeroes1 { +71 | | A(u8), +72 | | } + | |_^ + error: only C-like enums can implement FromZeroes --> tests/ui-nightly/enum.rs:70:1 | @@ -38,6 +90,15 @@ error: only C-like enums can implement FromZeroes 72 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:75:1 + | +75 | / enum FromZeroes2 { +76 | | A, +77 | | B(u8), +78 | | } + | |_^ + error: only C-like enums can implement FromZeroes --> tests/ui-nightly/enum.rs:75:1 | @@ -47,6 +108,15 @@ error: only C-like enums can implement FromZeroes 78 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:81:1 + | +81 | / enum FromZeroes3 { +82 | | A = 1, +83 | | B, +84 | | } + | |_^ + error: FromZeroes only supported on enums with a variant that has a discriminant of `0` --> tests/ui-nightly/enum.rs:81:1 | @@ -56,42 +126,105 @@ error: FromZeroes only supported on enums with a variant that has a discriminant 84 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:91:1 + | +91 | / #[repr(C)] +92 | | enum FromBytes1 { +93 | | A, +94 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-nightly/enum.rs:91:8 | 91 | #[repr(C)] | ^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:97:1 + | +97 | / #[repr(usize)] +98 | | enum FromBytes2 { +99 | | A, +100 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-nightly/enum.rs:97:8 | 97 | #[repr(usize)] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:103:1 + | +103 | / #[repr(isize)] +104 | | enum FromBytes3 { +105 | | A, +106 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-nightly/enum.rs:103:8 | 103 | #[repr(isize)] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:109:1 + | +109 | / #[repr(u32)] +110 | | enum FromBytes4 { +111 | | A, +112 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-nightly/enum.rs:109:8 | 109 | #[repr(u32)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:115:1 + | +115 | / #[repr(i32)] +116 | | enum FromBytes5 { +117 | | A, +118 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-nightly/enum.rs:115:8 | 115 | #[repr(i32)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:121:1 + | +121 | / #[repr(u64)] +122 | | enum FromBytes6 { +123 | | A, +124 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-nightly/enum.rs:121:8 | 121 | #[repr(u64)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-nightly/enum.rs:127:1 + | +127 | / #[repr(i64)] +128 | | enum FromBytes7 { +129 | | A, +130 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-nightly/enum.rs:127:8 | diff --git a/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs b/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs index cd65a6ed2cf..85c175dc484 100644 --- a/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs +++ b/zerocopy-derive/tests/ui-nightly/late_compile_pass.rs @@ -21,6 +21,15 @@ fn main() {} // the other errors we generate, and so if they're compiled in the same file, // the compiler will never get to that pass, and so we won't get the errors. +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +struct TryFromBytes1 { + value: NotZerocopy, +} + // // FromZeroes errors // diff --git a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr index 3c45dc4e840..4bfb187ccc0 100644 --- a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr @@ -6,10 +6,30 @@ warning: unused import: `zerocopy::KnownLayout` | = note: `#[warn(unused_imports)]` on by default -error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied --> tests/ui-nightly/late_compile_pass.rs:28:10 | -28 | #[derive(FromZeroes)] +28 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `TryFromBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:37:10 + | +37 | #[derive(FromZeroes)] | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` | = help: the following other types implement trait `FromZeroes`: @@ -27,9 +47,9 @@ error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied - --> tests/ui-nightly/late_compile_pass.rs:37:10 + --> tests/ui-nightly/late_compile_pass.rs:46:10 | -37 | #[derive(FromBytes)] +46 | #[derive(FromBytes)] | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` | = help: the following other types implement trait `FromBytes`: @@ -47,9 +67,9 @@ error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied - --> tests/ui-nightly/late_compile_pass.rs:37:10 + --> tests/ui-nightly/late_compile_pass.rs:46:10 | -37 | #[derive(FromBytes)] +46 | #[derive(FromBytes)] | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1` | = help: the following other types implement trait `FromZeroes`: @@ -70,9 +90,9 @@ note: required by a bound in `FromBytes` = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied - --> tests/ui-nightly/late_compile_pass.rs:46:10 + --> tests/ui-nightly/late_compile_pass.rs:55:10 | -46 | #[derive(AsBytes)] +55 | #[derive(AsBytes)] | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` | = help: the following other types implement trait `AsBytes`: @@ -90,9 +110,9 @@ error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-nightly/late_compile_pass.rs:56:10 + --> tests/ui-nightly/late_compile_pass.rs:65:10 | -56 | #[derive(Unaligned)] +65 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: @@ -110,9 +130,9 @@ error[E0277]: the trait bound `AU16: Unaligned` is not satisfied = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-nightly/late_compile_pass.rs:64:10 + --> tests/ui-nightly/late_compile_pass.rs:73:10 | -64 | #[derive(Unaligned)] +73 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: @@ -130,9 +150,9 @@ error[E0277]: the trait bound `AU16: Unaligned` is not satisfied = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-nightly/late_compile_pass.rs:71:10 + --> tests/ui-nightly/late_compile_pass.rs:80:10 | -71 | #[derive(Unaligned)] +80 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: diff --git a/zerocopy-derive/tests/ui-nightly/struct.rs b/zerocopy-derive/tests/ui-nightly/struct.rs index 3e31d51c770..68392c704ba 100644 --- a/zerocopy-derive/tests/ui-nightly/struct.rs +++ b/zerocopy-derive/tests/ui-nightly/struct.rs @@ -62,6 +62,34 @@ struct NoCell2 { a: [core::cell::UnsafeCell; 0], } +// +// TryFromBytes errors +// + +#[derive(TryFromBytes)] +#[repr(packed)] +struct TryFromBytesPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(packed(1))] +struct TryFromBytesPackedN { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed)] +struct TryFromBytesCPacked { + foo: AU16, +} + +#[derive(TryFromBytes)] +#[repr(C, packed(1))] +struct TryFromBytesCPackedN { + foo: AU16, +} + // // AsBytes errors // diff --git a/zerocopy-derive/tests/ui-nightly/struct.stderr b/zerocopy-derive/tests/ui-nightly/struct.stderr index f2602e9dd40..66aeb70f531 100644 --- a/zerocopy-derive/tests/ui-nightly/struct.stderr +++ b/zerocopy-derive/tests/ui-nightly/struct.stderr @@ -1,46 +1,70 @@ +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-nightly/struct.rs:70:8 + | +70 | #[repr(packed)] + | ^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-nightly/struct.rs:76:8 + | +76 | #[repr(packed(1))] + | ^^^^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-nightly/struct.rs:82:11 + | +82 | #[repr(C, packed)] + | ^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-nightly/struct.rs:88:11 + | +88 | #[repr(C, packed(1))] + | ^^^^^^^^^ + error: unsupported on generic structs that are not repr(transparent) or repr(packed) - --> tests/ui-nightly/struct.rs:69:10 + --> tests/ui-nightly/struct.rs:97:10 | -69 | #[derive(AsBytes)] +97 | #[derive(AsBytes)] | ^^^^^^^ | = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-nightly/struct.rs:94:11 - | -94 | #[repr(C, align(2))] - | ^^^^^^^^ + --> tests/ui-nightly/struct.rs:122:11 + | +122 | #[repr(C, align(2))] + | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-nightly/struct.rs:98:21 - | -98 | #[repr(transparent, align(2))] - | ^^^^^^^^ + --> tests/ui-nightly/struct.rs:126:21 + | +126 | #[repr(transparent, align(2))] + | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-nightly/struct.rs:104:16 + --> tests/ui-nightly/struct.rs:132:16 | -104 | #[repr(packed, align(2))] +132 | #[repr(packed, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-nightly/struct.rs:108:18 + --> tests/ui-nightly/struct.rs:136:18 | -108 | #[repr(align(1), align(2))] +136 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-nightly/struct.rs:112:8 + --> tests/ui-nightly/struct.rs:140:8 | -112 | #[repr(align(2), align(4))] +140 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0692]: transparent struct cannot have other repr hints - --> tests/ui-nightly/struct.rs:98:8 - | -98 | #[repr(transparent, align(2))] - | ^^^^^^^^^^^ ^^^^^^^^ + --> tests/ui-nightly/struct.rs:126:8 + | +126 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> tests/ui-nightly/struct.rs:31:10 @@ -156,29 +180,77 @@ error[E0277]: the trait bound `UnsafeCell: NoCell` is not satisfied = note: this error originates in the derive macro `NoCell` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `HasPadding: ShouldBe` is not satisfied - --> tests/ui-nightly/struct.rs:73:10 + --> tests/ui-nightly/struct.rs:101:10 + | +101 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` + | + = help: the trait `ShouldBe` is implemented for `HasPadding` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `HasPadding: ShouldBe` is not satisfied + --> tests/ui-nightly/struct.rs:108:10 + | +108 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` + | + = help: the trait `ShouldBe` is implemented for `HasPadding` + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:71:1 | -73 | #[derive(AsBytes)] - | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` +71 | struct TryFromBytesPacked { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the trait `ShouldBe` is implemented for `HasPadding` - = help: see issue #48214 - = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../util.rs + | + | pub struct AU16(u16); + | ^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `HasPadding: ShouldBe` is not satisfied - --> tests/ui-nightly/struct.rs:80:10 +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:77:1 | -80 | #[derive(AsBytes)] - | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` +77 | struct TryFromBytesPackedN { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: the trait `ShouldBe` is implemented for `HasPadding` - = help: see issue #48214 - = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../util.rs + | + | pub struct AU16(u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:83:1 + | +83 | struct TryFromBytesCPacked { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../util.rs + | + | pub struct AU16(u16); + | ^^^^^^^^^^^^^^^ + +error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type + --> tests/ui-nightly/struct.rs:89:1 + | +89 | struct TryFromBytesCPackedN { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `AU16` has a `#[repr(align)]` attribute + --> tests/ui-nightly/../util.rs + | + | pub struct AU16(u16); + | ^^^^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> tests/ui-nightly/struct.rs:105:1 + --> tests/ui-nightly/struct.rs:133:1 | -105 | struct Unaligned3; +133 | struct Unaligned3; | ^^^^^^^^^^^^^^^^^ diff --git a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr index f24dd4866d4..58934e22279 100644 --- a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr @@ -1,111 +1,41 @@ -error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied - --> tests/ui-stable/derive_transparent.rs:37:18 - | -37 | assert_impl_all!(TransparentStruct: FromZeroes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` - | - = help: the following other types implement trait `FromZeroes`: - bool - char - isize - i8 - i16 - i32 - i64 - i128 - and $N others -note: required for `TransparentStruct` to implement `FromZeroes` +error: cannot find derive macro `TryFromBytes` in this scope --> tests/ui-stable/derive_transparent.rs:27:19 | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-stable/derive_transparent.rs:37:1 +27 | #[derive(AsBytes, TryFromBytes, FromZeroes, FromBytes, Unaligned)] + | ^^^^^^^^^^^^ | -37 | assert_impl_all!(TransparentStruct: FromZeroes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `FromZeroes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied - --> tests/ui-stable/derive_transparent.rs:38:18 + ::: src/lib.rs | -38 | assert_impl_all!(TransparentStruct: FromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | pub fn derive_from_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { + | -------------------------------------------------------------------------------- similarly named derive macro `FromBytes` defined here | - = help: the following other types implement trait `FromBytes`: - isize - i8 - i16 - i32 - i64 - i128 - usize - u8 - and $N others -note: required for `TransparentStruct` to implement `FromBytes` - --> tests/ui-stable/derive_transparent.rs:27:31 +help: a derive macro with a similar name exists | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-stable/derive_transparent.rs:38:1 +27 | #[derive(AsBytes, FromBytes, FromZeroes, FromBytes, Unaligned)] + | ~~~~~~~~~ +help: consider importing one of these items | -38 | assert_impl_all!(TransparentStruct: FromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `FromBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) +14 + use zerocopy::TryFromBytes; + | +14 + use zerocopy_derive::TryFromBytes; + | -error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied - --> tests/ui-stable/derive_transparent.rs:39:18 +error[E0405]: cannot find trait `TryFromBytes` in this scope + --> tests/ui-stable/derive_transparent.rs:37:50 | -39 | assert_impl_all!(TransparentStruct: AsBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` +37 | assert_impl_all!(TransparentStruct: TryFromBytes); + | ^^^^^^^^^^^^ | - = help: the following other types implement trait `AsBytes`: - bool - char - isize - i8 - i16 - i32 - i64 - i128 - and $N others -note: required for `TransparentStruct` to implement `AsBytes` - --> tests/ui-stable/derive_transparent.rs:27:10 - | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-stable/derive_transparent.rs:39:1 - | -39 | assert_impl_all!(TransparentStruct: AsBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `AsBytes` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) - -error[E0277]: the trait bound `NotZerocopy: Unaligned` is not satisfied - --> tests/ui-stable/derive_transparent.rs:40:18 + ::: $WORKSPACE/src/lib.rs | -40 | assert_impl_all!(TransparentStruct: Unaligned); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unaligned` is not implemented for `NotZerocopy` + | pub unsafe trait FromBytes: FromZeroes { + | -------------------------------------- similarly named trait `FromBytes` defined here | - = help: the following other types implement trait `Unaligned`: - bool - i8 - u8 - TransparentStruct - U16 - U32 - U64 - U128 - and $N others -note: required for `TransparentStruct` to implement `Unaligned` - --> tests/ui-stable/derive_transparent.rs:27:42 +help: a trait with a similar name exists | -27 | #[derive(AsBytes, FromZeroes, FromBytes, Unaligned)] - | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro -note: required by a bound in `_::{closure#0}::assert_impl_all` - --> tests/ui-stable/derive_transparent.rs:40:1 +37 | assert_impl_all!(TransparentStruct: FromBytes); + | ~~~~~~~~~ +help: consider importing this trait | -40 | assert_impl_all!(TransparentStruct: Unaligned); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_impl_all` - = note: this error originates in the derive macro `Unaligned` which comes from the expansion of the macro `assert_impl_all` (in Nightly builds, run with -Z macro-backtrace for more info) +14 + use zerocopy::TryFromBytes; + | diff --git a/zerocopy-derive/tests/ui-stable/enum.stderr b/zerocopy-derive/tests/ui-stable/enum.stderr index 5a4e2e28a9c..4f3eb7a77e2 100644 --- a/zerocopy-derive/tests/ui-stable/enum.stderr +++ b/zerocopy-derive/tests/ui-stable/enum.stderr @@ -1,35 +1,87 @@ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:19:1 + | +19 | / #[repr("foo")] +20 | | enum Generic1 { +21 | | A, +22 | | } + | |_^ + error: unrecognized representation hint --> tests/ui-stable/enum.rs:19:8 | 19 | #[repr("foo")] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:25:1 + | +25 | / #[repr(foo)] +26 | | enum Generic2 { +27 | | A, +28 | | } + | |_^ + error: unrecognized representation hint --> tests/ui-stable/enum.rs:25:8 | 25 | #[repr(foo)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:31:1 + | +31 | / #[repr(transparent)] +32 | | enum Generic3 { +33 | | A, +34 | | } + | |_^ + error: unsupported representation for deriving FromBytes, AsBytes, or Unaligned on an enum --> tests/ui-stable/enum.rs:31:8 | 31 | #[repr(transparent)] | ^^^^^^^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:37:1 + | +37 | / #[repr(u8, u16)] +38 | | enum Generic4 { +39 | | A, +40 | | } + | |_^ + error: conflicting representation hints --> tests/ui-stable/enum.rs:37:1 | 37 | #[repr(u8, u16)] | ^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:43:1 + | +43 | / enum Generic5 { +44 | | A, +45 | | } + | |_^ + error: must have a non-align #[repr(...)] attribute in order to guarantee this type's memory layout - --> tests/ui-stable/enum.rs:42:22 + --> tests/ui-stable/enum.rs:42:36 | -42 | #[derive(FromZeroes, FromBytes)] - | ^^^^^^^^^ +42 | #[derive(TryFromBytes, FromZeroes, FromBytes)] + | ^^^^^^^^^ | = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:70:1 + | +70 | / enum FromZeroes1 { +71 | | A(u8), +72 | | } + | |_^ + error: only C-like enums can implement FromZeroes --> tests/ui-stable/enum.rs:70:1 | @@ -38,6 +90,15 @@ error: only C-like enums can implement FromZeroes 72 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:75:1 + | +75 | / enum FromZeroes2 { +76 | | A, +77 | | B(u8), +78 | | } + | |_^ + error: only C-like enums can implement FromZeroes --> tests/ui-stable/enum.rs:75:1 | @@ -47,6 +108,15 @@ error: only C-like enums can implement FromZeroes 78 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:81:1 + | +81 | / enum FromZeroes3 { +82 | | A = 1, +83 | | B, +84 | | } + | |_^ + error: FromZeroes only supported on enums with a variant that has a discriminant of `0` --> tests/ui-stable/enum.rs:81:1 | @@ -56,42 +126,105 @@ error: FromZeroes only supported on enums with a variant that has a discriminant 84 | | } | |_^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:91:1 + | +91 | / #[repr(C)] +92 | | enum FromBytes1 { +93 | | A, +94 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-stable/enum.rs:91:8 | 91 | #[repr(C)] | ^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:97:1 + | +97 | / #[repr(usize)] +98 | | enum FromBytes2 { +99 | | A, +100 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-stable/enum.rs:97:8 | 97 | #[repr(usize)] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:103:1 + | +103 | / #[repr(isize)] +104 | | enum FromBytes3 { +105 | | A, +106 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-stable/enum.rs:103:8 | 103 | #[repr(isize)] | ^^^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:109:1 + | +109 | / #[repr(u32)] +110 | | enum FromBytes4 { +111 | | A, +112 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-stable/enum.rs:109:8 | 109 | #[repr(u32)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:115:1 + | +115 | / #[repr(i32)] +116 | | enum FromBytes5 { +117 | | A, +118 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-stable/enum.rs:115:8 | 115 | #[repr(i32)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:121:1 + | +121 | / #[repr(u64)] +122 | | enum FromBytes6 { +123 | | A, +124 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-stable/enum.rs:121:8 | 121 | #[repr(u64)] | ^^^ +error: TryFromBytes not supported on enum types + --> tests/ui-stable/enum.rs:127:1 + | +127 | / #[repr(i64)] +128 | | enum FromBytes7 { +129 | | A, +130 | | } + | |_^ + error: FromBytes requires repr of "u8", "u16", "i8", or "i16" --> tests/ui-stable/enum.rs:127:8 | diff --git a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr index 808054ab4d6..5680ecc181e 100644 --- a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr @@ -6,10 +6,29 @@ warning: unused import: `zerocopy::KnownLayout` | = note: `#[warn(unused_imports)]` on by default -error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied --> tests/ui-stable/late_compile_pass.rs:28:10 | -28 | #[derive(FromZeroes)] +28 | #[derive(TryFromBytes)] + | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `TryFromBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others + = help: see issue #48214 + = note: this error originates in the derive macro `TryFromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:37:10 + | +37 | #[derive(FromZeroes)] | ^^^^^^^^^^ the trait `FromZeroes` is not implemented for `NotZerocopy` | = help: the following other types implement trait `FromZeroes`: @@ -26,9 +45,9 @@ error[E0277]: the trait bound `NotZerocopy: FromZeroes` is not satisfied = note: this error originates in the derive macro `FromZeroes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:37:10 + --> tests/ui-stable/late_compile_pass.rs:46:10 | -37 | #[derive(FromBytes)] +46 | #[derive(FromBytes)] | ^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` | = help: the following other types implement trait `FromBytes`: @@ -45,9 +64,9 @@ error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `FromBytes1: FromZeroes` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:37:10 + --> tests/ui-stable/late_compile_pass.rs:46:10 | -37 | #[derive(FromBytes)] +46 | #[derive(FromBytes)] | ^^^^^^^^^ the trait `FromZeroes` is not implemented for `FromBytes1` | = help: the following other types implement trait `FromZeroes`: @@ -68,9 +87,9 @@ note: required by a bound in `FromBytes` = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:46:10 + --> tests/ui-stable/late_compile_pass.rs:55:10 | -46 | #[derive(AsBytes)] +55 | #[derive(AsBytes)] | ^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` | = help: the following other types implement trait `AsBytes`: @@ -87,9 +106,9 @@ error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:56:10 + --> tests/ui-stable/late_compile_pass.rs:65:10 | -56 | #[derive(Unaligned)] +65 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: @@ -106,9 +125,9 @@ error[E0277]: the trait bound `AU16: Unaligned` is not satisfied = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:64:10 + --> tests/ui-stable/late_compile_pass.rs:73:10 | -64 | #[derive(Unaligned)] +73 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: @@ -125,9 +144,9 @@ error[E0277]: the trait bound `AU16: Unaligned` is not satisfied = note: this error originates in the derive macro `Unaligned` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `AU16: Unaligned` is not satisfied - --> tests/ui-stable/late_compile_pass.rs:71:10 + --> tests/ui-stable/late_compile_pass.rs:80:10 | -71 | #[derive(Unaligned)] +80 | #[derive(Unaligned)] | ^^^^^^^^^ the trait `Unaligned` is not implemented for `AU16` | = help: the following other types implement trait `Unaligned`: diff --git a/zerocopy-derive/tests/ui-stable/struct.stderr b/zerocopy-derive/tests/ui-stable/struct.stderr index 97ab4b097ad..8353233644d 100644 --- a/zerocopy-derive/tests/ui-stable/struct.stderr +++ b/zerocopy-derive/tests/ui-stable/struct.stderr @@ -1,46 +1,70 @@ +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-stable/struct.rs:70:8 + | +70 | #[repr(packed)] + | ^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-stable/struct.rs:76:8 + | +76 | #[repr(packed(1))] + | ^^^^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-stable/struct.rs:82:11 + | +82 | #[repr(C, packed)] + | ^^^^^^ + +error: cannot derive TryFromBytes with repr(packed) + --> tests/ui-stable/struct.rs:88:11 + | +88 | #[repr(C, packed(1))] + | ^^^^^^^^^ + error: unsupported on generic structs that are not repr(transparent) or repr(packed) - --> tests/ui-stable/struct.rs:69:10 + --> tests/ui-stable/struct.rs:97:10 | -69 | #[derive(AsBytes)] +97 | #[derive(AsBytes)] | ^^^^^^^ | = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:94:11 - | -94 | #[repr(C, align(2))] - | ^^^^^^^^ + --> tests/ui-stable/struct.rs:122:11 + | +122 | #[repr(C, align(2))] + | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:98:21 - | -98 | #[repr(transparent, align(2))] - | ^^^^^^^^ + --> tests/ui-stable/struct.rs:126:21 + | +126 | #[repr(transparent, align(2))] + | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:104:16 + --> tests/ui-stable/struct.rs:132:16 | -104 | #[repr(packed, align(2))] +132 | #[repr(packed, align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:108:18 + --> tests/ui-stable/struct.rs:136:18 | -108 | #[repr(align(1), align(2))] +136 | #[repr(align(1), align(2))] | ^^^^^^^^ error: cannot derive Unaligned with repr(align(N > 1)) - --> tests/ui-stable/struct.rs:112:8 + --> tests/ui-stable/struct.rs:140:8 | -112 | #[repr(align(2), align(4))] +140 | #[repr(align(2), align(4))] | ^^^^^^^^ error[E0692]: transparent struct cannot have other repr hints - --> tests/ui-stable/struct.rs:98:8 - | -98 | #[repr(transparent, align(2))] - | ^^^^^^^^^^^ ^^^^^^^^ + --> tests/ui-stable/struct.rs:126:8 + | +126 | #[repr(transparent, align(2))] + | ^^^^^^^^^^^ ^^^^^^^^ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> tests/ui-stable/struct.rs:31:10 @@ -150,21 +174,21 @@ error[E0277]: the trait bound `UnsafeCell: NoCell` is not satisfied = note: this error originates in the derive macro `NoCell` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `HasPadding: ShouldBe` is not satisfied - --> tests/ui-stable/struct.rs:73:10 - | -73 | #[derive(AsBytes)] - | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` - | - = help: the trait `ShouldBe` is implemented for `HasPadding` - = help: see issue #48214 - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui-stable/struct.rs:101:10 + | +101 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` + | + = help: the trait `ShouldBe` is implemented for `HasPadding` + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `HasPadding: ShouldBe` is not satisfied - --> tests/ui-stable/struct.rs:80:10 - | -80 | #[derive(AsBytes)] - | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` - | - = help: the trait `ShouldBe` is implemented for `HasPadding` - = help: see issue #48214 - = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + --> tests/ui-stable/struct.rs:108:10 + | +108 | #[derive(AsBytes)] + | ^^^^^^^ the trait `ShouldBe` is not implemented for `HasPadding` + | + = help: the trait `ShouldBe` is implemented for `HasPadding` + = help: see issue #48214 + = note: this error originates in the derive macro `AsBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/util.rs b/zerocopy-derive/tests/util.rs index 796d6224328..85aba05c08d 100644 --- a/zerocopy-derive/tests/util.rs +++ b/zerocopy-derive/tests/util.rs @@ -6,7 +6,7 @@ // This file may not be copied, modified, or distributed except according to // those terms. -use zerocopy::{AsBytes, FromBytes, FromZeroes, KnownLayout, NoCell}; +use zerocopy::{AsBytes, FromBytes, FromZeroes, KnownLayout, NoCell, TryFromBytes}; /// A type that doesn't implement any zerocopy traits. pub struct NotZerocopy(T); @@ -15,6 +15,6 @@ pub struct NotZerocopy(T); /// /// Though `u16` has alignment 2 on some platforms, it's not guaranteed. By /// contrast, `AU16` is guaranteed to have alignment 2. -#[derive(KnownLayout, NoCell, FromZeroes, FromBytes, AsBytes, Copy, Clone)] +#[derive(KnownLayout, NoCell, TryFromBytes, FromZeroes, FromBytes, AsBytes, Copy, Clone)] #[repr(C, align(2))] pub struct AU16(u16);