diff --git a/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr b/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr index 770ceec65f..8e27c9c8cb 100644 --- a/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr +++ b/tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs:18:28 | 18 | takes_try_from_bytes::(); - | ^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `takes_try_from_bytes` --> tests/ui-msrv/diagnostic-not-implemented-try-from-bytes.rs:21:28 diff --git a/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr b/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr index 3be2027da2..5536f61216 100644 --- a/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr +++ b/tests/ui-msrv/try_transmute-dst-not-tryfrombytes.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs:17:58 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `try_transmute` --> src/util/macro_util.rs @@ -11,11 +11,11 @@ note: required by a bound in `try_transmute` | ^^^^^^^^^^^^ required by this bound in `try_transmute` = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs:17:33 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `ValidityError` --> src/error.rs @@ -23,11 +23,11 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute-dst-not-tryfrombytes.rs:17:58 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `ValidityError` --> src/error.rs diff --git a/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr b/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr index 1fa8ebf5d9..a722fb99b5 100644 --- a/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr +++ b/tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `try_transmute_mut` --> src/util/macro_util.rs @@ -11,11 +11,11 @@ note: required by a bound in `try_transmute_mut` | ^^^^^^^^^^^^ required by this bound in `try_transmute_mut` = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs:20:33 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `ValidityError` --> src/error.rs @@ -23,11 +23,11 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `ValidityError` --> src/error.rs diff --git a/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr b/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr index b42ebac005..fb6e75f23e 100644 --- a/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr +++ b/tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `try_transmute_ref` --> src/util/macro_util.rs @@ -24,11 +24,11 @@ note: required by a bound in `try_transmute_ref` | ^^^^^^^^^ required by this bound in `try_transmute_ref` = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:33 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `ValidityError` --> src/error.rs @@ -36,11 +36,11 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | note: required by a bound in `ValidityError` --> src/error.rs diff --git a/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr b/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr index e7de20bb14..9e0db2d45f 100644 --- a/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr +++ b/tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/diagnostic-not-implemented-try-from-bytes.rs:18:28 | 18 | takes_try_from_bytes::(); - | ^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr b/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr index 5505ad83cf..db5a6a4ab7 100644 --- a/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr +++ b/tests/ui-nightly/try_transmute-dst-not-tryfrombytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs:17:33 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -21,14 +21,14 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs:17:58 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -48,14 +48,14 @@ note: required by a bound in `try_transmute` | ^^^^^^^^^^^^ required by this bound in `try_transmute` = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute-dst-not-tryfrombytes.rs:17:58 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr b/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr index cf1b8f5fcc..ae0d3114af 100644 --- a/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr +++ b/tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs:20:33 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -21,14 +21,14 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -48,14 +48,14 @@ note: required by a bound in `try_transmute_mut` | ^^^^^^^^^^^^ required by this bound in `try_transmute_mut` = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr b/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr index f78a3b10d4..7caf93a3b0 100644 --- a/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr +++ b/tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:33 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -21,14 +21,14 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -75,14 +75,14 @@ note: required by a bound in `try_transmute_ref` | ^^^^^^^^^ required by this bound in `try_transmute_ref` = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr b/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr index 4d0c12193b..322f6340e2 100644 --- a/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr +++ b/tests/ui-stable/diagnostic-not-implemented-try-from-bytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/diagnostic-not-implemented-try-from-bytes.rs:18:28 | 18 | takes_try_from_bytes::(); - | ^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr b/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr index f05af3ab7a..66dbade43b 100644 --- a/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr +++ b/tests/ui-stable/try_transmute-dst-not-tryfrombytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs:17:33 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -21,14 +21,14 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs:17:58 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -48,14 +48,14 @@ note: required by a bound in `try_transmute` | ^^^^^^^^^^^^ required by this bound in `try_transmute` = note: this error originates in the macro `try_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute-dst-not-tryfrombytes.rs:17:58 | 17 | let dst_not_try_from_bytes: Result = try_transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr b/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr index d07846840d..7f608de647 100644 --- a/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr +++ b/tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs:20:33 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -21,14 +21,14 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -48,14 +48,14 @@ note: required by a bound in `try_transmute_mut` | ^^^^^^^^^^^^ required by this bound in `try_transmute_mut` = note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute_mut-dst-not-tryfrombytes.rs:20:63 | 20 | let dst_not_try_from_bytes: Result<&mut NotZerocopy, _> = try_transmute_mut!(src); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr b/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr index 81de92645c..b8108c5dc5 100644 --- a/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr +++ b/tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:33 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -21,14 +21,14 @@ note: required by a bound in `ValidityError` | pub struct ValidityError { | ^^^^^^^^^^^^ required by this bound in `ValidityError` -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -75,14 +75,14 @@ note: required by a bound in `try_transmute_ref` | ^^^^^^^^^ required by this bound in `try_transmute_ref` = note: this error originates in the macro `try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/try_transmute_ref-dst-not-immutable-tryfrombytes.rs:19:59 | 19 | let dst_not_try_from_bytes: Result<&NotZerocopy, _> = try_transmute_ref!(&AU16(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T diff --git a/zerocopy-derive/src/enum.rs b/zerocopy-derive/src/enum.rs index 86bd4f4d1a..df531ea00d 100644 --- a/zerocopy-derive/src/enum.rs +++ b/zerocopy-derive/src/enum.rs @@ -134,7 +134,7 @@ fn generate_variant_structs( // We do this rather than emitting `#[derive(::zerocopy::TryFromBytes)]` // because that is not hygienic, and this is also more performant. - let try_from_bytes_impl = derive_try_from_bytes_inner(&variant_struct) + let try_from_bytes_impl = derive_try_from_bytes_inner(&variant_struct, Trait::TryFromBytes) .expect("derive_try_from_bytes_inner should not fail on synthesized type"); Some(quote! { diff --git a/zerocopy-derive/src/lib.rs b/zerocopy-derive/src/lib.rs index 792beaec94..b47474fc12 100644 --- a/zerocopy-derive/src/lib.rs +++ b/zerocopy-derive/src/lib.rs @@ -76,7 +76,7 @@ macro_rules! derive { #[proc_macro_derive($trait)] pub fn $outer(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { let ast = syn::parse_macro_input!(ts as DeriveInput); - $inner(&ast).into_ts().into() + $inner(&ast, Trait::$trait).into_ts().into() } }; } @@ -124,7 +124,7 @@ pub fn derive_as_bytes(ts: proc_macro::TokenStream) -> proc_macro::TokenStream { derive_into_bytes(ts) } -fn derive_known_layout_inner(ast: &DeriveInput) -> Result { +fn derive_known_layout_inner(ast: &DeriveInput, _top_level: Trait) -> Result { let is_repr_c_struct = match &ast.data { Data::Struct(..) => { let repr = StructUnionRepr::from_attrs(&ast.attrs)?; @@ -329,7 +329,7 @@ fn derive_known_layout_inner(ast: &DeriveInput) -> Result { }) } -fn derive_no_cell_inner(ast: &DeriveInput) -> TokenStream { +fn derive_no_cell_inner(ast: &DeriveInput, _top_level: Trait) -> TokenStream { match &ast.data { Data::Struct(strct) => impl_block( ast, @@ -361,16 +361,16 @@ fn derive_no_cell_inner(ast: &DeriveInput) -> TokenStream { } } -fn derive_try_from_bytes_inner(ast: &DeriveInput) -> Result { +fn derive_try_from_bytes_inner(ast: &DeriveInput, top_level: Trait) -> Result { match &ast.data { - Data::Struct(strct) => derive_try_from_bytes_struct(ast, strct), - Data::Enum(enm) => derive_try_from_bytes_enum(ast, enm), - Data::Union(unn) => Ok(derive_try_from_bytes_union(ast, unn)), + Data::Struct(strct) => derive_try_from_bytes_struct(ast, strct, top_level), + Data::Enum(enm) => derive_try_from_bytes_enum(ast, enm, top_level), + Data::Union(unn) => Ok(derive_try_from_bytes_union(ast, unn, top_level)), } } -fn derive_from_zeros_inner(ast: &DeriveInput) -> Result { - let try_from_bytes = derive_try_from_bytes_inner(ast)?; +fn derive_from_zeros_inner(ast: &DeriveInput, top_level: Trait) -> Result { + let try_from_bytes = derive_try_from_bytes_inner(ast, top_level)?; let from_zeros = match &ast.data { Data::Struct(strct) => derive_from_zeros_struct(ast, strct), Data::Enum(enm) => derive_from_zeros_enum(ast, enm)?, @@ -379,8 +379,8 @@ fn derive_from_zeros_inner(ast: &DeriveInput) -> Result { Ok(IntoIterator::into_iter([try_from_bytes, from_zeros]).collect()) } -fn derive_from_bytes_inner(ast: &DeriveInput) -> Result { - let from_zeros = derive_from_zeros_inner(ast)?; +fn derive_from_bytes_inner(ast: &DeriveInput, top_level: Trait) -> Result { + let from_zeros = derive_from_zeros_inner(ast, top_level)?; let from_bytes = match &ast.data { Data::Struct(strct) => derive_from_bytes_struct(ast, strct), Data::Enum(enm) => derive_from_bytes_enum(ast, enm)?, @@ -390,7 +390,7 @@ fn derive_from_bytes_inner(ast: &DeriveInput) -> Result { Ok(IntoIterator::into_iter([from_zeros, from_bytes]).collect()) } -fn derive_into_bytes_inner(ast: &DeriveInput) -> Result { +fn derive_into_bytes_inner(ast: &DeriveInput, _top_level: Trait) -> Result { match &ast.data { Data::Struct(strct) => derive_into_bytes_struct(ast, strct), Data::Enum(enm) => derive_into_bytes_enum(ast, enm), @@ -398,7 +398,7 @@ fn derive_into_bytes_inner(ast: &DeriveInput) -> Result { } } -fn derive_unaligned_inner(ast: &DeriveInput) -> Result { +fn derive_unaligned_inner(ast: &DeriveInput, _top_level: Trait) -> Result { match &ast.data { Data::Struct(strct) => derive_unaligned_struct(ast, strct), Data::Enum(enm) => derive_unaligned_enum(ast, enm), @@ -411,8 +411,9 @@ fn derive_unaligned_inner(ast: &DeriveInput) -> Result { fn derive_try_from_bytes_struct( ast: &DeriveInput, strct: &DataStruct, + top_level: Trait, ) -> Result { - let extras = Some({ + let extras = try_gen_trivial_is_bit_valid(ast, top_level).unwrap_or_else(|| { let fields = strct.fields(); let field_names = fields.iter().map(|(name, _ty)| name); let field_tys = fields.iter().map(|(_name, ty)| ty); @@ -456,17 +457,21 @@ fn derive_try_from_bytes_struct( FieldBounds::ALL_SELF, SelfBounds::None, None, - extras, + Some(extras), )) } /// A union is `TryFromBytes` if: /// - all of its fields are `TryFromBytes` and `Immutable` -fn derive_try_from_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> TokenStream { +fn derive_try_from_bytes_union( + ast: &DeriveInput, + unn: &DataUnion, + top_level: Trait, +) -> TokenStream { // TODO(#5): Remove the `Immutable` bound. let field_type_trait_bounds = FieldBounds::All(&[TraitBound::Slf, TraitBound::Other(Trait::Immutable)]); - let extras = Some({ + let extras = try_gen_trivial_is_bit_valid(ast, top_level).unwrap_or_else(|| { let fields = unn.fields(); let field_names = fields.iter().map(|(name, _ty)| name); let field_tys = fields.iter().map(|(_name, ty)| ty); @@ -510,15 +515,34 @@ fn derive_try_from_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> TokenStrea field_type_trait_bounds, SelfBounds::None, None, - extras, + Some(extras), ) } -fn derive_try_from_bytes_enum(ast: &DeriveInput, enm: &DataEnum) -> Result { +fn derive_try_from_bytes_enum( + ast: &DeriveInput, + enm: &DataEnum, + top_level: Trait, +) -> Result { let repr = EnumRepr::from_attrs(&ast.attrs)?; - // The enum derive requires some extra scaffolding - let extra = Some(r#enum::derive_is_bit_valid(&ast.ident, &repr, &ast.generics, enm)?); + // If an enum has no fields, it has a well-defined integer representation, + // and every possible bit pattern corresponds to a valid discriminant tag, + // then it *could* be `FromBytes` (even if the user hasn't derived + // `FromBytes`). This holds if, for `repr(uN)` or `repr(iN)`, there are 2^N + // variants. + let could_be_from_bytes = enum_size_from_repr(&repr) + .map(|size| enm.fields().is_empty() && enm.variants.len() == 1usize << size) + .unwrap_or(false); + + let trivial_is_bit_valid = try_gen_trivial_is_bit_valid(ast, top_level); + let extra = match (trivial_is_bit_valid, could_be_from_bytes) { + (Some(is_bit_valid), _) => is_bit_valid, + // SAFETY: It would be sound for the enum to implement `FomBytes`, as + // required by `gen_trivial_is_bit_valid_unchecked`. + (None, true) => unsafe { gen_trivial_is_bit_valid_unchecked() }, + (None, false) => r#enum::derive_is_bit_valid(&ast.ident, &repr, &ast.generics, enm)?, + }; Ok(impl_block( ast, @@ -527,10 +551,86 @@ fn derive_try_from_bytes_enum(ast: &DeriveInput, enm: &DataEnum) -> Result Option { + // If the top-level trait is `FromBytes` and `Self` has no type parameters, + // then the `FromBytes` derive will fail compilation if `Self` is not + // actually soundly `FromBytes`, and so we can rely on that for our + // `is_bit_valid` impl. It's plausible that we could make changes - or Rust + // could make changes (such as the "trivial bounds" language feature) - that + // make this no longer true. To hedge against these, we include an explicit + // `Self: FromBytes` check in the generated `is_bit_valid`, which is + // bulletproof. + if top_level == Trait::FromBytes && ast.generics.params.is_empty() { + Some(quote!( + // SAFETY: See inline. + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + { + } + + assert_is_from_bytes::(); + } + + // SAFETY: The preceding code only compiles if `Self: + // FromBytes`. Thus, this code only compiles if all initialized + // byte sequences represent valid instances of `Self`. + true + } + )) + } else { + None + } +} + +/// Generates a `TryFromBytes::is_bit_valid` instance that unconditionally +/// returns true. +/// +/// This should be used where possible, (although `try_gen_trivial_is_bit_valid` +/// should be preferred over this for safety reasons). Using this impl is faster +/// to codegen, faster to compile, and is friendlier on the optimizer. +/// +/// # Safety +/// +/// The caller must ensure that all initialized bit patterns are valid for +/// `Self`. +unsafe fn gen_trivial_is_bit_valid_unchecked() -> proc_macro2::TokenStream { + quote!( + // SAFETY: The caller of `gen_trivial_is_bit_valid_unchecked` has + // promised that all initialized bit patterns are valid for `Self`. + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true + } + ) +} + /// A struct is `FromZeros` if: /// - all fields are `FromZeros` fn derive_from_zeros_struct(ast: &DeriveInput, strct: &DataStruct) -> TokenStream { diff --git a/zerocopy-derive/src/output_tests.rs b/zerocopy-derive/src/output_tests.rs index d52d81c085..caad309312 100644 --- a/zerocopy-derive/src/output_tests.rs +++ b/zerocopy-derive/src/output_tests.rs @@ -35,7 +35,7 @@ use_as_trait_name!( /// tests less brittle and robust against meaningless formatting changes. // Adapted from https://github.com/joshlf/synstructure/blob/400499aaf54840056ff56718beb7810540e6be59/src/macros.rs#L212-L317 macro_rules! test { - ($name:path { $($i:tt)* } expands to { $($o:tt)* }) => { + ($name:ident { $($i:tt)* } expands to { $($o:tt)* }) => { { #[allow(dead_code)] fn ensure_compiles() { @@ -47,17 +47,18 @@ macro_rules! test { } }; - ($name:path { $($i:tt)* } expands to { $($o:tt)* } no_build) => { + ($name:ident { $($i:tt)* } expands to { $($o:tt)* } no_build) => { { let ts: proc_macro2::TokenStream = quote::quote!( $($i)* ); let ast = syn::parse2::(ts).unwrap(); - let res = $name(&ast); + let res = $name(&ast, crate::Trait::$name); let expected_toks = quote::quote!( $($o)* ); assert_eq_streams(expected_toks.into(), res.into_ts().into()); } }; } +#[track_caller] fn assert_eq_streams(expect: TokenStream, res: TokenStream) { let pretty = |ts: TokenStream| prettyplease::unparse(&syn::parse_file(&ts.to_string()).unwrap()); @@ -81,7 +82,9 @@ fn assert_eq_streams(expect: TokenStream, res: TokenStream) { "\ test failed: got: +``` {} +``` diff (expected vs got): ``` @@ -195,7 +198,7 @@ fn test_from_zeros() { } #[test] -fn test_from_bytes() { +fn test_from_bytes_struct() { test! { FromBytes { struct Foo; @@ -205,12 +208,21 @@ fn test_from_bytes() { fn only_derive_is_allowed_to_implement_this_trait() {} fn is_bit_valid<___ZerocopyAliasing>( - mut candidate: ::zerocopy::Maybe, + _candidate: ::zerocopy::Maybe, ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool where ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } + true } } @@ -228,6 +240,60 @@ fn test_from_bytes() { } } +#[test] +fn test_from_bytes_union() { + test! { + FromBytes { + union Foo { + a: u8, + } + } expands to { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo + where + u8: ::zerocopy::TryFromBytes + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } + + true + } + } + + #[allow(deprecated)] + unsafe impl ::zerocopy::FromZeros for Foo + where + u8: ::zerocopy::FromZeros + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + #[allow(deprecated)] + unsafe impl ::zerocopy::FromBytes for Foo + where + u8: ::zerocopy::FromBytes + ::zerocopy::Immutable, + { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + #[test] fn test_into_bytes() { test! { @@ -1165,3 +1231,592 @@ fn test_try_from_bytes_enum() { } no_build } } + +// This goes at the bottom because it's so verbose and it makes scrolling past +// other code a pain. +#[test] +fn test_from_bytes_enum() { + test! { + FromBytes { + #[repr(u8)] + enum Foo { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255, + } + } expands to { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + if false { + fn assert_is_from_bytes() + where + T: ::zerocopy::FromBytes, + T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized, + {} + assert_is_from_bytes::(); + } + + true + } + } + + #[allow(deprecated)] + unsafe impl ::zerocopy::FromZeros for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + + #[allow(deprecated)] + unsafe impl ::zerocopy::FromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + } + } no_build + } +} + +#[test] +fn test_try_from_bytes_trivial_is_bit_valid_enum() { + // Even when we aren't deriving `FromBytes` as the top-level trait, + // `TryFromBytes` on enums still detects whether we *could* derive + // `FromBytes`, and if so, performs the same "trivial `is_bit_valid`" + // optimization. + test! { + TryFromBytes { + #[repr(u8)] + enum Foo { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255, + } + } expands to { + #[allow(deprecated)] + unsafe impl ::zerocopy::TryFromBytes for Foo { + fn only_derive_is_allowed_to_implement_this_trait() {} + + fn is_bit_valid<___ZerocopyAliasing>( + _candidate: ::zerocopy::Maybe, + ) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool + where + ___ZerocopyAliasing: ::zerocopy::pointer::invariant::Aliasing + + ::zerocopy::pointer::invariant::AtLeast<::zerocopy::pointer::invariant::Shared>, + { + true + } + } + } no_build + } +} diff --git a/zerocopy-derive/tests/enum_from_bytes.rs b/zerocopy-derive/tests/enum_from_bytes.rs index 9ecec4c05d..4a9160125c 100644 --- a/zerocopy-derive/tests/enum_from_bytes.rs +++ b/zerocopy-derive/tests/enum_from_bytes.rs @@ -32,6 +32,19 @@ include!("include.rs"); // `Variant128` has a discriminant of -128) since Rust won't automatically wrap // a signed discriminant around without you explicitly telling it to. +#[test] +#[allow(deprecated)] +fn test_trivial_is_bit_valid() { + // Since we derive `FromBytes`, the implied `TryFromBytes` derive's + // `is_bit_valid` impl is trivial - it unconditionally returns `true`. + util::test_trivial_is_bit_valid::(); + util::test_trivial_is_bit_valid::(); + util::test_trivial_is_bit_valid::(); + util::test_trivial_is_bit_valid::(); + util::test_trivial_is_bit_valid::(); + util::test_trivial_is_bit_valid::(); +} + // Make sure no deprecation warning is generated from our derive (see #553). #[deprecated = "do not use"] #[derive(imp::FromBytes)] diff --git a/zerocopy-derive/tests/enum_try_from_bytes.rs b/zerocopy-derive/tests/enum_try_from_bytes.rs index a2bf9c5b70..8b866c411b 100644 --- a/zerocopy-derive/tests/enum_try_from_bytes.rs +++ b/zerocopy-derive/tests/enum_try_from_bytes.rs @@ -356,3 +356,273 @@ enum B { A(A), A2 { a: A }, } + +#[derive(imp::TryFromBytes)] +#[repr(u8)] +enum FooU8 { + Variant0, + Variant1, + Variant2, + Variant3, + Variant4, + Variant5, + Variant6, + Variant7, + Variant8, + Variant9, + Variant10, + Variant11, + Variant12, + Variant13, + Variant14, + Variant15, + Variant16, + Variant17, + Variant18, + Variant19, + Variant20, + Variant21, + Variant22, + Variant23, + Variant24, + Variant25, + Variant26, + Variant27, + Variant28, + Variant29, + Variant30, + Variant31, + Variant32, + Variant33, + Variant34, + Variant35, + Variant36, + Variant37, + Variant38, + Variant39, + Variant40, + Variant41, + Variant42, + Variant43, + Variant44, + Variant45, + Variant46, + Variant47, + Variant48, + Variant49, + Variant50, + Variant51, + Variant52, + Variant53, + Variant54, + Variant55, + Variant56, + Variant57, + Variant58, + Variant59, + Variant60, + Variant61, + Variant62, + Variant63, + Variant64, + Variant65, + Variant66, + Variant67, + Variant68, + Variant69, + Variant70, + Variant71, + Variant72, + Variant73, + Variant74, + Variant75, + Variant76, + Variant77, + Variant78, + Variant79, + Variant80, + Variant81, + Variant82, + Variant83, + Variant84, + Variant85, + Variant86, + Variant87, + Variant88, + Variant89, + Variant90, + Variant91, + Variant92, + Variant93, + Variant94, + Variant95, + Variant96, + Variant97, + Variant98, + Variant99, + Variant100, + Variant101, + Variant102, + Variant103, + Variant104, + Variant105, + Variant106, + Variant107, + Variant108, + Variant109, + Variant110, + Variant111, + Variant112, + Variant113, + Variant114, + Variant115, + Variant116, + Variant117, + Variant118, + Variant119, + Variant120, + Variant121, + Variant122, + Variant123, + Variant124, + Variant125, + Variant126, + Variant127, + Variant128, + Variant129, + Variant130, + Variant131, + Variant132, + Variant133, + Variant134, + Variant135, + Variant136, + Variant137, + Variant138, + Variant139, + Variant140, + Variant141, + Variant142, + Variant143, + Variant144, + Variant145, + Variant146, + Variant147, + Variant148, + Variant149, + Variant150, + Variant151, + Variant152, + Variant153, + Variant154, + Variant155, + Variant156, + Variant157, + Variant158, + Variant159, + Variant160, + Variant161, + Variant162, + Variant163, + Variant164, + Variant165, + Variant166, + Variant167, + Variant168, + Variant169, + Variant170, + Variant171, + Variant172, + Variant173, + Variant174, + Variant175, + Variant176, + Variant177, + Variant178, + Variant179, + Variant180, + Variant181, + Variant182, + Variant183, + Variant184, + Variant185, + Variant186, + Variant187, + Variant188, + Variant189, + Variant190, + Variant191, + Variant192, + Variant193, + Variant194, + Variant195, + Variant196, + Variant197, + Variant198, + Variant199, + Variant200, + Variant201, + Variant202, + Variant203, + Variant204, + Variant205, + Variant206, + Variant207, + Variant208, + Variant209, + Variant210, + Variant211, + Variant212, + Variant213, + Variant214, + Variant215, + Variant216, + Variant217, + Variant218, + Variant219, + Variant220, + Variant221, + Variant222, + Variant223, + Variant224, + Variant225, + Variant226, + Variant227, + Variant228, + Variant229, + Variant230, + Variant231, + Variant232, + Variant233, + Variant234, + Variant235, + Variant236, + Variant237, + Variant238, + Variant239, + Variant240, + Variant241, + Variant242, + Variant243, + Variant244, + Variant245, + Variant246, + Variant247, + Variant248, + Variant249, + Variant250, + Variant251, + Variant252, + Variant253, + Variant254, + Variant255, +} + +#[test] +fn test_trivial_is_bit_valid() { + // Though we don't derive `FromBytes`, `FooU8` *could* soundly implement + // `FromBytes`. Therefore, `TryFromBytes` derive's `is_bit_valid` impl is + // trivial - it unconditionally returns `true`. + util_assert_not_impl_any!(FooU8: imp::FromBytes); + util::test_trivial_is_bit_valid::(); +} diff --git a/zerocopy-derive/tests/include.rs b/zerocopy-derive/tests/include.rs index f6c03641ea..6c236a3cf9 100644 --- a/zerocopy-derive/tests/include.rs +++ b/zerocopy-derive/tests/include.rs @@ -26,8 +26,14 @@ mod imp { #[allow(unused)] pub use { ::core::{ - assert_eq, cell::UnsafeCell, convert::TryFrom, marker::PhantomData, mem::ManuallyDrop, - option::IntoIter, prelude::v1::*, primitive::*, + assert_eq, + cell::UnsafeCell, + convert::TryFrom, + marker::PhantomData, + mem::{ManuallyDrop, MaybeUninit}, + option::IntoIter, + prelude::v1::*, + primitive::*, }, ::std::prelude::v1::*, ::zerocopy::*, @@ -80,4 +86,42 @@ pub mod util { }; }; } + + #[macro_export] + macro_rules! test_trivial_is_bit_valid { + ($x:ty => $name:ident) => { + #[test] + fn $name() { + util::test_trivial_is_bit_valid::<$x>(); + } + }; + } + + // Under some circumstances, our `TryFromBytes` derive generates a trivial + // `is_bit_valid` impl that unconditionally returns `true`. This test + // attempts to validate that this is, indeed, the behavior of our + // `TryFromBytes` derive. It is not foolproof, but is likely to catch some + // mistakes. + // + // As of this writing, this happens when deriving `TryFromBytes` thanks to a + // top-level `#[derive(FromBytes)]`. + pub fn test_trivial_is_bit_valid() { + // This test works based on the insight that a trivial `is_bit_valid` + // impl should never load any bytes from memory. Thus, while it is + // technically a violation of `is_bit_valid`'s safety precondition to + // pass a pointer to uninitialized memory, the `is_bit_valid` impl we + // expect our derives to generate should never touch this memory, and + // thus should never exhibit UB. By contrast, if our derives are + // spuriously generating non-trivial `is_bit_valid` impls, this should + // cause UB which may be caught by Miri. + + let buf = super::imp::MaybeUninit::::uninit(); + let ptr = super::imp::Ptr::from_ref(&buf); + // SAFETY: `T` and `MaybeUninit` have the same layout, so this is a + // size-preserving cast. It is also a provenance-preserving cast. + let ptr = unsafe { ptr.cast_unsized(|p| p as *mut T) }; + // SAFETY: This is intentionally unsound; see the preceding comment. + let ptr = unsafe { ptr.assume_initialized() }; + assert!(::is_bit_valid(ptr)); + } } diff --git a/zerocopy-derive/tests/struct_from_bytes.rs b/zerocopy-derive/tests/struct_from_bytes.rs index 680b1c9e3c..8cc816c9e8 100644 --- a/zerocopy-derive/tests/struct_from_bytes.rs +++ b/zerocopy-derive/tests/struct_from_bytes.rs @@ -19,6 +19,7 @@ include!("include.rs"); struct Zst; util_assert_impl_all!(Zst: imp::FromBytes); +test_trivial_is_bit_valid!(Zst => test_zst_trivial_is_bit_valid); #[derive(imp::FromBytes)] struct One { @@ -26,6 +27,7 @@ struct One { } util_assert_impl_all!(One: imp::FromBytes); +test_trivial_is_bit_valid!(One => test_one_trivial_is_bit_valid); #[derive(imp::FromBytes)] struct Two { @@ -34,6 +36,7 @@ struct Two { } util_assert_impl_all!(Two: imp::FromBytes); +test_trivial_is_bit_valid!(Two => test_two_trivial_is_bit_valid); #[derive(imp::FromBytes)] struct Unsized { @@ -55,6 +58,7 @@ struct TypeParams<'a, T: ?imp::Sized, I: imp::Iterator> { util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::FromBytes); util_assert_impl_all!(TypeParams<'static, util::AU16, imp::IntoIter<()>>: imp::FromBytes); util_assert_impl_all!(TypeParams<'static, [util::AU16], imp::IntoIter<()>>: imp::FromBytes); +test_trivial_is_bit_valid!(TypeParams<'static, (), imp::IntoIter<()>> => test_type_params_trivial_is_bit_valid); // Deriving `FromBytes` should work if the struct has bounded parameters. @@ -70,3 +74,4 @@ where T: 'a + 'b + imp::FromBytes; util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::FromBytes); +test_trivial_is_bit_valid!(WithParams<'static, 'static, u8, 42> => test_with_params_trivial_is_bit_valid); diff --git a/zerocopy-derive/tests/struct_try_from_bytes.rs b/zerocopy-derive/tests/struct_try_from_bytes.rs index 23e21e653e..d212187cfa 100644 --- a/zerocopy-derive/tests/struct_try_from_bytes.rs +++ b/zerocopy-derive/tests/struct_try_from_bytes.rs @@ -26,7 +26,7 @@ fn zst() { imp::assert!(is_bit_valid); } -#[derive(imp::FromBytes)] +#[derive(imp::TryFromBytes)] #[repr(C)] struct One { a: u8, @@ -45,7 +45,7 @@ fn one() { imp::assert!(is_bit_valid); } -#[derive(imp::FromZeros)] +#[derive(imp::TryFromBytes)] #[repr(C)] struct Two { a: bool, @@ -87,7 +87,7 @@ fn two_bad() { imp::assert!(!is_bit_valid); } -#[derive(imp::FromBytes)] +#[derive(imp::TryFromBytes)] #[repr(C)] struct Unsized { a: [u8], @@ -116,7 +116,7 @@ fn un_sized() { imp::assert!(is_bit_valid); } -#[derive(imp::FromBytes)] +#[derive(imp::TryFromBytes)] #[repr(C)] struct TypeParams<'a, T: ?imp::Sized, I: imp::Iterator> { a: I::Item, @@ -133,7 +133,7 @@ util_assert_impl_all!(TypeParams<'static, [util::AU16], imp::IntoIter<()>>: imp: // Deriving `imp::TryFromBytes` should work if the struct has bounded parameters. -#[derive(imp::FromBytes)] +#[derive(imp::TryFromBytes)] #[repr(transparent)] struct WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::TryFromBytes, const N: usize>( imp::PhantomData<&'a &'b ()>, @@ -146,6 +146,31 @@ where util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::TryFromBytes); +#[derive(imp::FromBytes)] +#[repr(C)] +struct MaybeFromBytes(T); + +#[test] +fn test_maybe_from_bytes() { + // When deriving `FromBytes` on a type with no generic parameters, we emit a + // trivial `is_bit_valid` impl that always returns true. This test confirms + // that we *don't* spuriously do that when generic parameters are present. + + let candidate = ::zerocopy::Ptr::from_ref(&[2u8][..]); + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = unsafe { candidate.cast_unsized(|p| p as *mut MaybeFromBytes) }; + + // SAFETY: `[u8]` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = as imp::TryFromBytes>::is_bit_valid(candidate); + imp::assert!(!is_bit_valid); +} + #[derive(Debug, PartialEq, Eq, imp::TryFromBytes, imp::Immutable, imp::KnownLayout)] #[repr(C, packed)] struct CPacked { diff --git a/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr b/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr index e6e01d5100..20ebd03a16 100644 --- a/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-msrv/derive_transparent.stderr @@ -1,10 +1,10 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/derive_transparent.rs:34:1 | 34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | -note: required because of the requirements on the impl of `TryFromBytes` for `TransparentStruct` +note: required because of the requirements on the impl of `zerocopy::TryFromBytes` for `TransparentStruct` --> tests/ui-msrv/derive_transparent.rs:24:21 | 24 | #[derive(IntoBytes, FromBytes, Unaligned)] diff --git a/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr b/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr index 0c3d09567e..0b57efc7d1 100644 --- a/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr @@ -6,20 +6,20 @@ warning: unused import: `zerocopy::KnownLayout` | = note: `#[warn(unused_imports)]` on by default -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/late_compile_pass.rs:28:10 | 28 | #[derive(TryFromBytes)] - | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^ the trait `zerocopy::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: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/late_compile_pass.rs:37:10 | 37 | #[derive(FromZeros)] - | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = help: see issue #48214 = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -33,11 +33,11 @@ error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied = help: see issue #48214 = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-msrv/late_compile_pass.rs:46:10 | 46 | #[derive(FromBytes)] - | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` 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) diff --git a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr index 01e2c43ad8..be89f5180e 100644 --- a/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-nightly/derive_transparent.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/derive_transparent.rs:34:23 | 34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy`, which is required by `TransparentStruct: TryFromBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy`, which is required by `TransparentStruct: zerocopy::TryFromBytes` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -15,7 +15,7 @@ error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied AtomicI32 AtomicI64 and $N others -note: required for `TransparentStruct` to implement `TryFromBytes` +note: required for `TransparentStruct` to implement `zerocopy::TryFromBytes` --> tests/ui-nightly/derive_transparent.rs:24:21 | 24 | #[derive(IntoBytes, FromBytes, Unaligned)] diff --git a/zerocopy-derive/tests/ui-nightly/enum.stderr b/zerocopy-derive/tests/ui-nightly/enum.stderr index 5f04a7465a..ab1c48bd75 100644 --- a/zerocopy-derive/tests/ui-nightly/enum.stderr +++ b/zerocopy-derive/tests/ui-nightly/enum.stderr @@ -486,3 +486,32 @@ help: add `#![feature(trivial_bounds)]` to the crate attributes to enable | 9 + #![feature(trivial_bounds)] | + +error[E0277]: the trait bound `bool: FromBytes` is not satisfied + --> tests/ui-nightly/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `bool`, which is required by `FooU8: FromBytes` + | + = note: Consider adding `#[derive(FromBytes)]` to `bool` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required for `FooU8` to implement `FromBytes` + --> tests/ui-nightly/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_is_from_bytes` + --> tests/ui-nightly/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr index bca94cf334..99f22d741a 100644 --- a/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-nightly/late_compile_pass.stderr @@ -6,14 +6,14 @@ warning: unused import: `zerocopy::KnownLayout` | = note: `#[warn(unused_imports)]` on by default -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/late_compile_pass.rs:28:10 | 28 | #[derive(TryFromBytes)] - | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -30,14 +30,14 @@ help: add `#![feature(trivial_bounds)]` to the crate attributes to enable 9 + #![feature(trivial_bounds)] | -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/late_compile_pass.rs:37:10 | 37 | #[derive(FromZeros)] - | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -78,14 +78,14 @@ help: add `#![feature(trivial_bounds)]` to the crate attributes to enable 9 + #![feature(trivial_bounds)] | -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-nightly/late_compile_pass.rs:46:10 | 46 | #[derive(FromBytes)] - | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -245,3 +245,32 @@ help: add `#![feature(trivial_bounds)]` to the crate attributes to enable | 9 + #![feature(trivial_bounds)] | + +error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-nightly/late_compile_pass.rs:46:10 + | +46 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy`, which is required by `FromBytes1: zerocopy::FromBytes` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required for `FromBytes1` to implement `zerocopy::FromBytes` + --> tests/ui-nightly/late_compile_pass.rs:46:10 + | +46 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `::is_bit_valid::assert_is_from_bytes` + --> tests/ui-nightly/late_compile_pass.rs:46:10 + | +46 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr index 4480706ec9..b274b65433 100644 --- a/zerocopy-derive/tests/ui-stable/derive_transparent.stderr +++ b/zerocopy-derive/tests/ui-stable/derive_transparent.stderr @@ -1,11 +1,11 @@ -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/derive_transparent.rs:34:23 | 34 | util_assert_impl_all!(TransparentStruct: TryFromBytes); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy`, which is required by `TransparentStruct: TryFromBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy`, which is required by `TransparentStruct: zerocopy::TryFromBytes` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -15,7 +15,7 @@ error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied AtomicI32 AtomicI64 and $N others -note: required for `TransparentStruct` to implement `TryFromBytes` +note: required for `TransparentStruct` to implement `zerocopy::TryFromBytes` --> tests/ui-stable/derive_transparent.rs:24:21 | 24 | #[derive(IntoBytes, FromBytes, Unaligned)] diff --git a/zerocopy-derive/tests/ui-stable/enum.stderr b/zerocopy-derive/tests/ui-stable/enum.stderr index 9cdd56b0a5..9809efa96e 100644 --- a/zerocopy-derive/tests/ui-stable/enum.stderr +++ b/zerocopy-derive/tests/ui-stable/enum.stderr @@ -450,3 +450,32 @@ error[E0277]: `IntoBytes3` has inter-field padding = help: the trait `PaddingFree` is implemented for `()` = help: see issue #48214 = note: this error originates in the derive macro `IntoBytes` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `bool: FromBytes` is not satisfied + --> tests/ui-stable/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `FromBytes` is not implemented for `bool`, which is required by `FooU8: FromBytes` + | + = note: Consider adding `#[derive(FromBytes)]` to `bool` + = help: the following other types implement trait `FromBytes`: + () + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + AtomicU32 + and $N others +note: required for `FooU8` to implement `FromBytes` + --> tests/ui-stable/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `assert_is_from_bytes` + --> tests/ui-stable/enum.rs:191:10 + | +191 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr index d1bbbcc498..b6dbb04980 100644 --- a/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr +++ b/zerocopy-derive/tests/ui-stable/late_compile_pass.stderr @@ -6,14 +6,14 @@ warning: unused import: `zerocopy::KnownLayout` | = note: `#[warn(unused_imports)]` on by default -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/late_compile_pass.rs:28:10 | 28 | #[derive(TryFromBytes)] - | ^^^^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -26,14 +26,14 @@ error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied = 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: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/late_compile_pass.rs:37:10 | 37 | #[derive(FromZeros)] - | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -66,14 +66,14 @@ error[E0277]: the trait bound `NotZerocopy: FromZeros` is not satisfied = help: see issue #48214 = note: this error originates in the derive macro `FromZeros` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotZerocopy: TryFromBytes` is not satisfied +error[E0277]: the trait bound `NotZerocopy: zerocopy::TryFromBytes` is not satisfied --> tests/ui-stable/late_compile_pass.rs:46:10 | 46 | #[derive(FromBytes)] - | ^^^^^^^^^ the trait `TryFromBytes` is not implemented for `NotZerocopy` + | ^^^^^^^^^ the trait `zerocopy::TryFromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(TryFromBytes)]` to `NotZerocopy` - = help: the following other types implement trait `TryFromBytes`: + = help: the following other types implement trait `zerocopy::TryFromBytes`: () *const T *mut T @@ -205,3 +205,32 @@ error[E0277]: the trait bound `AU16: Unaligned` is not satisfied and $N others = 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 `NotZerocopy: zerocopy::FromBytes` is not satisfied + --> tests/ui-stable/late_compile_pass.rs:46:10 + | +46 | #[derive(FromBytes)] + | ^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy`, which is required by `FromBytes1: zerocopy::FromBytes` + | + = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` + = help: the following other types implement trait `zerocopy::FromBytes`: + () + AU16 + AtomicI16 + AtomicI32 + AtomicI64 + AtomicI8 + AtomicIsize + AtomicU16 + and $N others +note: required for `FromBytes1` to implement `zerocopy::FromBytes` + --> tests/ui-stable/late_compile_pass.rs:46:10 + | +46 | #[derive(FromBytes)] + | ^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +note: required by a bound in `::is_bit_valid::assert_is_from_bytes` + --> tests/ui-stable/late_compile_pass.rs:46:10 + | +46 | #[derive(FromBytes)] + | ^^^^^^^^^ required by this bound in `assert_is_from_bytes` + = note: this error originates in the derive macro `FromBytes` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/zerocopy-derive/tests/union_from_bytes.rs b/zerocopy-derive/tests/union_from_bytes.rs index ec41edb8f7..f8482248b1 100644 --- a/zerocopy-derive/tests/union_from_bytes.rs +++ b/zerocopy-derive/tests/union_from_bytes.rs @@ -21,6 +21,7 @@ union Zst { } util_assert_impl_all!(Zst: imp::FromBytes); +test_trivial_is_bit_valid!(Zst => test_zst_trivial_is_bit_valid); #[derive(imp::Immutable, imp::FromBytes)] union One { @@ -28,6 +29,7 @@ union One { } util_assert_impl_all!(One: imp::FromBytes); +test_trivial_is_bit_valid!(One => test_one_trivial_is_bit_valid); #[derive(imp::Immutable, imp::FromBytes)] union Two { @@ -36,6 +38,7 @@ union Two { } util_assert_impl_all!(Two: imp::FromBytes); +test_trivial_is_bit_valid!(Two => test_two_trivial_is_bit_valid); #[derive(imp::Immutable, imp::FromBytes)] union TypeParams<'a, T: imp::Copy, I: imp::Iterator> @@ -51,6 +54,7 @@ where } util_assert_impl_all!(TypeParams<'static, (), imp::IntoIter<()>>: imp::FromBytes); +test_trivial_is_bit_valid!(TypeParams<'static, (), imp::IntoIter<()>> => test_type_params_trivial_is_bit_valid); // Deriving `imp::FromBytes` should work if the union has bounded parameters. @@ -67,3 +71,4 @@ where } util_assert_impl_all!(WithParams<'static, 'static, u8, 42>: imp::FromBytes); +test_trivial_is_bit_valid!(WithParams<'static, 'static, u8, 42> => test_with_params_trivial_is_bit_valid); diff --git a/zerocopy-derive/tests/union_try_from_bytes.rs b/zerocopy-derive/tests/union_try_from_bytes.rs index 0f6658cf51..8c3183e5d8 100644 --- a/zerocopy-derive/tests/union_try_from_bytes.rs +++ b/zerocopy-derive/tests/union_try_from_bytes.rs @@ -15,7 +15,7 @@ include!("include.rs"); // A struct is `imp::TryFromBytes` if: // - any of its fields are `imp::TryFromBytes` -#[derive(imp::Immutable, imp::FromBytes)] +#[derive(imp::Immutable, imp::TryFromBytes)] union One { a: u8, } @@ -33,7 +33,7 @@ fn one() { assert!(is_bit_valid); } -#[derive(imp::Immutable, imp::FromZeros)] +#[derive(imp::Immutable, imp::TryFromBytes)] #[repr(C)] union Two { a: bool, @@ -82,7 +82,7 @@ fn two_bad() { assert!(!is_bit_valid); } -#[derive(imp::Immutable, imp::FromZeros)] +#[derive(imp::Immutable, imp::TryFromBytes)] #[repr(C)] union BoolAndZst { a: bool, @@ -111,7 +111,34 @@ fn bool_and_zst() { assert!(is_bit_valid); } -#[derive(imp::Immutable, imp::FromBytes)] +#[derive(imp::FromBytes)] +#[repr(C)] +union MaybeFromBytes { + t: T, +} + +#[test] +fn test_maybe_from_bytes() { + // When deriving `FromBytes` on a type with no generic parameters, we emit a + // trivial `is_bit_valid` impl that always returns true. This test confirms + // that we *don't* spuriously do that when generic parameters are present. + + let candidate = ::zerocopy::Ptr::from_ref(&[2u8][..]); + + // SAFETY: + // - The cast preserves address and size. As a result, the cast will address + // the same bytes as `c`. + // - The cast preserves provenance. + // - Neither the input nor output types contain any `UnsafeCell`s. + let candidate = unsafe { candidate.cast_unsized(|p| p as *mut MaybeFromBytes) }; + + // SAFETY: `[u8]` consists entirely of initialized bytes. + let candidate = unsafe { candidate.assume_initialized() }; + let is_bit_valid = as imp::TryFromBytes>::is_bit_valid(candidate); + imp::assert!(!is_bit_valid); +} + +#[derive(imp::Immutable, imp::TryFromBytes)] #[repr(C)] union TypeParams<'a, T: imp::Copy, I: imp::Iterator> where @@ -131,7 +158,7 @@ util_assert_impl_all!(TypeParams<'static, [util::AU16; 2], imp::IntoIter<()>>: i // Deriving `imp::TryFromBytes` should work if the union has bounded parameters. -#[derive(imp::Immutable, imp::FromBytes)] +#[derive(imp::Immutable, imp::TryFromBytes)] #[repr(C)] union WithParams<'a: 'b, 'b: 'a, T: 'a + 'b + imp::TryFromBytes, const N: usize> where