From a289b4d031a4dde1e03a334e8ae98f9af596ef66 Mon Sep 17 00:00:00 2001 From: Chris Wailes Date: Tue, 5 Dec 2023 11:18:39 -0800 Subject: Upgrade zerocopy to 0.7.29 This project was upgraded with external_updater. Usage: tools/external_updater/updater.sh update rust/crates/zerocopy For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md Test: TreeHugger Change-Id: I34aca5e69354354323b4d424ee89019eded62406 --- .cargo_vcs_info.json | 2 +- Android.bp | 12 +- CONTRIBUTING.md | 10 +- Cargo.toml | 32 +- Cargo.toml.orig | 37 +- INTERNAL.md | 17 +- LICENSE-APACHE | 202 + LICENSE-BSD | 24 + LICENSE-MIT | 26 + METADATA | 23 +- POLICIES.md | 95 + README.md | 63 +- cargo.sh | 52 +- clippy.toml | 10 + generate-readme.sh | 20 +- rustfmt.toml | 10 +- src/byteorder.rs | 414 +- src/derive_util.rs | 127 - src/lib.rs | 5501 +++++++++++++++++--- src/macro_util.rs | 670 +++ src/macros.rs | 213 +- src/third_party/rust/LICENSE-APACHE | 176 + src/third_party/rust/LICENSE-MIT | 23 + src/third_party/rust/README.fuchsia | 7 + src/third_party/rust/layout.rs | 45 + src/util.rs | 721 ++- src/wrappers.rs | 36 +- testdata/include_value/data | 1 + tests/trybuild.rs | 48 +- tests/ui-msrv/include_value_not_from_bytes.rs | 12 + tests/ui-msrv/include_value_not_from_bytes.stderr | 12 + tests/ui-msrv/include_value_wrong_size.rs | 11 + tests/ui-msrv/include_value_wrong_size.stderr | 9 + tests/ui-msrv/invalid-impls/invalid-impls.rs | 10 +- tests/ui-msrv/invalid-impls/invalid-impls.stderr | 72 +- tests/ui-msrv/max-align.rs | 99 + tests/ui-msrv/max-align.stderr | 5 + tests/ui-msrv/transmute-dst-not-frombytes.rs | 18 + tests/ui-msrv/transmute-dst-not-frombytes.stderr | 12 + tests/ui-msrv/transmute-illegal.rs | 10 - tests/ui-msrv/transmute-illegal.stderr | 18 - tests/ui-msrv/transmute-mut-alignment-increase.rs | 19 + .../transmute-mut-alignment-increase.stderr | 36 + tests/ui-msrv/transmute-mut-const.rs | 20 + tests/ui-msrv/transmute-mut-const.stderr | 41 + tests/ui-msrv/transmute-mut-dst-generic.rs | 18 + tests/ui-msrv/transmute-mut-dst-generic.stderr | 19 + tests/ui-msrv/transmute-mut-dst-not-a-reference.rs | 17 + .../transmute-mut-dst-not-a-reference.stderr | 39 + tests/ui-msrv/transmute-mut-dst-not-asbytes.rs | 24 + tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr | 12 + tests/ui-msrv/transmute-mut-dst-not-frombytes.rs | 24 + .../ui-msrv/transmute-mut-dst-not-frombytes.stderr | 12 + tests/ui-msrv/transmute-mut-dst-unsized.rs | 17 + tests/ui-msrv/transmute-mut-dst-unsized.stderr | 108 + tests/ui-msrv/transmute-mut-illegal-lifetime.rs | 15 + .../ui-msrv/transmute-mut-illegal-lifetime.stderr | 9 + tests/ui-msrv/transmute-mut-size-decrease.rs | 17 + tests/ui-msrv/transmute-mut-size-decrease.stderr | 36 + tests/ui-msrv/transmute-mut-size-increase.rs | 17 + tests/ui-msrv/transmute-mut-size-increase.stderr | 36 + tests/ui-msrv/transmute-mut-src-dst-generic.rs | 19 + tests/ui-msrv/transmute-mut-src-dst-generic.stderr | 19 + .../transmute-mut-src-dst-not-references.rs | 17 + .../transmute-mut-src-dst-not-references.stderr | 12 + tests/ui-msrv/transmute-mut-src-dst-unsized.rs | 17 + tests/ui-msrv/transmute-mut-src-dst-unsized.stderr | 237 + tests/ui-msrv/transmute-mut-src-generic.rs | 18 + tests/ui-msrv/transmute-mut-src-generic.stderr | 10 + tests/ui-msrv/transmute-mut-src-immutable.rs | 18 + tests/ui-msrv/transmute-mut-src-immutable.stderr | 11 + tests/ui-msrv/transmute-mut-src-not-a-reference.rs | 17 + .../transmute-mut-src-not-a-reference.stderr | 12 + tests/ui-msrv/transmute-mut-src-not-asbytes.rs | 24 + tests/ui-msrv/transmute-mut-src-not-asbytes.stderr | 25 + tests/ui-msrv/transmute-mut-src-not-frombytes.rs | 24 + .../ui-msrv/transmute-mut-src-not-frombytes.stderr | 25 + tests/ui-msrv/transmute-mut-src-unsized.rs | 16 + tests/ui-msrv/transmute-mut-src-unsized.stderr | 198 + tests/ui-msrv/transmute-ptr-to-usize.rs | 20 + tests/ui-msrv/transmute-ptr-to-usize.stderr | 37 + tests/ui-msrv/transmute-ref-alignment-increase.rs | 19 + .../transmute-ref-alignment-increase.stderr | 9 + tests/ui-msrv/transmute-ref-dst-generic.rs | 18 + tests/ui-msrv/transmute-ref-dst-generic.stderr | 19 + tests/ui-msrv/transmute-ref-dst-mutable.rs | 19 + tests/ui-msrv/transmute-ref-dst-mutable.stderr | 29 + tests/ui-msrv/transmute-ref-dst-not-a-reference.rs | 17 + .../transmute-ref-dst-not-a-reference.stderr | 29 + tests/ui-msrv/transmute-ref-dst-not-frombytes.rs | 18 + .../ui-msrv/transmute-ref-dst-not-frombytes.stderr | 12 + tests/ui-msrv/transmute-ref-dst-unsized.rs | 17 + tests/ui-msrv/transmute-ref-dst-unsized.stderr | 94 + tests/ui-msrv/transmute-ref-illegal-lifetime.rs | 15 + .../ui-msrv/transmute-ref-illegal-lifetime.stderr | 9 + tests/ui-msrv/transmute-ref-size-decrease.rs | 17 + tests/ui-msrv/transmute-ref-size-decrease.stderr | 9 + tests/ui-msrv/transmute-ref-size-increase.rs | 17 + tests/ui-msrv/transmute-ref-size-increase.stderr | 9 + tests/ui-msrv/transmute-ref-src-dst-generic.rs | 19 + tests/ui-msrv/transmute-ref-src-dst-generic.stderr | 19 + .../transmute-ref-src-dst-not-references.rs | 17 + .../transmute-ref-src-dst-not-references.stderr | 42 + tests/ui-msrv/transmute-ref-src-dst-unsized.rs | 17 + tests/ui-msrv/transmute-ref-src-dst-unsized.stderr | 195 + tests/ui-msrv/transmute-ref-src-generic.rs | 18 + tests/ui-msrv/transmute-ref-src-generic.stderr | 19 + tests/ui-msrv/transmute-ref-src-not-a-reference.rs | 17 + .../transmute-ref-src-not-a-reference.stderr | 12 + tests/ui-msrv/transmute-ref-src-not-asbytes.rs | 18 + tests/ui-msrv/transmute-ref-src-not-asbytes.stderr | 25 + tests/ui-msrv/transmute-ref-src-unsized.rs | 16 + tests/ui-msrv/transmute-ref-src-unsized.stderr | 170 + tests/ui-msrv/transmute-size-decrease.rs | 19 + tests/ui-msrv/transmute-size-decrease.stderr | 9 + tests/ui-msrv/transmute-size-increase.rs | 19 + tests/ui-msrv/transmute-size-increase.stderr | 9 + tests/ui-msrv/transmute-src-not-asbytes.rs | 18 + tests/ui-msrv/transmute-src-not-asbytes.stderr | 25 + tests/ui-nightly/include_value_not_from_bytes.rs | 12 + .../ui-nightly/include_value_not_from_bytes.stderr | 25 + tests/ui-nightly/include_value_wrong_size.rs | 11 + tests/ui-nightly/include_value_wrong_size.stderr | 9 + tests/ui-nightly/invalid-impls/invalid-impls.rs | 10 +- .../ui-nightly/invalid-impls/invalid-impls.stderr | 72 +- tests/ui-nightly/max-align.rs | 99 + tests/ui-nightly/max-align.stderr | 5 + tests/ui-nightly/transmute-dst-not-frombytes.rs | 18 + .../ui-nightly/transmute-dst-not-frombytes.stderr | 25 + tests/ui-nightly/transmute-illegal.rs | 10 - tests/ui-nightly/transmute-illegal.stderr | 16 - .../ui-nightly/transmute-mut-alignment-increase.rs | 19 + .../transmute-mut-alignment-increase.stderr | 9 + tests/ui-nightly/transmute-mut-const.rs | 20 + tests/ui-nightly/transmute-mut-const.stderr | 42 + tests/ui-nightly/transmute-mut-dst-generic.rs | 18 + tests/ui-nightly/transmute-mut-dst-generic.stderr | 19 + .../transmute-mut-dst-not-a-reference.rs | 17 + .../transmute-mut-dst-not-a-reference.stderr | 39 + tests/ui-nightly/transmute-mut-dst-not-asbytes.rs | 24 + .../transmute-mut-dst-not-asbytes.stderr | 25 + .../ui-nightly/transmute-mut-dst-not-frombytes.rs | 24 + .../transmute-mut-dst-not-frombytes.stderr | 25 + tests/ui-nightly/transmute-mut-dst-unsized.rs | 17 + tests/ui-nightly/transmute-mut-dst-unsized.stderr | 86 + tests/ui-nightly/transmute-mut-illegal-lifetime.rs | 15 + .../transmute-mut-illegal-lifetime.stderr | 12 + tests/ui-nightly/transmute-mut-size-decrease.rs | 17 + .../ui-nightly/transmute-mut-size-decrease.stderr | 9 + tests/ui-nightly/transmute-mut-size-increase.rs | 17 + .../ui-nightly/transmute-mut-size-increase.stderr | 9 + tests/ui-nightly/transmute-mut-src-dst-generic.rs | 19 + .../transmute-mut-src-dst-generic.stderr | 19 + .../transmute-mut-src-dst-not-references.rs | 17 + .../transmute-mut-src-dst-not-references.stderr | 15 + tests/ui-nightly/transmute-mut-src-dst-unsized.rs | 17 + .../transmute-mut-src-dst-unsized.stderr | 231 + tests/ui-nightly/transmute-mut-src-generic.rs | 18 + tests/ui-nightly/transmute-mut-src-generic.stderr | 10 + tests/ui-nightly/transmute-mut-src-immutable.rs | 18 + .../ui-nightly/transmute-mut-src-immutable.stderr | 11 + .../transmute-mut-src-not-a-reference.rs | 17 + .../transmute-mut-src-not-a-reference.stderr | 15 + tests/ui-nightly/transmute-mut-src-not-asbytes.rs | 24 + .../transmute-mut-src-not-asbytes.stderr | 48 + .../ui-nightly/transmute-mut-src-not-frombytes.rs | 24 + .../transmute-mut-src-not-frombytes.stderr | 48 + tests/ui-nightly/transmute-mut-src-unsized.rs | 16 + tests/ui-nightly/transmute-mut-src-unsized.stderr | 158 + tests/ui-nightly/transmute-ptr-to-usize.rs | 20 + tests/ui-nightly/transmute-ptr-to-usize.stderr | 30 + .../ui-nightly/transmute-ref-alignment-increase.rs | 19 + .../transmute-ref-alignment-increase.stderr | 9 + tests/ui-nightly/transmute-ref-dst-generic.rs | 18 + tests/ui-nightly/transmute-ref-dst-generic.stderr | 19 + tests/ui-nightly/transmute-ref-dst-mutable.rs | 19 + tests/ui-nightly/transmute-ref-dst-mutable.stderr | 29 + .../transmute-ref-dst-not-a-reference.rs | 17 + .../transmute-ref-dst-not-a-reference.stderr | 29 + .../ui-nightly/transmute-ref-dst-not-frombytes.rs | 18 + .../transmute-ref-dst-not-frombytes.stderr | 25 + tests/ui-nightly/transmute-ref-dst-unsized.rs | 17 + tests/ui-nightly/transmute-ref-dst-unsized.stderr | 69 + tests/ui-nightly/transmute-ref-illegal-lifetime.rs | 15 + .../transmute-ref-illegal-lifetime.stderr | 12 + tests/ui-nightly/transmute-ref-size-decrease.rs | 17 + .../ui-nightly/transmute-ref-size-decrease.stderr | 9 + tests/ui-nightly/transmute-ref-size-increase.rs | 17 + .../ui-nightly/transmute-ref-size-increase.stderr | 9 + tests/ui-nightly/transmute-ref-src-dst-generic.rs | 19 + .../transmute-ref-src-dst-generic.stderr | 19 + .../transmute-ref-src-dst-not-references.rs | 17 + .../transmute-ref-src-dst-not-references.stderr | 45 + tests/ui-nightly/transmute-ref-src-dst-unsized.rs | 17 + .../transmute-ref-src-dst-unsized.stderr | 183 + tests/ui-nightly/transmute-ref-src-generic.rs | 18 + tests/ui-nightly/transmute-ref-src-generic.stderr | 19 + .../transmute-ref-src-not-a-reference.rs | 17 + .../transmute-ref-src-not-a-reference.stderr | 15 + tests/ui-nightly/transmute-ref-src-not-asbytes.rs | 18 + .../transmute-ref-src-not-asbytes.stderr | 48 + tests/ui-nightly/transmute-ref-src-unsized.rs | 16 + tests/ui-nightly/transmute-ref-src-unsized.stderr | 127 + tests/ui-nightly/transmute-size-decrease.rs | 19 + tests/ui-nightly/transmute-size-decrease.stderr | 9 + tests/ui-nightly/transmute-size-increase.rs | 19 + tests/ui-nightly/transmute-size-increase.stderr | 9 + tests/ui-nightly/transmute-src-not-asbytes.rs | 18 + tests/ui-nightly/transmute-src-not-asbytes.stderr | 48 + tests/ui-stable/include_value_not_from_bytes.rs | 12 + .../ui-stable/include_value_not_from_bytes.stderr | 25 + tests/ui-stable/include_value_wrong_size.rs | 11 + tests/ui-stable/include_value_wrong_size.stderr | 9 + tests/ui-stable/invalid-impls/invalid-impls.rs | 10 +- tests/ui-stable/invalid-impls/invalid-impls.stderr | 72 +- tests/ui-stable/max-align.rs | 99 + tests/ui-stable/max-align.stderr | 5 + tests/ui-stable/transmute-dst-not-frombytes.rs | 18 + tests/ui-stable/transmute-dst-not-frombytes.stderr | 25 + tests/ui-stable/transmute-illegal.rs | 10 - tests/ui-stable/transmute-illegal.stderr | 16 - .../ui-stable/transmute-mut-alignment-increase.rs | 19 + .../transmute-mut-alignment-increase.stderr | 9 + tests/ui-stable/transmute-mut-const.rs | 20 + tests/ui-stable/transmute-mut-const.stderr | 41 + tests/ui-stable/transmute-mut-dst-generic.rs | 18 + tests/ui-stable/transmute-mut-dst-generic.stderr | 19 + .../ui-stable/transmute-mut-dst-not-a-reference.rs | 17 + .../transmute-mut-dst-not-a-reference.stderr | 39 + tests/ui-stable/transmute-mut-dst-not-asbytes.rs | 24 + .../ui-stable/transmute-mut-dst-not-asbytes.stderr | 25 + tests/ui-stable/transmute-mut-dst-not-frombytes.rs | 24 + .../transmute-mut-dst-not-frombytes.stderr | 25 + tests/ui-stable/transmute-mut-dst-unsized.rs | 17 + tests/ui-stable/transmute-mut-dst-unsized.stderr | 106 + tests/ui-stable/transmute-mut-illegal-lifetime.rs | 15 + .../transmute-mut-illegal-lifetime.stderr | 12 + tests/ui-stable/transmute-mut-size-decrease.rs | 17 + tests/ui-stable/transmute-mut-size-decrease.stderr | 9 + tests/ui-stable/transmute-mut-size-increase.rs | 17 + tests/ui-stable/transmute-mut-size-increase.stderr | 9 + tests/ui-stable/transmute-mut-src-dst-generic.rs | 19 + .../ui-stable/transmute-mut-src-dst-generic.stderr | 19 + .../transmute-mut-src-dst-not-references.rs | 17 + .../transmute-mut-src-dst-not-references.stderr | 15 + tests/ui-stable/transmute-mut-src-dst-unsized.rs | 17 + .../ui-stable/transmute-mut-src-dst-unsized.stderr | 288 + tests/ui-stable/transmute-mut-src-generic.rs | 18 + tests/ui-stable/transmute-mut-src-generic.stderr | 10 + tests/ui-stable/transmute-mut-src-immutable.rs | 18 + tests/ui-stable/transmute-mut-src-immutable.stderr | 11 + .../ui-stable/transmute-mut-src-not-a-reference.rs | 17 + .../transmute-mut-src-not-a-reference.stderr | 15 + tests/ui-stable/transmute-mut-src-not-asbytes.rs | 24 + .../ui-stable/transmute-mut-src-not-asbytes.stderr | 48 + tests/ui-stable/transmute-mut-src-not-frombytes.rs | 24 + .../transmute-mut-src-not-frombytes.stderr | 48 + tests/ui-stable/transmute-mut-src-unsized.rs | 16 + tests/ui-stable/transmute-mut-src-unsized.stderr | 195 + tests/ui-stable/transmute-ptr-to-usize.rs | 20 + tests/ui-stable/transmute-ptr-to-usize.stderr | 30 + .../ui-stable/transmute-ref-alignment-increase.rs | 19 + .../transmute-ref-alignment-increase.stderr | 9 + tests/ui-stable/transmute-ref-dst-generic.rs | 18 + tests/ui-stable/transmute-ref-dst-generic.stderr | 19 + tests/ui-stable/transmute-ref-dst-mutable.rs | 19 + tests/ui-stable/transmute-ref-dst-mutable.stderr | 29 + .../ui-stable/transmute-ref-dst-not-a-reference.rs | 17 + .../transmute-ref-dst-not-a-reference.stderr | 29 + tests/ui-stable/transmute-ref-dst-not-frombytes.rs | 18 + .../transmute-ref-dst-not-frombytes.stderr | 25 + tests/ui-stable/transmute-ref-dst-unsized.rs | 17 + tests/ui-stable/transmute-ref-dst-unsized.stderr | 89 + tests/ui-stable/transmute-ref-illegal-lifetime.rs | 15 + .../transmute-ref-illegal-lifetime.stderr | 12 + tests/ui-stable/transmute-ref-size-decrease.rs | 17 + tests/ui-stable/transmute-ref-size-decrease.stderr | 9 + tests/ui-stable/transmute-ref-size-increase.rs | 17 + tests/ui-stable/transmute-ref-size-increase.stderr | 9 + tests/ui-stable/transmute-ref-src-dst-generic.rs | 19 + .../ui-stable/transmute-ref-src-dst-generic.stderr | 19 + .../transmute-ref-src-dst-not-references.rs | 17 + .../transmute-ref-src-dst-not-references.stderr | 45 + tests/ui-stable/transmute-ref-src-dst-unsized.rs | 17 + .../ui-stable/transmute-ref-src-dst-unsized.stderr | 240 + tests/ui-stable/transmute-ref-src-generic.rs | 18 + tests/ui-stable/transmute-ref-src-generic.stderr | 19 + .../ui-stable/transmute-ref-src-not-a-reference.rs | 17 + .../transmute-ref-src-not-a-reference.stderr | 15 + tests/ui-stable/transmute-ref-src-not-asbytes.rs | 18 + .../ui-stable/transmute-ref-src-not-asbytes.stderr | 48 + tests/ui-stable/transmute-ref-src-unsized.rs | 16 + tests/ui-stable/transmute-ref-src-unsized.stderr | 164 + tests/ui-stable/transmute-size-decrease.rs | 19 + tests/ui-stable/transmute-size-decrease.stderr | 9 + tests/ui-stable/transmute-size-increase.rs | 19 + tests/ui-stable/transmute-size-increase.stderr | 9 + tests/ui-stable/transmute-src-not-asbytes.rs | 18 + tests/ui-stable/transmute-src-not-asbytes.stderr | 48 + 299 files changed, 15545 insertions(+), 1212 deletions(-) create mode 100644 LICENSE-APACHE create mode 100644 LICENSE-BSD create mode 100644 LICENSE-MIT create mode 100644 POLICIES.md create mode 100644 clippy.toml delete mode 100644 src/derive_util.rs create mode 100644 src/macro_util.rs create mode 100644 src/third_party/rust/LICENSE-APACHE create mode 100644 src/third_party/rust/LICENSE-MIT create mode 100644 src/third_party/rust/README.fuchsia create mode 100644 src/third_party/rust/layout.rs create mode 100644 testdata/include_value/data create mode 100644 tests/ui-msrv/include_value_not_from_bytes.rs create mode 100644 tests/ui-msrv/include_value_not_from_bytes.stderr create mode 100644 tests/ui-msrv/include_value_wrong_size.rs create mode 100644 tests/ui-msrv/include_value_wrong_size.stderr create mode 100644 tests/ui-msrv/max-align.rs create mode 100644 tests/ui-msrv/max-align.stderr create mode 100644 tests/ui-msrv/transmute-dst-not-frombytes.rs create mode 100644 tests/ui-msrv/transmute-dst-not-frombytes.stderr delete mode 100644 tests/ui-msrv/transmute-illegal.rs delete mode 100644 tests/ui-msrv/transmute-illegal.stderr create mode 100644 tests/ui-msrv/transmute-mut-alignment-increase.rs create mode 100644 tests/ui-msrv/transmute-mut-alignment-increase.stderr create mode 100644 tests/ui-msrv/transmute-mut-const.rs create mode 100644 tests/ui-msrv/transmute-mut-const.stderr create mode 100644 tests/ui-msrv/transmute-mut-dst-generic.rs create mode 100644 tests/ui-msrv/transmute-mut-dst-generic.stderr create mode 100644 tests/ui-msrv/transmute-mut-dst-not-a-reference.rs create mode 100644 tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr create mode 100644 tests/ui-msrv/transmute-mut-dst-not-asbytes.rs create mode 100644 tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr create mode 100644 tests/ui-msrv/transmute-mut-dst-not-frombytes.rs create mode 100644 tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr create mode 100644 tests/ui-msrv/transmute-mut-dst-unsized.rs create mode 100644 tests/ui-msrv/transmute-mut-dst-unsized.stderr create mode 100644 tests/ui-msrv/transmute-mut-illegal-lifetime.rs create mode 100644 tests/ui-msrv/transmute-mut-illegal-lifetime.stderr create mode 100644 tests/ui-msrv/transmute-mut-size-decrease.rs create mode 100644 tests/ui-msrv/transmute-mut-size-decrease.stderr create mode 100644 tests/ui-msrv/transmute-mut-size-increase.rs create mode 100644 tests/ui-msrv/transmute-mut-size-increase.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-dst-generic.rs create mode 100644 tests/ui-msrv/transmute-mut-src-dst-generic.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-dst-not-references.rs create mode 100644 tests/ui-msrv/transmute-mut-src-dst-not-references.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-dst-unsized.rs create mode 100644 tests/ui-msrv/transmute-mut-src-dst-unsized.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-generic.rs create mode 100644 tests/ui-msrv/transmute-mut-src-generic.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-immutable.rs create mode 100644 tests/ui-msrv/transmute-mut-src-immutable.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-not-a-reference.rs create mode 100644 tests/ui-msrv/transmute-mut-src-not-a-reference.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-not-asbytes.rs create mode 100644 tests/ui-msrv/transmute-mut-src-not-asbytes.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-not-frombytes.rs create mode 100644 tests/ui-msrv/transmute-mut-src-not-frombytes.stderr create mode 100644 tests/ui-msrv/transmute-mut-src-unsized.rs create mode 100644 tests/ui-msrv/transmute-mut-src-unsized.stderr create mode 100644 tests/ui-msrv/transmute-ptr-to-usize.rs create mode 100644 tests/ui-msrv/transmute-ptr-to-usize.stderr create mode 100644 tests/ui-msrv/transmute-ref-alignment-increase.rs create mode 100644 tests/ui-msrv/transmute-ref-alignment-increase.stderr create mode 100644 tests/ui-msrv/transmute-ref-dst-generic.rs create mode 100644 tests/ui-msrv/transmute-ref-dst-generic.stderr create mode 100644 tests/ui-msrv/transmute-ref-dst-mutable.rs create mode 100644 tests/ui-msrv/transmute-ref-dst-mutable.stderr create mode 100644 tests/ui-msrv/transmute-ref-dst-not-a-reference.rs create mode 100644 tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr create mode 100644 tests/ui-msrv/transmute-ref-dst-not-frombytes.rs create mode 100644 tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr create mode 100644 tests/ui-msrv/transmute-ref-dst-unsized.rs create mode 100644 tests/ui-msrv/transmute-ref-dst-unsized.stderr create mode 100644 tests/ui-msrv/transmute-ref-illegal-lifetime.rs create mode 100644 tests/ui-msrv/transmute-ref-illegal-lifetime.stderr create mode 100644 tests/ui-msrv/transmute-ref-size-decrease.rs create mode 100644 tests/ui-msrv/transmute-ref-size-decrease.stderr create mode 100644 tests/ui-msrv/transmute-ref-size-increase.rs create mode 100644 tests/ui-msrv/transmute-ref-size-increase.stderr create mode 100644 tests/ui-msrv/transmute-ref-src-dst-generic.rs create mode 100644 tests/ui-msrv/transmute-ref-src-dst-generic.stderr create mode 100644 tests/ui-msrv/transmute-ref-src-dst-not-references.rs create mode 100644 tests/ui-msrv/transmute-ref-src-dst-not-references.stderr create mode 100644 tests/ui-msrv/transmute-ref-src-dst-unsized.rs create mode 100644 tests/ui-msrv/transmute-ref-src-dst-unsized.stderr create mode 100644 tests/ui-msrv/transmute-ref-src-generic.rs create mode 100644 tests/ui-msrv/transmute-ref-src-generic.stderr create mode 100644 tests/ui-msrv/transmute-ref-src-not-a-reference.rs create mode 100644 tests/ui-msrv/transmute-ref-src-not-a-reference.stderr create mode 100644 tests/ui-msrv/transmute-ref-src-not-asbytes.rs create mode 100644 tests/ui-msrv/transmute-ref-src-not-asbytes.stderr create mode 100644 tests/ui-msrv/transmute-ref-src-unsized.rs create mode 100644 tests/ui-msrv/transmute-ref-src-unsized.stderr create mode 100644 tests/ui-msrv/transmute-size-decrease.rs create mode 100644 tests/ui-msrv/transmute-size-decrease.stderr create mode 100644 tests/ui-msrv/transmute-size-increase.rs create mode 100644 tests/ui-msrv/transmute-size-increase.stderr create mode 100644 tests/ui-msrv/transmute-src-not-asbytes.rs create mode 100644 tests/ui-msrv/transmute-src-not-asbytes.stderr create mode 100644 tests/ui-nightly/include_value_not_from_bytes.rs create mode 100644 tests/ui-nightly/include_value_not_from_bytes.stderr create mode 100644 tests/ui-nightly/include_value_wrong_size.rs create mode 100644 tests/ui-nightly/include_value_wrong_size.stderr create mode 100644 tests/ui-nightly/max-align.rs create mode 100644 tests/ui-nightly/max-align.stderr create mode 100644 tests/ui-nightly/transmute-dst-not-frombytes.rs create mode 100644 tests/ui-nightly/transmute-dst-not-frombytes.stderr delete mode 100644 tests/ui-nightly/transmute-illegal.rs delete mode 100644 tests/ui-nightly/transmute-illegal.stderr create mode 100644 tests/ui-nightly/transmute-mut-alignment-increase.rs create mode 100644 tests/ui-nightly/transmute-mut-alignment-increase.stderr create mode 100644 tests/ui-nightly/transmute-mut-const.rs create mode 100644 tests/ui-nightly/transmute-mut-const.stderr create mode 100644 tests/ui-nightly/transmute-mut-dst-generic.rs create mode 100644 tests/ui-nightly/transmute-mut-dst-generic.stderr create mode 100644 tests/ui-nightly/transmute-mut-dst-not-a-reference.rs create mode 100644 tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr create mode 100644 tests/ui-nightly/transmute-mut-dst-not-asbytes.rs create mode 100644 tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr create mode 100644 tests/ui-nightly/transmute-mut-dst-not-frombytes.rs create mode 100644 tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr create mode 100644 tests/ui-nightly/transmute-mut-dst-unsized.rs create mode 100644 tests/ui-nightly/transmute-mut-dst-unsized.stderr create mode 100644 tests/ui-nightly/transmute-mut-illegal-lifetime.rs create mode 100644 tests/ui-nightly/transmute-mut-illegal-lifetime.stderr create mode 100644 tests/ui-nightly/transmute-mut-size-decrease.rs create mode 100644 tests/ui-nightly/transmute-mut-size-decrease.stderr create mode 100644 tests/ui-nightly/transmute-mut-size-increase.rs create mode 100644 tests/ui-nightly/transmute-mut-size-increase.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-dst-generic.rs create mode 100644 tests/ui-nightly/transmute-mut-src-dst-generic.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-dst-not-references.rs create mode 100644 tests/ui-nightly/transmute-mut-src-dst-not-references.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-dst-unsized.rs create mode 100644 tests/ui-nightly/transmute-mut-src-dst-unsized.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-generic.rs create mode 100644 tests/ui-nightly/transmute-mut-src-generic.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-immutable.rs create mode 100644 tests/ui-nightly/transmute-mut-src-immutable.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-not-a-reference.rs create mode 100644 tests/ui-nightly/transmute-mut-src-not-a-reference.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-not-asbytes.rs create mode 100644 tests/ui-nightly/transmute-mut-src-not-asbytes.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-not-frombytes.rs create mode 100644 tests/ui-nightly/transmute-mut-src-not-frombytes.stderr create mode 100644 tests/ui-nightly/transmute-mut-src-unsized.rs create mode 100644 tests/ui-nightly/transmute-mut-src-unsized.stderr create mode 100644 tests/ui-nightly/transmute-ptr-to-usize.rs create mode 100644 tests/ui-nightly/transmute-ptr-to-usize.stderr create mode 100644 tests/ui-nightly/transmute-ref-alignment-increase.rs create mode 100644 tests/ui-nightly/transmute-ref-alignment-increase.stderr create mode 100644 tests/ui-nightly/transmute-ref-dst-generic.rs create mode 100644 tests/ui-nightly/transmute-ref-dst-generic.stderr create mode 100644 tests/ui-nightly/transmute-ref-dst-mutable.rs create mode 100644 tests/ui-nightly/transmute-ref-dst-mutable.stderr create mode 100644 tests/ui-nightly/transmute-ref-dst-not-a-reference.rs create mode 100644 tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr create mode 100644 tests/ui-nightly/transmute-ref-dst-not-frombytes.rs create mode 100644 tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr create mode 100644 tests/ui-nightly/transmute-ref-dst-unsized.rs create mode 100644 tests/ui-nightly/transmute-ref-dst-unsized.stderr create mode 100644 tests/ui-nightly/transmute-ref-illegal-lifetime.rs create mode 100644 tests/ui-nightly/transmute-ref-illegal-lifetime.stderr create mode 100644 tests/ui-nightly/transmute-ref-size-decrease.rs create mode 100644 tests/ui-nightly/transmute-ref-size-decrease.stderr create mode 100644 tests/ui-nightly/transmute-ref-size-increase.rs create mode 100644 tests/ui-nightly/transmute-ref-size-increase.stderr create mode 100644 tests/ui-nightly/transmute-ref-src-dst-generic.rs create mode 100644 tests/ui-nightly/transmute-ref-src-dst-generic.stderr create mode 100644 tests/ui-nightly/transmute-ref-src-dst-not-references.rs create mode 100644 tests/ui-nightly/transmute-ref-src-dst-not-references.stderr create mode 100644 tests/ui-nightly/transmute-ref-src-dst-unsized.rs create mode 100644 tests/ui-nightly/transmute-ref-src-dst-unsized.stderr create mode 100644 tests/ui-nightly/transmute-ref-src-generic.rs create mode 100644 tests/ui-nightly/transmute-ref-src-generic.stderr create mode 100644 tests/ui-nightly/transmute-ref-src-not-a-reference.rs create mode 100644 tests/ui-nightly/transmute-ref-src-not-a-reference.stderr create mode 100644 tests/ui-nightly/transmute-ref-src-not-asbytes.rs create mode 100644 tests/ui-nightly/transmute-ref-src-not-asbytes.stderr create mode 100644 tests/ui-nightly/transmute-ref-src-unsized.rs create mode 100644 tests/ui-nightly/transmute-ref-src-unsized.stderr create mode 100644 tests/ui-nightly/transmute-size-decrease.rs create mode 100644 tests/ui-nightly/transmute-size-decrease.stderr create mode 100644 tests/ui-nightly/transmute-size-increase.rs create mode 100644 tests/ui-nightly/transmute-size-increase.stderr create mode 100644 tests/ui-nightly/transmute-src-not-asbytes.rs create mode 100644 tests/ui-nightly/transmute-src-not-asbytes.stderr create mode 100644 tests/ui-stable/include_value_not_from_bytes.rs create mode 100644 tests/ui-stable/include_value_not_from_bytes.stderr create mode 100644 tests/ui-stable/include_value_wrong_size.rs create mode 100644 tests/ui-stable/include_value_wrong_size.stderr create mode 100644 tests/ui-stable/max-align.rs create mode 100644 tests/ui-stable/max-align.stderr create mode 100644 tests/ui-stable/transmute-dst-not-frombytes.rs create mode 100644 tests/ui-stable/transmute-dst-not-frombytes.stderr delete mode 100644 tests/ui-stable/transmute-illegal.rs delete mode 100644 tests/ui-stable/transmute-illegal.stderr create mode 100644 tests/ui-stable/transmute-mut-alignment-increase.rs create mode 100644 tests/ui-stable/transmute-mut-alignment-increase.stderr create mode 100644 tests/ui-stable/transmute-mut-const.rs create mode 100644 tests/ui-stable/transmute-mut-const.stderr create mode 100644 tests/ui-stable/transmute-mut-dst-generic.rs create mode 100644 tests/ui-stable/transmute-mut-dst-generic.stderr create mode 100644 tests/ui-stable/transmute-mut-dst-not-a-reference.rs create mode 100644 tests/ui-stable/transmute-mut-dst-not-a-reference.stderr create mode 100644 tests/ui-stable/transmute-mut-dst-not-asbytes.rs create mode 100644 tests/ui-stable/transmute-mut-dst-not-asbytes.stderr create mode 100644 tests/ui-stable/transmute-mut-dst-not-frombytes.rs create mode 100644 tests/ui-stable/transmute-mut-dst-not-frombytes.stderr create mode 100644 tests/ui-stable/transmute-mut-dst-unsized.rs create mode 100644 tests/ui-stable/transmute-mut-dst-unsized.stderr create mode 100644 tests/ui-stable/transmute-mut-illegal-lifetime.rs create mode 100644 tests/ui-stable/transmute-mut-illegal-lifetime.stderr create mode 100644 tests/ui-stable/transmute-mut-size-decrease.rs create mode 100644 tests/ui-stable/transmute-mut-size-decrease.stderr create mode 100644 tests/ui-stable/transmute-mut-size-increase.rs create mode 100644 tests/ui-stable/transmute-mut-size-increase.stderr create mode 100644 tests/ui-stable/transmute-mut-src-dst-generic.rs create mode 100644 tests/ui-stable/transmute-mut-src-dst-generic.stderr create mode 100644 tests/ui-stable/transmute-mut-src-dst-not-references.rs create mode 100644 tests/ui-stable/transmute-mut-src-dst-not-references.stderr create mode 100644 tests/ui-stable/transmute-mut-src-dst-unsized.rs create mode 100644 tests/ui-stable/transmute-mut-src-dst-unsized.stderr create mode 100644 tests/ui-stable/transmute-mut-src-generic.rs create mode 100644 tests/ui-stable/transmute-mut-src-generic.stderr create mode 100644 tests/ui-stable/transmute-mut-src-immutable.rs create mode 100644 tests/ui-stable/transmute-mut-src-immutable.stderr create mode 100644 tests/ui-stable/transmute-mut-src-not-a-reference.rs create mode 100644 tests/ui-stable/transmute-mut-src-not-a-reference.stderr create mode 100644 tests/ui-stable/transmute-mut-src-not-asbytes.rs create mode 100644 tests/ui-stable/transmute-mut-src-not-asbytes.stderr create mode 100644 tests/ui-stable/transmute-mut-src-not-frombytes.rs create mode 100644 tests/ui-stable/transmute-mut-src-not-frombytes.stderr create mode 100644 tests/ui-stable/transmute-mut-src-unsized.rs create mode 100644 tests/ui-stable/transmute-mut-src-unsized.stderr create mode 100644 tests/ui-stable/transmute-ptr-to-usize.rs create mode 100644 tests/ui-stable/transmute-ptr-to-usize.stderr create mode 100644 tests/ui-stable/transmute-ref-alignment-increase.rs create mode 100644 tests/ui-stable/transmute-ref-alignment-increase.stderr create mode 100644 tests/ui-stable/transmute-ref-dst-generic.rs create mode 100644 tests/ui-stable/transmute-ref-dst-generic.stderr create mode 100644 tests/ui-stable/transmute-ref-dst-mutable.rs create mode 100644 tests/ui-stable/transmute-ref-dst-mutable.stderr create mode 100644 tests/ui-stable/transmute-ref-dst-not-a-reference.rs create mode 100644 tests/ui-stable/transmute-ref-dst-not-a-reference.stderr create mode 100644 tests/ui-stable/transmute-ref-dst-not-frombytes.rs create mode 100644 tests/ui-stable/transmute-ref-dst-not-frombytes.stderr create mode 100644 tests/ui-stable/transmute-ref-dst-unsized.rs create mode 100644 tests/ui-stable/transmute-ref-dst-unsized.stderr create mode 100644 tests/ui-stable/transmute-ref-illegal-lifetime.rs create mode 100644 tests/ui-stable/transmute-ref-illegal-lifetime.stderr create mode 100644 tests/ui-stable/transmute-ref-size-decrease.rs create mode 100644 tests/ui-stable/transmute-ref-size-decrease.stderr create mode 100644 tests/ui-stable/transmute-ref-size-increase.rs create mode 100644 tests/ui-stable/transmute-ref-size-increase.stderr create mode 100644 tests/ui-stable/transmute-ref-src-dst-generic.rs create mode 100644 tests/ui-stable/transmute-ref-src-dst-generic.stderr create mode 100644 tests/ui-stable/transmute-ref-src-dst-not-references.rs create mode 100644 tests/ui-stable/transmute-ref-src-dst-not-references.stderr create mode 100644 tests/ui-stable/transmute-ref-src-dst-unsized.rs create mode 100644 tests/ui-stable/transmute-ref-src-dst-unsized.stderr create mode 100644 tests/ui-stable/transmute-ref-src-generic.rs create mode 100644 tests/ui-stable/transmute-ref-src-generic.stderr create mode 100644 tests/ui-stable/transmute-ref-src-not-a-reference.rs create mode 100644 tests/ui-stable/transmute-ref-src-not-a-reference.stderr create mode 100644 tests/ui-stable/transmute-ref-src-not-asbytes.rs create mode 100644 tests/ui-stable/transmute-ref-src-not-asbytes.stderr create mode 100644 tests/ui-stable/transmute-ref-src-unsized.rs create mode 100644 tests/ui-stable/transmute-ref-src-unsized.stderr create mode 100644 tests/ui-stable/transmute-size-decrease.rs create mode 100644 tests/ui-stable/transmute-size-decrease.stderr create mode 100644 tests/ui-stable/transmute-size-increase.rs create mode 100644 tests/ui-stable/transmute-size-increase.stderr create mode 100644 tests/ui-stable/transmute-src-not-asbytes.rs create mode 100644 tests/ui-stable/transmute-src-not-asbytes.stderr diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index e74a0f5..80e9fc6 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "c150d4f1b75fc21240574b6b7dbbcdc236d388b0" + "sha1": "5b76223e0eddea87e0f81429e218d12de94cd954" }, "path_in_vcs": "" } \ No newline at end of file diff --git a/Android.bp b/Android.bp index b632469..0190d67 100644 --- a/Android.bp +++ b/Android.bp @@ -23,9 +23,9 @@ rust_library { host_supported: true, crate_name: "zerocopy", cargo_env_compat: true, - cargo_pkg_version: "0.7.5", + cargo_pkg_version: "0.7.29", srcs: ["src/lib.rs"], - edition: "2021", + edition: "2018", features: [ "byteorder", "derive", @@ -46,9 +46,9 @@ rust_library_rlib { name: "libzerocopy_nostd", crate_name: "zerocopy", cargo_env_compat: true, - cargo_pkg_version: "0.7.5", + cargo_pkg_version: "0.7.29", srcs: ["src/lib.rs"], - edition: "2021", + edition: "2018", features: [ "alloc", "byteorder", @@ -77,9 +77,9 @@ rust_library_rlib { name: "libzerocopy_nostd_noalloc", crate_name: "zerocopy", cargo_env_compat: true, - cargo_pkg_version: "0.7.5", + cargo_pkg_version: "0.7.29", srcs: ["src/lib.rs"], - edition: "2021", + edition: "2018", features: [ "byteorder", "derive", diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d79e93..929e809 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,10 @@ - + # How to Contribute diff --git a/Cargo.toml b/Cargo.toml index 802ec0b..c4b1c9d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,23 +10,31 @@ # See Cargo.toml.orig for the original contents. [package] -edition = "2021" -rust-version = "1.61.0" +edition = "2018" +rust-version = "1.60.0" name = "zerocopy" -version = "0.7.5" +version = "0.7.29" authors = ["Joshua Liebow-Feeser "] exclude = [".*"] description = "Utilities for zero-copy parsing and serialization" readme = "README.md" -license = "BSD-2-Clause" +license = "BSD-2-Clause OR Apache-2.0 OR MIT" repository = "https://github.com/google/zerocopy" [package.metadata.ci] -pinned-nightly = "nightly-2023-05-25" -pinned-stable = "1.69.0" +pinned-nightly = "nightly-2023-12-04" +pinned-stable = "1.74.0" [package.metadata.docs.rs] all-features = true +rustdoc-args = [ + "--cfg", + "doc_cfg", + "--generate-link-to-definition", +] + +[package.metadata.playground] +features = ["__internal_use_only_features_that_work_on_stable"] [dependencies.byteorder] version = "1.3" @@ -34,12 +42,15 @@ optional = true default-features = false [dependencies.zerocopy-derive] -version = "=0.7.5" +version = "=0.7.29" optional = true [dev-dependencies.assert_matches] version = "1.5" +[dev-dependencies.elain] +version = "0.3.0" + [dev-dependencies.itertools] version = "0.11" @@ -54,10 +65,11 @@ version = "1.0" version = "1.1" [dev-dependencies.trybuild] -version = "=1.0.80" +version = "=1.0.85" +features = ["diff"] [dev-dependencies.zerocopy-derive] -version = "=0.7.5" +version = "=0.7.29" [features] __internal_use_only_features_that_work_on_stable = [ @@ -72,4 +84,4 @@ simd = [] simd-nightly = ["simd"] [target."cfg(any())".dependencies.zerocopy-derive] -version = "=0.7.5" +version = "=0.7.29" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index aa05c44..9355f08 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,10 @@ -# Copyright 2018 The Fuchsia Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. +# Copyright 2018 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. # Put both crates in a single workspace so that `trybuild` compiler errors have # paths that are stable regardless of the path to the repository root. This @@ -9,24 +13,28 @@ [workspace] [package] -edition = "2021" +edition = "2018" name = "zerocopy" -version = "0.7.5" +version = "0.7.29" authors = ["Joshua Liebow-Feeser "] description = "Utilities for zero-copy parsing and serialization" -license = "BSD-2-Clause" +license = "BSD-2-Clause OR Apache-2.0 OR MIT" repository = "https://github.com/google/zerocopy" -rust-version = "1.61.0" +rust-version = "1.60.0" exclude = [".*"] [package.metadata.docs.rs] all-features = true +rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] [package.metadata.ci] # The versions of the stable and nightly compiler toolchains to use in CI. -pinned-stable = "1.69.0" -pinned-nightly = "nightly-2023-05-25" +pinned-stable = "1.74.0" +pinned-nightly = "nightly-2023-12-04" + +[package.metadata.playground] +features = ["__internal_use_only_features_that_work_on_stable"] [features] default = ["byteorder"] @@ -41,7 +49,7 @@ simd-nightly = ["simd"] __internal_use_only_features_that_work_on_stable = ["alloc", "derive", "simd"] [dependencies] -zerocopy-derive = { version = "=0.7.5", path = "zerocopy-derive", optional = true } +zerocopy-derive = { version = "=0.7.29", path = "zerocopy-derive", optional = true } [dependencies.byteorder] version = "1.3" @@ -52,7 +60,7 @@ optional = true # zerocopy-derive remain equal, even if the 'derive' feature isn't used. # See: https://github.com/matklad/macro-dep-test [target.'cfg(any())'.dependencies] -zerocopy-derive = { version = "=0.7.5", path = "zerocopy-derive" } +zerocopy-derive = { version = "=0.7.29", path = "zerocopy-derive" } [dev-dependencies] assert_matches = "1.5" @@ -60,10 +68,13 @@ itertools = "0.11" rand = { version = "0.8.5", features = ["small_rng"] } rustversion = "1.0" static_assertions = "1.1" +testutil = { path = "testutil" } # Pinned to a specific version so that the version used for local development # and the version used in CI are guaranteed to be the same. Future versions # sometimes change the output format slightly, so a version mismatch can cause # CI test failures. -trybuild = "=1.0.80" +trybuild = { version = "=1.0.85", features = ["diff"] } # In tests, unlike in production, zerocopy-derive is not optional -zerocopy-derive = { version = "=0.7.5", path = "zerocopy-derive" } +zerocopy-derive = { version = "=0.7.29", path = "zerocopy-derive" } +# TODO(#381) Remove this dependency once we have our own layout gadgets. +elain = "0.3.0" diff --git a/INTERNAL.md b/INTERNAL.md index 4c9ed6a..4e7f440 100644 --- a/INTERNAL.md +++ b/INTERNAL.md @@ -1,3 +1,11 @@ + + # Internal details This file documents various internal details of zerocopy and its infrastructure @@ -18,8 +26,11 @@ have a working Miri, so we need to pin to one that does (see https://rust-lang.github.io/rustup-components-history/). Updating the versions pinned in CI may cause the UI tests to break. In order to -fix UI tests after a version update, set the environment variable -`TRYBUILD=overwrite` while running `cargo test`. +fix UI tests after a version update, run: + +``` +$ TRYBUILD=overwrite ./cargo.sh +all test +``` ## Crate versions @@ -30,4 +41,4 @@ when published on crates.io, both crates effectively constitute a single atomic version. So long as the code in zerocopy is compatible with the code in zerocopy-derive in the same Git commit, then publishing them both is fine. This frees us from the normal task of reasoning about compatibility with a range of -semver-compatible versions of different crates. \ No newline at end of file +semver-compatible versions of different crates. diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..2dc22c1 --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Fuchsia Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/LICENSE-BSD b/LICENSE-BSD new file mode 100644 index 0000000..7ed244f --- /dev/null +++ b/LICENSE-BSD @@ -0,0 +1,24 @@ +Copyright 2019 The Fuchsia Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..26e1521 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,26 @@ +Copyright 2023 The Fuchsia Authors + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + diff --git a/METADATA b/METADATA index 2b18dc0..762e3de 100644 --- a/METADATA +++ b/METADATA @@ -5,19 +5,20 @@ name: "zerocopy" description: "Utilities for zero-copy parsing and serialization" third_party { - url { - type: HOMEPAGE - value: "https://crates.io/crates/zerocopy" - } - url { - type: ARCHIVE - value: "https://static.crates.io/crates/zerocopy/zerocopy-0.7.5.crate" - } - version: "0.7.5" license_type: NOTICE last_upgrade_date { year: 2023 - month: 9 - day: 28 + month: 12 + day: 5 + } + identifier { + type: "crates.io" + value: "https://crates.io/crates/zerocopy" + version: "" + } + identifier { + type: "Archive" + value: "https://static.crates.io/crates/zerocopy/zerocopy-0.7.29.crate" + version: "0.7.29" } } diff --git a/POLICIES.md b/POLICIES.md new file mode 100644 index 0000000..a2f175c --- /dev/null +++ b/POLICIES.md @@ -0,0 +1,95 @@ + + +# Zerocopy's Policies + +## Soundness + +Zerocopy is expressly designed for use in security-critical contexts. It is used +in hardware security firmware, cryptographic implementations, hypervisors, and +more. We understand that software in these contexts has a very high bar for +correctness, and we take our responsibility to meet that bar very seriously. + +This section describes policies which are designed to ensure the correctness and +soundness of our code and prevent regressions. + +### Forwards-compatibility + +Rust does not currently have a formal memory model. As such, while Rust provides +guarantees about the semantics of some operations, the semantics of many +operations is up in the air and subject to change. + +Zerocopy strives to ensure that our code - and code emitted by our custom +derives - is sound under any version of Rust as early as our MSRV, and will +continue to be sound under any future version of Rust. The policies in this +section are designed to help ensure that we live up to this goal. + +### Safety comments + +Each non-test `unsafe` block must be annotated with a "safety comment" which +provides a rationale for its soundness. In order to ensure that our soundness is +forwards-compatible, safety comments must satisfy the following criteria: +- Safety comments must constitute a (possibly informal) proof that all of Rust's + soundness rules are upheld. +- Safety comments must only rely for their correctness on statements which + appear in the stable versions of the [Rust Reference] or standard library + documentation (ie, the docs for [core], [alloc], and [std]); arguments which + rely on text from the beta or nightly versions of these documents are not + considered complete. +- All statements from the Reference or standard library documentation which are + relied upon for soundness must be quoted in the safety comment. This ensures + that there is no ambiguity as to what aspect of the text is being cited. This + is especially important in cases where the text of these documents changes in + the future. Such changes are of course required to be backwards-compatible, + but may change the manner in which a particular guarantee is explained. + +We use the [`clippy::undocumented_unsafe_blocks`] lint to ensure that `unsafe` +blocks cannot be added without a safety comment. Note that there are a few +outstanding uncommented `unsafe` blocks which are tracked in [#429]. Our goal is +to reach 100% safety comment coverage and not regress once we've reached it. + +[Rust Reference]: https://doc.rust-lang.org/reference/ +[core]: https://doc.rust-lang.org/stable/core/ +[alloc]: https://doc.rust-lang.org/stable/alloc/ +[std]: https://doc.rust-lang.org/stable/std/ +[`clippy::undocumented_unsafe_blocks`]: https://rust-lang.github.io/rust-clippy/master/index.html#/undocumented_unsafe_blocks +[#429]: https://github.com/google/zerocopy/issues/429 + +#### Exceptions to our safety comment policy + +In rare circumstances, the soundness of an `unsafe` block may depend upon +semantics which are widely agreed upon but not formally guaranteed. In order to +avoid slowing down zerocopy's development to an unreasonable degree, a safety +comment may violate our safety comment policy so long as all of the following +hold: +- The safety comment's correctness may rely on semantics which are not + guaranteed in official Rust documentation *so long as* a member of the Rust + team has articulated in an official communication (e.g. a comment on a Rust + GitHub repo) that Rust intends to guarantee particular semantics. +- There exists an active effort to formalize the guarantee in Rust's official + documentation. + +### Target architecture support + +Zerocopy bases its soundness on guarantees made about the semantics of Rust +which appear in the Rust Reference or standard library documentation; zerocopy +is sound so long as these guarantees hold. There are known cases in which these +guarantees do not hold on certain target architectures (see +[rust-lang/unsafe-code-guidelines#461]); on such target architectures, zerocopy +may be unsound. We consider it outside of zerocopy's scope to reason about these +cases. Zerocopy makes no effort maintain soundness in cases where Rust's +documented guarantees do not hold. + +[rust-lang/unsafe-code-guidelines#461]: https://github.com/rust-lang/unsafe-code-guidelines/issues/461 + +## MSRV + +Our minimum supported Rust version (MSRV) is encoded in our `Cargo.toml` file. +We consider an increase in MSRV to be a semver-breaking change, and will only +increase our MSRV during semver-breaking version changes (e.g., 0.1 -> 0.2, 1.0 +-> 2.0, etc). diff --git a/README.md b/README.md index d9d3d90..3d423bd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ - src/lib.rs:1524:34 +/// | +/// 5 | const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]); +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/// | +/// = note: source type: `AlignOf<[u8; 2]>` (8 bits) +/// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) +/// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) +/// ``` +/// +/// This is saying that `max(align_of::(), align_of::()) != +/// align_of::()`, which is equivalent to `align_of::() < +/// align_of::()`. +#[macro_export] +macro_rules! transmute_ref { + ($e:expr) => {{ + // NOTE: This must be a macro (rather than a function with trait bounds) + // because there's no way, in a generic context, to enforce that two + // types have the same size or alignment. + + // Ensure that the source type is a reference or a mutable reference + // (note that mutable references are implicitly reborrowed here). + let e: &_ = $e; + + #[allow(unused, clippy::diverging_sub_expression)] + if false { + // This branch, though never taken, ensures that the type of `e` is + // `&T` where `T: 't + Sized + AsBytes`, that the type of this macro + // expression is `&U` where `U: 'u + Sized + FromBytes`, and that + // `'t` outlives `'u`. + + struct AssertIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T); + let _ = AssertIsAsBytes(e); + + struct AssertIsFromBytes<'a, U: ::core::marker::Sized + $crate::FromBytes>(&'a U); + #[allow(unused, unreachable_code)] + let u = AssertIsFromBytes(loop {}); + u.0 + } else if false { + // This branch, though never taken, ensures that `size_of::() == + // size_of::()` and that that `align_of::() >= + // align_of::()`. + + // `t` is inferred to have type `T` because it's assigned to `e` (of + // type `&T`) as `&t`. + let mut t = unreachable!(); + e = &t; + + // `u` is inferred to have type `U` because it's used as `&u` as the + // value returned from this branch. + let u; + + $crate::assert_size_eq!(t, u); + $crate::assert_align_gt_eq!(t, u); + + &u + } else { + // SAFETY: For source type `Src` and destination type `Dst`: + // - We know that `Src: AsBytes` and `Dst: FromBytes` thanks to the + // uses of `AssertIsAsBytes` and `AssertIsFromBytes` above. + // - We know that `size_of::() == size_of::()` thanks to + // the use of `assert_size_eq!` above. + // - We know that `align_of::() >= align_of::()` thanks to + // the use of `assert_align_gt_eq!` above. + unsafe { $crate::macro_util::transmute_ref(e) } + } + }} +} + +/// Safely transmutes a mutable reference of one type to an mutable reference of +/// another type of the same size. +/// +/// The expression `$e` must have a concrete type, `&mut T`, where `T: Sized + +/// AsBytes`. The `transmute_mut!` expression must also have a concrete type, +/// `&mut U` (`U` is inferred from the calling context), where `U: Sized + +/// FromBytes`. It must be the case that `align_of::() >= align_of::()`. +/// +/// The lifetime of the input type, `&mut T`, must be the same as or outlive the +/// lifetime of the output type, `&mut U`. +/// +/// # Examples +/// +/// ``` +/// # use zerocopy::transmute_mut; +/// let mut one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7]; +/// +/// let two_dimensional: &mut [[u8; 4]; 2] = transmute_mut!(&mut one_dimensional); +/// +/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]); +/// +/// two_dimensional.reverse(); +/// +/// assert_eq!(one_dimensional, [4, 5, 6, 7, 0, 1, 2, 3]); +/// ``` +/// +/// # Alignment increase error message +/// +/// Because of limitations on macros, the error message generated when +/// `transmute_mut!` is used to transmute from a type of lower alignment to a +/// type of higher alignment is somewhat confusing. For example, the following +/// code: +/// +/// ```compile_fail +/// const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]); +/// ``` +/// +/// ...generates the following error: +/// +/// ```text +/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types +/// --> src/lib.rs:1524:34 +/// | +/// 5 | const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]); +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/// | +/// = note: source type: `AlignOf<[u8; 2]>` (8 bits) +/// = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits) +/// = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) +/// ``` +/// +/// This is saying that `max(align_of::(), align_of::()) != +/// align_of::()`, which is equivalent to `align_of::() < +/// align_of::()`. +#[macro_export] +macro_rules! transmute_mut { + ($e:expr) => {{ + // NOTE: This must be a macro (rather than a function with trait bounds) + // because there's no way, in a generic context, to enforce that two + // types have the same size or alignment. + + // Ensure that the source type is a mutable reference. + let e: &mut _ = $e; + + #[allow(unused, clippy::diverging_sub_expression)] + if false { + // This branch, though never taken, ensures that the type of `e` is + // `&mut T` where `T: 't + Sized + FromBytes + AsBytes`, that the + // type of this macro expression is `&mut U` where `U: 'u + Sized + + // FromBytes + AsBytes`. + + // We use immutable references here rather than mutable so that, if + // this macro is used in a const context (in which, as of this + // writing, mutable references are banned), the error message + // appears to originate in the user's code rather than in the + // internals of this macro. + struct AssertSrcIsFromBytes<'a, T: ::core::marker::Sized + $crate::FromBytes>(&'a T); + struct AssertSrcIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T); + struct AssertDstIsFromBytes<'a, T: ::core::marker::Sized + $crate::FromBytes>(&'a T); + struct AssertDstIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T); + + if true { + let _ = AssertSrcIsFromBytes(&*e); + } else { + let _ = AssertSrcIsAsBytes(&*e); + } + + if true { + #[allow(unused, unreachable_code)] + let u = AssertDstIsFromBytes(loop {}); + &mut *u.0 + } else { + #[allow(unused, unreachable_code)] + let u = AssertDstIsAsBytes(loop {}); + &mut *u.0 + } + } else if false { + // This branch, though never taken, ensures that `size_of::() == + // size_of::()` and that that `align_of::() >= + // align_of::()`. + + // `t` is inferred to have type `T` because it's assigned to `e` (of + // type `&mut T`) as `&mut t`. + let mut t = unreachable!(); + e = &mut t; + + // `u` is inferred to have type `U` because it's used as `&mut u` as + // the value returned from this branch. + let u; + + $crate::assert_size_eq!(t, u); + $crate::assert_align_gt_eq!(t, u); + + &mut u + } else { + // SAFETY: For source type `Src` and destination type `Dst`: + // - We know that `Src: FromBytes + AsBytes` and `Dst: FromBytes + + // AsBytes` thanks to the uses of `AssertSrcIsFromBytes`, + // `AssertSrcIsAsBytes`, `AssertDstIsFromBytes`, and + // `AssertDstIsAsBytes` above. + // - We know that `size_of::() == size_of::()` thanks to + // the use of `assert_size_eq!` above. + // - We know that `align_of::() >= align_of::()` thanks to + // the use of `assert_align_gt_eq!` above. + unsafe { $crate::macro_util::transmute_mut(e) } } }} } +/// Includes a file and safely transmutes it to a value of an arbitrary type. +/// +/// The file will be included as a byte array, `[u8; N]`, which will be +/// transmuted to another type, `T`. `T` is inferred from the calling context, +/// and must implement [`FromBytes`]. +/// +/// The file is located relative to the current file (similarly to how modules +/// are found). The provided path is interpreted in a platform-specific way at +/// compile time. So, for instance, an invocation with a Windows path containing +/// backslashes `\` would not compile correctly on Unix. +/// +/// `include_value!` is ignorant of byte order. For byte order-aware types, see +/// the [`byteorder`] module. +/// +/// # Examples +/// +/// Assume there are two files in the same directory with the following +/// contents: +/// +/// File `data` (no trailing newline): +/// +/// ```text +/// abcd +/// ``` +/// +/// File `main.rs`: +/// +/// ```rust +/// use zerocopy::include_value; +/// # macro_rules! include_value { +/// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) }; +/// # } +/// +/// fn main() { +/// let as_u32: u32 = include_value!("data"); +/// assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); +/// let as_i32: i32 = include_value!("data"); +/// assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); +/// } +/// ``` +#[doc(alias("include_bytes", "include_data", "include_type"))] +#[macro_export] +macro_rules! include_value { + ($file:expr $(,)?) => { + $crate::transmute!(*::core::include_bytes!($file)) + }; +} + /// A typed reference derived from a byte slice. /// /// A `Ref` is a reference to a `T` which is stored in a byte slice, `B`. @@ -1775,10 +4250,8 @@ where Some(len) => len, None => return None, }; - if bytes.len() < expected_len { - return None; - } - let (bytes, suffix) = bytes.split_at(expected_len); + let split_at = bytes.len().checked_sub(expected_len)?; + let (bytes, suffix) = bytes.split_at(split_at); Self::new_slice(suffix).map(move |l| (bytes, l)) } } @@ -2254,7 +4727,7 @@ where /// and no mutable references to the same memory may be constructed during /// `'a`. unsafe fn deref_helper<'a>(&self) -> &'a T { - // TODO(#61): Add a "SAFETY" comment and remove this `allow`. + // TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe { &*self.0.as_ptr().cast::() @@ -2279,7 +4752,7 @@ where /// and no other references - mutable or immutable - to the same memory may /// be constructed during `'a`. unsafe fn deref_mut_helper<'a>(&mut self) -> &'a mut T { - // TODO(#61): Add a "SAFETY" comment and remove this `allow`. + // TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe { &mut *self.0.as_mut_ptr().cast::() @@ -2308,7 +4781,7 @@ where debug_assert_eq!(len % elem_size, 0); len / elem_size }; - // TODO(#61): Add a "SAFETY" comment and remove this `allow`. + // TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe { slice::from_raw_parts(self.0.as_ptr().cast::(), elems) @@ -2338,7 +4811,7 @@ where debug_assert_eq!(len % elem_size, 0); len / elem_size }; - // TODO(#61): Add a "SAFETY" comment and remove this `allow`. + // TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe { slice::from_raw_parts_mut(self.0.as_mut_ptr().cast::(), elems) @@ -2612,7 +5085,6 @@ where mod sealed { pub trait ByteSliceSealed {} - pub trait KnownLayoutSealed {} } // ByteSlice and ByteSliceMut abstract over [u8] references (&[u8], &mut [u8], @@ -2680,7 +5152,7 @@ pub unsafe trait ByteSliceMut: ByteSlice + DerefMut { } impl<'a> sealed::ByteSliceSealed for &'a [u8] {} -// TODO(#61): Add a "SAFETY" comment and remove this `allow`. +// TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<'a> ByteSlice for &'a [u8] { #[inline] @@ -2690,7 +5162,7 @@ unsafe impl<'a> ByteSlice for &'a [u8] { } impl<'a> sealed::ByteSliceSealed for &'a mut [u8] {} -// TODO(#61): Add a "SAFETY" comment and remove this `allow`. +// TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<'a> ByteSlice for &'a mut [u8] { #[inline] @@ -2700,7 +5172,7 @@ unsafe impl<'a> ByteSlice for &'a mut [u8] { } impl<'a> sealed::ByteSliceSealed for cell::Ref<'a, [u8]> {} -// TODO(#61): Add a "SAFETY" comment and remove this `allow`. +// TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<'a> ByteSlice for cell::Ref<'a, [u8]> { #[inline] @@ -2710,7 +5182,7 @@ unsafe impl<'a> ByteSlice for cell::Ref<'a, [u8]> { } impl<'a> sealed::ByteSliceSealed for RefMut<'a, [u8]> {} -// TODO(#61): Add a "SAFETY" comment and remove this `allow`. +// TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<'a> ByteSlice for RefMut<'a, [u8]> { #[inline] @@ -2719,15 +5191,16 @@ unsafe impl<'a> ByteSlice for RefMut<'a, [u8]> { } } -// TODO(#61): Add a "SAFETY" comment and remove this `allow`. +// TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<'a> ByteSliceMut for &'a mut [u8] {} -// TODO(#61): Add a "SAFETY" comment and remove this `allow`. +// TODO(#429): Add a "SAFETY" comment and remove this `allow`. #[allow(clippy::undocumented_unsafe_blocks)] unsafe impl<'a> ByteSliceMut for RefMut<'a, [u8]> {} #[cfg(feature = "alloc")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] mod alloc_support { use alloc::vec::Vec; @@ -2775,6 +5248,8 @@ mod alloc_support { #[cfg(test)] mod tests { + use core::convert::TryFrom as _; + use super::*; #[test] @@ -2950,7 +5425,7 @@ pub use alloc_support::*; mod tests { #![allow(clippy::unreadable_literal)] - use core::ops::Deref; + use core::{cell::UnsafeCell, convert::TryInto as _, ops::Deref}; use static_assertions::assert_impl_all; @@ -2978,23 +5453,212 @@ mod tests { } } + /// Tests of when a sized `DstLayout` is extended with a sized field. + #[allow(clippy::decimal_literal_representation)] + #[test] + fn test_dst_layout_extend_sized_with_sized() { + // This macro constructs a layout corresponding to a `u8` and extends it + // with a zero-sized trailing field of given alignment `n`. The macro + // tests that the resulting layout has both size and alignment `min(n, + // P)` for all valid values of `repr(packed(P))`. + macro_rules! test_align_is_size { + ($n:expr) => { + let base = DstLayout::for_type::(); + let trailing_field = DstLayout::for_type::>(); + + let packs = + core::iter::once(None).chain((0..29).map(|p| NonZeroUsize::new(2usize.pow(p)))); + + for pack in packs { + let composite = base.extend(trailing_field, pack); + let max_align = pack.unwrap_or(DstLayout::CURRENT_MAX_ALIGN); + let align = $n.min(max_align.get()); + assert_eq!( + composite, + DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::Sized { _size: align } + } + ) + } + }; + } + + test_align_is_size!(1); + test_align_is_size!(2); + test_align_is_size!(4); + test_align_is_size!(8); + test_align_is_size!(16); + test_align_is_size!(32); + test_align_is_size!(64); + test_align_is_size!(128); + test_align_is_size!(256); + test_align_is_size!(512); + test_align_is_size!(1024); + test_align_is_size!(2048); + test_align_is_size!(4096); + test_align_is_size!(8192); + test_align_is_size!(16384); + test_align_is_size!(32768); + test_align_is_size!(65536); + test_align_is_size!(131072); + test_align_is_size!(262144); + test_align_is_size!(524288); + test_align_is_size!(1048576); + test_align_is_size!(2097152); + test_align_is_size!(4194304); + test_align_is_size!(8388608); + test_align_is_size!(16777216); + test_align_is_size!(33554432); + test_align_is_size!(67108864); + test_align_is_size!(33554432); + test_align_is_size!(134217728); + test_align_is_size!(268435456); + } + + /// Tests of when a sized `DstLayout` is extended with a DST field. + #[test] + fn test_dst_layout_extend_sized_with_dst() { + // Test that for all combinations of real-world alignments and + // `repr_packed` values, that the extension of a sized `DstLayout`` with + // a DST field correctly computes the trailing offset in the composite + // layout. + + let aligns = (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()); + let packs = core::iter::once(None).chain(aligns.clone().map(Some)); + + for align in aligns { + for pack in packs.clone() { + let base = DstLayout::for_type::(); + let elem_size = 42; + let trailing_field_offset = 11; + + let trailing_field = DstLayout { + align, + size_info: SizeInfo::SliceDst(TrailingSliceLayout { + _elem_size: elem_size, + _offset: 11, + }), + }; + + let composite = base.extend(trailing_field, pack); + + let max_align = pack.unwrap_or(DstLayout::CURRENT_MAX_ALIGN).get(); + + let align = align.get().min(max_align); + + assert_eq!( + composite, + DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::SliceDst(TrailingSliceLayout { + _elem_size: elem_size, + _offset: align + trailing_field_offset, + }), + } + ) + } + } + } + + /// Tests that calling `pad_to_align` on a sized `DstLayout` adds the + /// expected amount of trailing padding. + #[test] + fn test_dst_layout_pad_to_align_with_sized() { + // For all valid alignments `align`, construct a one-byte layout aligned + // to `align`, call `pad_to_align`, and assert that the size of the + // resulting layout is equal to `align`. + for align in (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()) { + let layout = DstLayout { align, size_info: SizeInfo::Sized { _size: 1 } }; + + assert_eq!( + layout.pad_to_align(), + DstLayout { align, size_info: SizeInfo::Sized { _size: align.get() } } + ); + } + + // Test explicitly-provided combinations of unpadded and padded + // counterparts. + + macro_rules! test { + (unpadded { size: $unpadded_size:expr, align: $unpadded_align:expr } + => padded { size: $padded_size:expr, align: $padded_align:expr }) => { + let unpadded = DstLayout { + align: NonZeroUsize::new($unpadded_align).unwrap(), + size_info: SizeInfo::Sized { _size: $unpadded_size }, + }; + let padded = unpadded.pad_to_align(); + + assert_eq!( + padded, + DstLayout { + align: NonZeroUsize::new($padded_align).unwrap(), + size_info: SizeInfo::Sized { _size: $padded_size }, + } + ); + }; + } + + test!(unpadded { size: 0, align: 4 } => padded { size: 0, align: 4 }); + test!(unpadded { size: 1, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 2, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 3, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 4, align: 4 } => padded { size: 4, align: 4 }); + test!(unpadded { size: 5, align: 4 } => padded { size: 8, align: 4 }); + test!(unpadded { size: 6, align: 4 } => padded { size: 8, align: 4 }); + test!(unpadded { size: 7, align: 4 } => padded { size: 8, align: 4 }); + test!(unpadded { size: 8, align: 4 } => padded { size: 8, align: 4 }); + + let current_max_align = DstLayout::CURRENT_MAX_ALIGN.get(); + + test!(unpadded { size: 1, align: current_max_align } + => padded { size: current_max_align, align: current_max_align }); + + test!(unpadded { size: current_max_align + 1, align: current_max_align } + => padded { size: current_max_align * 2, align: current_max_align }); + } + + /// Tests that calling `pad_to_align` on a DST `DstLayout` is a no-op. + #[test] + fn test_dst_layout_pad_to_align_with_dst() { + for align in (0..29).map(|p| NonZeroUsize::new(2usize.pow(p)).unwrap()) { + for offset in 0..10 { + for elem_size in 0..10 { + let layout = DstLayout { + align, + size_info: SizeInfo::SliceDst(TrailingSliceLayout { + _offset: offset, + _elem_size: elem_size, + }), + }; + assert_eq!(layout.pad_to_align(), layout); + } + } + } + } + // This test takes a long time when running under Miri, so we skip it in // that case. This is acceptable because this is a logic test that doesn't // attempt to expose UB. #[test] #[cfg_attr(miri, ignore)] - fn test_validate_cast_and_convert_metadata() { - fn layout( - base_size: usize, - align: usize, - _trailing_slice_elem_size: Option, - ) -> DstLayout { - DstLayout { - _base_layout: Layout::from_size_align(base_size, align).unwrap(), - _trailing_slice_elem_size, + fn testvalidate_cast_and_convert_metadata() { + impl From for SizeInfo { + fn from(_size: usize) -> SizeInfo { + SizeInfo::Sized { _size } + } + } + + impl From<(usize, usize)> for SizeInfo { + fn from((_offset, _elem_size): (usize, usize)) -> SizeInfo { + SizeInfo::SliceDst(TrailingSliceLayout { _offset, _elem_size }) } } + fn layout>(s: S, align: usize) -> DstLayout { + DstLayout { size_info: s.into(), align: NonZeroUsize::new(align).unwrap() } + } + /// This macro accepts arguments in the form of: /// /// layout(_, _, _).validate(_, _, _), Ok(Some((_, _))) @@ -3032,30 +5696,64 @@ mod tests { /// `a..b`). In this case, wrap the expression in parentheses, and it /// will become valid `tt`. macro_rules! test { - ( - layout($base_size:tt, $align:tt, $trailing_size:tt) + ($(:$sizes:expr =>)? + layout($size:tt, $align:tt) .validate($addr:tt, $bytes_len:tt, $cast_type:tt), $expect:pat $(,)? ) => { itertools::iproduct!( - test!(@generate_usize $base_size), + test!(@generate_size $size), test!(@generate_align $align), - test!(@generate_opt_usize $trailing_size), test!(@generate_usize $addr), test!(@generate_usize $bytes_len), test!(@generate_cast_type $cast_type) - ).for_each(|(base_size, align, trailing_size, addr, bytes_len, cast_type)| { + ).for_each(|(size_info, align, addr, bytes_len, cast_type)| { + // Temporarily disable the panic hook installed by the test + // harness. If we don't do this, all panic messages will be + // kept in an internal log. On its own, this isn't a + // problem, but if a non-caught panic ever happens (ie, in + // code later in this test not in this macro), all of the + // previously-buffered messages will be dumped, hiding the + // real culprit. + let previous_hook = std::panic::take_hook(); + // I don't understand why, but this seems to be required in + // addition to the previous line. + std::panic::set_hook(Box::new(|_| {})); let actual = std::panic::catch_unwind(|| { - layout(base_size, align, trailing_size)._validate_cast_and_convert_metadata(addr, bytes_len, cast_type) + layout(size_info, align).validate_cast_and_convert_metadata(addr, bytes_len, cast_type) }).map_err(|d| { *d.downcast::<&'static str>().expect("expected string panic message").as_ref() }); + std::panic::set_hook(previous_hook); + assert_matches::assert_matches!( actual, $expect, - "layout({base_size}, {align}, {trailing_size:?}).validate_cast_and_convert_metadata({addr}, {bytes_len}, {cast_type:?})", + "layout({size_info:?}, {align}).validate_cast_and_convert_metadata({addr}, {bytes_len}, {cast_type:?})", ); }); }; (@generate_usize _) => { 0..8 }; + // Generate sizes for both Sized and !Sized types. + (@generate_size _) => { + test!(@generate_size (_)).chain(test!(@generate_size (_, _))) + }; + // Generate sizes for both Sized and !Sized types by chaining + // specified iterators for each. + (@generate_size ($sized_sizes:tt | $unsized_sizes:tt)) => { + test!(@generate_size ($sized_sizes)).chain(test!(@generate_size $unsized_sizes)) + }; + // Generate sizes for Sized types. + (@generate_size (_)) => { test!(@generate_size (0..8)) }; + (@generate_size ($sizes:expr)) => { $sizes.into_iter().map(Into::::into) }; + // Generate sizes for !Sized types. + (@generate_size ($min_sizes:tt, $elem_sizes:tt)) => { + itertools::iproduct!( + test!(@generate_min_size $min_sizes), + test!(@generate_elem_size $elem_sizes) + ).map(Into::::into) + }; + (@generate_fixed_size _) => { (0..8).into_iter().map(Into::::into) }; + (@generate_min_size _) => { 0..8 }; + (@generate_elem_size _) => { 1..8 }; (@generate_align _) => { [1, 2, 4, 8, 16] }; (@generate_opt_usize _) => { [None].into_iter().chain((0..8).map(Some).into_iter()) }; (@generate_cast_type _) => { [_CastType::_Prefix, _CastType::_Suffix] }; @@ -3068,146 +5766,911 @@ mod tests { (@$_:ident $vals:expr) => { $vals }; } - const EVENS: [usize; 5] = [0, 2, 4, 6, 8]; - const NZ_EVENS: [usize; 5] = [2, 4, 6, 8, 10]; - const ODDS: [usize; 5] = [1, 3, 5, 7, 9]; + const EVENS: [usize; 8] = [0, 2, 4, 6, 8, 10, 12, 14]; + const ODDS: [usize; 8] = [1, 3, 5, 7, 9, 11, 13, 15]; + + // base_size is too big for the memory region. + test!(layout(((1..8) | ((1..8), (1..8))), _).validate(_, [0], _), Ok(None)); + test!(layout(((2..8) | ((2..8), (2..8))), _).validate(_, [1], _), Ok(None)); + + // addr is unaligned for prefix cast + test!(layout(_, [2]).validate(ODDS, _, _Prefix), Ok(None)); + test!(layout(_, [2]).validate(ODDS, _, _Prefix), Ok(None)); + + // addr is aligned, but end of buffer is unaligned for suffix cast + test!(layout(_, [2]).validate(EVENS, ODDS, _Suffix), Ok(None)); + test!(layout(_, [2]).validate(EVENS, ODDS, _Suffix), Ok(None)); + + // Unfortunately, these constants cannot easily be used in the + // implementation of `validate_cast_and_convert_metadata`, since + // `panic!` consumes a string literal, not an expression. + // + // It's important that these messages be in a separate module. If they + // were at the function's top level, we'd pass them to `test!` as, e.g., + // `Err(TRAILING)`, which would run into a subtle Rust footgun - the + // `TRAILING` identifier would be treated as a pattern to match rather + // than a value to check for equality. + mod msgs { + pub(super) const TRAILING: &str = + "attempted to cast to slice type with zero-sized element"; + pub(super) const OVERFLOW: &str = "`addr` + `bytes_len` > usize::MAX"; + } + + // casts with ZST trailing element types are unsupported + test!(layout((_, [0]), _).validate(_, _, _), Err(msgs::TRAILING),); + + // addr + bytes_len must not overflow usize + test!(layout(_, _).validate([usize::MAX], (1..100), _), Err(msgs::OVERFLOW)); + test!(layout(_, _).validate((1..100), [usize::MAX], _), Err(msgs::OVERFLOW)); + test!( + layout(_, _).validate( + [usize::MAX / 2 + 1, usize::MAX], + [usize::MAX / 2 + 1, usize::MAX], + _ + ), + Err(msgs::OVERFLOW) + ); + + // Validates that `validate_cast_and_convert_metadata` satisfies its own + // documented safety postconditions, and also a few other properties + // that aren't documented but we want to guarantee anyway. + fn validate_behavior( + (layout, addr, bytes_len, cast_type): (DstLayout, usize, usize, _CastType), + ) { + if let Some((elems, split_at)) = + layout.validate_cast_and_convert_metadata(addr, bytes_len, cast_type) + { + let (size_info, align) = (layout.size_info, layout.align); + let debug_str = format!( + "layout({size_info:?}, {align}).validate_cast_and_convert_metadata({addr}, {bytes_len}, {cast_type:?}) => ({elems}, {split_at})", + ); + + // If this is a sized type (no trailing slice), then `elems` is + // meaningless, but in practice we set it to 0. Callers are not + // allowed to rely on this, but a lot of math is nicer if + // they're able to, and some callers might accidentally do that. + let sized = matches!(layout.size_info, SizeInfo::Sized { .. }); + assert!(!(sized && elems != 0), "{}", debug_str); + + let resulting_size = match layout.size_info { + SizeInfo::Sized { _size } => _size, + SizeInfo::SliceDst(TrailingSliceLayout { + _offset: offset, + _elem_size: elem_size, + }) => { + let padded_size = |elems| { + let without_padding = offset + elems * elem_size; + without_padding + + util::core_layout::padding_needed_for(without_padding, align) + }; + + let resulting_size = padded_size(elems); + // Test that `validate_cast_and_convert_metadata` + // computed the largest possible value that fits in the + // given range. + assert!(padded_size(elems + 1) > bytes_len, "{}", debug_str); + resulting_size + } + }; + + // Test safety postconditions guaranteed by + // `validate_cast_and_convert_metadata`. + assert!(resulting_size <= bytes_len, "{}", debug_str); + match cast_type { + _CastType::_Prefix => { + assert_eq!(addr % align, 0, "{}", debug_str); + assert_eq!(resulting_size, split_at, "{}", debug_str); + } + _CastType::_Suffix => { + assert_eq!(split_at, bytes_len - resulting_size, "{}", debug_str); + assert_eq!((addr + split_at) % align, 0, "{}", debug_str); + } + } + } else { + let min_size = match layout.size_info { + SizeInfo::Sized { _size } => _size, + SizeInfo::SliceDst(TrailingSliceLayout { _offset, .. }) => { + _offset + util::core_layout::padding_needed_for(_offset, layout.align) + } + }; + + // If a cast is invalid, it is either because... + // 1. there are insufficent bytes at the given region for type: + let insufficient_bytes = bytes_len < min_size; + // 2. performing the cast would misalign type: + let base = match cast_type { + _CastType::_Prefix => 0, + _CastType::_Suffix => bytes_len, + }; + let misaligned = (base + addr) % layout.align != 0; + + assert!(insufficient_bytes || misaligned); + } + } + + let sizes = 0..8; + let elem_sizes = 1..8; + let size_infos = sizes + .clone() + .map(Into::::into) + .chain(itertools::iproduct!(sizes, elem_sizes).map(Into::::into)); + let layouts = itertools::iproduct!(size_infos, [1, 2, 4, 8, 16, 32]) + .filter(|(size_info, align)| !matches!(size_info, SizeInfo::Sized { _size } if _size % align != 0)) + .map(|(size_info, align)| layout(size_info, align)); + itertools::iproduct!(layouts, 0..8, 0..8, [_CastType::_Prefix, _CastType::_Suffix]) + .for_each(validate_behavior); + } + + #[test] + #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] + fn test_validate_rust_layout() { + use core::ptr::NonNull; + + // This test synthesizes pointers with various metadata and uses Rust's + // built-in APIs to confirm that Rust makes decisions about type layout + // which are consistent with what we believe is guaranteed by the + // language. If this test fails, it doesn't just mean our code is wrong + // - it means we're misunderstanding the language's guarantees. + + #[derive(Debug)] + struct MacroArgs { + offset: usize, + align: NonZeroUsize, + elem_size: Option, + } + + /// # Safety + /// + /// `test` promises to only call `addr_of_slice_field` on a `NonNull` + /// which points to a valid `T`. + /// + /// `with_elems` must produce a pointer which points to a valid `T`. + fn test NonNull>( + args: MacroArgs, + with_elems: W, + addr_of_slice_field: Option) -> NonNull>, + ) { + let dst = args.elem_size.is_some(); + let layout = { + let size_info = match args.elem_size { + Some(elem_size) => SizeInfo::SliceDst(TrailingSliceLayout { + _offset: args.offset, + _elem_size: elem_size, + }), + None => SizeInfo::Sized { + // Rust only supports types whose sizes are a multiple + // of their alignment. If the macro created a type like + // this: + // + // #[repr(C, align(2))] + // struct Foo([u8; 1]); + // + // ...then Rust will automatically round the type's size + // up to 2. + _size: args.offset + + util::core_layout::padding_needed_for(args.offset, args.align), + }, + }; + DstLayout { size_info, align: args.align } + }; + + for elems in 0..128 { + let ptr = with_elems(elems); + + if let Some(addr_of_slice_field) = addr_of_slice_field { + let slc_field_ptr = addr_of_slice_field(ptr).as_ptr(); + // SAFETY: Both `slc_field_ptr` and `ptr` are pointers to + // the same valid Rust object. + let offset: usize = + unsafe { slc_field_ptr.byte_offset_from(ptr.as_ptr()).try_into().unwrap() }; + assert_eq!(offset, args.offset); + } + + // SAFETY: `ptr` points to a valid `T`. + let (size, align) = unsafe { + (mem::size_of_val_raw(ptr.as_ptr()), mem::align_of_val_raw(ptr.as_ptr())) + }; + + // Avoid expensive allocation when running under Miri. + let assert_msg = if !cfg!(miri) { + format!("\n{args:?}\nsize:{size}, align:{align}") + } else { + String::new() + }; + + let without_padding = + args.offset + args.elem_size.map(|elem_size| elems * elem_size).unwrap_or(0); + assert!(size >= without_padding, "{}", assert_msg); + assert_eq!(align, args.align.get(), "{}", assert_msg); + + // This encodes the most important part of the test: our + // understanding of how Rust determines the layout of repr(C) + // types. Sized repr(C) types are trivial, but DST types have + // some subtlety. Note that: + // - For sized types, `without_padding` is just the size of the + // type that we constructed for `Foo`. Since we may have + // requested a larger alignment, `Foo` may actually be larger + // than this, hence `padding_needed_for`. + // - For unsized types, `without_padding` is dynamically + // computed from the offset, the element size, and element + // count. We expect that the size of the object should be + // `offset + elem_size * elems` rounded up to the next + // alignment. + let expected_size = without_padding + + util::core_layout::padding_needed_for(without_padding, args.align); + assert_eq!(expected_size, size, "{}", assert_msg); + + // For zero-sized element types, + // `validate_cast_and_convert_metadata` just panics, so we skip + // testing those types. + if args.elem_size.map(|elem_size| elem_size > 0).unwrap_or(true) { + let addr = ptr.addr().get(); + let (got_elems, got_split_at) = layout + .validate_cast_and_convert_metadata(addr, size, _CastType::_Prefix) + .unwrap(); + // Avoid expensive allocation when running under Miri. + let assert_msg = if !cfg!(miri) { + format!( + "{}\nvalidate_cast_and_convert_metadata({addr}, {size})", + assert_msg + ) + } else { + String::new() + }; + assert_eq!(got_split_at, size, "{}", assert_msg); + if dst { + assert!(got_elems >= elems, "{}", assert_msg); + if got_elems != elems { + // If `validate_cast_and_convert_metadata` + // returned more elements than `elems`, that + // means that `elems` is not the maximum number + // of elements that can fit in `size` - in other + // words, there is enough padding at the end of + // the value to fit at least one more element. + // If we use this metadata to synthesize a + // pointer, despite having a different element + // count, we still expect it to have the same + // size. + let got_ptr = with_elems(got_elems); + // SAFETY: `got_ptr` is a pointer to a valid `T`. + let size_of_got_ptr = unsafe { mem::size_of_val_raw(got_ptr.as_ptr()) }; + assert_eq!(size_of_got_ptr, size, "{}", assert_msg); + } + } else { + // For sized casts, the returned element value is + // technically meaningless, and we don't guarantee any + // particular value. In practice, it's always zero. + assert_eq!(got_elems, 0, "{}", assert_msg) + } + } + } + } + + macro_rules! validate_against_rust { + ($offset:literal, $align:literal $(, $elem_size:literal)?) => {{ + #[repr(C, align($align))] + struct Foo([u8; $offset]$(, [[u8; $elem_size]])?); + + let args = MacroArgs { + offset: $offset, + align: $align.try_into().unwrap(), + elem_size: { + #[allow(unused)] + let ret = None::; + $(let ret = Some($elem_size);)? + ret + } + }; + + #[repr(C, align($align))] + struct FooAlign; + // Create an aligned buffer to use in order to synthesize + // pointers to `Foo`. We don't ever load values from these + // pointers - we just do arithmetic on them - so having a "real" + // block of memory as opposed to a validly-aligned-but-dangling + // pointer is only necessary to make Miri happy since we run it + // with "strict provenance" checking enabled. + let aligned_buf = Align::<_, FooAlign>::new([0u8; 1024]); + let with_elems = |elems| { + let slc = NonNull::slice_from_raw_parts(NonNull::from(&aligned_buf.t), elems); + #[allow(clippy::as_conversions)] + NonNull::new(slc.as_ptr() as *mut Foo).unwrap() + }; + let addr_of_slice_field = { + #[allow(unused)] + let f = None::) -> NonNull>; + $( + // SAFETY: `test` promises to only call `f` with a `ptr` + // to a valid `Foo`. + let f: Option) -> NonNull> = Some(|ptr: NonNull| unsafe { + NonNull::new(ptr::addr_of_mut!((*ptr.as_ptr()).1)).unwrap().cast::() + }); + let _ = $elem_size; + )? + f + }; + + test::(args, with_elems, addr_of_slice_field); + }}; + } + + // Every permutation of: + // - offset in [0, 4] + // - align in [1, 16] + // - elem_size in [0, 4] (plus no elem_size) + validate_against_rust!(0, 1); + validate_against_rust!(0, 1, 0); + validate_against_rust!(0, 1, 1); + validate_against_rust!(0, 1, 2); + validate_against_rust!(0, 1, 3); + validate_against_rust!(0, 1, 4); + validate_against_rust!(0, 2); + validate_against_rust!(0, 2, 0); + validate_against_rust!(0, 2, 1); + validate_against_rust!(0, 2, 2); + validate_against_rust!(0, 2, 3); + validate_against_rust!(0, 2, 4); + validate_against_rust!(0, 4); + validate_against_rust!(0, 4, 0); + validate_against_rust!(0, 4, 1); + validate_against_rust!(0, 4, 2); + validate_against_rust!(0, 4, 3); + validate_against_rust!(0, 4, 4); + validate_against_rust!(0, 8); + validate_against_rust!(0, 8, 0); + validate_against_rust!(0, 8, 1); + validate_against_rust!(0, 8, 2); + validate_against_rust!(0, 8, 3); + validate_against_rust!(0, 8, 4); + validate_against_rust!(0, 16); + validate_against_rust!(0, 16, 0); + validate_against_rust!(0, 16, 1); + validate_against_rust!(0, 16, 2); + validate_against_rust!(0, 16, 3); + validate_against_rust!(0, 16, 4); + validate_against_rust!(1, 1); + validate_against_rust!(1, 1, 0); + validate_against_rust!(1, 1, 1); + validate_against_rust!(1, 1, 2); + validate_against_rust!(1, 1, 3); + validate_against_rust!(1, 1, 4); + validate_against_rust!(1, 2); + validate_against_rust!(1, 2, 0); + validate_against_rust!(1, 2, 1); + validate_against_rust!(1, 2, 2); + validate_against_rust!(1, 2, 3); + validate_against_rust!(1, 2, 4); + validate_against_rust!(1, 4); + validate_against_rust!(1, 4, 0); + validate_against_rust!(1, 4, 1); + validate_against_rust!(1, 4, 2); + validate_against_rust!(1, 4, 3); + validate_against_rust!(1, 4, 4); + validate_against_rust!(1, 8); + validate_against_rust!(1, 8, 0); + validate_against_rust!(1, 8, 1); + validate_against_rust!(1, 8, 2); + validate_against_rust!(1, 8, 3); + validate_against_rust!(1, 8, 4); + validate_against_rust!(1, 16); + validate_against_rust!(1, 16, 0); + validate_against_rust!(1, 16, 1); + validate_against_rust!(1, 16, 2); + validate_against_rust!(1, 16, 3); + validate_against_rust!(1, 16, 4); + validate_against_rust!(2, 1); + validate_against_rust!(2, 1, 0); + validate_against_rust!(2, 1, 1); + validate_against_rust!(2, 1, 2); + validate_against_rust!(2, 1, 3); + validate_against_rust!(2, 1, 4); + validate_against_rust!(2, 2); + validate_against_rust!(2, 2, 0); + validate_against_rust!(2, 2, 1); + validate_against_rust!(2, 2, 2); + validate_against_rust!(2, 2, 3); + validate_against_rust!(2, 2, 4); + validate_against_rust!(2, 4); + validate_against_rust!(2, 4, 0); + validate_against_rust!(2, 4, 1); + validate_against_rust!(2, 4, 2); + validate_against_rust!(2, 4, 3); + validate_against_rust!(2, 4, 4); + validate_against_rust!(2, 8); + validate_against_rust!(2, 8, 0); + validate_against_rust!(2, 8, 1); + validate_against_rust!(2, 8, 2); + validate_against_rust!(2, 8, 3); + validate_against_rust!(2, 8, 4); + validate_against_rust!(2, 16); + validate_against_rust!(2, 16, 0); + validate_against_rust!(2, 16, 1); + validate_against_rust!(2, 16, 2); + validate_against_rust!(2, 16, 3); + validate_against_rust!(2, 16, 4); + validate_against_rust!(3, 1); + validate_against_rust!(3, 1, 0); + validate_against_rust!(3, 1, 1); + validate_against_rust!(3, 1, 2); + validate_against_rust!(3, 1, 3); + validate_against_rust!(3, 1, 4); + validate_against_rust!(3, 2); + validate_against_rust!(3, 2, 0); + validate_against_rust!(3, 2, 1); + validate_against_rust!(3, 2, 2); + validate_against_rust!(3, 2, 3); + validate_against_rust!(3, 2, 4); + validate_against_rust!(3, 4); + validate_against_rust!(3, 4, 0); + validate_against_rust!(3, 4, 1); + validate_against_rust!(3, 4, 2); + validate_against_rust!(3, 4, 3); + validate_against_rust!(3, 4, 4); + validate_against_rust!(3, 8); + validate_against_rust!(3, 8, 0); + validate_against_rust!(3, 8, 1); + validate_against_rust!(3, 8, 2); + validate_against_rust!(3, 8, 3); + validate_against_rust!(3, 8, 4); + validate_against_rust!(3, 16); + validate_against_rust!(3, 16, 0); + validate_against_rust!(3, 16, 1); + validate_against_rust!(3, 16, 2); + validate_against_rust!(3, 16, 3); + validate_against_rust!(3, 16, 4); + validate_against_rust!(4, 1); + validate_against_rust!(4, 1, 0); + validate_against_rust!(4, 1, 1); + validate_against_rust!(4, 1, 2); + validate_against_rust!(4, 1, 3); + validate_against_rust!(4, 1, 4); + validate_against_rust!(4, 2); + validate_against_rust!(4, 2, 0); + validate_against_rust!(4, 2, 1); + validate_against_rust!(4, 2, 2); + validate_against_rust!(4, 2, 3); + validate_against_rust!(4, 2, 4); + validate_against_rust!(4, 4); + validate_against_rust!(4, 4, 0); + validate_against_rust!(4, 4, 1); + validate_against_rust!(4, 4, 2); + validate_against_rust!(4, 4, 3); + validate_against_rust!(4, 4, 4); + validate_against_rust!(4, 8); + validate_against_rust!(4, 8, 0); + validate_against_rust!(4, 8, 1); + validate_against_rust!(4, 8, 2); + validate_against_rust!(4, 8, 3); + validate_against_rust!(4, 8, 4); + validate_against_rust!(4, 16); + validate_against_rust!(4, 16, 0); + validate_against_rust!(4, 16, 1); + validate_against_rust!(4, 16, 2); + validate_against_rust!(4, 16, 3); + validate_against_rust!(4, 16, 4); + } + + #[test] + fn test_known_layout() { + // Test that `$ty` and `ManuallyDrop<$ty>` have the expected layout. + // Test that `PhantomData<$ty>` has the same layout as `()` regardless + // of `$ty`. + macro_rules! test { + ($ty:ty, $expect:expr) => { + let expect = $expect; + assert_eq!(<$ty as KnownLayout>::LAYOUT, expect); + assert_eq!( as KnownLayout>::LAYOUT, expect); + assert_eq!( as KnownLayout>::LAYOUT, <() as KnownLayout>::LAYOUT); + }; + } + + let layout = |offset, align, _trailing_slice_elem_size| DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: match _trailing_slice_elem_size { + None => SizeInfo::Sized { _size: offset }, + Some(elem_size) => SizeInfo::SliceDst(TrailingSliceLayout { + _offset: offset, + _elem_size: elem_size, + }), + }, + }; + + test!((), layout(0, 1, None)); + test!(u8, layout(1, 1, None)); + // Use `align_of` because `u64` alignment may be smaller than 8 on some + // platforms. + test!(u64, layout(8, mem::align_of::(), None)); + test!(AU64, layout(8, 8, None)); + + test!(Option<&'static ()>, usize::LAYOUT); + + test!([()], layout(0, 1, Some(0))); + test!([u8], layout(0, 1, Some(1))); + test!(str, layout(0, 1, Some(1))); + } + + #[cfg(feature = "derive")] + #[test] + fn test_known_layout_derive() { + // In this and other files (`late_compile_pass.rs`, + // `mid_compile_pass.rs`, and `struct.rs`), we test success and failure + // modes of `derive(KnownLayout)` for the following combination of + // properties: + // + // +------------+--------------------------------------+-----------+ + // | | trailing field properties | | + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // |------------+----------+----------------+----------+-----------| + // | N | N | N | N | KL00 | + // | N | N | N | Y | KL01 | + // | N | N | Y | N | KL02 | + // | N | N | Y | Y | KL03 | + // | N | Y | N | N | KL04 | + // | N | Y | N | Y | KL05 | + // | N | Y | Y | N | KL06 | + // | N | Y | Y | Y | KL07 | + // | Y | N | N | N | KL08 | + // | Y | N | N | Y | KL09 | + // | Y | N | Y | N | KL10 | + // | Y | N | Y | Y | KL11 | + // | Y | Y | N | N | KL12 | + // | Y | Y | N | Y | KL13 | + // | Y | Y | Y | N | KL14 | + // | Y | Y | Y | Y | KL15 | + // +------------+----------+----------------+----------+-----------+ + + struct NotKnownLayout { + _t: T, + } + + #[derive(KnownLayout)] + #[repr(C)] + struct AlignSize + where + elain::Align: elain::Alignment, + { + _align: elain::Align, + _size: [u8; SIZE], + } + + type AU16 = AlignSize<2, 2>; + type AU32 = AlignSize<4, 4>; + + fn _assert_kl(_: &T) {} + + let sized_layout = |align, size| DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::Sized { _size: size }, + }; + + let unsized_layout = |align, elem_size, offset| DstLayout { + align: NonZeroUsize::new(align).unwrap(), + size_info: SizeInfo::SliceDst(TrailingSliceLayout { + _offset: offset, + _elem_size: elem_size, + }), + }; + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | N | N | Y | KL01 | + #[derive(KnownLayout)] + struct KL01(NotKnownLayout, NotKnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(4, 8)); + + // ...with `align(N)`: + #[derive(KnownLayout)] + #[repr(align(64))] + struct KL01Align(NotKnownLayout, NotKnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(64, 64)); + + // ...with `packed`: + #[derive(KnownLayout)] + #[repr(packed)] + struct KL01Packed(NotKnownLayout, NotKnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 6)); + + // ...with `packed(N)`: + #[derive(KnownLayout)] + #[repr(packed(2))] + struct KL01PackedN(NotKnownLayout, NotKnownLayout); + + assert_impl_all!(KL01PackedN: KnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(2, 6)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | N | Y | Y | KL03 | + #[derive(KnownLayout)] + struct KL03(NotKnownLayout, u8); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 1)); + + // ... with `align(N)` + #[derive(KnownLayout)] + #[repr(align(64))] + struct KL03Align(NotKnownLayout, u8); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(64, 64)); + + // ... with `packed`: + #[derive(KnownLayout)] + #[repr(packed)] + struct KL03Packed(NotKnownLayout, u8); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 5)); + + // ... with `packed(N)` + #[derive(KnownLayout)] + #[repr(packed(2))] + struct KL03PackedN(NotKnownLayout, u8); + + assert_impl_all!(KL03PackedN: KnownLayout); + + let expected = DstLayout::for_type::(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(2, 6)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | Y | N | Y | KL05 | + #[derive(KnownLayout)] + struct KL05(u8, T); + + fn _test_kl05(t: T) -> impl KnownLayout { + KL05(0u8, t) + } + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | N | Y | Y | Y | KL07 | + #[derive(KnownLayout)] + struct KL07(u8, T); + + fn _test_kl07(t: T) -> impl KnownLayout { + let _ = KL07(0u8, t); + } + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | N | Y | N | KL10 | + #[derive(KnownLayout)] + #[repr(C)] + struct KL10(NotKnownLayout, [u8]); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), None) + .extend(<[u8] as KnownLayout>::LAYOUT, None) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(4, 1, 4)); + + // ...with `align(N)`: + #[derive(KnownLayout)] + #[repr(C, align(64))] + struct KL10Align(NotKnownLayout, [u8]); + + let repr_align = NonZeroUsize::new(64); + + let expected = DstLayout::new_zst(repr_align) + .extend(DstLayout::for_type::>(), None) + .extend(<[u8] as KnownLayout>::LAYOUT, None) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(64, 1, 4)); + + // ...with `packed`: + #[derive(KnownLayout)] + #[repr(C, packed)] + struct KL10Packed(NotKnownLayout, [u8]); + + let repr_packed = NonZeroUsize::new(1); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(1, 1, 4)); + + // ...with `packed(N)`: + #[derive(KnownLayout)] + #[repr(C, packed(2))] + struct KL10PackedN(NotKnownLayout, [u8]); + + let repr_packed = NonZeroUsize::new(2); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(<[u8] as KnownLayout>::LAYOUT, repr_packed) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, unsized_layout(2, 1, 4)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | N | Y | Y | KL11 | + #[derive(KnownLayout)] + #[repr(C)] + struct KL11(NotKnownLayout, u8); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), None) + .extend(::LAYOUT, None) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(8, 16)); - // base_size is too big for the memory region. - test!(layout((1..8), _, ((1..8).map(Some))).validate(_, [0], _), Ok(None)); - test!(layout((2..8), _, ((1..8).map(Some))).validate(_, [1], _), Ok(None)); + // ...with `align(N)`: + #[derive(KnownLayout)] + #[repr(C, align(64))] + struct KL11Align(NotKnownLayout, u8); - // addr is unaligned for prefix cast - test!(layout(_, [2], [None]).validate(ODDS, _, _Prefix), Ok(None)); - test!(layout(_, [2], (NZ_EVENS.map(Some))).validate(ODDS, _, _Prefix), Ok(None)); + let repr_align = NonZeroUsize::new(64); - // addr is aligned, but end of buffer is unaligned for suffix cast - test!(layout(_, [2], [None]).validate(EVENS, ODDS, _Suffix), Ok(None)); - test!(layout(_, [2], (NZ_EVENS.map(Some))).validate(EVENS, ODDS, _Suffix), Ok(None)); + let expected = DstLayout::new_zst(repr_align) + .extend(DstLayout::for_type::>(), None) + .extend(::LAYOUT, None) + .pad_to_align(); - // Unfortunately, these constants cannot easily be used in the - // implementation of `validate_cast_and_convert_metadata`, since - // `panic!` consumes a string literal, not an expression. - // - // It's important that these messages be in a separate module. If they - // were at the function's top level, we'd pass them to `test!` as, e.g., - // `Err(TRAILING)`, which would run into a subtle Rust footgun - the - // `TRAILING` identifier would be treated as a pattern to match rather - // than a value to check for equality. - mod msgs { - pub(super) const TRAILING: &str = - "attempted to cast to slice type with zero-sized element"; - pub(super) const OVERFLOW: &str = "`addr` + `bytes_len` > usize::MAX"; - } + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(64, 64)); - // casts with ZST trailing element types are unsupported - test!(layout(_, _, [Some(0)]).validate(_, _, _), Err(msgs::TRAILING),); + // ...with `packed`: + #[derive(KnownLayout)] + #[repr(C, packed)] + struct KL11Packed(NotKnownLayout, u8); - // addr + bytes_len must not overflow usize - test!( - layout(_, [1], (NZ_EVENS.map(Some))).validate([usize::MAX], (1..100), _), - Err(msgs::OVERFLOW) - ); - test!(layout(_, [1], [None]).validate((1..100), [usize::MAX], _), Err(msgs::OVERFLOW)); - test!( - layout([1], [1], [None]).validate( - [usize::MAX / 2 + 1, usize::MAX], - [usize::MAX / 2 + 1, usize::MAX], - _ - ), - Err(msgs::OVERFLOW) - ); + let repr_packed = NonZeroUsize::new(1); - // Validates that `validate_cast_and_convert_metadata` satisfies its own - // documented safety postconditions, and also a few other properties - // that aren't documented but we want to guarantee anyway. - fn validate_behavior( - (layout, addr, bytes_len, cast_type): (DstLayout, usize, usize, _CastType), - ) { - if let Some((elems, split_at)) = - layout._validate_cast_and_convert_metadata(addr, bytes_len, cast_type) - { - let (base_size, align, trailing_elem_size) = ( - layout._base_layout.size(), - layout._base_layout.align(), - layout._trailing_slice_elem_size, - ); + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(::LAYOUT, repr_packed) + .pad_to_align(); - let debug_str = format!( - "layout({base_size}, {align}, {trailing_elem_size:?}).validate_cast_and_convert_metadata({addr}, {bytes_len}, {cast_type:?}) => ({elems}, {split_at})", - ); + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(1, 9)); - // If this is a sized type (no trailing slice), then `elems` is - // meaningless, but in practice we set it to 0. Callers are not - // allowed to rely on this, but a lot of math is nicer if - // they're able to, and some callers might accidentally do that. - assert!(!(trailing_elem_size.is_none() && elems != 0), "{}", debug_str); - - let resulting_size = base_size + (elems * trailing_elem_size.unwrap_or(0)); - // Test that, for unsized types, `validate_cast_and_convert_metadata` computed the - // largest possible value that fits in the given byte range. - assert!( - trailing_elem_size - .map(|elem_size| resulting_size + elem_size > bytes_len) - .unwrap_or(true), - "{}", - debug_str - ); + // ...with `packed(N)`: + #[derive(KnownLayout)] + #[repr(C, packed(2))] + struct KL11PackedN(NotKnownLayout, u8); - // Test safety postconditions guaranteed by `validate_cast_and_convert_metadata`. - assert!(resulting_size <= bytes_len); - match cast_type { - _CastType::_Prefix => { - assert_eq!(addr % align, 0, "{}", debug_str); - assert_eq!(resulting_size, split_at, "{}", debug_str); - } - _CastType::_Suffix => { - assert_eq!(split_at, bytes_len - resulting_size, "{}", debug_str); - assert_eq!((addr + split_at) % align, 0, "{}", debug_str); - } - } - } + let repr_packed = NonZeroUsize::new(2); + + let expected = DstLayout::new_zst(None) + .extend(DstLayout::for_type::>(), repr_packed) + .extend(::LAYOUT, repr_packed) + .pad_to_align(); + + assert_eq!(::LAYOUT, expected); + assert_eq!(::LAYOUT, sized_layout(2, 10)); + + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | Y | Y | N | KL14 | + #[derive(KnownLayout)] + #[repr(C)] + struct KL14(u8, T); + + fn _test_kl14(kl: &KL14) { + _assert_kl(kl) } - let layouts = itertools::iproduct!(0..8, [1, 2, 4, 8], (1..8).map(Some).chain([None])) - .filter(|(size, align, trailing_elem_size)| { - size % align == 0 && trailing_elem_size.unwrap_or(*align) % align == 0 - }) - .map(|(s, a, t)| layout(s, a, t)); - itertools::iproduct!(layouts, 0..8, 0..8, [_CastType::_Prefix, _CastType::_Suffix]) - .for_each(validate_behavior); - } + // | `repr(C)`? | generic? | `KnownLayout`? | `Sized`? | Type Name | + // | Y | Y | Y | Y | KL15 | + #[derive(KnownLayout)] + #[repr(C)] + struct KL15(u8, T); - #[test] - fn test_known_layout() { - // Test that `$ty` and `ManuallyDrop<$ty>` have the expected layout. - // Test that `PhantomData<$ty>` has the same layout as `()` regardless - // of `$ty`. - macro_rules! test { - ($ty:ty, $expect:expr) => { - let expect = $expect; - assert_eq!(<$ty as KnownLayout>::LAYOUT, expect); - assert_eq!( as KnownLayout>::LAYOUT, expect); - assert_eq!( as KnownLayout>::LAYOUT, <() as KnownLayout>::LAYOUT); - }; + fn _test_kl15(t: T) -> impl KnownLayout { + let _ = KL15(0u8, t); } - let layout = |base_size, align, _trailing_slice_elem_size| DstLayout { - _base_layout: Layout::from_size_align(base_size, align).unwrap(), - _trailing_slice_elem_size, - }; + // Test a variety of combinations of field types: + // - () + // - u8 + // - AU16 + // - [()] + // - [u8] + // - [AU16] - test!((), layout(0, 1, None)); - test!(u8, layout(1, 1, None)); - // Use `align_of` because `u64` alignment may be smaller than 8 on some - // platforms. - test!(u64, layout(8, mem::align_of::(), None)); - test!(AU64, layout(8, 8, None)); + #[allow(clippy::upper_case_acronyms)] + #[derive(KnownLayout)] + #[repr(C)] + struct KLTU(T, U); - test!(Option<&'static ()>, usize::LAYOUT); + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 0)); - test!([()], layout(0, 1, Some(0))); - test!([u8], layout(0, 1, Some(1))); - test!(str, layout(0, 1, Some(1))); + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 1)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 0, 0)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 1, 0)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 2, 0)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 1)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(1, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 4)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 0, 1)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(1, 1, 1)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 4)); + + assert_eq!( as KnownLayout>::LAYOUT, sized_layout(2, 4)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 0, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 1, 2)); + + assert_eq!( as KnownLayout>::LAYOUT, unsized_layout(2, 2, 2)); + + // Test a variety of field counts. + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF0; + + assert_eq!(::LAYOUT, sized_layout(1, 0)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF1([u8]); + + assert_eq!(::LAYOUT, unsized_layout(1, 1, 0)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF2(NotKnownLayout, [u8]); + + assert_eq!(::LAYOUT, unsized_layout(1, 1, 1)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF3(NotKnownLayout, NotKnownLayout, [u8]); + + assert_eq!(::LAYOUT, unsized_layout(2, 1, 4)); + + #[derive(KnownLayout)] + #[repr(C)] + struct KLF4(NotKnownLayout, NotKnownLayout, NotKnownLayout, [u8]); + + assert_eq!(::LAYOUT, unsized_layout(4, 1, 8)); } #[test] @@ -3300,6 +6763,7 @@ mod tests { panic!("PanicOnDrop::drop"); } } + #[allow(clippy::let_unit_value)] let _: () = transmute!(PanicOnDrop(())); // Test that `transmute!` is legal in a const context. @@ -3309,6 +6773,95 @@ mod tests { assert_eq!(X, ARRAY_OF_ARRAYS); } + #[test] + fn test_transmute_ref() { + // Test that memory is transmuted as expected. + let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; + let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; + let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s); + assert_eq!(*x, array_of_arrays); + let x: &[u8; 8] = transmute_ref!(&array_of_arrays); + assert_eq!(*x, array_of_u8s); + + // Test that `transmute_ref!` is legal in a const context. + const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7]; + const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]]; + #[allow(clippy::redundant_static_lifetimes)] + const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S); + assert_eq!(*X, ARRAY_OF_ARRAYS); + + // Test that it's legal to transmute a reference while shrinking the + // lifetime (note that `X` has the lifetime `'static`). + let x: &[u8; 8] = transmute_ref!(X); + assert_eq!(*x, ARRAY_OF_U8S); + + // Test that `transmute_ref!` supports decreasing alignment. + let u = AU64(0); + let array = [0, 0, 0, 0, 0, 0, 0, 0]; + let x: &[u8; 8] = transmute_ref!(&u); + assert_eq!(*x, array); + + // Test that a mutable reference can be turned into an immutable one. + let mut x = 0u8; + #[allow(clippy::useless_transmute)] + let y: &u8 = transmute_ref!(&mut x); + assert_eq!(*y, 0); + } + + #[test] + fn test_transmute_mut() { + // Test that memory is transmuted as expected. + let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7]; + let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]]; + let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s); + assert_eq!(*x, array_of_arrays); + let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays); + assert_eq!(*x, array_of_u8s); + + { + // Test that it's legal to transmute a reference while shrinking the + // lifetime. + let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays); + assert_eq!(*x, array_of_u8s); + } + // Test that `transmute_mut!` supports decreasing alignment. + let mut u = AU64(0); + let array = [0, 0, 0, 0, 0, 0, 0, 0]; + let x: &[u8; 8] = transmute_mut!(&mut u); + assert_eq!(*x, array); + + // Test that a mutable reference can be turned into an immutable one. + let mut x = 0u8; + #[allow(clippy::useless_transmute)] + let y: &u8 = transmute_mut!(&mut x); + assert_eq!(*y, 0); + } + + #[test] + fn test_macros_evaluate_args_once() { + let mut ctr = 0; + let _: usize = transmute!({ + ctr += 1; + 0usize + }); + assert_eq!(ctr, 1); + + let mut ctr = 0; + let _: &usize = transmute_ref!({ + ctr += 1; + &0usize + }); + assert_eq!(ctr, 1); + } + + #[test] + fn test_include_value() { + const AS_U32: u32 = include_value!("../testdata/include_value/data"); + assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd'])); + const AS_I32: i32 = include_value!("../testdata/include_value/data"); + assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd'])); + } + #[test] fn test_address() { // Test that the `Deref` and `DerefMut` implementations return a @@ -3445,7 +6998,8 @@ mod tests { let mut buf = Align::<[u8; 8], AU64>::default(); // `buf.t` should be aligned to 8, so this should always succeed. test_new_helper(Ref::<_, AU64>::new(&mut buf.t[..]).unwrap()); - buf.t = [0xFFu8; 8]; + let ascending: [u8; 8] = (0..8).collect::>().try_into().unwrap(); + buf.t = ascending; test_new_helper(Ref::<_, AU64>::new_zeroed(&mut buf.t[..]).unwrap()); { // In a block so that `r` and `suffix` don't live too long. @@ -3455,7 +7009,7 @@ mod tests { test_new_helper(r); } { - buf.t = [0xFFu8; 8]; + buf.t = ascending; let (r, suffix) = Ref::<_, AU64>::new_from_prefix_zeroed(&mut buf.t[..]).unwrap(); assert!(suffix.is_empty()); test_new_helper(r); @@ -3467,44 +7021,54 @@ mod tests { test_new_helper(r); } { - buf.t = [0xFFu8; 8]; + buf.t = ascending; let (prefix, r) = Ref::<_, AU64>::new_from_suffix_zeroed(&mut buf.t[..]).unwrap(); assert!(prefix.is_empty()); test_new_helper(r); } - // A buffer with alignment 8 and length 16. - let mut buf = Align::<[u8; 16], AU64>::default(); + // A buffer with alignment 8 and length 24. We choose this length very + // intentionally: if we instead used length 16, then the prefix and + // suffix lengths would be identical. In the past, we used length 16, + // which resulted in this test failing to discover the bug uncovered in + // #506. + let mut buf = Align::<[u8; 24], AU64>::default(); // `buf.t` should be aligned to 8 and have a length which is a multiple // of `size_of::()`, so this should always succeed. - test_new_helper_slice(Ref::<_, [AU64]>::new_slice(&mut buf.t[..]).unwrap(), 2); - buf.t = [0xFFu8; 16]; - test_new_helper_slice(Ref::<_, [AU64]>::new_slice_zeroed(&mut buf.t[..]).unwrap(), 2); + test_new_helper_slice(Ref::<_, [AU64]>::new_slice(&mut buf.t[..]).unwrap(), 3); + let ascending: [u8; 24] = (0..24).collect::>().try_into().unwrap(); + // 16 ascending bytes followed by 8 zeros. + let mut ascending_prefix = ascending; + ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); + // 8 zeros followed by 16 ascending bytes. + let mut ascending_suffix = ascending; + ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); + test_new_helper_slice(Ref::<_, [AU64]>::new_slice_zeroed(&mut buf.t[..]).unwrap(), 3); { - buf.set_default(); + buf.t = ascending_suffix; let (r, suffix) = Ref::<_, [AU64]>::new_slice_from_prefix(&mut buf.t[..], 1).unwrap(); - assert_eq!(suffix, [0; 8]); + assert_eq!(suffix, &ascending[8..]); test_new_helper_slice(r, 1); } { - buf.t = [0xFFu8; 16]; + buf.t = ascending_suffix; let (r, suffix) = Ref::<_, [AU64]>::new_slice_from_prefix_zeroed(&mut buf.t[..], 1).unwrap(); - assert_eq!(suffix, [0xFF; 8]); + assert_eq!(suffix, &ascending[8..]); test_new_helper_slice(r, 1); } { - buf.set_default(); + buf.t = ascending_prefix; let (prefix, r) = Ref::<_, [AU64]>::new_slice_from_suffix(&mut buf.t[..], 1).unwrap(); - assert_eq!(prefix, [0; 8]); + assert_eq!(prefix, &ascending[..16]); test_new_helper_slice(r, 1); } { - buf.t = [0xFFu8; 16]; + buf.t = ascending_prefix; let (prefix, r) = Ref::<_, [AU64]>::new_slice_from_suffix_zeroed(&mut buf.t[..], 1).unwrap(); - assert_eq!(prefix, [0xFF; 8]); + assert_eq!(prefix, &ascending[..16]); test_new_helper_slice(r, 1); } } @@ -3672,6 +7236,71 @@ mod tests { } } + #[test] + fn test_ref_from_mut_from() { + // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` success cases + // Exhaustive coverage for these methods is covered by the `Ref` tests above, + // which these helper methods defer to. + + let mut buf = + Align::<[u8; 16], AU64>::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + + assert_eq!( + AU64::ref_from(&buf.t[8..]).unwrap().0.to_ne_bytes(), + [8, 9, 10, 11, 12, 13, 14, 15] + ); + let suffix = AU64::mut_from(&mut buf.t[8..]).unwrap(); + suffix.0 = 0x0101010101010101; + // The `[u8:9]` is a non-half size of the full buffer, which would catch + // `from_prefix` having the same implementation as `from_suffix` (issues #506, #511). + assert_eq!(<[u8; 9]>::ref_from_suffix(&buf.t[..]).unwrap(), &[7u8, 1, 1, 1, 1, 1, 1, 1, 1]); + let suffix = AU64::mut_from_suffix(&mut buf.t[1..]).unwrap(); + suffix.0 = 0x0202020202020202; + <[u8; 10]>::mut_from_suffix(&mut buf.t[..]).unwrap()[0] = 42; + assert_eq!(<[u8; 9]>::ref_from_prefix(&buf.t[..]).unwrap(), &[0, 1, 2, 3, 4, 5, 42, 7, 2]); + <[u8; 2]>::mut_from_prefix(&mut buf.t[..]).unwrap()[1] = 30; + assert_eq!(buf.t, [0, 30, 2, 3, 4, 5, 42, 7, 2, 2, 2, 2, 2, 2, 2, 2]); + } + + #[test] + fn test_ref_from_mut_from_error() { + // Test `FromBytes::{ref_from, mut_from}{,_prefix,_suffix}` error cases. + + // Fail because the buffer is too large. + let mut buf = Align::<[u8; 16], AU64>::default(); + // `buf.t` should be aligned to 8, so only the length check should fail. + assert!(AU64::ref_from(&buf.t[..]).is_none()); + assert!(AU64::mut_from(&mut buf.t[..]).is_none()); + assert!(<[u8; 8]>::ref_from(&buf.t[..]).is_none()); + assert!(<[u8; 8]>::mut_from(&mut buf.t[..]).is_none()); + + // Fail because the buffer is too small. + let mut buf = Align::<[u8; 4], AU64>::default(); + assert!(AU64::ref_from(&buf.t[..]).is_none()); + assert!(AU64::mut_from(&mut buf.t[..]).is_none()); + assert!(<[u8; 8]>::ref_from(&buf.t[..]).is_none()); + assert!(<[u8; 8]>::mut_from(&mut buf.t[..]).is_none()); + assert!(AU64::ref_from_prefix(&buf.t[..]).is_none()); + assert!(AU64::mut_from_prefix(&mut buf.t[..]).is_none()); + assert!(AU64::ref_from_suffix(&buf.t[..]).is_none()); + assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_none()); + assert!(<[u8; 8]>::ref_from_prefix(&buf.t[..]).is_none()); + assert!(<[u8; 8]>::mut_from_prefix(&mut buf.t[..]).is_none()); + assert!(<[u8; 8]>::ref_from_suffix(&buf.t[..]).is_none()); + assert!(<[u8; 8]>::mut_from_suffix(&mut buf.t[..]).is_none()); + + // Fail because the alignment is insufficient. + let mut buf = Align::<[u8; 13], AU64>::default(); + assert!(AU64::ref_from(&buf.t[1..]).is_none()); + assert!(AU64::mut_from(&mut buf.t[1..]).is_none()); + assert!(AU64::ref_from(&buf.t[1..]).is_none()); + assert!(AU64::mut_from(&mut buf.t[1..]).is_none()); + assert!(AU64::ref_from_prefix(&buf.t[1..]).is_none()); + assert!(AU64::mut_from_prefix(&mut buf.t[1..]).is_none()); + assert!(AU64::ref_from_suffix(&buf.t[..]).is_none()); + assert!(AU64::mut_from_suffix(&mut buf.t[..]).is_none()); + } + #[test] #[allow(clippy::cognitive_complexity)] fn test_new_error() { @@ -3988,9 +7617,152 @@ mod tests { #[test] fn test_impls() { + use core::borrow::Borrow; + + // A type that can supply test cases for testing + // `TryFromBytes::is_bit_valid`. All types passed to `assert_impls!` + // must implement this trait; that macro uses it to generate runtime + // tests for `TryFromBytes` impls. + // + // All `T: FromBytes` types are provided with a blanket impl. Other + // types must implement `TryFromBytesTestable` directly (ie using + // `impl_try_from_bytes_testable!`). + trait TryFromBytesTestable { + fn with_passing_test_cases(f: F); + fn with_failing_test_cases(f: F); + } + + impl TryFromBytesTestable for T { + fn with_passing_test_cases(f: F) { + // Test with a zeroed value. + f(&Self::new_zeroed()); + + let ffs = { + let mut t = Self::new_zeroed(); + let ptr: *mut T = &mut t; + // SAFETY: `T: FromBytes` + unsafe { ptr::write_bytes(ptr.cast::(), 0xFF, mem::size_of::()) }; + t + }; + + // Test with a value initialized with 0xFF. + f(&ffs); + } + + fn with_failing_test_cases(_f: F) {} + } + + // Implements `TryFromBytesTestable`. + macro_rules! impl_try_from_bytes_testable { + // Base case for recursion (when the list of types has run out). + (=> @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => {}; + // Implements for type(s) with no type parameters. + ($ty:ty $(,$tys:ty)* => @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => { + impl TryFromBytesTestable for $ty { + impl_try_from_bytes_testable!( + @methods @success $($success_case),* + $(, @failure $($failure_case),*)? + ); + } + impl_try_from_bytes_testable!($($tys),* => @success $($success_case),* $(, @failure $($failure_case),*)?); + }; + // Implements for multiple types with no type parameters. + ($($($ty:ty),* => @success $($success_case:expr), * $(, @failure $($failure_case:expr),*)?;)*) => { + $( + impl_try_from_bytes_testable!($($ty),* => @success $($success_case),* $(, @failure $($failure_case),*)*); + )* + }; + // Implements only the methods; caller must invoke this from inside + // an impl block. + (@methods @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => { + fn with_passing_test_cases(_f: F) { + $( + _f($success_case.borrow()); + )* + } + + fn with_failing_test_cases(_f: F) { + $($( + // `unused_qualifications` is spuriously triggered on + // `Option::::None`. + #[allow(unused_qualifications)] + let case = $failure_case.as_bytes(); + _f(case.as_bytes()); + )*)? + } + }; + } + + // Note that these impls are only for types which are not `FromBytes`. + // `FromBytes` types are covered by a preceding blanket impl. + impl_try_from_bytes_testable!( + bool => @success true, false, + @failure 2u8, 3u8, 0xFFu8; + char => @success '\u{0}', '\u{D7FF}', '\u{E000}', '\u{10FFFF}', + @failure 0xD800u32, 0xDFFFu32, 0x110000u32; + str => @success "", "hello", "❤️🧡💛💚💙💜", + @failure [0, 159, 146, 150]; + [u8] => @success [], [0, 1, 2]; + NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, + NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, + NonZeroUsize, NonZeroIsize + => @success Self::new(1).unwrap(), + // Doing this instead of `0` ensures that we always satisfy + // the size and alignment requirements of `Self` (whereas + // `0` may be any integer type with a different size or + // alignment than some `NonZeroXxx` types). + @failure Option::::None; + [bool] + => @success [true, false], [false, true], + @failure [2u8], [3u8], [0xFFu8], [0u8, 1u8, 2u8]; + ); + // Asserts that `$ty` implements any `$trait` and doesn't implement any // `!$trait`. Note that all `$trait`s must come before any `!$trait`s. + // + // For `T: TryFromBytes`, uses `TryFromBytesTestable` to test success + // and failure cases for `TryFromBytes::is_bit_valid`. macro_rules! assert_impls { + ($ty:ty: TryFromBytes) => { + <$ty as TryFromBytesTestable>::with_passing_test_cases(|val| { + let c = Ptr::from(val); + // SAFETY: + // - Since `val` is a normal reference, `c` is guranteed to + // be aligned, to point to a single allocation, and to + // have a size which doesn't overflow `isize`. + // - Since `val` is a valid `$ty`, `c`'s referent satisfies + // the bit validity constraints of `is_bit_valid`, which + // are a superset of the bit validity constraints of + // `$ty`. + let res = unsafe { <$ty as TryFromBytes>::is_bit_valid(c) }; + assert!(res, "{}::is_bit_valid({:?}): got false, expected true", stringify!($ty), val); + + // TODO(#5): In addition to testing `is_bit_valid`, test the + // methods built on top of it. This would both allow us to + // test their implementations and actually convert the bytes + // to `$ty`, giving Miri a chance to catch if this is + // unsound (ie, if our `is_bit_valid` impl is buggy). + // + // The following code was tried, but it doesn't work because + // a) some types are not `AsBytes` and, b) some types are + // not `Sized`. + // + // let r = <$ty as TryFromBytes>::try_from_ref(val.as_bytes()).unwrap(); + // assert_eq!(r, &val); + // let r = <$ty as TryFromBytes>::try_from_mut(val.as_bytes_mut()).unwrap(); + // assert_eq!(r, &mut val); + // let v = <$ty as TryFromBytes>::try_read_from(val.as_bytes()).unwrap(); + // assert_eq!(v, val); + }); + #[allow(clippy::as_conversions)] + <$ty as TryFromBytesTestable>::with_failing_test_cases(|c| { + let res = <$ty as TryFromBytes>::try_from_ref(c); + assert!(res.is_none(), "{}::is_bit_valid({:?}): got true, expected false", stringify!($ty), c); + }); + + #[allow(dead_code)] + const _: () = { static_assertions::assert_impl_all!($ty: TryFromBytes); }; + }; ($ty:ty: $trait:ident) => { #[allow(dead_code)] const _: () = { static_assertions::assert_impl_all!($ty: $trait); }; @@ -4010,77 +7782,416 @@ mod tests { }; } - assert_impls!((): FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(u8: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(i8: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(u16: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(i16: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(u32: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(i32: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(u64: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(i64: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(u128: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(i128: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(usize: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(isize: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(f32: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(f64: FromZeroes, FromBytes, AsBytes, !Unaligned); - - assert_impls!(bool: FromZeroes, AsBytes, Unaligned, !FromBytes); - assert_impls!(char: FromZeroes, AsBytes, !FromBytes, !Unaligned); - assert_impls!(str: FromZeroes, AsBytes, Unaligned, !FromBytes); - - assert_impls!(NonZeroU8: AsBytes, Unaligned, !FromZeroes, !FromBytes); - assert_impls!(NonZeroI8: AsBytes, Unaligned, !FromZeroes, !FromBytes); - assert_impls!(NonZeroU16: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroI16: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroU32: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroI32: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroU64: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroI64: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroU128: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroI128: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroUsize: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - assert_impls!(NonZeroIsize: AsBytes, !FromZeroes, !FromBytes, !Unaligned); - - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); - assert_impls!(Option: FromZeroes, FromBytes, AsBytes, !Unaligned); + // NOTE: The negative impl assertions here are not necessarily + // prescriptive. They merely serve as change detectors to make sure + // we're aware of what trait impls are getting added with a given + // change. Of course, some impls would be invalid (e.g., `bool: + // FromBytes`), and so this change detection is very important. + + assert_impls!((): KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!(u8: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!(i8: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!(u16: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(i16: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(u32: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(i32: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(u64: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(i64: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(u128: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(i128: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(usize: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(isize: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(f32: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(f64: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + + assert_impls!(bool: KnownLayout, TryFromBytes, FromZeroes, AsBytes, Unaligned, !FromBytes); + assert_impls!(char: KnownLayout, TryFromBytes, FromZeroes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(str: KnownLayout, TryFromBytes, FromZeroes, AsBytes, Unaligned, !FromBytes); + + assert_impls!(NonZeroU8: KnownLayout, TryFromBytes, AsBytes, Unaligned, !FromZeroes, !FromBytes); + assert_impls!(NonZeroI8: KnownLayout, TryFromBytes, AsBytes, Unaligned, !FromZeroes, !FromBytes); + assert_impls!(NonZeroU16: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroI16: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroU32: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroI32: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroU64: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroI64: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroU128: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroI128: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroUsize: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + assert_impls!(NonZeroIsize: KnownLayout, TryFromBytes, AsBytes, !FromBytes, !Unaligned); + + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); // Implements none of the ZC traits. struct NotZerocopy; - assert_impls!(PhantomData: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(PhantomData<[u8]>: FromZeroes, FromBytes, AsBytes, Unaligned); + #[rustfmt::skip] + type FnManyArgs = fn( + NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, + ) -> (NotZerocopy, NotZerocopy); + + // Allowed, because we're not actually using this type for FFI. + #[allow(improper_ctypes_definitions)] + #[rustfmt::skip] + type ECFnManyArgs = extern "C" fn( + NotZerocopy, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, + ) -> (NotZerocopy, NotZerocopy); + + #[cfg(feature = "alloc")] + assert_impls!(Option>>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option]>>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option<&'static UnsafeCell>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option<&'static [UnsafeCell]>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option<&'static mut UnsafeCell>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option<&'static mut [UnsafeCell]>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option>>: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option]>>: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(Option: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + + assert_impls!(PhantomData: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!(PhantomData<[u8]>: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + + assert_impls!(ManuallyDrop: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes); + assert_impls!(ManuallyDrop<[u8]>: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes); + assert_impls!(ManuallyDrop: !TryFromBytes, !KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(ManuallyDrop<[NotZerocopy]>: !TryFromBytes, !KnownLayout, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + + assert_impls!(MaybeUninit: KnownLayout, TryFromBytes, FromZeroes, FromBytes, Unaligned, !AsBytes); + assert_impls!(MaybeUninit: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + + assert_impls!(Wrapping: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!(Wrapping: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + + assert_impls!(Unalign: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes); + assert_impls!(Unalign: Unaligned, !KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes); + + assert_impls!([u8]: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, Unaligned); + assert_impls!([bool]: KnownLayout, TryFromBytes, FromZeroes, AsBytes, Unaligned, !FromBytes); + assert_impls!([NotZerocopy]: !KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!([u8; 0]: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes); + assert_impls!([NotZerocopy; 0]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!([u8; 1]: KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned, !TryFromBytes); + assert_impls!([NotZerocopy; 1]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + + assert_impls!(*const NotZerocopy: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(*mut NotZerocopy: KnownLayout, FromZeroes, !TryFromBytes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(*const [NotZerocopy]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(*mut [NotZerocopy]: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(*const dyn Debug: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + assert_impls!(*mut dyn Debug: KnownLayout, !TryFromBytes, !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + + #[cfg(feature = "simd")] + { + #[allow(unused_macros)] + macro_rules! test_simd_arch_mod { + ($arch:ident, $($typ:ident),*) => { + { + use core::arch::$arch::{$($typ),*}; + use crate::*; + $( assert_impls!($typ: KnownLayout, TryFromBytes, FromZeroes, FromBytes, AsBytes, !Unaligned); )* + } + }; + } + #[cfg(target_arch = "x86")] + test_simd_arch_mod!(x86, __m128, __m128d, __m128i, __m256, __m256d, __m256i); + + #[cfg(all(feature = "simd-nightly", target_arch = "x86"))] + test_simd_arch_mod!(x86, __m512bh, __m512, __m512d, __m512i); + + #[cfg(target_arch = "x86_64")] + test_simd_arch_mod!(x86_64, __m128, __m128d, __m128i, __m256, __m256d, __m256i); + + #[cfg(all(feature = "simd-nightly", target_arch = "x86_64"))] + test_simd_arch_mod!(x86_64, __m512bh, __m512, __m512d, __m512i); + + #[cfg(target_arch = "wasm32")] + test_simd_arch_mod!(wasm32, v128); + + #[cfg(all(feature = "simd-nightly", target_arch = "powerpc"))] + test_simd_arch_mod!( + powerpc, + vector_bool_long, + vector_double, + vector_signed_long, + vector_unsigned_long + ); + + #[cfg(all(feature = "simd-nightly", target_arch = "powerpc64"))] + test_simd_arch_mod!( + powerpc64, + vector_bool_long, + vector_double, + vector_signed_long, + vector_unsigned_long + ); + #[cfg(target_arch = "aarch64")] + #[rustfmt::skip] + test_simd_arch_mod!( + aarch64, float32x2_t, float32x4_t, float64x1_t, float64x2_t, int8x8_t, int8x8x2_t, + int8x8x3_t, int8x8x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int16x4_t, + int16x8_t, int32x2_t, int32x4_t, int64x1_t, int64x2_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t, + poly8x8x4_t, poly8x16_t, poly8x16x2_t, poly8x16x3_t, poly8x16x4_t, poly16x4_t, poly16x8_t, + poly64x1_t, poly64x2_t, uint8x8_t, uint8x8x2_t, uint8x8x3_t, uint8x8x4_t, uint8x16_t, + uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint16x4_t, uint16x8_t, uint32x2_t, uint32x4_t, + uint64x1_t, uint64x2_t + ); + #[cfg(all(feature = "simd-nightly", target_arch = "arm"))] + #[rustfmt::skip] + test_simd_arch_mod!(arm, int8x4_t, uint8x4_t); + } + } +} + +#[cfg(kani)] +mod proofs { + use super::*; + + impl kani::Arbitrary for DstLayout { + fn any() -> Self { + let align: NonZeroUsize = kani::any(); + let size_info: SizeInfo = kani::any(); + + kani::assume(align.is_power_of_two()); + kani::assume(align < DstLayout::THEORETICAL_MAX_ALIGN); + + // For testing purposes, we most care about instantiations of + // `DstLayout` that can correspond to actual Rust types. We use + // `Layout` to verify that our `DstLayout` satisfies the validity + // conditions of Rust layouts. + kani::assume( + match size_info { + SizeInfo::Sized { _size } => Layout::from_size_align(_size, align.get()), + SizeInfo::SliceDst(TrailingSliceLayout { _offset, _elem_size }) => { + // `SliceDst`` cannot encode an exact size, but we know + // it is at least `_offset` bytes. + Layout::from_size_align(_offset, align.get()) + } + } + .is_ok(), + ); + + Self { align: align, size_info: size_info } + } + } + + impl kani::Arbitrary for SizeInfo { + fn any() -> Self { + let is_sized: bool = kani::any(); + + match is_sized { + true => { + let size: usize = kani::any(); + + kani::assume(size <= isize::MAX as _); + + SizeInfo::Sized { _size: size } + } + false => SizeInfo::SliceDst(kani::any()), + } + } + } + + impl kani::Arbitrary for TrailingSliceLayout { + fn any() -> Self { + let elem_size: usize = kani::any(); + let offset: usize = kani::any(); + + kani::assume(elem_size < isize::MAX as _); + kani::assume(offset < isize::MAX as _); + + TrailingSliceLayout { _elem_size: elem_size, _offset: offset } + } + } + + #[kani::proof] + fn prove_dst_layout_extend() { + use crate::util::{core_layout::padding_needed_for, max, min}; + + let base: DstLayout = kani::any(); + let field: DstLayout = kani::any(); + let packed: Option = kani::any(); + + if let Some(max_align) = packed { + kani::assume(max_align.is_power_of_two()); + kani::assume(base.align <= max_align); + } + + // The base can only be extended if it's sized. + kani::assume(matches!(base.size_info, SizeInfo::Sized { .. })); + let base_size = if let SizeInfo::Sized { _size: size } = base.size_info { + size + } else { + unreachable!(); + }; + + // Under the above conditions, `DstLayout::extend` will not panic. + let composite = base.extend(field, packed); + + // The field's alignment is clamped by `max_align` (i.e., the + // `packed` attribute, if any) [1]. + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers: + // + // The alignments of each field, for the purpose of positioning + // fields, is the smaller of the specified alignment and the + // alignment of the field's type. + let field_align = min(field.align, packed.unwrap_or(DstLayout::THEORETICAL_MAX_ALIGN)); + + // The struct's alignment is the maximum of its previous alignment and + // `field_align`. + assert_eq!(composite.align, max(base.align, field_align)); + + // Compute the minimum amount of inter-field padding needed to + // satisfy the field's alignment, and offset of the trailing field. + // [1] + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html#the-alignment-modifiers: + // + // Inter-field padding is guaranteed to be the minimum required in + // order to satisfy each field's (possibly altered) alignment. + let padding = padding_needed_for(base_size, field_align); + let offset = base_size + padding; + + // For testing purposes, we'll also construct `alloc::Layout` + // stand-ins for `DstLayout`, and show that `extend` behaves + // comparably on both types. + let base_analog = Layout::from_size_align(base_size, base.align.get()).unwrap(); + + match field.size_info { + SizeInfo::Sized { _size: field_size } => { + if let SizeInfo::Sized { _size: composite_size } = composite.size_info { + // If the trailing field is sized, the resulting layout + // will be sized. Its size will be the sum of the + // preceeding layout, the size of the new field, and the + // size of inter-field padding between the two. + assert_eq!(composite_size, offset + field_size); + + let field_analog = + Layout::from_size_align(field_size, field_align.get()).unwrap(); + + if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog) + { + assert_eq!(actual_offset, offset); + assert_eq!(actual_composite.size(), composite_size); + assert_eq!(actual_composite.align(), composite.align.get()); + } else { + // An error here reflects that composite of `base` + // and `field` cannot correspond to a real Rust type + // fragment, because such a fragment would violate + // the basic invariants of a valid Rust layout. At + // the time of writing, `DstLayout` is a little more + // permissive than `Layout`, so we don't assert + // anything in this branch (e.g., unreachability). + } + } else { + panic!("The composite of two sized layouts must be sized.") + } + } + SizeInfo::SliceDst(TrailingSliceLayout { + _offset: field_offset, + _elem_size: field_elem_size, + }) => { + if let SizeInfo::SliceDst(TrailingSliceLayout { + _offset: composite_offset, + _elem_size: composite_elem_size, + }) = composite.size_info + { + // The offset of the trailing slice component is the sum + // of the offset of the trailing field and the trailing + // slice offset within that field. + assert_eq!(composite_offset, offset + field_offset); + // The elem size is unchanged. + assert_eq!(composite_elem_size, field_elem_size); + + let field_analog = + Layout::from_size_align(field_offset, field_align.get()).unwrap(); + + if let Ok((actual_composite, actual_offset)) = base_analog.extend(field_analog) + { + assert_eq!(actual_offset, offset); + assert_eq!(actual_composite.size(), composite_offset); + assert_eq!(actual_composite.align(), composite.align.get()); + } else { + // An error here reflects that composite of `base` + // and `field` cannot correspond to a real Rust type + // fragment, because such a fragment would violate + // the basic invariants of a valid Rust layout. At + // the time of writing, `DstLayout` is a little more + // permissive than `Layout`, so we don't assert + // anything in this branch (e.g., unreachability). + } + } else { + panic!("The extension of a layout with a DST must result in a DST.") + } + } + } + } - assert_impls!(ManuallyDrop: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(ManuallyDrop<[u8]>: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(ManuallyDrop: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); - assert_impls!(ManuallyDrop<[NotZerocopy]>: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + #[kani::proof] + #[kani::should_panic] + fn prove_dst_layout_extend_dst_panics() { + let base: DstLayout = kani::any(); + let field: DstLayout = kani::any(); + let packed: Option = kani::any(); - assert_impls!(MaybeUninit: FromZeroes, FromBytes, Unaligned, !AsBytes); - assert_impls!(MaybeUninit: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + if let Some(max_align) = packed { + kani::assume(max_align.is_power_of_two()); + kani::assume(base.align <= max_align); + } - assert_impls!(Wrapping: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(Wrapping: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + kani::assume(matches!(base.size_info, SizeInfo::SliceDst(..))); - assert_impls!(Unalign: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!(Unalign: Unaligned, !FromZeroes, !FromBytes, !AsBytes); + let _ = base.extend(field, packed); + } - assert_impls!([u8]: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!([NotZerocopy]: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); - assert_impls!([u8; 0]: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!([NotZerocopy; 0]: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); - assert_impls!([u8; 1]: FromZeroes, FromBytes, AsBytes, Unaligned); - assert_impls!([NotZerocopy; 1]: !FromZeroes, !FromBytes, !AsBytes, !Unaligned); + #[kani::proof] + fn prove_dst_layout_pad_to_align() { + use crate::util::core_layout::padding_needed_for; + + let layout: DstLayout = kani::any(); + + let padded: DstLayout = layout.pad_to_align(); + + // Calling `pad_to_align` does not alter the `DstLayout`'s alignment. + assert_eq!(padded.align, layout.align); + + if let SizeInfo::Sized { _size: unpadded_size } = layout.size_info { + if let SizeInfo::Sized { _size: padded_size } = padded.size_info { + // If the layout is sized, it will remain sized after padding is + // added. Its sum will be its unpadded size and the size of the + // trailing padding needed to satisfy its alignment + // requirements. + let padding = padding_needed_for(unpadded_size, layout.align); + assert_eq!(padded_size, unpadded_size + padding); + + // Prove that calling `DstLayout::pad_to_align` behaves + // identically to `Layout::pad_to_align`. + let layout_analog = + Layout::from_size_align(unpadded_size, layout.align.get()).unwrap(); + let padded_analog = layout_analog.pad_to_align(); + assert_eq!(padded_analog.align(), layout.align.get()); + assert_eq!(padded_analog.size(), padded_size); + } else { + panic!("The padding of a sized layout must result in a sized layout.") + } + } else { + // If the layout is a DST, padding cannot be statically added. + assert_eq!(padded.size_info, layout.size_info); + } } } diff --git a/src/macro_util.rs b/src/macro_util.rs new file mode 100644 index 0000000..24fec4f --- /dev/null +++ b/src/macro_util.rs @@ -0,0 +1,670 @@ +// Copyright 2022 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. + +//! Utilities used by macros and by `zerocopy-derive`. +//! +//! These are defined here `zerocopy` rather than in code generated by macros or +//! by `zerocopy-derive` so that they can be compiled once rather than +//! recompiled for every invocation (e.g., if they were defined in generated +//! code, then deriving `AsBytes` and `FromBytes` on three different types would +//! result in the code in question being emitted and compiled six different +//! times). + +#![allow(missing_debug_implementations)] + +use core::{marker::PhantomData, mem::ManuallyDrop}; + +// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this +// `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] +use core::ptr::{self, NonNull}; + +/// A compile-time check that should be one particular value. +pub trait ShouldBe {} + +/// A struct for checking whether `T` contains padding. +pub struct HasPadding(PhantomData); + +impl ShouldBe for HasPadding {} + +/// A type whose size is equal to `align_of::()`. +#[repr(C)] +pub struct AlignOf { + // This field ensures that: + // - The size is always at least 1 (the minimum possible alignment). + // - If the alignment is greater than 1, Rust has to round up to the next + // multiple of it in order to make sure that `Align`'s size is a multiple + // of that alignment. Without this field, its size could be 0, which is a + // valid multiple of any alignment. + _u: u8, + _a: [T; 0], +} + +impl AlignOf { + #[inline(never)] // Make `missing_inline_in_public_items` happy. + pub fn into_t(self) -> T { + unreachable!() + } +} + +/// A type whose size is equal to `max(align_of::(), align_of::())`. +#[repr(C)] +pub union MaxAlignsOf { + _t: ManuallyDrop>, + _u: ManuallyDrop>, +} + +impl MaxAlignsOf { + #[inline(never)] // Make `missing_inline_in_public_items` happy. + pub fn new(_t: T, _u: U) -> MaxAlignsOf { + unreachable!() + } +} + +const _64K: usize = 1 << 16; + +// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this +// `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] +#[repr(C, align(65536))] +struct Aligned64kAllocation([u8; _64K]); + +/// A pointer to an aligned allocation of size 2^16. +/// +/// # Safety +/// +/// `ALIGNED_64K_ALLOCATION` is guaranteed to point to the entirety of an +/// allocation with size and alignment 2^16, and to have valid provenance. +// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this +// `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] +pub const ALIGNED_64K_ALLOCATION: NonNull<[u8]> = { + const REF: &Aligned64kAllocation = &Aligned64kAllocation([0; _64K]); + let ptr: *const Aligned64kAllocation = REF; + let ptr: *const [u8] = ptr::slice_from_raw_parts(ptr.cast(), _64K); + // SAFETY: + // - `ptr` is derived from a Rust reference, which is guaranteed to be + // non-null. + // - `ptr` is derived from an `&Aligned64kAllocation`, which has size and + // alignment `_64K` as promised. Its length is initialized to `_64K`, + // which means that it refers to the entire allocation. + // - `ptr` is derived from a Rust reference, which is guaranteed to have + // valid provenance. + // + // TODO(#429): Once `NonNull::new_unchecked` docs document that it preserves + // provenance, cite those docs. + // TODO: Replace this `as` with `ptr.cast_mut()` once our MSRV >= 1.65 + #[allow(clippy::as_conversions)] + unsafe { + NonNull::new_unchecked(ptr as *mut _) + } +}; + +/// Computes the offset of the base of the field `$trailing_field_name` within +/// the type `$ty`. +/// +/// `trailing_field_offset!` produces code which is valid in a `const` context. +// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this +// `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! trailing_field_offset { + ($ty:ty, $trailing_field_name:tt) => {{ + let min_size = { + let zero_elems: *const [()] = + $crate::macro_util::core_reexport::ptr::slice_from_raw_parts( + $crate::macro_util::core_reexport::ptr::NonNull::<()>::dangling() + .as_ptr() + .cast_const(), + 0, + ); + // SAFETY: + // - If `$ty` is `Sized`, `size_of_val_raw` is always safe to call. + // - Otherwise: + // - If `$ty` is not a slice DST, this pointer conversion will + // fail due to "mismatched vtable kinds", and compilation will + // fail. + // - If `$ty` is a slice DST, the safety requirement is that "the + // length of the slice tail must be an initialized integer, and + // the size of the entire value (dynamic tail length + + // statically sized prefix) must fit in isize." The length is + // initialized to 0 above, and Rust guarantees that no type's + // minimum size may overflow `isize`. [1] + // + // [1] TODO(#429), + // TODO(https://github.com/rust-lang/unsafe-code-guidelines/issues/465#issuecomment-1782206516): + // Citation for this? + unsafe { + #[allow(clippy::as_conversions)] + $crate::macro_util::core_reexport::mem::size_of_val_raw(zero_elems as *const $ty) + } + }; + + assert!(min_size <= _64K); + + #[allow(clippy::as_conversions)] + let ptr = ALIGNED_64K_ALLOCATION.as_ptr() as *const $ty; + + // SAFETY: + // - Thanks to the preceding `assert!`, we know that the value with zero + // elements fits in `_64K` bytes, and thus in the allocation addressed + // by `ALIGNED_64K_ALLOCATION`. The offset of the trailing field is + // guaranteed to be no larger than this size, so this field projection + // is guaranteed to remain in-bounds of its allocation. + // - Because the minimum size is no larger than `_64K` bytes, and + // because an object's size must always be a multiple of its alignment + // [1], we know that `$ty`'s alignment is no larger than `_64K`. The + // allocation addressed by `ALIGNED_64K_ALLOCATION` is guaranteed to + // be aligned to `_64K`, so `ptr` is guaranteed to satisfy `$ty`'s + // alignment. + // + // Note that, as of [2], this requirement is technically unnecessary + // for Rust versions >= 1.75.0, but no harm in guaranteeing it anyway + // until we bump our MSRV. + // + // [1] Per https://doc.rust-lang.org/reference/type-layout.html: + // + // The size of a value is always a multiple of its alignment. + // + // [2] https://github.com/rust-lang/reference/pull/1387 + let field = unsafe { + $crate::macro_util::core_reexport::ptr::addr_of!((*ptr).$trailing_field_name) + }; + // SAFETY: + // - Both `ptr` and `field` are derived from the same allocated object. + // - By the preceding safety comment, `field` is in bounds of that + // allocated object. + // - The distance, in bytes, between `ptr` and `field` is required to be + // a multiple of the size of `u8`, which is trivially true because + // `u8`'s size is 1. + // - The distance, in bytes, cannot overflow `isize`. This is guaranteed + // because no allocated object can have a size larger than can fit in + // `isize`. [1] + // - The distance being in-bounds cannot rely on wrapping around the + // address space. This is guaranteed because the same is guaranteed of + // allocated objects. [1] + // + // [1] TODO(#429), TODO(https://github.com/rust-lang/rust/pull/116675): + // Once these are guaranteed in the Reference, cite it. + let offset = unsafe { field.cast::().offset_from(ptr.cast::()) }; + // Guaranteed not to be lossy: `field` comes after `ptr`, so the offset + // from `ptr` to `field` is guaranteed to be positive. + assert!(offset >= 0); + Some( + #[allow(clippy::as_conversions)] + { + offset as usize + }, + ) + }}; +} + +/// Computes alignment of `$ty: ?Sized`. +/// +/// `align_of!` produces code which is valid in a `const` context. +// TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove this +// `cfg` when `size_of_val_raw` is stabilized. +#[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! align_of { + ($ty:ty) => {{ + // SAFETY: `OffsetOfTrailingIsAlignment` is `repr(C)`, and its layout is + // guaranteed [1] to begin with the single-byte layout for `_byte`, + // followed by the padding needed to align `_trailing`, then the layout + // for `_trailing`, and finally any trailing padding bytes needed to + // correctly-align the entire struct. + // + // This macro computes the alignment of `$ty` by counting the number of + // bytes preceeding `_trailing`. For instance, if the alignment of `$ty` + // is `1`, then no padding is required align `_trailing` and it will be + // located immediately after `_byte` at offset 1. If the alignment of + // `$ty` is 2, then a single padding byte is required before + // `_trailing`, and `_trailing` will be located at offset 2. + + // This correspondence between offset and alignment holds for all valid + // Rust alignments, and we confirm this exhaustively (or, at least up to + // the maximum alignment supported by `trailing_field_offset!`) in + // `test_align_of_dst`. + // + // [1]: https://doc.rust-lang.org/nomicon/other-reprs.html#reprc + + #[repr(C)] + struct OffsetOfTrailingIsAlignment { + _byte: u8, + _trailing: $ty, + } + + trailing_field_offset!(OffsetOfTrailingIsAlignment, _trailing) + }}; +} + +/// Does the struct type `$t` have padding? +/// +/// `$ts` is the list of the type of every field in `$t`. `$t` must be a +/// struct type, or else `struct_has_padding!`'s result may be meaningless. +/// +/// Note that `struct_has_padding!`'s results are independent of `repr` since +/// they only consider the size of the type and the sizes of the fields. +/// Whatever the repr, the size of the type already takes into account any +/// padding that the compiler has decided to add. Structs with well-defined +/// representations (such as `repr(C)`) can use this macro to check for padding. +/// Note that while this may yield some consistent value for some `repr(Rust)` +/// structs, it is not guaranteed across platforms or compilations. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! struct_has_padding { + ($t:ty, $($ts:ty),*) => { + core::mem::size_of::<$t>() > 0 $(+ core::mem::size_of::<$ts>())* + }; +} + +/// Does the union type `$t` have padding? +/// +/// `$ts` is the list of the type of every field in `$t`. `$t` must be a +/// union type, or else `union_has_padding!`'s result may be meaningless. +/// +/// Note that `union_has_padding!`'s results are independent of `repr` since +/// they only consider the size of the type and the sizes of the fields. +/// Whatever the repr, the size of the type already takes into account any +/// padding that the compiler has decided to add. Unions with well-defined +/// representations (such as `repr(C)`) can use this macro to check for padding. +/// Note that while this may yield some consistent value for some `repr(Rust)` +/// unions, it is not guaranteed across platforms or compilations. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! union_has_padding { + ($t:ty, $($ts:ty),*) => { + false $(|| core::mem::size_of::<$t>() != core::mem::size_of::<$ts>())* + }; +} + +/// Does `t` have alignment greater than or equal to `u`? If not, this macro +/// produces a compile error. It must be invoked in a dead codepath. This is +/// used in `transmute_ref!` and `transmute_mut!`. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! assert_align_gt_eq { + ($t:ident, $u: ident) => {{ + // The comments here should be read in the context of this macro's + // invocations in `transmute_ref!` and `transmute_mut!`. + if false { + // The type wildcard in this bound is inferred to be `T` because + // `align_of.into_t()` is assigned to `t` (which has type `T`). + let align_of: $crate::macro_util::AlignOf<_> = unreachable!(); + $t = align_of.into_t(); + // `max_aligns` is inferred to have type `MaxAlignsOf` because + // of the inferred types of `t` and `u`. + let mut max_aligns = $crate::macro_util::MaxAlignsOf::new($t, $u); + + // This transmute will only compile successfully if + // `align_of::() == max(align_of::(), align_of::())` - in + // other words, if `align_of::() >= align_of::()`. + // + // SAFETY: This code is never run. + max_aligns = unsafe { $crate::macro_util::core_reexport::mem::transmute(align_of) }; + } else { + loop {} + } + }}; +} + +/// Do `t` and `u` have the same size? If not, this macro produces a compile +/// error. It must be invoked in a dead codepath. This is used in +/// `transmute_ref!` and `transmute_mut!`. +#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. +#[macro_export] +macro_rules! assert_size_eq { + ($t:ident, $u: ident) => {{ + // The comments here should be read in the context of this macro's + // invocations in `transmute_ref!` and `transmute_mut!`. + if false { + // SAFETY: This code is never run. + $u = unsafe { + // Clippy: It's okay to transmute a type to itself. + #[allow(clippy::useless_transmute)] + $crate::macro_util::core_reexport::mem::transmute($t) + }; + } else { + loop {} + } + }}; +} + +/// Transmutes a reference of one type to a reference of another type. +/// +/// # Safety +/// +/// The caller must guarantee that: +/// - `Src: AsBytes` +/// - `Dst: FromBytes` +/// - `size_of::() == size_of::()` +/// - `align_of::() >= align_of::()` +#[inline(always)] +pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + src: &'src Src, +) -> &'dst Dst { + let src: *const Src = src; + let dst = src.cast::(); + // SAFETY: + // - We know that it is sound to view the target type of the input reference + // (`Src`) as the target type of the output reference (`Dst`) because the + // caller has guaranteed that `Src: AsBytes`, `Dst: FromBytes`, and + // `size_of::() == size_of::()`. + // - We know that there are no `UnsafeCell`s, and thus we don't have to + // worry about `UnsafeCell` overlap, because `Src: AsBytes` and `Dst: + // FromBytes` both forbid `UnsafeCell`s. + // - The caller has guaranteed that alignment is not increased. + // - We know that the returned lifetime will not outlive the input lifetime + // thanks to the lifetime bounds on this function. + unsafe { &*dst } +} + +/// Transmutes a mutable reference of one type to a mutable reference of another +/// type. +/// +/// # Safety +/// +/// The caller must guarantee that: +/// - `Src: FromBytes + AsBytes` +/// - `Dst: FromBytes + AsBytes` +/// - `size_of::() == size_of::()` +/// - `align_of::() >= align_of::()` +#[inline(always)] +pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + src: &'src mut Src, +) -> &'dst mut Dst { + let src: *mut Src = src; + let dst = src.cast::(); + // SAFETY: + // - We know that it is sound to view the target type of the input reference + // (`Src`) as the target type of the output reference (`Dst`) and + // vice-versa because the caller has guaranteed that `Src: FromBytes + + // AsBytes`, `Dst: FromBytes + AsBytes`, and `size_of::() == + // size_of::()`. + // - We know that there are no `UnsafeCell`s, and thus we don't have to + // worry about `UnsafeCell` overlap, because `Src: FromBytes + AsBytes` + // and `Dst: FromBytes + AsBytes` forbid `UnsafeCell`s. + // - The caller has guaranteed that alignment is not increased. + // - We know that the returned lifetime will not outlive the input lifetime + // thanks to the lifetime bounds on this function. + unsafe { &mut *dst } +} + +// NOTE: We can't change this to a `pub use core as core_reexport` until [1] is +// fixed or we update to a semver-breaking version (as of this writing, 0.8.0) +// on the `main` branch. +// +// [1] https://github.com/obi1kenobi/cargo-semver-checks/issues/573 +pub mod core_reexport { + pub use core::*; + + pub mod mem { + pub use core::mem::*; + } +} + +#[cfg(test)] +mod tests { + use core::mem; + + use super::*; + use crate::util::testutil::*; + + #[test] + fn test_align_of() { + macro_rules! test { + ($ty:ty) => { + assert_eq!(mem::size_of::>(), mem::align_of::<$ty>()); + }; + } + + test!(()); + test!(u8); + test!(AU64); + test!([AU64; 2]); + } + + #[test] + fn test_max_aligns_of() { + macro_rules! test { + ($t:ty, $u:ty) => { + assert_eq!( + mem::size_of::>(), + core::cmp::max(mem::align_of::<$t>(), mem::align_of::<$u>()) + ); + }; + } + + test!(u8, u8); + test!(u8, AU64); + test!(AU64, u8); + } + + #[test] + fn test_typed_align_check() { + // Test that the type-based alignment check used in + // `assert_align_gt_eq!` behaves as expected. + + macro_rules! assert_t_align_gteq_u_align { + ($t:ty, $u:ty, $gteq:expr) => { + assert_eq!( + mem::size_of::>() == mem::size_of::>(), + $gteq + ); + }; + } + + assert_t_align_gteq_u_align!(u8, u8, true); + assert_t_align_gteq_u_align!(AU64, AU64, true); + assert_t_align_gteq_u_align!(AU64, u8, true); + assert_t_align_gteq_u_align!(u8, AU64, false); + } + + // TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove + // this `cfg` when `size_of_val_raw` is stabilized. + #[allow(clippy::decimal_literal_representation)] + #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] + #[test] + fn test_trailing_field_offset() { + assert_eq!(mem::align_of::(), _64K); + + macro_rules! test { + (#[$cfg:meta] ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => {{ + #[$cfg] + struct Test($($ts,)* $trailing_field_ty); + assert_eq!(test!(@offset $($ts),* ; $trailing_field_ty), $expect); + }}; + (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),* ; $trailing_field_ty:ty) => $expect:expr) => { + test!(#[$cfg] ($($ts),* ; $trailing_field_ty) => $expect); + test!($(#[$cfgs])* ($($ts),* ; $trailing_field_ty) => $expect); + }; + (@offset ; $_trailing:ty) => { trailing_field_offset!(Test, 0) }; + (@offset $_t:ty ; $_trailing:ty) => { trailing_field_offset!(Test, 1) }; + } + + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; u8) => Some(0)); + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)](; [u8]) => Some(0)); + test!(#[repr(C)] #[repr(packed)] (u8; u8) => Some(1)); + test!(#[repr(C)] (; AU64) => Some(0)); + test!(#[repr(C)] (; [AU64]) => Some(0)); + test!(#[repr(C)] (u8; AU64) => Some(8)); + test!(#[repr(C)] (u8; [AU64]) => Some(8)); + test!(#[repr(C)] (; Nested) => Some(0)); + test!(#[repr(C)] (; Nested) => Some(0)); + test!(#[repr(C)] (u8; Nested) => Some(8)); + test!(#[repr(C)] (u8; Nested) => Some(8)); + + // Test that `packed(N)` limits the offset of the trailing field. + test!(#[repr(C, packed( 1))] (u8; elain::Align< 2>) => Some( 1)); + test!(#[repr(C, packed( 2))] (u8; elain::Align< 4>) => Some( 2)); + test!(#[repr(C, packed( 4))] (u8; elain::Align< 8>) => Some( 4)); + test!(#[repr(C, packed( 8))] (u8; elain::Align< 16>) => Some( 8)); + test!(#[repr(C, packed( 16))] (u8; elain::Align< 32>) => Some( 16)); + test!(#[repr(C, packed( 32))] (u8; elain::Align< 64>) => Some( 32)); + test!(#[repr(C, packed( 64))] (u8; elain::Align< 128>) => Some( 64)); + test!(#[repr(C, packed( 128))] (u8; elain::Align< 256>) => Some( 128)); + test!(#[repr(C, packed( 256))] (u8; elain::Align< 512>) => Some( 256)); + test!(#[repr(C, packed( 512))] (u8; elain::Align< 1024>) => Some( 512)); + test!(#[repr(C, packed( 1024))] (u8; elain::Align< 2048>) => Some( 1024)); + test!(#[repr(C, packed( 2048))] (u8; elain::Align< 4096>) => Some( 2048)); + test!(#[repr(C, packed( 4096))] (u8; elain::Align< 8192>) => Some( 4096)); + test!(#[repr(C, packed( 8192))] (u8; elain::Align< 16384>) => Some( 8192)); + test!(#[repr(C, packed( 16384))] (u8; elain::Align< 32768>) => Some( 16384)); + test!(#[repr(C, packed( 32768))] (u8; elain::Align< 65536>) => Some( 32768)); + test!(#[repr(C, packed( 65536))] (u8; elain::Align< 131072>) => Some( 65536)); + /* Alignments above 65536 are not yet supported. + test!(#[repr(C, packed( 131072))] (u8; elain::Align< 262144>) => Some( 131072)); + test!(#[repr(C, packed( 262144))] (u8; elain::Align< 524288>) => Some( 262144)); + test!(#[repr(C, packed( 524288))] (u8; elain::Align< 1048576>) => Some( 524288)); + test!(#[repr(C, packed( 1048576))] (u8; elain::Align< 2097152>) => Some( 1048576)); + test!(#[repr(C, packed( 2097152))] (u8; elain::Align< 4194304>) => Some( 2097152)); + test!(#[repr(C, packed( 4194304))] (u8; elain::Align< 8388608>) => Some( 4194304)); + test!(#[repr(C, packed( 8388608))] (u8; elain::Align< 16777216>) => Some( 8388608)); + test!(#[repr(C, packed( 16777216))] (u8; elain::Align< 33554432>) => Some( 16777216)); + test!(#[repr(C, packed( 33554432))] (u8; elain::Align< 67108864>) => Some( 33554432)); + test!(#[repr(C, packed( 67108864))] (u8; elain::Align< 33554432>) => Some( 67108864)); + test!(#[repr(C, packed( 33554432))] (u8; elain::Align<134217728>) => Some( 33554432)); + test!(#[repr(C, packed(134217728))] (u8; elain::Align<268435456>) => Some(134217728)); + test!(#[repr(C, packed(268435456))] (u8; elain::Align<268435456>) => Some(268435456)); + */ + + // Test that `align(N)` does not limit the offset of the trailing field. + test!(#[repr(C, align( 1))] (u8; elain::Align< 2>) => Some( 2)); + test!(#[repr(C, align( 2))] (u8; elain::Align< 4>) => Some( 4)); + test!(#[repr(C, align( 4))] (u8; elain::Align< 8>) => Some( 8)); + test!(#[repr(C, align( 8))] (u8; elain::Align< 16>) => Some( 16)); + test!(#[repr(C, align( 16))] (u8; elain::Align< 32>) => Some( 32)); + test!(#[repr(C, align( 32))] (u8; elain::Align< 64>) => Some( 64)); + test!(#[repr(C, align( 64))] (u8; elain::Align< 128>) => Some( 128)); + test!(#[repr(C, align( 128))] (u8; elain::Align< 256>) => Some( 256)); + test!(#[repr(C, align( 256))] (u8; elain::Align< 512>) => Some( 512)); + test!(#[repr(C, align( 512))] (u8; elain::Align< 1024>) => Some( 1024)); + test!(#[repr(C, align( 1024))] (u8; elain::Align< 2048>) => Some( 2048)); + test!(#[repr(C, align( 2048))] (u8; elain::Align< 4096>) => Some( 4096)); + test!(#[repr(C, align( 4096))] (u8; elain::Align< 8192>) => Some( 8192)); + test!(#[repr(C, align( 8192))] (u8; elain::Align< 16384>) => Some( 16384)); + test!(#[repr(C, align( 16384))] (u8; elain::Align< 32768>) => Some( 32768)); + test!(#[repr(C, align( 32768))] (u8; elain::Align< 65536>) => Some( 65536)); + /* Alignments above 65536 are not yet supported. + test!(#[repr(C, align( 65536))] (u8; elain::Align< 131072>) => Some( 131072)); + test!(#[repr(C, align( 131072))] (u8; elain::Align< 262144>) => Some( 262144)); + test!(#[repr(C, align( 262144))] (u8; elain::Align< 524288>) => Some( 524288)); + test!(#[repr(C, align( 524288))] (u8; elain::Align< 1048576>) => Some( 1048576)); + test!(#[repr(C, align( 1048576))] (u8; elain::Align< 2097152>) => Some( 2097152)); + test!(#[repr(C, align( 2097152))] (u8; elain::Align< 4194304>) => Some( 4194304)); + test!(#[repr(C, align( 4194304))] (u8; elain::Align< 8388608>) => Some( 8388608)); + test!(#[repr(C, align( 8388608))] (u8; elain::Align< 16777216>) => Some( 16777216)); + test!(#[repr(C, align( 16777216))] (u8; elain::Align< 33554432>) => Some( 33554432)); + test!(#[repr(C, align( 33554432))] (u8; elain::Align< 67108864>) => Some( 67108864)); + test!(#[repr(C, align( 67108864))] (u8; elain::Align< 33554432>) => Some( 33554432)); + test!(#[repr(C, align( 33554432))] (u8; elain::Align<134217728>) => Some(134217728)); + test!(#[repr(C, align(134217728))] (u8; elain::Align<268435456>) => Some(268435456)); + */ + } + + // TODO(#29), TODO(https://github.com/rust-lang/rust/issues/69835): Remove + // this `cfg` when `size_of_val_raw` is stabilized. + #[allow(clippy::decimal_literal_representation)] + #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] + #[test] + fn test_align_of_dst() { + // Test that `align_of!` correctly computes the alignment of DSTs. + assert_eq!(align_of!([elain::Align<1>]), Some(1)); + assert_eq!(align_of!([elain::Align<2>]), Some(2)); + assert_eq!(align_of!([elain::Align<4>]), Some(4)); + assert_eq!(align_of!([elain::Align<8>]), Some(8)); + assert_eq!(align_of!([elain::Align<16>]), Some(16)); + assert_eq!(align_of!([elain::Align<32>]), Some(32)); + assert_eq!(align_of!([elain::Align<64>]), Some(64)); + assert_eq!(align_of!([elain::Align<128>]), Some(128)); + assert_eq!(align_of!([elain::Align<256>]), Some(256)); + assert_eq!(align_of!([elain::Align<512>]), Some(512)); + assert_eq!(align_of!([elain::Align<1024>]), Some(1024)); + assert_eq!(align_of!([elain::Align<2048>]), Some(2048)); + assert_eq!(align_of!([elain::Align<4096>]), Some(4096)); + assert_eq!(align_of!([elain::Align<8192>]), Some(8192)); + assert_eq!(align_of!([elain::Align<16384>]), Some(16384)); + assert_eq!(align_of!([elain::Align<32768>]), Some(32768)); + assert_eq!(align_of!([elain::Align<65536>]), Some(65536)); + /* Alignments above 65536 are not yet supported. + assert_eq!(align_of!([elain::Align<131072>]), Some(131072)); + assert_eq!(align_of!([elain::Align<262144>]), Some(262144)); + assert_eq!(align_of!([elain::Align<524288>]), Some(524288)); + assert_eq!(align_of!([elain::Align<1048576>]), Some(1048576)); + assert_eq!(align_of!([elain::Align<2097152>]), Some(2097152)); + assert_eq!(align_of!([elain::Align<4194304>]), Some(4194304)); + assert_eq!(align_of!([elain::Align<8388608>]), Some(8388608)); + assert_eq!(align_of!([elain::Align<16777216>]), Some(16777216)); + assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432)); + assert_eq!(align_of!([elain::Align<67108864>]), Some(67108864)); + assert_eq!(align_of!([elain::Align<33554432>]), Some(33554432)); + assert_eq!(align_of!([elain::Align<134217728>]), Some(134217728)); + assert_eq!(align_of!([elain::Align<268435456>]), Some(268435456)); + */ + } + + #[test] + fn test_struct_has_padding() { + // Test that, for each provided repr, `struct_has_padding!` reports the + // expected value. + macro_rules! test { + (#[$cfg:meta] ($($ts:ty),*) => $expect:expr) => {{ + #[$cfg] + struct Test($($ts),*); + assert_eq!(struct_has_padding!(Test, $($ts),*), $expect); + }}; + (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),*) => $expect:expr) => { + test!(#[$cfg] ($($ts),*) => $expect); + test!($(#[$cfgs])* ($($ts),*) => $expect); + }; + } + + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] () => false); + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8) => false); + test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8, ()) => false); + test!(#[repr(C)] #[repr(packed)] (u8, u8) => false); + + test!(#[repr(C)] (u8, AU64) => true); + // Rust won't let you put `#[repr(packed)]` on a type which contains a + // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here. + // It's not ideal, but it definitely has align > 1 on /some/ of our CI + // targets, and this isn't a particularly complex macro we're testing + // anyway. + test!(#[repr(packed)] (u8, u64) => false); + } + + #[test] + fn test_union_has_padding() { + // Test that, for each provided repr, `union_has_padding!` reports the + // expected value. + macro_rules! test { + (#[$cfg:meta] {$($fs:ident: $ts:ty),*} => $expect:expr) => {{ + #[$cfg] + #[allow(unused)] // fields are never read + union Test{ $($fs: $ts),* } + assert_eq!(union_has_padding!(Test, $($ts),*), $expect); + }}; + (#[$cfg:meta] $(#[$cfgs:meta])* {$($fs:ident: $ts:ty),*} => $expect:expr) => { + test!(#[$cfg] {$($fs: $ts),*} => $expect); + test!($(#[$cfgs])* {$($fs: $ts),*} => $expect); + }; + } + + test!(#[repr(C)] #[repr(packed)] {a: u8} => false); + test!(#[repr(C)] #[repr(packed)] {a: u8, b: u8} => false); + + // Rust won't let you put `#[repr(packed)]` on a type which contains a + // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here. + // It's not ideal, but it definitely has align > 1 on /some/ of our CI + // targets, and this isn't a particularly complex macro we're testing + // anyway. + test!(#[repr(C)] #[repr(packed)] {a: u8, b: u64} => true); + } +} diff --git a/src/macros.rs b/src/macros.rs index aebc8d6..2da78af 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,6 +1,10 @@ -// Copyright 2023 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// 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. /// Documents multiple unsafe blocks with a single safety comment. /// @@ -22,20 +26,46 @@ /// The macro invocations are emitted, each decorated with the following /// attribute: `#[allow(clippy::undocumented_unsafe_blocks)]`. macro_rules! safety_comment { - (#[doc = r" SAFETY:"] $($(#[doc = $_doc:literal])* $macro:ident!$args:tt;)*) => { - #[allow(clippy::undocumented_unsafe_blocks)] - const _: () = { $($macro!$args;)* }; + (#[doc = r" SAFETY:"] $($(#[$attr:meta])* $macro:ident!$args:tt;)*) => { + #[allow(clippy::undocumented_unsafe_blocks, unused_attributes)] + const _: () = { $($(#[$attr])* $macro!$args;)* }; } } /// Unsafely implements trait(s) for a type. +/// +/// # Safety +/// +/// The trait impl must be sound. +/// +/// When implementing `TryFromBytes`: +/// - If no `is_bit_valid` impl is provided, then it must be valid for +/// `is_bit_valid` to unconditionally return `true`. In other words, it must +/// be the case that any initialized sequence of bytes constitutes a valid +/// instance of `$ty`. +/// - If an `is_bit_valid` impl is provided, then: +/// - Regardless of whether the provided closure takes a `Ptr<$repr>` or +/// `&$repr` argument, it must be the case that, given `t: *mut $ty` and +/// `let r = t as *mut $repr`, `r` refers to an object of equal or lesser +/// size than the object referred to by `t`. +/// - If the provided closure takes a `&$repr` argument, then given a `Ptr<'a, +/// $ty>` which satisfies the preconditions of +/// `TryFromBytes::<$ty>::is_bit_valid`, it must be guaranteed that the +/// memory referenced by that `Ptr` always contains a valid `$repr`. +/// - The alignment of `$repr` is less than or equal to the alignment of +/// `$ty`. +/// - The impl of `is_bit_valid` must only return `true` for its argument +/// `Ptr<$repr>` if the original `Ptr<$ty>` refers to a valid `$ty`. macro_rules! unsafe_impl { // Implement `$trait` for `$ty` with no bounds. - ($ty:ty: $trait:ty) => { - unsafe impl $trait for $ty { #[allow(clippy::missing_inline_in_public_items)] fn only_derive_is_allowed_to_implement_this_trait() {} } + ($(#[$attr:meta])* $ty:ty: $trait:ident $(; |$candidate:ident: &$repr:ty| $is_bit_valid:expr)?) => { + $(#[$attr])* + unsafe impl $trait for $ty { + unsafe_impl!(@method $trait $(; |$candidate: &$repr| $is_bit_valid)?); + } }; // Implement all `$traits` for `$ty` with no bounds. - ($ty:ty: $($traits:ty),*) => { + ($ty:ty: $($traits:ident),*) => { $( unsafe_impl!($ty: $traits); )* }; // This arm is identical to the following one, except it contains a @@ -64,40 +94,142 @@ macro_rules! unsafe_impl { // The following arm has the same behavior with the exception of the lack of // support for a leading `const` parameter. ( + $(#[$attr:meta])* const $constname:ident : $constty:ident $(,)? $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* - => $trait:ident for $ty:ty + => $trait:ident for $ty:ty $(; |$candidate:ident $(: &$ref_repr:ty)? $(: Ptr<$ptr_repr:ty>)?| $is_bit_valid:expr)? ) => { unsafe_impl!( @inner + $(#[$attr])* @const $constname: $constty, $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)* - => $trait for $ty + => $trait for $ty $(; |$candidate $(: &$ref_repr)? $(: Ptr<$ptr_repr>)?| $is_bit_valid)? ); }; ( + $(#[$attr:meta])* $($tyvar:ident $(: $(? $optbound:ident $(+)?)* $($bound:ident $(+)?)* )?),* - => $trait:ident for $ty:ty + => $trait:ident for $ty:ty $(; |$candidate:ident $(: &$ref_repr:ty)? $(: Ptr<$ptr_repr:ty>)?| $is_bit_valid:expr)? ) => { unsafe_impl!( @inner + $(#[$attr])* $($tyvar $(: $(? $optbound +)* + $($bound +)*)?,)* - => $trait for $ty + => $trait for $ty $(; |$candidate $(: &$ref_repr)? $(: Ptr<$ptr_repr>)?| $is_bit_valid)? ); }; ( @inner + $(#[$attr:meta])* $(@const $constname:ident : $constty:ident,)* $($tyvar:ident $(: $(? $optbound:ident +)* + $($bound:ident +)* )?,)* - => $trait:ident for $ty:ty + => $trait:ident for $ty:ty $(; |$candidate:ident $(: &$ref_repr:ty)? $(: Ptr<$ptr_repr:ty>)?| $is_bit_valid:expr)? ) => { + $(#[$attr])* unsafe impl<$(const $constname: $constty,)* $($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> $trait for $ty { + unsafe_impl!(@method $trait $(; |$candidate: $(&$ref_repr)? $(Ptr<$ptr_repr>)?| $is_bit_valid)?); + } + }; + + (@method TryFromBytes ; |$candidate:ident: &$repr:ty| $is_bit_valid:expr) => { + #[inline] + unsafe fn is_bit_valid(candidate: Ptr<'_, Self>) -> bool { + // SAFETY: + // - The argument to `cast_unsized` is `|p| p as *mut _` as required + // by that method's safety precondition. + // - The caller has promised that the cast results in an object of + // equal or lesser size. + // - The caller has promised that `$repr`'s alignment is less than + // or equal to `Self`'s alignment. + #[allow(clippy::as_conversions)] + let candidate = unsafe { candidate.cast_unsized::<$repr, _>(|p| p as *mut _) }; + // SAFETY: + // - The caller has promised that the referenced memory region will + // contain a valid `$repr` for `'a`. + // - The memory may not be referenced by any mutable references. + // This is a precondition of `is_bit_valid`. + // - The memory may not be mutated even via `UnsafeCell`s. This is a + // precondition of `is_bit_valid`. + // - There must not exist any references to the same memory region + // which contain `UnsafeCell`s at byte ranges which are not + // identical to the byte ranges at which `T` contains + // `UnsafeCell`s. This is a precondition of `is_bit_valid`. + let $candidate: &$repr = unsafe { candidate.as_ref() }; + $is_bit_valid + } + }; + (@method TryFromBytes ; |$candidate:ident: Ptr<$repr:ty>| $is_bit_valid:expr) => { + #[inline] + unsafe fn is_bit_valid(candidate: Ptr<'_, Self>) -> bool { + // SAFETY: + // - The argument to `cast_unsized` is `|p| p as *mut _` as required + // by that method's safety precondition. + // - The caller has promised that the cast results in an object of + // equal or lesser size. + // - The caller has promised that `$repr`'s alignment is less than + // or equal to `Self`'s alignment. + #[allow(clippy::as_conversions)] + let $candidate = unsafe { candidate.cast_unsized::<$repr, _>(|p| p as *mut _) }; + $is_bit_valid + } + }; + (@method TryFromBytes) => { #[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() {} + }; + (@method $trait:ident; |$_candidate:ident $(: &$_ref_repr:ty)? $(: NonNull<$_ptr_repr:ty>)?| $_is_bit_valid:expr) => { + compile_error!("Can't provide `is_bit_valid` impl for trait other than `TryFromBytes`"); + }; +} + +/// Implements a trait for a type, bounding on each memeber of the power set of +/// a set of type variables. This is useful for implementing traits for tuples +/// or `fn` types. +/// +/// The last argument is the name of a macro which will be called in every +/// `impl` block, and is expected to expand to the name of the type for which to +/// implement the trait. +/// +/// For example, the invocation: +/// ```ignore +/// unsafe_impl_for_power_set!(A, B => Foo for type!(...)) +/// ``` +/// ...expands to: +/// ```ignore +/// unsafe impl Foo for type!() { ... } +/// unsafe impl Foo for type!(B) { ... } +/// unsafe impl Foo for type!(A, B) { ... } +/// ``` +macro_rules! unsafe_impl_for_power_set { + ($first:ident $(, $rest:ident)* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)) => { + unsafe_impl_for_power_set!($($rest),* $(-> $ret)? => $trait for $macro!(...)); + unsafe_impl_for_power_set!(@impl $first $(, $rest)* $(-> $ret)? => $trait for $macro!(...)); + }; + ($(-> $ret:ident)? => $trait:ident for $macro:ident!(...)) => { + unsafe_impl_for_power_set!(@impl $(-> $ret)? => $trait for $macro!(...)); + }; + (@impl $($vars:ident),* $(-> $ret:ident)? => $trait:ident for $macro:ident!(...)) => { + unsafe impl<$($vars,)* $($ret)?> $trait for $macro!($($vars),* $(-> $ret)?) { #[allow(clippy::missing_inline_in_public_items)] fn only_derive_is_allowed_to_implement_this_trait() {} } }; } +/// Expands to an `Option` type with the given argument types and +/// return type. Designed for use with `unsafe_impl_for_power_set`. +macro_rules! opt_extern_c_fn { + ($($args:ident),* -> $ret:ident) => { Option $ret> }; +} + +/// Expands to a `Option` type with the given argument types and return +/// type. Designed for use with `unsafe_impl_for_power_set`. +macro_rules! opt_fn { + ($($args:ident),* -> $ret:ident) => { Option $ret> }; +} + /// Implements trait(s) for a type or verifies the given implementation by /// referencing an existing (derived) implementation. /// @@ -204,11 +336,26 @@ macro_rules! impl_known_layout { }; ($($ty:ty),*) => { $(impl_known_layout!(@inner , => $ty);)* }; (@inner $(const $constvar:ident : $constty:ty)? , $($tyvar:ident $(: ?$optbound:ident)?)? => $ty:ty) => { - impl<$(const $constvar : $constty,)? $($tyvar $(: ?$optbound)?)?> sealed::KnownLayoutSealed for $ty {} - // SAFETY: Delegates safety to `DstLayout::for_type`. - unsafe impl<$(const $constvar : $constty,)? $($tyvar $(: ?$optbound)?)?> KnownLayout for $ty { - const LAYOUT: DstLayout = DstLayout::for_type::<$ty>(); - } + const _: () = { + use core::ptr::NonNull; + + // SAFETY: Delegates safety to `DstLayout::for_type`. + unsafe impl<$(const $constvar : $constty,)? $($tyvar $(: ?$optbound)?)?> KnownLayout for $ty { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() where Self: Sized {} + + const LAYOUT: DstLayout = DstLayout::for_type::<$ty>(); + + // SAFETY: `.cast` preserves address and provenance. + // + // TODO(#429): Add documentation to `.cast` that promises that + // it preserves provenance. + #[inline(always)] + fn raw_from_ptr_len(bytes: NonNull, _elems: usize) -> NonNull { + bytes.cast::() + } + } + }; }; } @@ -225,10 +372,30 @@ macro_rules! impl_known_layout { /// and this operation must preserve referent size (ie, `size_of_val_raw`). macro_rules! unsafe_impl_known_layout { ($($tyvar:ident: ?Sized + KnownLayout =>)? #[repr($repr:ty)] $ty:ty) => { - impl<$($tyvar: ?Sized + KnownLayout)?> sealed::KnownLayoutSealed for $ty {} - unsafe impl<$($tyvar: ?Sized + KnownLayout)?> KnownLayout for $ty { - const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT; - } + const _: () = { + use core::ptr::NonNull; + + unsafe impl<$($tyvar: ?Sized + KnownLayout)?> KnownLayout for $ty { + #[allow(clippy::missing_inline_in_public_items)] + fn only_derive_is_allowed_to_implement_this_trait() {} + + const LAYOUT: DstLayout = <$repr as KnownLayout>::LAYOUT; + + // SAFETY: All operations preserve address and provenance. + // Caller has promised that the `as` cast preserves size. + // + // TODO(#429): Add documentation to `NonNull::new_unchecked` + // that it preserves provenance. + #[inline(always)] + #[allow(unused_qualifications)] // for `core::ptr::NonNull` + fn raw_from_ptr_len(bytes: NonNull, elems: usize) -> NonNull { + #[allow(clippy::as_conversions)] + let ptr = <$repr>::raw_from_ptr_len(bytes, elems).as_ptr() as *mut Self; + // SAFETY: `ptr` was converted from `bytes`, which is non-null. + unsafe { NonNull::new_unchecked(ptr) } + } + } + }; }; } diff --git a/src/third_party/rust/LICENSE-APACHE b/src/third_party/rust/LICENSE-APACHE new file mode 100644 index 0000000..1b5ec8b --- /dev/null +++ b/src/third_party/rust/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/src/third_party/rust/LICENSE-MIT b/src/third_party/rust/LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/src/third_party/rust/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/third_party/rust/README.fuchsia b/src/third_party/rust/README.fuchsia new file mode 100644 index 0000000..e0a23dd --- /dev/null +++ b/src/third_party/rust/README.fuchsia @@ -0,0 +1,7 @@ +Name: rust +License File: LICENSE-APACHE +License File: LICENSE-MIT +Description: + +See https://github.com/google/zerocopy/pull/492 for an explanation of why this +file exists. diff --git a/src/third_party/rust/layout.rs b/src/third_party/rust/layout.rs new file mode 100644 index 0000000..19ef7c6 --- /dev/null +++ b/src/third_party/rust/layout.rs @@ -0,0 +1,45 @@ +use core::num::NonZeroUsize; + +/// Returns the amount of padding we must insert after `len` bytes to ensure +/// that the following address will satisfy `align` (measured in bytes). +/// +/// e.g., if `len` is 9, then `padding_needed_for(len, 4)` returns 3, because +/// that is the minimum number of bytes of padding required to get a 4-aligned +/// address (assuming that the corresponding memory block starts at a 4-aligned +/// address). +/// +/// The return value of this function has no meaning if `align` is not a +/// power-of-two. +/// +/// # Panics +/// +/// May panic if `align` is not a power of two. +// +// TODO(#419): Replace `len` with a witness type for region size. +#[allow(unused)] +#[inline(always)] +pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize { + // Rounded up value is: + // len_rounded_up = (len + align - 1) & !(align - 1); + // and then we return the padding difference: `len_rounded_up - len`. + // + // We use modular arithmetic throughout: + // + // 1. align is guaranteed to be > 0, so align - 1 is always + // valid. + // + // 2. `len + align - 1` can overflow by at most `align - 1`, + // so the &-mask with `!(align - 1)` will ensure that in the + // case of overflow, `len_rounded_up` will itself be 0. + // Thus the returned padding, when added to `len`, yields 0, + // which trivially satisfies the alignment `align`. + // + // (Of course, attempts to allocate blocks of memory whose + // size and padding overflow in the above manner should cause + // the allocator to yield an error anyway.) + + let align = align.get(); + debug_assert!(align.is_power_of_two()); + let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1); + len_rounded_up.wrapping_sub(len) +} diff --git a/src/util.rs b/src/util.rs index ed810dc..b35cc07 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,552 @@ -// Copyright 2023 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// 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. -use core::mem; +#[path = "third_party/rust/layout.rs"] +pub(crate) mod core_layout; + +use core::{mem, num::NonZeroUsize}; + +pub(crate) mod ptr { + use core::{ + fmt::{Debug, Formatter}, + marker::PhantomData, + ptr::NonNull, + }; + + use crate::{util::AsAddress, KnownLayout, _CastType}; + + /// A raw pointer with more restrictions. + /// + /// `Ptr` is similar to `NonNull`, but it is more restrictive in the + /// following ways: + /// - It must derive from a valid allocation + /// - It must reference a byte range which is contained inside the + /// allocation from which it derives + /// - As a consequence, the byte range it references must have a size + /// which does not overflow `isize` + /// - It must satisfy `T`'s alignment requirement + /// + /// Thanks to these restrictions, it is easier to prove the soundness of + /// some operations using `Ptr`s. + /// + /// `Ptr<'a, T>` is [covariant] in `'a` and `T`. + /// + /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html + pub struct Ptr<'a, T: 'a + ?Sized> { + // INVARIANTS: + // 1. `ptr` is derived from some valid Rust allocation, `A` + // 2. `ptr` has the same provenance as `A` + // 3. `ptr` addresses a byte range which is entirely contained in `A` + // 4. `ptr` addresses a byte range whose length fits in an `isize` + // 5. `ptr` addresses a byte range which does not wrap around the address + // space + // 6. `ptr` is validly-aligned for `T` + // 7. `A` is guaranteed to live for at least `'a` + // 8. `T: 'a` + ptr: NonNull, + _lifetime: PhantomData<&'a ()>, + } + + impl<'a, T: ?Sized> Copy for Ptr<'a, T> {} + impl<'a, T: ?Sized> Clone for Ptr<'a, T> { + #[inline] + fn clone(&self) -> Self { + *self + } + } + + impl<'a, T: ?Sized> Ptr<'a, T> { + /// Returns a shared reference to the value. + /// + /// # Safety + /// + /// For the duration of `'a`: + /// - The referenced memory must contain a validly-initialized `T` for + /// the duration of `'a`. + /// - The referenced memory must not also be referenced by any mutable + /// references. + /// - The referenced memory must not be mutated, even via an + /// [`UnsafeCell`]. + /// - There must not exist any references to the same memory region + /// which contain `UnsafeCell`s at byte ranges which are not identical + /// to the byte ranges at which `T` contains `UnsafeCell`s. + /// + /// [`UnsafeCell`]: core::cell::UnsafeCell + // TODO(#429): The safety requirements are likely overly-restrictive. + // Notably, mutation via `UnsafeCell`s is probably fine. Once the rules + // are more clearly defined, we should relax the safety requirements. + // For an example of why this is subtle, see: + // https://github.com/rust-lang/unsafe-code-guidelines/issues/463#issuecomment-1736771593 + #[allow(unused)] + pub(crate) unsafe fn as_ref(&self) -> &'a T { + // SAFETY: + // - By invariant, `self.ptr` is properly-aligned for `T`. + // - By invariant, `self.ptr` is "dereferenceable" in that it points + // to a single allocation. + // - By invariant, the allocation is live for `'a`. + // - The caller promises that no mutable references exist to this + // region during `'a`. + // - The caller promises that `UnsafeCell`s match exactly. + // - The caller promises that no mutation will happen during `'a`, + // even via `UnsafeCell`s. + // - The caller promises that the memory region contains a + // validly-intialized `T`. + unsafe { self.ptr.as_ref() } + } + + /// Casts to a different (unsized) target type. + /// + /// # Safety + /// + /// The caller promises that + /// - `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 less + /// 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>( + self, + cast: F, + ) -> Ptr<'a, U> { + let ptr = cast(self.ptr.as_ptr()); + // SAFETY: Caller promises that `cast` is just an `as` cast. We call + // `cast` on `self.ptr.as_ptr()`, which is non-null by construction. + let ptr = unsafe { NonNull::new_unchecked(ptr) }; + // SAFETY: + // - By invariant, `self.ptr` is derived from some valid Rust + // allocation, and since `ptr` is just `self.ptr as *mut U`, so is + // `ptr`. + // - By invariant, `self.ptr` has the same provenance as `A`, and so + // the same is true of `ptr`. + // - By invariant, `self.ptr` addresses a byte range which is + // entirely contained in `A`, and so the same is true of `ptr`. + // - By invariant, `self.ptr` addresses a byte range whose length + // fits in an `isize`, and so the same is true of `ptr`. + // - By invariant, `self.ptr` addresses a byte range which does not + // wrap around the address space, and so the same is true of + // `ptr`. + // - By invariant, `self.ptr` is validly-aligned for `T`. Since + // `ptr` has the same address, and since the caller promises that + // the alignment of `U` is less than or equal to the alignment of + // `T`, `ptr` is validly-aligned for `U`. + // - By invariant, `A` is guaranteed to live for at least `'a`. + // - `U: 'a` + Ptr { ptr, _lifetime: PhantomData } + } + } + + impl<'a> Ptr<'a, [u8]> { + /// Attempts to cast `self` to a `U` using the given cast type. + /// + /// Returns `None` if the resulting `U` would be invalidly-aligned or if + /// no `U` can fit in `self`. On success, returns a pointer to the + /// largest-possible `U` which fits in `self`. + /// + /// # Safety + /// + /// The caller may assume that this implementation is correct, and may + /// rely on that assumption for the soundness of their code. In + /// particular, the caller may assume that, if `try_cast_into` returns + /// `Some((ptr, split_at))`, then: + /// - If this is a prefix cast, `ptr` refers to the byte range `[0, + /// split_at)` in `self`. + /// - If this is a suffix cast, `ptr` refers to the byte range + /// `[split_at, self.len())` in `self`. + /// + /// # Panics + /// + /// Panics if `U` is a DST whose trailing slice element is zero-sized. + pub(crate) fn try_cast_into( + &self, + cast_type: _CastType, + ) -> Option<(Ptr<'a, U>, usize)> { + // PANICS: By invariant, the byte range addressed by `self.ptr` does + // not wrap around the address space. This implies that the sum of + // the address (represented as a `usize`) and length do not overflow + // `usize`, as required by `validate_cast_and_convert_metadata`. + // Thus, this call to `validate_cast_and_convert_metadata` won't + // panic. + let (elems, split_at) = U::LAYOUT.validate_cast_and_convert_metadata( + AsAddress::addr(self.ptr.as_ptr()), + self.len(), + cast_type, + )?; + let offset = match cast_type { + _CastType::_Prefix => 0, + _CastType::_Suffix => split_at, + }; + + let ptr = self.ptr.cast::().as_ptr(); + // SAFETY: `offset` is either `0` or `split_at`. + // `validate_cast_and_convert_metadata` promises that `split_at` is + // in the range `[0, self.len()]`. Thus, in both cases, `offset` is + // in `[0, self.len()]`. Thus: + // - The resulting pointer is in or one byte past the end of the + // same byte range as `self.ptr`. Since, by invariant, `self.ptr` + // addresses a byte range entirely contained within a single + // allocation, the pointer resulting from this operation is within + // or one byte past the end of that same allocation. + // - By invariant, `self.len() <= isize::MAX`. Since `offset <= + // self.len()`, `offset <= isize::MAX`. + // - By invariant, `self.ptr` addresses a byte range which does not + // wrap around the address space. This means that the base pointer + // plus the `self.len()` does not overflow `usize`. Since `offset + // <= self.len()`, this addition does not overflow `usize`. + let base = unsafe { ptr.add(offset) }; + // SAFETY: Since `add` is not allowed to wrap around, the preceding line + // produces a pointer whose address is greater than or equal to that of + // `ptr`. Since `ptr` is a `NonNull`, `base` is also non-null. + let base = unsafe { NonNull::new_unchecked(base) }; + let ptr = U::raw_from_ptr_len(base, elems); + // SAFETY: + // - By invariant, `self.ptr` is derived from some valid Rust + // allocation, `A`, and has the same provenance as `A`. All + // operations performed on `self.ptr` and values derived from it + // in this method preserve provenance, so: + // - `ptr` is derived from a valid Rust allocation, `A`. + // - `ptr` has the same provenance as `A`. + // - `validate_cast_and_convert_metadata` promises that the object + // described by `elems` and `split_at` lives at a byte range which + // is a subset of the input byte range. Thus: + // - Since, by invariant, `self.ptr` addresses a byte range + // entirely contained in `A`, so does `ptr`. + // - Since, by invariant, `self.ptr` addresses a range whose + // length is not longer than `isize::MAX` bytes, so does `ptr`. + // - Since, by invariant, `self.ptr` addresses a range which does + // not wrap around the address space, so does `ptr`. + // - `validate_cast_and_convert_metadata` promises that the object + // described by `split_at` is validly-aligned for `U`. + // - By invariant on `self`, `A` is guaranteed to live for at least + // `'a`. + // - `U: 'a` by trait bound. + Some((Ptr { ptr, _lifetime: PhantomData }, split_at)) + } + + /// Attempts to cast `self` into a `U`, failing if all of the bytes of + /// `self` cannot be treated as a `U`. + /// + /// In particular, this method fails if `self` is not validly-aligned + /// for `U` or if `self`'s size is not a valid size for `U`. + /// + /// # Safety + /// + /// On success, the caller may assume that the returned pointer + /// references the same byte range as `self`. + #[allow(unused)] + #[inline(always)] + pub(crate) fn try_cast_into_no_leftover( + &self, + ) -> Option> { + // TODO(#67): Remove this allow. See NonNulSlicelExt for more + // details. + #[allow(unstable_name_collisions)] + match self.try_cast_into(_CastType::_Prefix) { + Some((slf, split_at)) if split_at == self.len() => Some(slf), + Some(_) | None => None, + } + } + } + + impl<'a, T> Ptr<'a, [T]> { + /// The number of slice elements referenced by `self`. + /// + /// # Safety + /// + /// Unsafe code my rely on `len` satisfying the above contract. + fn len(&self) -> usize { + #[allow(clippy::as_conversions)] + let slc = self.ptr.as_ptr() as *const [()]; + // SAFETY: + // - `()` has alignment 1, so `slc` is trivially aligned. + // - `slc` was derived from a non-null pointer. + // - The size is 0 regardless of the length, so it is sound to + // materialize a reference regardless of location. + // - By invariant, `self.ptr` has valid provenance. + let slc = unsafe { &*slc }; + // This is correct because the preceding `as` cast preserves the + // number of slice elements. Per + // https://doc.rust-lang.org/nightly/reference/expressions/operator-expr.html#slice-dst-pointer-to-pointer-cast: + // + // For slice types like `[T]` and `[U]`, the raw pointer types + // `*const [T]`, `*mut [T]`, `*const [U]`, and `*mut [U]` encode + // the number of elements in this slice. Casts between these raw + // pointer types preserve the number of elements. Note that, as a + // consequence, such casts do *not* necessarily preserve the size + // of the pointer's referent (e.g., casting `*const [u16]` to + // `*const [u8]` will result in a raw pointer which refers to an + // object of half the size of the original). The same holds for + // `str` and any compound type whose unsized tail is a slice type, + // such as struct `Foo(i32, [u8])` or `(u64, Foo)`. + // + // TODO(#429), + // TODO(https://github.com/rust-lang/reference/pull/1417): Once this + // text is available on the Stable docs, cite those instead of the + // Nightly docs. + slc.len() + } + + pub(crate) fn iter(&self) -> impl Iterator> { + // TODO(#429): Once `NonNull::cast` documents that it preserves + // provenance, cite those docs. + let base = self.ptr.cast::().as_ptr(); + (0..self.len()).map(move |i| { + // TODO(https://github.com/rust-lang/rust/issues/74265): Use + // `NonNull::get_unchecked_mut`. + + // SAFETY: If the following conditions are not satisfied + // `pointer::cast` may induce Undefined Behavior [1]: + // > 1. Both the starting and resulting pointer must be either + // > in bounds or one byte past the end of the same allocated + // > object. + // > 2. The computed offset, in bytes, cannot overflow an + // > `isize`. + // > 3. The offset being in bounds cannot rely on “wrapping + // > around” the address space. That is, the + // > infinite-precision sum must fit in a `usize`. + // + // [1] https://doc.rust-lang.org/std/primitive.pointer.html#method.add + // + // We satisfy all three of these conditions here: + // 1. `base` (by invariant on `self`) points to an allocated + // object. By contract, `self.len()` accurately reflects the + // number of elements in the slice. `i` is in bounds of + // `c.len()` by construction, and so the result of this + // addition cannot overflow past the end of the allocation + // referred to by `c`. + // 2. By invariant on `Ptr`, `self` addresses a byte range whose + // length fits in an `isize`. Since `elem` is contained in + // `self`, the computed offset of `elem` must fit within + // `isize.` + // 3. By invariant on `Ptr`, `self` addresses a byte range which + // does not wrap around the address space. Since `elem` is + // contained in `self`, the computed offset of `elem` must + // wrap around the address space. + // + // TODO(#429): Once `pointer::add` documents that it preserves + // provenance, cite those docs. + let elem = unsafe { base.add(i) }; + + // SAFETY: + // - `elem` must not be null. `base` is constructed from a + // `NonNull` pointer, and the addition that produces `elem` + // must not overflow or wrap around, so `elem >= base > 0`. + // + // TODO(#429): Once `NonNull::new_unchecked` documents that it + // preserves provenance, cite those docs. + let elem = unsafe { NonNull::new_unchecked(elem) }; + + // SAFETY: The safety invariants of `Ptr` (see definition) are + // satisfied: + // 1. `elem` is derived from a valid Rust allocation, because + // `self` is derived from a valid Rust allocation, by + // invariant on `Ptr` + // 2. `elem` has the same provenance as `self`, because it + // derived from `self` using a series of + // provenance-preserving operations + // 3. `elem` is entirely contained in the allocation of `self` + // (see above) + // 4. `elem` addresses a byte range whose length fits in an + // `isize` (see above) + // 5. `elem` addresses a byte range which does not wrap around + // the address space (see above) + // 6. `elem` is validly-aligned for `T`. `self`, which + // represents a `[T]` is validly aligned for `T`, and `elem` + // is an element within that `[T]` + // 7. The allocation of `elem` is guaranteed to live for at + // least `'a`, because `elem` is entirely contained in + // `self`, which lives for at least `'a` by invariant on + // `Ptr`. + // 8. `T: 'a`, because `elem` is an element within `[T]`, and + // `[T]: 'a` by invariant on `Ptr` + Ptr { ptr: elem, _lifetime: PhantomData } + }) + } + } + + impl<'a, T: 'a + ?Sized> From<&'a T> for Ptr<'a, T> { + #[inline(always)] + fn from(t: &'a T) -> Ptr<'a, T> { + // SAFETY: `t` points to a valid Rust allocation, `A`, by + // construction. Thus: + // - `ptr` is derived from `A` + // - Since we use `NonNull::from`, which preserves provenance, `ptr` + // has the same provenance as `A` + // - Since `NonNull::from` creates a pointer which addresses the + // same bytes as `t`, `ptr` addresses a byte range entirely + // contained in (in this case, identical to) `A` + // - Since `t: &T`, it addresses no more than `isize::MAX` bytes [1] + // - Since `t: &T`, it addresses a byte range which does not wrap + // around the address space [2] + // - Since it is constructed from a valid `&T`, `ptr` is + // validly-aligned for `T` + // - Since `t: &'a T`, the allocation `A` is guaranteed to live for + // at least `'a` + // - `T: 'a` by trait bound + // + // TODO(#429), + // TODO(https://github.com/rust-lang/rust/issues/116181): Once it's + // documented, reference the guarantee that `NonNull::from` + // preserves provenance. + // + // TODO(#429), + // TODO(https://github.com/rust-lang/unsafe-code-guidelines/issues/465): + // - [1] Where does the reference document that allocations fit in + // `isize`? + // - [2] Where does the reference document that allocations don't + // wrap around the address space? + Ptr { ptr: NonNull::from(t), _lifetime: PhantomData } + } + } + + impl<'a, T: 'a + ?Sized> Debug for Ptr<'a, T> { + #[inline] + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + self.ptr.fmt(f) + } + } + + #[cfg(test)] + mod tests { + use core::mem::{self, MaybeUninit}; + + use super::*; + use crate::{util::testutil::AU64, FromBytes}; + + #[test] + fn test_ptrtry_cast_into_soundness() { + // This test is designed so that if `Ptr::try_cast_into_xxx` are + // buggy, it will manifest as unsoundness that Miri can detect. + + // - If `size_of::() == 0`, `N == 4` + // - Else, `N == 4 * size_of::()` + fn test() { + let mut bytes = [MaybeUninit::::uninit(); N]; + let initialized = [MaybeUninit::new(0u8); N]; + for start in 0..=bytes.len() { + for end in start..=bytes.len() { + // Set all bytes to uninitialized other than those in + // the range we're going to pass to `try_cast_from`. + // This allows Miri to detect out-of-bounds reads + // because they read uninitialized memory. Without this, + // some out-of-bounds reads would still be in-bounds of + // `bytes`, and so might spuriously be accepted. + bytes = [MaybeUninit::::uninit(); N]; + let bytes = &mut bytes[start..end]; + // Initialize only the byte range we're going to pass to + // `try_cast_from`. + bytes.copy_from_slice(&initialized[start..end]); + + let bytes = { + let bytes: *const [MaybeUninit] = bytes; + #[allow(clippy::as_conversions)] + let bytes = bytes as *const [u8]; + // SAFETY: We just initialized these bytes to valid + // `u8`s. + unsafe { &*bytes } + }; + + /// # Safety + /// + /// - `slf` must reference a byte range which is + /// entirely initialized. + /// - `slf` must reference a byte range which is only + /// referenced by shared references which do not + /// contain `UnsafeCell`s during its lifetime. + unsafe fn validate_and_get_len( + slf: Ptr<'_, T>, + ) -> usize { + // SAFETY: + // - Since all bytes in `slf` are initialized and + // `T: FromBytes`, `slf` contains a valid `T`. + // - The caller promises that the referenced memory + // is not also referenced by any mutable + // references. + // - The caller promises that the referenced memory + // is not also referenced as a type which contains + // `UnsafeCell`s. + let t = unsafe { slf.as_ref() }; + + let bytes = { + let len = mem::size_of_val(t); + let t: *const T = t; + // SAFETY: + // - We know `t`'s bytes are all initialized + // because we just read it from `slf`, which + // points to an initialized range of bytes. If + // there's a bug and this doesn't hold, then + // that's exactly what we're hoping Miri will + // catch! + // - Since `T: FromBytes`, `T` doesn't contain + // any `UnsafeCell`s, so it's okay for `t: T` + // and a `&[u8]` to the same memory to be + // alive concurrently. + unsafe { core::slice::from_raw_parts(t.cast::(), len) } + }; + + // This assertion ensures that `t`'s bytes are read + // and compared to another value, which in turn + // ensures that Miri gets a chance to notice if any + // of `t`'s bytes are uninitialized, which they + // shouldn't be (see the comment above). + assert_eq!(bytes, vec![0u8; bytes.len()]); + + mem::size_of_val(t) + } + + for cast_type in [_CastType::_Prefix, _CastType::_Suffix] { + if let Some((slf, split_at)) = + Ptr::from(bytes).try_cast_into::(cast_type) + { + // SAFETY: All bytes in `bytes` have been + // initialized. + let len = unsafe { validate_and_get_len(slf) }; + match cast_type { + _CastType::_Prefix => assert_eq!(split_at, len), + _CastType::_Suffix => assert_eq!(split_at, bytes.len() - len), + } + } + } + + if let Some(slf) = Ptr::from(bytes).try_cast_into_no_leftover::() { + // SAFETY: All bytes in `bytes` have been + // initialized. + let len = unsafe { validate_and_get_len(slf) }; + assert_eq!(len, bytes.len()); + } + } + } + } + + macro_rules! test { + ($($ty:ty),*) => { + $({ + const S: usize = core::mem::size_of::<$ty>(); + const N: usize = if S == 0 { 4 } else { S * 4 }; + test::(); + // We don't support casting into DSTs whose trailing slice + // element is a ZST. + if S > 0 { + test::(); + } + // TODO: Test with a slice DST once we have any that + // implement `KnownLayout + FromBytes`. + })* + }; + } + + test!(()); + test!(u8, u16, u32, u64, u128, usize, AU64); + test!(i8, i16, i32, i64, i128, isize); + test!(f32, f64); + } + } +} pub(crate) trait AsAddress { fn addr(self) -> usize; @@ -27,10 +571,11 @@ impl<'a, T: ?Sized> AsAddress for &'a mut T { impl AsAddress for *const T { #[inline(always)] fn addr(self) -> usize { - // TODO(https://github.com/rust-lang/rust/issues/95228): Use `.addr()` - // instead of `as usize` once it's stable, and get rid of this `allow`. - // Currently, `as usize` is the only way to accomplish this. + // TODO(#181), TODO(https://github.com/rust-lang/rust/issues/95228): Use + // `.addr()` instead of `as usize` once it's stable, and get rid of this + // `allow`. Currently, `as usize` is the only way to accomplish this. #[allow(clippy::as_conversions)] + #[cfg_attr(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS, allow(lossy_provenance_casts))] return self.cast::<()>() as usize; } } @@ -53,6 +598,74 @@ pub(crate) fn aligned_to(t: T) -> bool { remainder == 0 } +/// Round `n` down to the largest value `m` such that `m <= n` and `m % align == +/// 0`. +/// +/// # Panics +/// +/// May panic if `align` is not a power of two. Even if it doesn't panic in this +/// case, it will produce nonsense results. +#[inline(always)] +pub(crate) const fn round_down_to_next_multiple_of_alignment( + n: usize, + align: NonZeroUsize, +) -> usize { + let align = align.get(); + debug_assert!(align.is_power_of_two()); + + // Subtraction can't underflow because `align.get() >= 1`. + #[allow(clippy::arithmetic_side_effects)] + let mask = !(align - 1); + n & mask +} + +pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize { + if a.get() < b.get() { + b + } else { + a + } +} + +pub(crate) const fn min(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize { + if a.get() > b.get() { + b + } else { + a + } +} + +/// Since we support multiple versions of Rust, there are often features which +/// have been stabilized in the most recent stable release which do not yet +/// exist (stably) on our MSRV. This module provides polyfills for those +/// features so that we can write more "modern" code, and just remove the +/// polyfill once our MSRV supports the corresponding feature. Without this, +/// we'd have to write worse/more verbose code and leave TODO comments sprinkled +/// throughout the codebase to update to the new pattern once it's stabilized. +/// +/// Each trait is imported as `_` at the crate root; each polyfill should "just +/// work" at usage sites. +pub(crate) mod polyfills { + use core::ptr::{self, NonNull}; + + // A polyfill for `NonNull::slice_from_raw_parts` that we can use before our + // MSRV is 1.70, when that function was stabilized. + // + // TODO(#67): Once our MSRV is 1.70, remove this. + pub(crate) trait NonNullExt { + fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]>; + } + + impl NonNullExt for NonNull { + #[inline(always)] + fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]> { + let ptr = ptr::slice_from_raw_parts_mut(data.as_ptr(), len); + // SAFETY: `ptr` is converted from `data`, which is non-null. + unsafe { NonNull::new_unchecked(ptr) } + } + } +} + #[cfg(test)] pub(crate) mod testutil { use core::fmt::{self, Display, Formatter}; @@ -83,7 +696,18 @@ pub(crate) mod testutil { // Though `u64` has alignment 8 on some platforms, it's not guaranteed. // By contrast, `AU64` is guaranteed to have alignment 8. #[derive( - FromZeroes, FromBytes, AsBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone, + KnownLayout, + FromZeroes, + FromBytes, + AsBytes, + Eq, + PartialEq, + Ord, + PartialOrd, + Default, + Debug, + Copy, + Clone, )] #[repr(C, align(8))] pub(crate) struct AU64(pub(crate) u64); @@ -101,5 +725,84 @@ pub(crate) mod testutil { } } - impl_known_layout!(AU64); + #[derive( + FromZeroes, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone, + )] + #[repr(C)] + pub(crate) struct Nested { + _t: T, + _u: U, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_round_down_to_next_multiple_of_alignment() { + fn alt_impl(n: usize, align: NonZeroUsize) -> usize { + let mul = n / align.get(); + mul * align.get() + } + + for align in [1, 2, 4, 8, 16] { + for n in 0..256 { + let align = NonZeroUsize::new(align).unwrap(); + let want = alt_impl(n, align); + let got = round_down_to_next_multiple_of_alignment(n, align); + assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({n}, {align})"); + } + } + } +} + +#[cfg(kani)] +mod proofs { + use super::*; + + #[kani::proof] + fn prove_round_down_to_next_multiple_of_alignment() { + fn model_impl(n: usize, align: NonZeroUsize) -> usize { + assert!(align.get().is_power_of_two()); + let mul = n / align.get(); + mul * align.get() + } + + let align: NonZeroUsize = kani::any(); + kani::assume(align.get().is_power_of_two()); + let n: usize = kani::any(); + + let expected = model_impl(n, align); + let actual = round_down_to_next_multiple_of_alignment(n, align); + assert_eq!(expected, actual, "round_down_to_next_multiple_of_alignment({n}, {align})"); + } + + // Restricted to nightly since we use the unstable `usize::next_multiple_of` + // in our model implementation. + #[cfg(__INTERNAL_USE_ONLY_NIGHLTY_FEATURES_IN_TESTS)] + #[kani::proof] + fn prove_padding_needed_for() { + fn model_impl(len: usize, align: NonZeroUsize) -> usize { + let padded = len.next_multiple_of(align.get()); + let padding = padded - len; + padding + } + + let align: NonZeroUsize = kani::any(); + kani::assume(align.get().is_power_of_two()); + let len: usize = kani::any(); + // Constrain `len` to valid Rust lengths, since our model implementation + // isn't robust to overflow. + kani::assume(len <= isize::MAX as usize); + kani::assume(align.get() < 1 << 29); + + let expected = model_impl(len, align); + let actual = core_layout::padding_needed_for(len, align); + assert_eq!(expected, actual, "padding_needed_for({len}, {align})"); + + let padded_len = actual + len; + assert_eq!(padded_len % align, 0); + assert!(padded_len / align >= len / align); + } } diff --git a/src/wrappers.rs b/src/wrappers.rs index a0e6ac7..532d872 100644 --- a/src/wrappers.rs +++ b/src/wrappers.rs @@ -1,6 +1,10 @@ -// Copyright 2023 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// 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. use core::{ cmp::Ordering, @@ -54,10 +58,16 @@ use super::*; // [3] https://github.com/google/zerocopy/issues/209 #[allow(missing_debug_implementations)] #[derive(Default, Copy)] -#[cfg_attr(any(feature = "derive", test), derive(FromZeroes, FromBytes, AsBytes, Unaligned))] +#[cfg_attr( + any(feature = "derive", test), + derive(KnownLayout, FromZeroes, FromBytes, AsBytes, Unaligned) +)] #[repr(C, packed)] pub struct Unalign(T); +#[cfg(not(any(feature = "derive", test)))] +impl_known_layout!(T => Unalign); + safety_comment! { /// SAFETY: /// - `Unalign` is `repr(packed)`, so it is unaligned regardless of the @@ -268,17 +278,13 @@ impl Unalign { impl Drop for WriteBackOnDrop { fn drop(&mut self) { - // SAFETY: See inline comments. - unsafe { - // SAFETY: We never use `copy` again as required by - // `ManuallyDrop::take`. - let copy = ManuallyDrop::take(&mut self.copy); - // SAFETY: `slf` is the raw pointer value of `self`. We know - // it is valid for writes and properly aligned because - // `self` is a mutable reference, which guarantees both of - // these properties. - ptr::write(self.slf, Unalign::new(copy)); - } + // SAFETY: We never use `copy` again as required by + // `ManuallyDrop::take`. + let copy = unsafe { ManuallyDrop::take(&mut self.copy) }; + // SAFETY: `slf` is the raw pointer value of `self`. We know it + // is valid for writes and properly aligned because `self` is a + // mutable reference, which guarantees both of these properties. + unsafe { ptr::write(self.slf, Unalign::new(copy)) }; } } diff --git a/testdata/include_value/data b/testdata/include_value/data new file mode 100644 index 0000000..85df507 --- /dev/null +++ b/testdata/include_value/data @@ -0,0 +1 @@ +abcd \ No newline at end of file diff --git a/tests/trybuild.rs b/tests/trybuild.rs index 4ed01f7..24abc28 100644 --- a/tests/trybuild.rs +++ b/tests/trybuild.rs @@ -1,33 +1,23 @@ -// Copyright 2019 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// Copyright 2019 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. -// UI tests depend on the exact error messages emitted by rustc, but those error -// messages are not stable, and sometimes change between Rust versions. Thus, we -// maintain one set of UI tests for each Rust version that we test in CI, and we -// pin to specific versions in CI (a specific stable version, a specific date of -// the nightly compiler, and a specific MSRV). Updating those pinned versions -// may also require updating these tests. -// - `tests/ui-nightly` - Contains the source of truth for our UI test source -// files (`.rs`), and contains `.err` and `.out` files for nightly -// - `tests/ui-stable` - Contains symlinks to the `.rs` files in -// `tests/ui-nightly`, and contains `.err` and `.out` files for stable -// - `tests/ui-msrv` - Contains symlinks to the `.rs` files in -// `tests/ui-nightly`, and contains `.err` and `.out` files for MSRV - -#[rustversion::nightly] -const SOURCE_FILES_DIR: &str = "tests/ui-nightly"; -#[rustversion::stable(1.69.0)] -const SOURCE_FILES_DIR: &str = "tests/ui-stable"; -#[rustversion::stable(1.61.0)] -const SOURCE_FILES_DIR: &str = "tests/ui-msrv"; - -const SOURCE_FILES_DIR: &str = "tests/ui-stable"; +use testutil::ToolchainVersion; #[test] +#[cfg_attr(miri, ignore)] fn ui() { + let version = ToolchainVersion::extract_from_pwd().unwrap(); + // See the doc comment on this method for an explanation of what this does + // and why we store source files in different directories. + let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning(); + let t = trybuild::TestCases::new(); - t.compile_fail(format!("{SOURCE_FILES_DIR}/*.rs")); + t.compile_fail(format!("tests/{source_files_dirname}/*.rs")); } // The file `invalid-impls.rs` directly includes `src/macros.rs` in order to @@ -39,7 +29,13 @@ fn ui() { // tests the correct behavior when the "derive" feature is enabled. #[cfg(feature = "derive")] #[test] +#[cfg_attr(miri, ignore)] fn ui_invalid_impls() { + let version = ToolchainVersion::extract_from_pwd().unwrap(); + // See the doc comment on this method for an explanation of what this does + // and why we store source files in different directories. + let source_files_dirname = version.get_ui_source_files_dirname_and_maybe_print_warning(); + let t = trybuild::TestCases::new(); - t.compile_fail(format!("{SOURCE_FILES_DIR}/invalid-impls/*.rs")); + t.compile_fail(format!("tests/{source_files_dirname}/invalid-impls/*.rs")); } diff --git a/tests/ui-msrv/include_value_not_from_bytes.rs b/tests/ui-msrv/include_value_not_from_bytes.rs new file mode 100644 index 0000000..45b6138 --- /dev/null +++ b/tests/ui-msrv/include_value_not_from_bytes.rs @@ -0,0 +1,12 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because `UnsafeCell: !FromBytes`. +const NOT_FROM_BYTES: core::cell::UnsafeCell = + include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-msrv/include_value_not_from_bytes.stderr b/tests/ui-msrv/include_value_not_from_bytes.stderr new file mode 100644 index 0000000..21f6443 --- /dev/null +++ b/tests/ui-msrv/include_value_not_from_bytes.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `UnsafeCell: FromBytes` is not satisfied + --> tests/ui-msrv/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `UnsafeCell` + | +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-msrv/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/include_value_wrong_size.rs b/tests/ui-msrv/include_value_wrong_size.rs new file mode 100644 index 0000000..d87b306 --- /dev/null +++ b/tests/ui-msrv/include_value_wrong_size.rs @@ -0,0 +1,11 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because the file is 4 bytes long, not 8. +const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-msrv/include_value_wrong_size.stderr b/tests/ui-msrv/include_value_wrong_size.stderr new file mode 100644 index 0000000..3004584 --- /dev/null +++ b/tests/ui-msrv/include_value_wrong_size.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/include_value_wrong_size.rs:11:25 + | +11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/invalid-impls/invalid-impls.rs b/tests/ui-msrv/invalid-impls/invalid-impls.rs index b9a60bd..ea96390 100644 --- a/tests/ui-msrv/invalid-impls/invalid-impls.rs +++ b/tests/ui-msrv/invalid-impls/invalid-impls.rs @@ -1,6 +1,10 @@ -// Copyright 2022 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// Copyright 2022 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. // Since some macros from `macros.rs` are unused. #![allow(unused)] diff --git a/tests/ui-msrv/invalid-impls/invalid-impls.stderr b/tests/ui-msrv/invalid-impls/invalid-impls.stderr index fee0cd9..c1de466 100644 --- a/tests/ui-msrv/invalid-impls/invalid-impls.stderr +++ b/tests/ui-msrv/invalid-impls/invalid-impls.stderr @@ -4,15 +4,15 @@ error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied | impl<$($tyvar $(: $(? $optbound +)* $($bound +)*)?),*> Subtrait for $ty {} | ^^^^^^^^ the trait `zerocopy::FromZeroes` is not implemented for `T` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:22:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1 | -22 | impl_or_verify!(T => FromZeroes for Foo); +26 | 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:18:10 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:10 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] | ^^^^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs @@ -20,15 +20,15 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:22:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:26:1 | -22 | impl_or_verify!(T => FromZeroes for Foo); +26 | 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` - | -22 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); - | ++++++++++++++++++++++ + | +26 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); + | ++++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::FromBytes` is not satisfied --> tests/ui-msrv/invalid-impls/../../../src/macros.rs @@ -36,15 +36,15 @@ 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:23:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1 | -23 | impl_or_verify!(T => FromBytes for Foo); +27 | 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:18:22 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:22 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] | ^^^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs @@ -52,15 +52,15 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:23:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:27:1 | -23 | impl_or_verify!(T => FromBytes for Foo); +27 | 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` - | -23 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); - | +++++++++++++++++++++ + | +27 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); + | +++++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::AsBytes` is not satisfied --> tests/ui-msrv/invalid-impls/../../../src/macros.rs @@ -68,15 +68,15 @@ 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:24:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1 | -24 | impl_or_verify!(T => AsBytes for Foo); +28 | 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:18:33 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:33 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] | ^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs @@ -84,15 +84,15 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:24:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:28:1 | -24 | impl_or_verify!(T => AsBytes for Foo); +28 | 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` - | -24 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); - | +++++++++++++++++++ + | +28 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); + | +++++++++++++++++++ error[E0277]: the trait bound `T: zerocopy::Unaligned` is not satisfied --> tests/ui-msrv/invalid-impls/../../../src/macros.rs @@ -100,15 +100,15 @@ 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:25:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1 | -25 | impl_or_verify!(T => Unaligned for Foo); +29 | 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:18:42 + --> tests/ui-msrv/invalid-impls/invalid-impls.rs:22:42 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] | ^^^^^^^^^ note: required by a bound in `_::Subtrait` --> tests/ui-msrv/invalid-impls/../../../src/macros.rs @@ -116,12 +116,12 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `_::Subtrait` | - ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:25:1 + ::: tests/ui-msrv/invalid-impls/invalid-impls.rs:29:1 | -25 | impl_or_verify!(T => Unaligned for Foo); +29 | 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` - | -25 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); - | +++++++++++++++++++++ + | +29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); + | +++++++++++++++++++++ diff --git a/tests/ui-msrv/max-align.rs b/tests/ui-msrv/max-align.rs new file mode 100644 index 0000000..53e3eb9 --- /dev/null +++ b/tests/ui-msrv/max-align.rs @@ -0,0 +1,99 @@ +// 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. + +#[repr(C, align(1))] +struct Align1; + +#[repr(C, align(2))] +struct Align2; + +#[repr(C, align(4))] +struct Align4; + +#[repr(C, align(8))] +struct Align8; + +#[repr(C, align(16))] +struct Align16; + +#[repr(C, align(32))] +struct Align32; + +#[repr(C, align(64))] +struct Align64; + +#[repr(C, align(128))] +struct Align128; + +#[repr(C, align(256))] +struct Align256; + +#[repr(C, align(512))] +struct Align512; + +#[repr(C, align(1024))] +struct Align1024; + +#[repr(C, align(2048))] +struct Align2048; + +#[repr(C, align(4096))] +struct Align4096; + +#[repr(C, align(8192))] +struct Align8192; + +#[repr(C, align(16384))] +struct Align16384; + +#[repr(C, align(32768))] +struct Align32768; + +#[repr(C, align(65536))] +struct Align65536; + +#[repr(C, align(131072))] +struct Align131072; + +#[repr(C, align(262144))] +struct Align262144; + +#[repr(C, align(524288))] +struct Align524288; + +#[repr(C, align(1048576))] +struct Align1048576; + +#[repr(C, align(2097152))] +struct Align2097152; + +#[repr(C, align(4194304))] +struct Align4194304; + +#[repr(C, align(8388608))] +struct Align8388608; + +#[repr(C, align(16777216))] +struct Align16777216; + +#[repr(C, align(33554432))] +struct Align33554432; + +#[repr(C, align(67108864))] +struct Align67108864; + +#[repr(C, align(134217728))] +struct Align13421772; + +#[repr(C, align(268435456))] +struct Align26843545; + +#[repr(C, align(1073741824))] +struct Align1073741824; + +fn main() {} diff --git a/tests/ui-msrv/max-align.stderr b/tests/ui-msrv/max-align.stderr new file mode 100644 index 0000000..6ab6e47 --- /dev/null +++ b/tests/ui-msrv/max-align.stderr @@ -0,0 +1,5 @@ +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> tests/ui-msrv/max-align.rs:96:11 + | +96 | #[repr(C, align(1073741824))] + | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-msrv/transmute-dst-not-frombytes.rs b/tests/ui-msrv/transmute-dst-not-frombytes.rs new file mode 100644 index 0000000..c4caaff --- /dev/null +++ b/tests/ui-msrv/transmute-dst-not-frombytes.rs @@ -0,0 +1,18 @@ +// Copyright 2022 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); diff --git a/tests/ui-msrv/transmute-dst-not-frombytes.stderr b/tests/ui-msrv/transmute-dst-not-frombytes.stderr new file mode 100644 index 0000000..b4afbbd --- /dev/null +++ b/tests/ui-msrv/transmute-dst-not-frombytes.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-msrv/transmute-dst-not-frombytes.rs:18:41 + | +18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-msrv/transmute-dst-not-frombytes.rs:18:41 + | +18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-illegal.rs b/tests/ui-msrv/transmute-illegal.rs deleted file mode 100644 index 74b8439..0000000 --- a/tests/ui-msrv/transmute-illegal.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2022 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -extern crate zerocopy; - -fn main() {} - -// It is unsound to inspect the usize value of a pointer during const eval. -const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); diff --git a/tests/ui-msrv/transmute-illegal.stderr b/tests/ui-msrv/transmute-illegal.stderr deleted file mode 100644 index 37c124a..0000000 --- a/tests/ui-msrv/transmute-illegal.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied - --> tests/ui-msrv/transmute-illegal.rs:10:30 - | -10 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize` - | - = help: the following implementations were found: - - - - - and $N others -note: required by a bound in `POINTER_VALUE::transmute` - --> tests/ui-msrv/transmute-illegal.rs:10:30 - | -10 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `POINTER_VALUE::transmute` - = note: this error originates in the macro `zerocopy::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-alignment-increase.rs b/tests/ui-msrv/transmute-mut-alignment-increase.rs new file mode 100644 index 0000000..0928564 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-alignment-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); diff --git a/tests/ui-msrv/transmute-mut-alignment-increase.stderr b/tests/ui-msrv/transmute-mut-alignment-increase.stderr new file mode 100644 index 0000000..033031c --- /dev/null +++ b/tests/ui-msrv/transmute-mut-alignment-increase.stderr @@ -0,0 +1,36 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:39 + | +19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: mutable references are not allowed in constants + --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:54 + | +19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + +error[E0015]: cannot call non-const fn `transmute_mut::<[u8; 2], AU16>` in constants + --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:39 + | +19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> tests/ui-msrv/transmute-mut-alignment-increase.rs:19:59 + | +19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); + | --------------------^^^^^^^^- + | | | + | | creates a temporary which is freed while still in use + | temporary value is freed at the end of this statement + | using this value as a constant requires that borrow lasts for `'static` diff --git a/tests/ui-msrv/transmute-mut-const.rs b/tests/ui-msrv/transmute-mut-const.rs new file mode 100644 index 0000000..021b562 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-const.rs @@ -0,0 +1,20 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + +// `transmute_mut!` cannot, generally speaking, be used in const contexts. +const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); diff --git a/tests/ui-msrv/transmute-mut-const.stderr b/tests/ui-msrv/transmute-mut-const.stderr new file mode 100644 index 0000000..30bfe45 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-const.stderr @@ -0,0 +1,41 @@ +warning: taking a mutable reference to a `const` item + --> tests/ui-msrv/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(const_item_mutation)]` on by default + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> tests/ui-msrv/transmute-mut-const.rs:17:1 + | +17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0658]: mutable references are not allowed in constants + --> tests/ui-msrv/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + +error[E0015]: cannot call non-const fn `transmute_mut::<[u8; 2], [u8; 2]>` in constants + --> tests/ui-msrv/transmute-mut-const.rs:20:37 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> tests/ui-msrv/transmute-mut-const.rs:20:57 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | --------------------^^^^^^^^^^^^- + | | | + | | creates a temporary which is freed while still in use + | temporary value is freed at the end of this statement + | using this value as a constant requires that borrow lasts for `'static` diff --git a/tests/ui-msrv/transmute-mut-dst-generic.rs b/tests/ui-msrv/transmute-mut-dst-generic.rs new file mode 100644 index 0000000..7068f10 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_mut(u: &mut u8) -> &mut T { + // `transmute_mut!` requires the destination type to be concrete. + transmute_mut!(u) +} diff --git a/tests/ui-msrv/transmute-mut-dst-generic.stderr b/tests/ui-msrv/transmute-mut-dst-generic.stderr new file mode 100644 index 0000000..f6b54ce --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-mut-dst-generic.rs:17:5 + | +17 | transmute_mut!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `T` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-mut-dst-generic.rs:17:5 + | +17 | transmute_mut!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (8 bits) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs b/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs new file mode 100644 index 0000000..33a9ecd --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); diff --git a/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr b/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr new file mode 100644 index 0000000..8f0ea80 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-dst-not-asbytes.rs b/tests/ui-msrv/transmute-mut-dst-not-asbytes.rs new file mode 100644 index 0000000..b72f129 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-not-asbytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `AsBytes` +const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr b/tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr new file mode 100644 index 0000000..7e2dd78 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Dst: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-dst-not-asbytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Dst` + | +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-msrv/transmute-mut-dst-not-asbytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs b/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs new file mode 100644 index 0000000..102fced --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-not-frombytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr b/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr new file mode 100644 index 0000000..663e085 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst` + | +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-msrv/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-dst-unsized.rs b/tests/ui-msrv/transmute-mut-dst-unsized.rs new file mode 100644 index 0000000..693ccda --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); diff --git a/tests/ui-msrv/transmute-mut-dst-unsized.stderr b/tests/ui-msrv/transmute-mut-dst-unsized.stderr new file mode 100644 index 0000000..cb60a82 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-dst-unsized.stderr @@ -0,0 +1,108 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(e: T) -> U; + | ^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-illegal-lifetime.rs b/tests/ui-msrv/transmute-mut-illegal-lifetime.rs new file mode 100644 index 0000000..c31765e --- /dev/null +++ b/tests/ui-msrv/transmute-mut-illegal-lifetime.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() {} + +fn increase_lifetime() { + let mut x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); +} diff --git a/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr b/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr new file mode 100644 index 0000000..5ff7145 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-illegal-lifetime.stderr @@ -0,0 +1,9 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-msrv/transmute-mut-illegal-lifetime.rs:14:56 + | +14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); + | ---------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff --git a/tests/ui-msrv/transmute-mut-size-decrease.rs b/tests/ui-msrv/transmute-mut-size-decrease.rs new file mode 100644 index 0000000..c6eec3a --- /dev/null +++ b/tests/ui-msrv/transmute-mut-size-decrease.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// We require that the size of the destination type is not smaller than the size +// of the source type. +const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); diff --git a/tests/ui-msrv/transmute-mut-size-decrease.stderr b/tests/ui-msrv/transmute-mut-size-decrease.stderr new file mode 100644 index 0000000..2bfc218 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-size-decrease.stderr @@ -0,0 +1,36 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:32 + | +17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 2]` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: mutable references are not allowed in constants + --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:47 + | +17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + +error[E0015]: cannot call non-const fn `transmute_mut::<[u8; 2], u8>` in constants + --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:32 + | +17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> tests/ui-msrv/transmute-mut-size-decrease.rs:17:52 + | +17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); + | --------------------^^^^^^^^- + | | | + | | creates a temporary which is freed while still in use + | temporary value is freed at the end of this statement + | using this value as a constant requires that borrow lasts for `'static` diff --git a/tests/ui-msrv/transmute-mut-size-increase.rs b/tests/ui-msrv/transmute-mut-size-increase.rs new file mode 100644 index 0000000..a4657c2 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-size-increase.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); diff --git a/tests/ui-msrv/transmute-mut-size-increase.stderr b/tests/ui-msrv/transmute-mut-size-increase.stderr new file mode 100644 index 0000000..6e866a0 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-size-increase.stderr @@ -0,0 +1,36 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-mut-size-increase.rs:17:37 + | +17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0658]: mutable references are not allowed in constants + --> tests/ui-msrv/transmute-mut-size-increase.rs:17:52 + | +17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); + | ^^^^^^^^ + | + = note: see issue #57349 for more information + +error[E0015]: cannot call non-const fn `transmute_mut::` in constants + --> tests/ui-msrv/transmute-mut-size-increase.rs:17:37 + | +17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> tests/ui-msrv/transmute-mut-size-increase.rs:17:57 + | +17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); + | --------------------^^^- + | | | + | | creates a temporary which is freed while still in use + | temporary value is freed at the end of this statement + | using this value as a constant requires that borrow lasts for `'static` diff --git a/tests/ui-msrv/transmute-mut-src-dst-generic.rs b/tests/ui-msrv/transmute-mut-src-dst-generic.rs new file mode 100644 index 0000000..aed7ded --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-dst-generic.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_mut(t: &mut T) -> &mut U { + // `transmute_mut!` requires the source and destination types to be + // concrete. + transmute_mut!(t) +} diff --git a/tests/ui-msrv/transmute-mut-src-dst-generic.stderr b/tests/ui-msrv/transmute-mut-src-dst-generic.stderr new file mode 100644 index 0000000..1162f21 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-mut-src-dst-generic.rs:18:5 + | +18 | transmute_mut!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `U` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-mut-src-dst-generic.rs:18:5 + | +18 | transmute_mut!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-src-dst-not-references.rs b/tests/ui-msrv/transmute-mut-src-dst-not-references.rs new file mode 100644 index 0000000..98cc520 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-dst-not-references.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); diff --git a/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr b/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr new file mode 100644 index 0000000..c500a93 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-dst-not-references.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-src-dst-not-references.rs:17:59 + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | | help: consider mutably borrowing here: `&mut 0usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` diff --git a/tests/ui-msrv/transmute-mut-src-dst-unsized.rs b/tests/ui-msrv/transmute-mut-src-dst-unsized.rs new file mode 100644 index 0000000..1bebcf2 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between unsized source and +// destination types. +const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); diff --git a/tests/ui-msrv/transmute-mut-src-dst-unsized.stderr b/tests/ui-msrv/transmute-mut-src-dst-unsized.stderr new file mode 100644 index 0000000..00201a6 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-dst-unsized.stderr @@ -0,0 +1,237 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(e: T) -> U; + | ^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-src-generic.rs b/tests/ui-msrv/transmute-mut-src-generic.rs new file mode 100644 index 0000000..a3ef397 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes}; + +fn main() {} + +fn transmute_mut(t: &mut T) -> &mut u8 { + // `transmute_mut!` requires the source type to be concrete. + transmute_mut!(t) +} diff --git a/tests/ui-msrv/transmute-mut-src-generic.stderr b/tests/ui-msrv/transmute-mut-src-generic.stderr new file mode 100644 index 0000000..8a9296c --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-generic.stderr @@ -0,0 +1,10 @@ +error[E0405]: cannot find trait `FromBytes` in this scope + --> tests/ui-msrv/transmute-mut-src-generic.rs:15:31 + | +15 | fn transmute_mut(t: &mut T) -> &mut u8 { + | ^^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +11 | use zerocopy::FromBytes; + | diff --git a/tests/ui-msrv/transmute-mut-src-immutable.rs b/tests/ui-msrv/transmute-mut-src-immutable.rs new file mode 100644 index 0000000..08088d0 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-immutable.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +fn ref_src_immutable() { + // `transmute_mut!` requires that its source type be a mutable reference. + let _: &mut u8 = transmute_mut!(&0u8); +} diff --git a/tests/ui-msrv/transmute-mut-src-immutable.stderr b/tests/ui-msrv/transmute-mut-src-immutable.stderr new file mode 100644 index 0000000..8262f16 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-immutable.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-src-immutable.rs:17:37 + | +17 | let _: &mut u8 = transmute_mut!(&0u8); + | ---------------^^^^- + | | | + | | types differ in mutability + | expected due to this + | + = note: expected mutable reference `&mut _` + found reference `&u8` diff --git a/tests/ui-msrv/transmute-mut-src-not-a-reference.rs b/tests/ui-msrv/transmute-mut-src-not-a-reference.rs new file mode 100644 index 0000000..bf8bc32 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); diff --git a/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr b/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr new file mode 100644 index 0000000..3a6bdf7 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-not-a-reference.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-mut-src-not-a-reference.rs:17:53 + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | | help: consider mutably borrowing here: `&mut 0usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` diff --git a/tests/ui-msrv/transmute-mut-src-not-asbytes.rs b/tests/ui-msrv/transmute-mut-src-not-asbytes.rs new file mode 100644 index 0000000..6a14f12 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-not-asbytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-msrv/transmute-mut-src-not-asbytes.stderr b/tests/ui-msrv/transmute-mut-src-not-asbytes.stderr new file mode 100644 index 0000000..4056975 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-not-asbytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Src: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src` + | +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src` + | +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-msrv/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-src-not-frombytes.rs b/tests/ui-msrv/transmute-mut-src-not-frombytes.rs new file mode 100644 index 0000000..2ebe036 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-not-frombytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `FromBytes` +const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr b/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr new file mode 100644 index 0000000..b859c41 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-not-frombytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-msrv/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-mut-src-unsized.rs b/tests/ui-msrv/transmute-mut-src-unsized.rs new file mode 100644 index 0000000..413dd68 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-unsized.rs @@ -0,0 +1,16 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); diff --git a/tests/ui-msrv/transmute-mut-src-unsized.stderr b/tests/ui-msrv/transmute-mut-src-unsized.stderr new file mode 100644 index 0000000..6b18695 --- /dev/null +++ b/tests/ui-msrv/transmute-mut-src-unsized.stderr @@ -0,0 +1,198 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(e: T) -> U; + | ^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ptr-to-usize.rs b/tests/ui-msrv/transmute-ptr-to-usize.rs new file mode 100644 index 0000000..5af8859 --- /dev/null +++ b/tests/ui-msrv/transmute-ptr-to-usize.rs @@ -0,0 +1,20 @@ +// Copyright 2022 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. + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// It is unclear whether we can or should support this transmutation, especially +// in a const context. This test ensures that even if such a transmutation +// becomes valid due to the requisite implementations of `FromBytes` being +// added, that we re-examine whether it should specifically be valid in a const +// context. +const POINTER_VALUE: usize = transmute!(&0usize as *const usize); diff --git a/tests/ui-msrv/transmute-ptr-to-usize.stderr b/tests/ui-msrv/transmute-ptr-to-usize.stderr new file mode 100644 index 0000000..06b1bba --- /dev/null +++ b/tests/ui-msrv/transmute-ptr-to-usize.stderr @@ -0,0 +1,37 @@ +error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize` + | + = help: the following implementations were found: + + + + + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize` + | + = help: the following implementations were found: + + + + + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-alignment-increase.rs b/tests/ui-msrv/transmute-ref-alignment-increase.rs new file mode 100644 index 0000000..bf1988c --- /dev/null +++ b/tests/ui-msrv/transmute-ref-alignment-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]); diff --git a/tests/ui-msrv/transmute-ref-alignment-increase.stderr b/tests/ui-msrv/transmute-ref-alignment-increase.stderr new file mode 100644 index 0000000..72864e1 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-alignment-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-alignment-increase.rs:19:35 + | +19 | const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-dst-generic.rs b/tests/ui-msrv/transmute-ref-dst-generic.rs new file mode 100644 index 0000000..bf4a0f9 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, FromBytes}; + +fn main() {} + +fn transmute_ref(u: &u8) -> &T { + // `transmute_ref!` requires the destination type to be concrete. + transmute_ref!(u) +} diff --git a/tests/ui-msrv/transmute-ref-dst-generic.stderr b/tests/ui-msrv/transmute-ref-dst-generic.stderr new file mode 100644 index 0000000..ec7ec74 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-dst-generic.rs:17:5 + | +17 | transmute_ref!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `T` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-dst-generic.rs:17:5 + | +17 | transmute_ref!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (8 bits) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-dst-mutable.rs b/tests/ui-msrv/transmute-ref-dst-mutable.rs new file mode 100644 index 0000000..fa0e6e4 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-mutable.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `transmute_ref!` requires that its destination type be an immutable + // reference. + let _: &mut u8 = transmute_ref!(&0u8); +} diff --git a/tests/ui-msrv/transmute-ref-dst-mutable.stderr b/tests/ui-msrv/transmute-ref-dst-mutable.stderr new file mode 100644 index 0000000..5ccf2cd --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-mutable.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs b/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs new file mode 100644 index 0000000..de55f9a --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); diff --git a/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr b/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr new file mode 100644 index 0000000..9a61c4c --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-not-a-reference.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs b/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs new file mode 100644 index 0000000..d81f64d --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-not-frombytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); diff --git a/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr b/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr new file mode 100644 index 0000000..d317675 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-not-frombytes.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-msrv/transmute-ref-dst-not-frombytes.rs:18:42 + | +18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-msrv/transmute-ref-dst-not-frombytes.rs:18:42 + | +18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-dst-unsized.rs b/tests/ui-msrv/transmute-ref-dst-unsized.rs new file mode 100644 index 0000000..625f1fa --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); diff --git a/tests/ui-msrv/transmute-ref-dst-unsized.stderr b/tests/ui-msrv/transmute-ref-dst-unsized.stderr new file mode 100644 index 0000000..78135de --- /dev/null +++ b/tests/ui-msrv/transmute-ref-dst-unsized.stderr @@ -0,0 +1,94 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(e: T) -> U; + | ^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-illegal-lifetime.rs b/tests/ui-msrv/transmute-ref-illegal-lifetime.rs new file mode 100644 index 0000000..8dd191e --- /dev/null +++ b/tests/ui-msrv/transmute-ref-illegal-lifetime.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() {} + +fn increase_lifetime() { + let x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static u64 = zerocopy::transmute_ref!(&x); +} diff --git a/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr b/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr new file mode 100644 index 0000000..866ea56 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-illegal-lifetime.stderr @@ -0,0 +1,9 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-msrv/transmute-ref-illegal-lifetime.rs:14:52 + | +14 | let _: &'static u64 = zerocopy::transmute_ref!(&x); + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff --git a/tests/ui-msrv/transmute-ref-size-decrease.rs b/tests/ui-msrv/transmute-ref-size-decrease.rs new file mode 100644 index 0000000..1d66a54 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-size-decrease.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]); diff --git a/tests/ui-msrv/transmute-ref-size-decrease.stderr b/tests/ui-msrv/transmute-ref-size-decrease.stderr new file mode 100644 index 0000000..95669f9 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-size-decrease.rs:17:28 + | +17 | const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 2]` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-size-increase.rs b/tests/ui-msrv/transmute-ref-size-increase.rs new file mode 100644 index 0000000..cdca560 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-size-increase.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8); diff --git a/tests/ui-msrv/transmute-ref-size-increase.stderr b/tests/ui-msrv/transmute-ref-size-increase.stderr new file mode 100644 index 0000000..10f0e10 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-size-increase.rs:17:33 + | +17 | const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-src-dst-generic.rs b/tests/ui-msrv/transmute-ref-src-dst-generic.rs new file mode 100644 index 0000000..409d785 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-dst-generic.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_ref(t: &T) -> &U { + // `transmute_ref!` requires the source and destination types to be + // concrete. + transmute_ref!(t) +} diff --git a/tests/ui-msrv/transmute-ref-src-dst-generic.stderr b/tests/ui-msrv/transmute-ref-src-dst-generic.stderr new file mode 100644 index 0000000..eb3268f --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-src-dst-generic.rs:18:5 + | +18 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `U` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-src-dst-generic.rs:18:5 + | +18 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-src-dst-not-references.rs b/tests/ui-msrv/transmute-ref-src-dst-not-references.rs new file mode 100644 index 0000000..114e917 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-dst-not-references.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); diff --git a/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr b/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr new file mode 100644 index 0000000..2c5e23b --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-dst-not-references.stderr @@ -0,0 +1,42 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:54 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected reference, found `usize` + | | help: consider borrowing here: `&0usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-src-dst-unsized.rs b/tests/ui-msrv/transmute-ref-src-dst-unsized.rs new file mode 100644 index 0000000..6bfe7ff --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between unsized source and +// destination types. +const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); diff --git a/tests/ui-msrv/transmute-ref-src-dst-unsized.stderr b/tests/ui-msrv/transmute-ref-src-dst-unsized.stderr new file mode 100644 index 0000000..adfd597 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-dst-unsized.stderr @@ -0,0 +1,195 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(e: T) -> U; + | ^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-src-generic.rs b/tests/ui-msrv/transmute-ref-src-generic.rs new file mode 100644 index 0000000..010281c --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, AsBytes}; + +fn main() {} + +fn transmute_ref(t: &T) -> &u8 { + // `transmute_ref!` requires the source type to be concrete. + transmute_ref!(t) +} diff --git a/tests/ui-msrv/transmute-ref-src-generic.stderr b/tests/ui-msrv/transmute-ref-src-generic.stderr new file mode 100644 index 0000000..4cb3e51 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-src-generic.rs:17:5 + | +17 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-ref-src-generic.rs:17:5 + | +17 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-src-not-a-reference.rs b/tests/ui-msrv/transmute-ref-src-not-a-reference.rs new file mode 100644 index 0000000..90661b3 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); diff --git a/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr b/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr new file mode 100644 index 0000000..0f4aeec --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-not-a-reference.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> tests/ui-msrv/transmute-ref-src-not-a-reference.rs:17:49 + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected reference, found `usize` + | | help: consider borrowing here: `&0usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` diff --git a/tests/ui-msrv/transmute-ref-src-not-asbytes.rs b/tests/ui-msrv/transmute-ref-src-not-asbytes.rs new file mode 100644 index 0000000..6ab19f3 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-not-asbytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); diff --git a/tests/ui-msrv/transmute-ref-src-not-asbytes.stderr b/tests/ui-msrv/transmute-ref-src-not-asbytes.stderr new file mode 100644 index 0000000..6b80d4f --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-not-asbytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-ref-src-unsized.rs b/tests/ui-msrv/transmute-ref-src-unsized.rs new file mode 100644 index 0000000..14e72b4 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-unsized.rs @@ -0,0 +1,16 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); diff --git a/tests/ui-msrv/transmute-ref-src-unsized.stderr b/tests/ui-msrv/transmute-ref-src-unsized.stderr new file mode 100644 index 0000000..43bac53 --- /dev/null +++ b/tests/ui-msrv/transmute-ref-src-unsized.stderr @@ -0,0 +1,170 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(e: T) -> U; + | ^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-msrv/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all function arguments must have a statically known size + = note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-size-decrease.rs b/tests/ui-msrv/transmute-size-decrease.rs new file mode 100644 index 0000000..1d56831 --- /dev/null +++ b/tests/ui-msrv/transmute-size-decrease.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: u8 = transmute!(AU16(0)); diff --git a/tests/ui-msrv/transmute-size-decrease.stderr b/tests/ui-msrv/transmute-size-decrease.stderr new file mode 100644 index 0000000..ffa5688 --- /dev/null +++ b/tests/ui-msrv/transmute-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-size-decrease.rs:19:27 + | +19 | const DECREASE_SIZE: u8 = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-size-increase.rs b/tests/ui-msrv/transmute-size-increase.rs new file mode 100644 index 0000000..32f9363 --- /dev/null +++ b/tests/ui-msrv/transmute-size-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(0u8); diff --git a/tests/ui-msrv/transmute-size-increase.stderr b/tests/ui-msrv/transmute-size-increase.stderr new file mode 100644 index 0000000..865d0ca --- /dev/null +++ b/tests/ui-msrv/transmute-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-size-increase.rs:19:29 + | +19 | const INCREASE_SIZE: AU16 = transmute!(0u8); + | ^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-msrv/transmute-src-not-asbytes.rs b/tests/ui-msrv/transmute-src-not-asbytes.rs new file mode 100644 index 0000000..dd73021 --- /dev/null +++ b/tests/ui-msrv/transmute-src-not-asbytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); diff --git a/tests/ui-msrv/transmute-src-not-asbytes.stderr b/tests/ui-msrv/transmute-src-not-asbytes.stderr new file mode 100644 index 0000000..93eeda0 --- /dev/null +++ b/tests/ui-msrv/transmute-src-not-asbytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-msrv/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/include_value_not_from_bytes.rs b/tests/ui-nightly/include_value_not_from_bytes.rs new file mode 100644 index 0000000..45b6138 --- /dev/null +++ b/tests/ui-nightly/include_value_not_from_bytes.rs @@ -0,0 +1,12 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because `UnsafeCell: !FromBytes`. +const NOT_FROM_BYTES: core::cell::UnsafeCell = + include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-nightly/include_value_not_from_bytes.stderr b/tests/ui-nightly/include_value_not_from_bytes.stderr new file mode 100644 index 0000000..d948a0d --- /dev/null +++ b/tests/ui-nightly/include_value_not_from_bytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `UnsafeCell: FromBytes` is not satisfied + --> tests/ui-nightly/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `UnsafeCell` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-nightly/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/include_value_wrong_size.rs b/tests/ui-nightly/include_value_wrong_size.rs new file mode 100644 index 0000000..d87b306 --- /dev/null +++ b/tests/ui-nightly/include_value_wrong_size.rs @@ -0,0 +1,11 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because the file is 4 bytes long, not 8. +const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-nightly/include_value_wrong_size.stderr b/tests/ui-nightly/include_value_wrong_size.stderr new file mode 100644 index 0000000..f592ece --- /dev/null +++ b/tests/ui-nightly/include_value_wrong_size.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/include_value_wrong_size.rs:11:25 + | +11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/invalid-impls/invalid-impls.rs b/tests/ui-nightly/invalid-impls/invalid-impls.rs index b9a60bd..ea96390 100644 --- a/tests/ui-nightly/invalid-impls/invalid-impls.rs +++ b/tests/ui-nightly/invalid-impls/invalid-impls.rs @@ -1,6 +1,10 @@ -// Copyright 2022 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// Copyright 2022 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. // Since some macros from `macros.rs` are unused. #![allow(unused)] diff --git a/tests/ui-nightly/invalid-impls/invalid-impls.stderr b/tests/ui-nightly/invalid-impls/invalid-impls.stderr index 7d839ac..e5651d1 100644 --- a/tests/ui-nightly/invalid-impls/invalid-impls.stderr +++ b/tests/ui-nightly/invalid-impls/invalid-impls.stderr @@ -1,13 +1,13 @@ error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied - --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:37 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:26:37 | -22 | impl_or_verify!(T => FromZeroes for Foo); +26 | 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:18:10 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:10 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -15,26 +15,26 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:22:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:26:1 | -22 | impl_or_verify!(T => FromZeroes for Foo); +26 | 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` - | -22 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); - | ++++++++++++++++++++++ + | +26 | 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:23:36 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:27:36 | -23 | impl_or_verify!(T => FromBytes for Foo); +27 | 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:18:22 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:22 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -42,26 +42,26 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:23:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:27:1 | -23 | impl_or_verify!(T => FromBytes for Foo); +27 | 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` - | -23 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); - | +++++++++++++++++++++ + | +27 | 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:24:34 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:28:34 | -24 | impl_or_verify!(T => AsBytes for Foo); +28 | 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:18:33 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:33 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -69,26 +69,26 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:24:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:28:1 | -24 | impl_or_verify!(T => AsBytes for Foo); +28 | 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` - | -24 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); - | +++++++++++++++++++ + | +28 | 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:25:36 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:29:36 | -25 | impl_or_verify!(T => Unaligned for Foo); +29 | 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:18:42 + --> tests/ui-nightly/invalid-impls/invalid-impls.rs:22:42 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -96,12 +96,12 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:25:1 + ::: tests/ui-nightly/invalid-impls/invalid-impls.rs:29:1 | -25 | impl_or_verify!(T => Unaligned for Foo); +29 | 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` - | -25 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); - | +++++++++++++++++++++ + | +29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); + | +++++++++++++++++++++ diff --git a/tests/ui-nightly/max-align.rs b/tests/ui-nightly/max-align.rs new file mode 100644 index 0000000..53e3eb9 --- /dev/null +++ b/tests/ui-nightly/max-align.rs @@ -0,0 +1,99 @@ +// 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. + +#[repr(C, align(1))] +struct Align1; + +#[repr(C, align(2))] +struct Align2; + +#[repr(C, align(4))] +struct Align4; + +#[repr(C, align(8))] +struct Align8; + +#[repr(C, align(16))] +struct Align16; + +#[repr(C, align(32))] +struct Align32; + +#[repr(C, align(64))] +struct Align64; + +#[repr(C, align(128))] +struct Align128; + +#[repr(C, align(256))] +struct Align256; + +#[repr(C, align(512))] +struct Align512; + +#[repr(C, align(1024))] +struct Align1024; + +#[repr(C, align(2048))] +struct Align2048; + +#[repr(C, align(4096))] +struct Align4096; + +#[repr(C, align(8192))] +struct Align8192; + +#[repr(C, align(16384))] +struct Align16384; + +#[repr(C, align(32768))] +struct Align32768; + +#[repr(C, align(65536))] +struct Align65536; + +#[repr(C, align(131072))] +struct Align131072; + +#[repr(C, align(262144))] +struct Align262144; + +#[repr(C, align(524288))] +struct Align524288; + +#[repr(C, align(1048576))] +struct Align1048576; + +#[repr(C, align(2097152))] +struct Align2097152; + +#[repr(C, align(4194304))] +struct Align4194304; + +#[repr(C, align(8388608))] +struct Align8388608; + +#[repr(C, align(16777216))] +struct Align16777216; + +#[repr(C, align(33554432))] +struct Align33554432; + +#[repr(C, align(67108864))] +struct Align67108864; + +#[repr(C, align(134217728))] +struct Align13421772; + +#[repr(C, align(268435456))] +struct Align26843545; + +#[repr(C, align(1073741824))] +struct Align1073741824; + +fn main() {} diff --git a/tests/ui-nightly/max-align.stderr b/tests/ui-nightly/max-align.stderr new file mode 100644 index 0000000..0cadb9a --- /dev/null +++ b/tests/ui-nightly/max-align.stderr @@ -0,0 +1,5 @@ +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> tests/ui-nightly/max-align.rs:96:11 + | +96 | #[repr(C, align(1073741824))] + | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-nightly/transmute-dst-not-frombytes.rs b/tests/ui-nightly/transmute-dst-not-frombytes.rs new file mode 100644 index 0000000..c4caaff --- /dev/null +++ b/tests/ui-nightly/transmute-dst-not-frombytes.rs @@ -0,0 +1,18 @@ +// Copyright 2022 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); diff --git a/tests/ui-nightly/transmute-dst-not-frombytes.stderr b/tests/ui-nightly/transmute-dst-not-frombytes.stderr new file mode 100644 index 0000000..a9f1f7b --- /dev/null +++ b/tests/ui-nightly/transmute-dst-not-frombytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-nightly/transmute-dst-not-frombytes.rs:18:41 + | +18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-nightly/transmute-dst-not-frombytes.rs:18:41 + | +18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-illegal.rs b/tests/ui-nightly/transmute-illegal.rs deleted file mode 100644 index 74b8439..0000000 --- a/tests/ui-nightly/transmute-illegal.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2022 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -extern crate zerocopy; - -fn main() {} - -// It is unsound to inspect the usize value of a pointer during const eval. -const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); diff --git a/tests/ui-nightly/transmute-illegal.stderr b/tests/ui-nightly/transmute-illegal.stderr deleted file mode 100644 index a57544b..0000000 --- a/tests/ui-nightly/transmute-illegal.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied - --> tests/ui-nightly/transmute-illegal.rs:10:30 - | -10 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | the trait `AsBytes` is not implemented for `*const usize` - | required by a bound introduced by this call - | - = help: the trait `AsBytes` is implemented for `usize` -note: required by a bound in `POINTER_VALUE::transmute` - --> tests/ui-nightly/transmute-illegal.rs:10:30 - | -10 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `transmute` - = note: this error originates in the macro `zerocopy::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-alignment-increase.rs b/tests/ui-nightly/transmute-mut-alignment-increase.rs new file mode 100644 index 0000000..0928564 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-alignment-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); diff --git a/tests/ui-nightly/transmute-mut-alignment-increase.stderr b/tests/ui-nightly/transmute-mut-alignment-increase.stderr new file mode 100644 index 0000000..0666f8b --- /dev/null +++ b/tests/ui-nightly/transmute-mut-alignment-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-mut-alignment-increase.rs:19:39 + | +19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-const.rs b/tests/ui-nightly/transmute-mut-const.rs new file mode 100644 index 0000000..021b562 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-const.rs @@ -0,0 +1,20 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + +// `transmute_mut!` cannot, generally speaking, be used in const contexts. +const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); diff --git a/tests/ui-nightly/transmute-mut-const.stderr b/tests/ui-nightly/transmute-mut-const.stderr new file mode 100644 index 0000000..fa53ed0 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-const.stderr @@ -0,0 +1,42 @@ +warning: taking a mutable reference to a `const` item + --> tests/ui-nightly/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> tests/ui-nightly/transmute-mut-const.rs:17:1 + | +17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +error[E0658]: mutable references are not allowed in constants + --> tests/ui-nightly/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `transmute_mut::<'_, '_, [u8; 2], [u8; 2]>` in constants + --> tests/ui-nightly/transmute-mut-const.rs:20:37 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> tests/ui-nightly/transmute-mut-const.rs:20:57 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | --------------------^^^^^^^^^^^^- + | | | + | | creates a temporary value which is freed while still in use + | temporary value is freed at the end of this statement + | using this value as a constant requires that borrow lasts for `'static` diff --git a/tests/ui-nightly/transmute-mut-dst-generic.rs b/tests/ui-nightly/transmute-mut-dst-generic.rs new file mode 100644 index 0000000..7068f10 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_mut(u: &mut u8) -> &mut T { + // `transmute_mut!` requires the destination type to be concrete. + transmute_mut!(u) +} diff --git a/tests/ui-nightly/transmute-mut-dst-generic.stderr b/tests/ui-nightly/transmute-mut-dst-generic.stderr new file mode 100644 index 0000000..f278558 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-mut-dst-generic.rs:17:5 + | +17 | transmute_mut!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `T` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-mut-dst-generic.rs:17:5 + | +17 | transmute_mut!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (8 bits) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs b/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs new file mode 100644 index 0000000..33a9ecd --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); diff --git a/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr b/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr new file mode 100644 index 0000000..a84547b --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-not-a-reference.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-dst-not-asbytes.rs b/tests/ui-nightly/transmute-mut-dst-not-asbytes.rs new file mode 100644 index 0000000..b72f129 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-not-asbytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `AsBytes` +const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr b/tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr new file mode 100644 index 0000000..54c8e60 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-not-asbytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Dst: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-dst-not-asbytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `Dst` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-nightly/transmute-mut-dst-not-asbytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs b/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs new file mode 100644 index 0000000..102fced --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-not-frombytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr b/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr new file mode 100644 index 0000000..ea2123b --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-not-frombytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `Dst` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-nightly/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-dst-unsized.rs b/tests/ui-nightly/transmute-mut-dst-unsized.rs new file mode 100644 index 0000000..693ccda --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); diff --git a/tests/ui-nightly/transmute-mut-dst-unsized.stderr b/tests/ui-nightly/transmute-mut-dst-unsized.stderr new file mode 100644 index 0000000..a670e25 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-dst-unsized.stderr @@ -0,0 +1,86 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-illegal-lifetime.rs b/tests/ui-nightly/transmute-mut-illegal-lifetime.rs new file mode 100644 index 0000000..c31765e --- /dev/null +++ b/tests/ui-nightly/transmute-mut-illegal-lifetime.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() {} + +fn increase_lifetime() { + let mut x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); +} diff --git a/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr b/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr new file mode 100644 index 0000000..b826fcc --- /dev/null +++ b/tests/ui-nightly/transmute-mut-illegal-lifetime.stderr @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-nightly/transmute-mut-illegal-lifetime.rs:14:56 + | +12 | let mut x = 0u64; + | ----- binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); + | ---------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff --git a/tests/ui-nightly/transmute-mut-size-decrease.rs b/tests/ui-nightly/transmute-mut-size-decrease.rs new file mode 100644 index 0000000..c6eec3a --- /dev/null +++ b/tests/ui-nightly/transmute-mut-size-decrease.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// We require that the size of the destination type is not smaller than the size +// of the source type. +const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); diff --git a/tests/ui-nightly/transmute-mut-size-decrease.stderr b/tests/ui-nightly/transmute-mut-size-decrease.stderr new file mode 100644 index 0000000..ac1e35c --- /dev/null +++ b/tests/ui-nightly/transmute-mut-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-mut-size-decrease.rs:17:32 + | +17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 2]` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-size-increase.rs b/tests/ui-nightly/transmute-mut-size-increase.rs new file mode 100644 index 0000000..a4657c2 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-size-increase.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); diff --git a/tests/ui-nightly/transmute-mut-size-increase.stderr b/tests/ui-nightly/transmute-mut-size-increase.stderr new file mode 100644 index 0000000..d343bd6 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-mut-size-increase.rs:17:37 + | +17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-src-dst-generic.rs b/tests/ui-nightly/transmute-mut-src-dst-generic.rs new file mode 100644 index 0000000..aed7ded --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-dst-generic.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_mut(t: &mut T) -> &mut U { + // `transmute_mut!` requires the source and destination types to be + // concrete. + transmute_mut!(t) +} diff --git a/tests/ui-nightly/transmute-mut-src-dst-generic.stderr b/tests/ui-nightly/transmute-mut-src-dst-generic.stderr new file mode 100644 index 0000000..e3f3a3f --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-mut-src-dst-generic.rs:18:5 + | +18 | transmute_mut!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `U` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-mut-src-dst-generic.rs:18:5 + | +18 | transmute_mut!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-src-dst-not-references.rs b/tests/ui-nightly/transmute-mut-src-dst-not-references.rs new file mode 100644 index 0000000..98cc520 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-dst-not-references.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); diff --git a/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr b/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr new file mode 100644 index 0000000..df3cf2d --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-dst-not-references.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-src-dst-not-references.rs:17:59 + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(&mut 0usize); + | ++++ diff --git a/tests/ui-nightly/transmute-mut-src-dst-unsized.rs b/tests/ui-nightly/transmute-mut-src-dst-unsized.rs new file mode 100644 index 0000000..1bebcf2 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between unsized source and +// destination types. +const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); diff --git a/tests/ui-nightly/transmute-mut-src-dst-unsized.stderr b/tests/ui-nightly/transmute-mut-src-dst-unsized.stderr new file mode 100644 index 0000000..0f41a42 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-dst-unsized.stderr @@ -0,0 +1,231 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-src-generic.rs b/tests/ui-nightly/transmute-mut-src-generic.rs new file mode 100644 index 0000000..a3ef397 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes}; + +fn main() {} + +fn transmute_mut(t: &mut T) -> &mut u8 { + // `transmute_mut!` requires the source type to be concrete. + transmute_mut!(t) +} diff --git a/tests/ui-nightly/transmute-mut-src-generic.stderr b/tests/ui-nightly/transmute-mut-src-generic.stderr new file mode 100644 index 0000000..c06d775 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-generic.stderr @@ -0,0 +1,10 @@ +error[E0405]: cannot find trait `FromBytes` in this scope + --> tests/ui-nightly/transmute-mut-src-generic.rs:15:31 + | +15 | fn transmute_mut(t: &mut T) -> &mut u8 { + | ^^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +11 + use zerocopy::FromBytes; + | diff --git a/tests/ui-nightly/transmute-mut-src-immutable.rs b/tests/ui-nightly/transmute-mut-src-immutable.rs new file mode 100644 index 0000000..08088d0 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-immutable.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +fn ref_src_immutable() { + // `transmute_mut!` requires that its source type be a mutable reference. + let _: &mut u8 = transmute_mut!(&0u8); +} diff --git a/tests/ui-nightly/transmute-mut-src-immutable.stderr b/tests/ui-nightly/transmute-mut-src-immutable.stderr new file mode 100644 index 0000000..7b7969d --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-immutable.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-src-immutable.rs:17:37 + | +17 | let _: &mut u8 = transmute_mut!(&0u8); + | ---------------^^^^- + | | | + | | types differ in mutability + | expected due to this + | + = note: expected mutable reference `&mut _` + found reference `&u8` diff --git a/tests/ui-nightly/transmute-mut-src-not-a-reference.rs b/tests/ui-nightly/transmute-mut-src-not-a-reference.rs new file mode 100644 index 0000000..bf8bc32 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); diff --git a/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr b/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr new file mode 100644 index 0000000..12b7674 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-not-a-reference.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-mut-src-not-a-reference.rs:17:53 + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(&mut 0usize); + | ++++ diff --git a/tests/ui-nightly/transmute-mut-src-not-asbytes.rs b/tests/ui-nightly/transmute-mut-src-not-asbytes.rs new file mode 100644 index 0000000..6a14f12 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-not-asbytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-nightly/transmute-mut-src-not-asbytes.stderr b/tests/ui-nightly/transmute-mut-src-not-asbytes.stderr new file mode 100644 index 0000000..b755d3c --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-not-asbytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `Src: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `Src` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src` + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-nightly/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-src-not-frombytes.rs b/tests/ui-nightly/transmute-mut-src-not-frombytes.rs new file mode 100644 index 0000000..2ebe036 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-not-frombytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `FromBytes` +const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr b/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr new file mode 100644 index 0000000..5a9f0a7 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-not-frombytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `Src` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-nightly/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-mut-src-unsized.rs b/tests/ui-nightly/transmute-mut-src-unsized.rs new file mode 100644 index 0000000..413dd68 --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-unsized.rs @@ -0,0 +1,16 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); diff --git a/tests/ui-nightly/transmute-mut-src-unsized.stderr b/tests/ui-nightly/transmute-mut-src-unsized.stderr new file mode 100644 index 0000000..99475ad --- /dev/null +++ b/tests/ui-nightly/transmute-mut-src-unsized.stderr @@ -0,0 +1,158 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ptr-to-usize.rs b/tests/ui-nightly/transmute-ptr-to-usize.rs new file mode 100644 index 0000000..5af8859 --- /dev/null +++ b/tests/ui-nightly/transmute-ptr-to-usize.rs @@ -0,0 +1,20 @@ +// Copyright 2022 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. + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// It is unclear whether we can or should support this transmutation, especially +// in a const context. This test ensures that even if such a transmutation +// becomes valid due to the requisite implementations of `FromBytes` being +// added, that we re-examine whether it should specifically be valid in a const +// context. +const POINTER_VALUE: usize = transmute!(&0usize as *const usize); diff --git a/tests/ui-nightly/transmute-ptr-to-usize.stderr b/tests/ui-nightly/transmute-ptr-to-usize.stderr new file mode 100644 index 0000000..2fcba2f --- /dev/null +++ b/tests/ui-nightly/transmute-ptr-to-usize.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `*const usize` + | required by a bound introduced by this call + | + = help: the trait `AsBytes` is implemented for `usize` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize` + | + = help: the trait `AsBytes` is implemented for `usize` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-alignment-increase.rs b/tests/ui-nightly/transmute-ref-alignment-increase.rs new file mode 100644 index 0000000..bf1988c --- /dev/null +++ b/tests/ui-nightly/transmute-ref-alignment-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]); diff --git a/tests/ui-nightly/transmute-ref-alignment-increase.stderr b/tests/ui-nightly/transmute-ref-alignment-increase.stderr new file mode 100644 index 0000000..1cef246 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-alignment-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-alignment-increase.rs:19:35 + | +19 | const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-dst-generic.rs b/tests/ui-nightly/transmute-ref-dst-generic.rs new file mode 100644 index 0000000..bf4a0f9 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, FromBytes}; + +fn main() {} + +fn transmute_ref(u: &u8) -> &T { + // `transmute_ref!` requires the destination type to be concrete. + transmute_ref!(u) +} diff --git a/tests/ui-nightly/transmute-ref-dst-generic.stderr b/tests/ui-nightly/transmute-ref-dst-generic.stderr new file mode 100644 index 0000000..4c94d50 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-dst-generic.rs:17:5 + | +17 | transmute_ref!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `T` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-dst-generic.rs:17:5 + | +17 | transmute_ref!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (8 bits) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-dst-mutable.rs b/tests/ui-nightly/transmute-ref-dst-mutable.rs new file mode 100644 index 0000000..fa0e6e4 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-mutable.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `transmute_ref!` requires that its destination type be an immutable + // reference. + let _: &mut u8 = transmute_ref!(&0u8); +} diff --git a/tests/ui-nightly/transmute-ref-dst-mutable.stderr b/tests/ui-nightly/transmute-ref-dst-mutable.stderr new file mode 100644 index 0000000..0cbdd17 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-mutable.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs b/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs new file mode 100644 index 0000000..de55f9a --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); diff --git a/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr b/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr new file mode 100644 index 0000000..847d547 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-not-a-reference.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs b/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs new file mode 100644 index 0000000..d81f64d --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-not-frombytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); diff --git a/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr b/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr new file mode 100644 index 0000000..e4791d7 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-not-frombytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:18:42 + | +18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-nightly/transmute-ref-dst-not-frombytes.rs:18:42 + | +18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-dst-unsized.rs b/tests/ui-nightly/transmute-ref-dst-unsized.rs new file mode 100644 index 0000000..625f1fa --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); diff --git a/tests/ui-nightly/transmute-ref-dst-unsized.stderr b/tests/ui-nightly/transmute-ref-dst-unsized.stderr new file mode 100644 index 0000000..3d0f6d0 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-dst-unsized.stderr @@ -0,0 +1,69 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-illegal-lifetime.rs b/tests/ui-nightly/transmute-ref-illegal-lifetime.rs new file mode 100644 index 0000000..8dd191e --- /dev/null +++ b/tests/ui-nightly/transmute-ref-illegal-lifetime.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() {} + +fn increase_lifetime() { + let x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static u64 = zerocopy::transmute_ref!(&x); +} diff --git a/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr b/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr new file mode 100644 index 0000000..e16a557 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-illegal-lifetime.stderr @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-nightly/transmute-ref-illegal-lifetime.rs:14:52 + | +12 | let x = 0u64; + | - binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static u64 = zerocopy::transmute_ref!(&x); + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff --git a/tests/ui-nightly/transmute-ref-size-decrease.rs b/tests/ui-nightly/transmute-ref-size-decrease.rs new file mode 100644 index 0000000..1d66a54 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-size-decrease.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]); diff --git a/tests/ui-nightly/transmute-ref-size-decrease.stderr b/tests/ui-nightly/transmute-ref-size-decrease.stderr new file mode 100644 index 0000000..793ecc5 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-size-decrease.rs:17:28 + | +17 | const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 2]` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-size-increase.rs b/tests/ui-nightly/transmute-ref-size-increase.rs new file mode 100644 index 0000000..cdca560 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-size-increase.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8); diff --git a/tests/ui-nightly/transmute-ref-size-increase.stderr b/tests/ui-nightly/transmute-ref-size-increase.stderr new file mode 100644 index 0000000..40c69f6 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-size-increase.rs:17:33 + | +17 | const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-src-dst-generic.rs b/tests/ui-nightly/transmute-ref-src-dst-generic.rs new file mode 100644 index 0000000..409d785 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-dst-generic.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_ref(t: &T) -> &U { + // `transmute_ref!` requires the source and destination types to be + // concrete. + transmute_ref!(t) +} diff --git a/tests/ui-nightly/transmute-ref-src-dst-generic.stderr b/tests/ui-nightly/transmute-ref-src-dst-generic.stderr new file mode 100644 index 0000000..6a3a4fd --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-src-dst-generic.rs:18:5 + | +18 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `U` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-src-dst-generic.rs:18:5 + | +18 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-src-dst-not-references.rs b/tests/ui-nightly/transmute-ref-src-dst-not-references.rs new file mode 100644 index 0000000..114e917 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-dst-not-references.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); diff --git a/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr b/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr new file mode 100644 index 0000000..0f1f7fc --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-dst-not-references.stderr @@ -0,0 +1,45 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:54 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(&0usize); + | + + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-src-dst-unsized.rs b/tests/ui-nightly/transmute-ref-src-dst-unsized.rs new file mode 100644 index 0000000..6bfe7ff --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between unsized source and +// destination types. +const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); diff --git a/tests/ui-nightly/transmute-ref-src-dst-unsized.stderr b/tests/ui-nightly/transmute-ref-src-dst-unsized.stderr new file mode 100644 index 0000000..02e62bc --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-dst-unsized.stderr @@ -0,0 +1,183 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-src-generic.rs b/tests/ui-nightly/transmute-ref-src-generic.rs new file mode 100644 index 0000000..010281c --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, AsBytes}; + +fn main() {} + +fn transmute_ref(t: &T) -> &u8 { + // `transmute_ref!` requires the source type to be concrete. + transmute_ref!(t) +} diff --git a/tests/ui-nightly/transmute-ref-src-generic.stderr b/tests/ui-nightly/transmute-ref-src-generic.stderr new file mode 100644 index 0000000..a168f44 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-src-generic.rs:17:5 + | +17 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-ref-src-generic.rs:17:5 + | +17 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-src-not-a-reference.rs b/tests/ui-nightly/transmute-ref-src-not-a-reference.rs new file mode 100644 index 0000000..90661b3 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); diff --git a/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr b/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr new file mode 100644 index 0000000..be477c6 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-not-a-reference.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-nightly/transmute-ref-src-not-a-reference.rs:17:49 + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(&0usize); + | + diff --git a/tests/ui-nightly/transmute-ref-src-not-asbytes.rs b/tests/ui-nightly/transmute-ref-src-not-asbytes.rs new file mode 100644 index 0000000..6ab19f3 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-not-asbytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); diff --git a/tests/ui-nightly/transmute-ref-src-not-asbytes.stderr b/tests/ui-nightly/transmute-ref-src-not-asbytes.stderr new file mode 100644 index 0000000..eb28ccf --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-not-asbytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-ref-src-unsized.rs b/tests/ui-nightly/transmute-ref-src-unsized.rs new file mode 100644 index 0000000..14e72b4 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-unsized.rs @@ -0,0 +1,16 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); diff --git a/tests/ui-nightly/transmute-ref-src-unsized.stderr b/tests/ui-nightly/transmute-ref-src-unsized.stderr new file mode 100644 index 0000000..b280429 --- /dev/null +++ b/tests/ui-nightly/transmute-ref-src-unsized.stderr @@ -0,0 +1,127 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-nightly/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-size-decrease.rs b/tests/ui-nightly/transmute-size-decrease.rs new file mode 100644 index 0000000..1d56831 --- /dev/null +++ b/tests/ui-nightly/transmute-size-decrease.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: u8 = transmute!(AU16(0)); diff --git a/tests/ui-nightly/transmute-size-decrease.stderr b/tests/ui-nightly/transmute-size-decrease.stderr new file mode 100644 index 0000000..83742d7 --- /dev/null +++ b/tests/ui-nightly/transmute-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-size-decrease.rs:19:27 + | +19 | const DECREASE_SIZE: u8 = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-size-increase.rs b/tests/ui-nightly/transmute-size-increase.rs new file mode 100644 index 0000000..32f9363 --- /dev/null +++ b/tests/ui-nightly/transmute-size-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(0u8); diff --git a/tests/ui-nightly/transmute-size-increase.stderr b/tests/ui-nightly/transmute-size-increase.stderr new file mode 100644 index 0000000..230bb17 --- /dev/null +++ b/tests/ui-nightly/transmute-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-size-increase.rs:19:29 + | +19 | const INCREASE_SIZE: AU16 = transmute!(0u8); + | ^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-nightly/transmute-src-not-asbytes.rs b/tests/ui-nightly/transmute-src-not-asbytes.rs new file mode 100644 index 0000000..dd73021 --- /dev/null +++ b/tests/ui-nightly/transmute-src-not-asbytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); diff --git a/tests/ui-nightly/transmute-src-not-asbytes.stderr b/tests/ui-nightly/transmute-src-not-asbytes.stderr new file mode 100644 index 0000000..b36a820 --- /dev/null +++ b/tests/ui-nightly/transmute-src-not-asbytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-nightly/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/include_value_not_from_bytes.rs b/tests/ui-stable/include_value_not_from_bytes.rs new file mode 100644 index 0000000..45b6138 --- /dev/null +++ b/tests/ui-stable/include_value_not_from_bytes.rs @@ -0,0 +1,12 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because `UnsafeCell: !FromBytes`. +const NOT_FROM_BYTES: core::cell::UnsafeCell = + include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-stable/include_value_not_from_bytes.stderr b/tests/ui-stable/include_value_not_from_bytes.stderr new file mode 100644 index 0000000..7e9a035 --- /dev/null +++ b/tests/ui-stable/include_value_not_from_bytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `UnsafeCell: FromBytes` is not satisfied + --> tests/ui-stable/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `UnsafeCell` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-stable/include_value_not_from_bytes.rs:12:5 + | +12 | include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/include_value_wrong_size.rs b/tests/ui-stable/include_value_wrong_size.rs new file mode 100644 index 0000000..d87b306 --- /dev/null +++ b/tests/ui-stable/include_value_wrong_size.rs @@ -0,0 +1,11 @@ +// Copyright 2022 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#[macro_use] +extern crate zerocopy; + +fn main() {} + +// Should fail because the file is 4 bytes long, not 8. +const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); diff --git a/tests/ui-stable/include_value_wrong_size.stderr b/tests/ui-stable/include_value_wrong_size.stderr new file mode 100644 index 0000000..956d74c --- /dev/null +++ b/tests/ui-stable/include_value_wrong_size.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/include_value_wrong_size.rs:11:25 + | +11 | const WRONG_SIZE: u64 = include_value!("../../testdata/include_value/data"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 4]` (32 bits) + = note: target type: `u64` (64 bits) + = note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/invalid-impls/invalid-impls.rs b/tests/ui-stable/invalid-impls/invalid-impls.rs index b9a60bd..ea96390 100644 --- a/tests/ui-stable/invalid-impls/invalid-impls.rs +++ b/tests/ui-stable/invalid-impls/invalid-impls.rs @@ -1,6 +1,10 @@ -// Copyright 2022 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// Copyright 2022 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. // Since some macros from `macros.rs` are unused. #![allow(unused)] diff --git a/tests/ui-stable/invalid-impls/invalid-impls.stderr b/tests/ui-stable/invalid-impls/invalid-impls.stderr index f613377..7737d67 100644 --- a/tests/ui-stable/invalid-impls/invalid-impls.stderr +++ b/tests/ui-stable/invalid-impls/invalid-impls.stderr @@ -1,13 +1,13 @@ error[E0277]: the trait bound `T: zerocopy::FromZeroes` is not satisfied - --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:37 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:26:37 | -22 | impl_or_verify!(T => FromZeroes for Foo); +26 | 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:18:10 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:10 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -15,26 +15,26 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:22:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:26:1 | -22 | impl_or_verify!(T => FromZeroes for Foo); +26 | 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` - | -22 | impl_or_verify!(T: zerocopy::FromZeroes => FromZeroes for Foo); - | ++++++++++++++++++++++ + | +26 | 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:23:36 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:27:36 | -23 | impl_or_verify!(T => FromBytes for Foo); +27 | 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:18:22 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:22 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -42,26 +42,26 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:23:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:27:1 | -23 | impl_or_verify!(T => FromBytes for Foo); +27 | 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` - | -23 | impl_or_verify!(T: zerocopy::FromBytes => FromBytes for Foo); - | +++++++++++++++++++++ + | +27 | 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:24:34 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:28:34 | -24 | impl_or_verify!(T => AsBytes for Foo); +28 | 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:18:33 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:33 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -69,26 +69,26 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:24:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:28:1 | -24 | impl_or_verify!(T => AsBytes for Foo); +28 | 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` - | -24 | impl_or_verify!(T: zerocopy::AsBytes => AsBytes for Foo); - | +++++++++++++++++++ + | +28 | 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:25:36 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:29:36 | -25 | impl_or_verify!(T => Unaligned for Foo); +29 | 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:18:42 + --> tests/ui-stable/invalid-impls/invalid-impls.rs:22:42 | -18 | #[derive(FromZeroes, FromBytes, AsBytes, Unaligned)] +22 | #[derive(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 @@ -96,12 +96,12 @@ note: required by a bound in `_::Subtrait` | trait Subtrait: $trait {} | ^^^^^^ required by this bound in `Subtrait` | - ::: tests/ui-stable/invalid-impls/invalid-impls.rs:25:1 + ::: tests/ui-stable/invalid-impls/invalid-impls.rs:29:1 | -25 | impl_or_verify!(T => Unaligned for Foo); +29 | 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` - | -25 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); - | +++++++++++++++++++++ + | +29 | impl_or_verify!(T: zerocopy::Unaligned => Unaligned for Foo); + | +++++++++++++++++++++ diff --git a/tests/ui-stable/max-align.rs b/tests/ui-stable/max-align.rs new file mode 100644 index 0000000..53e3eb9 --- /dev/null +++ b/tests/ui-stable/max-align.rs @@ -0,0 +1,99 @@ +// 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. + +#[repr(C, align(1))] +struct Align1; + +#[repr(C, align(2))] +struct Align2; + +#[repr(C, align(4))] +struct Align4; + +#[repr(C, align(8))] +struct Align8; + +#[repr(C, align(16))] +struct Align16; + +#[repr(C, align(32))] +struct Align32; + +#[repr(C, align(64))] +struct Align64; + +#[repr(C, align(128))] +struct Align128; + +#[repr(C, align(256))] +struct Align256; + +#[repr(C, align(512))] +struct Align512; + +#[repr(C, align(1024))] +struct Align1024; + +#[repr(C, align(2048))] +struct Align2048; + +#[repr(C, align(4096))] +struct Align4096; + +#[repr(C, align(8192))] +struct Align8192; + +#[repr(C, align(16384))] +struct Align16384; + +#[repr(C, align(32768))] +struct Align32768; + +#[repr(C, align(65536))] +struct Align65536; + +#[repr(C, align(131072))] +struct Align131072; + +#[repr(C, align(262144))] +struct Align262144; + +#[repr(C, align(524288))] +struct Align524288; + +#[repr(C, align(1048576))] +struct Align1048576; + +#[repr(C, align(2097152))] +struct Align2097152; + +#[repr(C, align(4194304))] +struct Align4194304; + +#[repr(C, align(8388608))] +struct Align8388608; + +#[repr(C, align(16777216))] +struct Align16777216; + +#[repr(C, align(33554432))] +struct Align33554432; + +#[repr(C, align(67108864))] +struct Align67108864; + +#[repr(C, align(134217728))] +struct Align13421772; + +#[repr(C, align(268435456))] +struct Align26843545; + +#[repr(C, align(1073741824))] +struct Align1073741824; + +fn main() {} diff --git a/tests/ui-stable/max-align.stderr b/tests/ui-stable/max-align.stderr new file mode 100644 index 0000000..ea472f2 --- /dev/null +++ b/tests/ui-stable/max-align.stderr @@ -0,0 +1,5 @@ +error[E0589]: invalid `repr(align)` attribute: larger than 2^29 + --> tests/ui-stable/max-align.rs:96:11 + | +96 | #[repr(C, align(1073741824))] + | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui-stable/transmute-dst-not-frombytes.rs b/tests/ui-stable/transmute-dst-not-frombytes.rs new file mode 100644 index 0000000..c4caaff --- /dev/null +++ b/tests/ui-stable/transmute-dst-not-frombytes.rs @@ -0,0 +1,18 @@ +// Copyright 2022 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); diff --git a/tests/ui-stable/transmute-dst-not-frombytes.stderr b/tests/ui-stable/transmute-dst-not-frombytes.stderr new file mode 100644 index 0000000..b008bcd --- /dev/null +++ b/tests/ui-stable/transmute-dst-not-frombytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-stable/transmute-dst-not-frombytes.rs:18:41 + | +18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-stable/transmute-dst-not-frombytes.rs:18:41 + | +18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-illegal.rs b/tests/ui-stable/transmute-illegal.rs deleted file mode 100644 index 74b8439..0000000 --- a/tests/ui-stable/transmute-illegal.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2022 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -extern crate zerocopy; - -fn main() {} - -// It is unsound to inspect the usize value of a pointer during const eval. -const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); diff --git a/tests/ui-stable/transmute-illegal.stderr b/tests/ui-stable/transmute-illegal.stderr deleted file mode 100644 index e9ac240..0000000 --- a/tests/ui-stable/transmute-illegal.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied - --> tests/ui-stable/transmute-illegal.rs:10:30 - | -10 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | the trait `AsBytes` is not implemented for `*const usize` - | required by a bound introduced by this call - | - = help: the trait `AsBytes` is implemented for `usize` -note: required by a bound in `POINTER_VALUE::transmute` - --> tests/ui-stable/transmute-illegal.rs:10:30 - | -10 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `transmute` - = note: this error originates in the macro `zerocopy::transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-alignment-increase.rs b/tests/ui-stable/transmute-mut-alignment-increase.rs new file mode 100644 index 0000000..0928564 --- /dev/null +++ b/tests/ui-stable/transmute-mut-alignment-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); diff --git a/tests/ui-stable/transmute-mut-alignment-increase.stderr b/tests/ui-stable/transmute-mut-alignment-increase.stderr new file mode 100644 index 0000000..252fec9 --- /dev/null +++ b/tests/ui-stable/transmute-mut-alignment-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-mut-alignment-increase.rs:19:39 + | +19 | const INCREASE_ALIGNMENT: &mut AU16 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-const.rs b/tests/ui-stable/transmute-mut-const.rs new file mode 100644 index 0000000..021b562 --- /dev/null +++ b/tests/ui-stable/transmute-mut-const.rs @@ -0,0 +1,20 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + +// `transmute_mut!` cannot, generally speaking, be used in const contexts. +const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); diff --git a/tests/ui-stable/transmute-mut-const.stderr b/tests/ui-stable/transmute-mut-const.stderr new file mode 100644 index 0000000..a89ea67 --- /dev/null +++ b/tests/ui-stable/transmute-mut-const.stderr @@ -0,0 +1,41 @@ +warning: taking a mutable reference to a `const` item + --> tests/ui-stable/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: each usage of a `const` item creates a new temporary + = note: the mutable reference will refer to this temporary, not the original `const` item +note: `const` item defined here + --> tests/ui-stable/transmute-mut-const.rs:17:1 + | +17 | const ARRAY_OF_U8S: [u8; 2] = [0u8; 2]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(const_item_mutation)]` on by default + +error[E0658]: mutable references are not allowed in constants + --> tests/ui-stable/transmute-mut-const.rs:20:52 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + +error[E0015]: cannot call non-const fn `transmute_mut::<'_, '_, [u8; 2], [u8; 2]>` in constants + --> tests/ui-stable/transmute-mut-const.rs:20:37 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0716]: temporary value dropped while borrowed + --> tests/ui-stable/transmute-mut-const.rs:20:57 + | +20 | const CONST_CONTEXT: &mut [u8; 2] = transmute_mut!(&mut ARRAY_OF_U8S); + | --------------------^^^^^^^^^^^^- + | | | + | | creates a temporary value which is freed while still in use + | temporary value is freed at the end of this statement + | using this value as a constant requires that borrow lasts for `'static` diff --git a/tests/ui-stable/transmute-mut-dst-generic.rs b/tests/ui-stable/transmute-mut-dst-generic.rs new file mode 100644 index 0000000..7068f10 --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_mut(u: &mut u8) -> &mut T { + // `transmute_mut!` requires the destination type to be concrete. + transmute_mut!(u) +} diff --git a/tests/ui-stable/transmute-mut-dst-generic.stderr b/tests/ui-stable/transmute-mut-dst-generic.stderr new file mode 100644 index 0000000..0000eb0 --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-mut-dst-generic.rs:17:5 + | +17 | transmute_mut!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `T` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-mut-dst-generic.rs:17:5 + | +17 | transmute_mut!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (8 bits) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-dst-not-a-reference.rs b/tests/ui-stable/transmute-mut-dst-not-a-reference.rs new file mode 100644 index 0000000..33a9ecd --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); diff --git a/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr b/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr new file mode 100644 index 0000000..14ee444 --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-not-a-reference.stderr @@ -0,0 +1,39 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _` + | + = note: expected type `usize` + found mutable reference `&mut _` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-dst-not-asbytes.rs b/tests/ui-stable/transmute-mut-dst-not-asbytes.rs new file mode 100644 index 0000000..b72f129 --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-not-asbytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `AsBytes` +const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-stable/transmute-mut-dst-not-asbytes.stderr b/tests/ui-stable/transmute-mut-dst-not-asbytes.stderr new file mode 100644 index 0000000..f3cacca --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-not-asbytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Dst: AsBytes` is not satisfied + --> tests/ui-stable/transmute-mut-dst-not-asbytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `Dst` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-stable/transmute-mut-dst-not-asbytes.rs:24:36 + | +24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-dst-not-frombytes.rs b/tests/ui-stable/transmute-mut-dst-not-frombytes.rs new file mode 100644 index 0000000..102fced --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-not-frombytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr b/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr new file mode 100644 index 0000000..39bb4fd --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-not-frombytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `Dst: FromBytes` is not satisfied + --> tests/ui-stable/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `Dst` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-stable/transmute-mut-dst-not-frombytes.rs:24:38 + | +24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-dst-unsized.rs b/tests/ui-stable/transmute-mut-dst-unsized.rs new file mode 100644 index 0000000..693ccda --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); diff --git a/tests/ui-stable/transmute-mut-dst-unsized.stderr b/tests/ui-stable/transmute-mut-dst-unsized.stderr new file mode 100644 index 0000000..0772785 --- /dev/null +++ b/tests/ui-stable/transmute-mut-dst-unsized.stderr @@ -0,0 +1,106 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-dst-unsized.rs:17:32 + | +17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-illegal-lifetime.rs b/tests/ui-stable/transmute-mut-illegal-lifetime.rs new file mode 100644 index 0000000..c31765e --- /dev/null +++ b/tests/ui-stable/transmute-mut-illegal-lifetime.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() {} + +fn increase_lifetime() { + let mut x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); +} diff --git a/tests/ui-stable/transmute-mut-illegal-lifetime.stderr b/tests/ui-stable/transmute-mut-illegal-lifetime.stderr new file mode 100644 index 0000000..7f12813 --- /dev/null +++ b/tests/ui-stable/transmute-mut-illegal-lifetime.stderr @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-stable/transmute-mut-illegal-lifetime.rs:14:56 + | +12 | let mut x = 0u64; + | ----- binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static mut u64 = zerocopy::transmute_mut!(&mut x); + | ---------------- ^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff --git a/tests/ui-stable/transmute-mut-size-decrease.rs b/tests/ui-stable/transmute-mut-size-decrease.rs new file mode 100644 index 0000000..c6eec3a --- /dev/null +++ b/tests/ui-stable/transmute-mut-size-decrease.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// We require that the size of the destination type is not smaller than the size +// of the source type. +const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); diff --git a/tests/ui-stable/transmute-mut-size-decrease.stderr b/tests/ui-stable/transmute-mut-size-decrease.stderr new file mode 100644 index 0000000..2399913 --- /dev/null +++ b/tests/ui-stable/transmute-mut-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-mut-size-decrease.rs:17:32 + | +17 | const DECREASE_SIZE: &mut u8 = transmute_mut!(&mut [0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 2]` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-size-increase.rs b/tests/ui-stable/transmute-mut-size-increase.rs new file mode 100644 index 0000000..a4657c2 --- /dev/null +++ b/tests/ui-stable/transmute-mut-size-increase.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); diff --git a/tests/ui-stable/transmute-mut-size-increase.stderr b/tests/ui-stable/transmute-mut-size-increase.stderr new file mode 100644 index 0000000..1427c7b --- /dev/null +++ b/tests/ui-stable/transmute-mut-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-mut-size-increase.rs:17:37 + | +17 | const INCREASE_SIZE: &mut [u8; 2] = transmute_mut!(&mut 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-src-dst-generic.rs b/tests/ui-stable/transmute-mut-src-dst-generic.rs new file mode 100644 index 0000000..aed7ded --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-dst-generic.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_mut(t: &mut T) -> &mut U { + // `transmute_mut!` requires the source and destination types to be + // concrete. + transmute_mut!(t) +} diff --git a/tests/ui-stable/transmute-mut-src-dst-generic.stderr b/tests/ui-stable/transmute-mut-src-dst-generic.stderr new file mode 100644 index 0000000..ddb8bb6 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-mut-src-dst-generic.rs:18:5 + | +18 | transmute_mut!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `U` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-mut-src-dst-generic.rs:18:5 + | +18 | transmute_mut!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-src-dst-not-references.rs b/tests/ui-stable/transmute-mut-src-dst-not-references.rs new file mode 100644 index 0000000..98cc520 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-dst-not-references.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); diff --git a/tests/ui-stable/transmute-mut-src-dst-not-references.stderr b/tests/ui-stable/transmute-mut-src-dst-not-references.stderr new file mode 100644 index 0000000..c0d9e0f --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-dst-not-references.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-src-dst-not-references.rs:17:59 + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(&mut 0usize); + | ++++ diff --git a/tests/ui-stable/transmute-mut-src-dst-unsized.rs b/tests/ui-stable/transmute-mut-src-dst-unsized.rs new file mode 100644 index 0000000..1bebcf2 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting between unsized source and +// destination types. +const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); diff --git a/tests/ui-stable/transmute-mut-src-dst-unsized.stderr b/tests/ui-stable/transmute-mut-src-dst-unsized.stderr new file mode 100644 index 0000000..8cf7664 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-dst-unsized.stderr @@ -0,0 +1,288 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsFromBytes` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertDstIsAsBytes` + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-dst-unsized.rs:17:36 + | +17 | const SRC_DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-src-generic.rs b/tests/ui-stable/transmute-mut-src-generic.rs new file mode 100644 index 0000000..a3ef397 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_mut, AsBytes}; + +fn main() {} + +fn transmute_mut(t: &mut T) -> &mut u8 { + // `transmute_mut!` requires the source type to be concrete. + transmute_mut!(t) +} diff --git a/tests/ui-stable/transmute-mut-src-generic.stderr b/tests/ui-stable/transmute-mut-src-generic.stderr new file mode 100644 index 0000000..fc4809e --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-generic.stderr @@ -0,0 +1,10 @@ +error[E0405]: cannot find trait `FromBytes` in this scope + --> tests/ui-stable/transmute-mut-src-generic.rs:15:31 + | +15 | fn transmute_mut(t: &mut T) -> &mut u8 { + | ^^^^^^^^^ not found in this scope + | +help: consider importing this trait + | +11 + use zerocopy::FromBytes; + | diff --git a/tests/ui-stable/transmute-mut-src-immutable.rs b/tests/ui-stable/transmute-mut-src-immutable.rs new file mode 100644 index 0000000..08088d0 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-immutable.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +fn ref_src_immutable() { + // `transmute_mut!` requires that its source type be a mutable reference. + let _: &mut u8 = transmute_mut!(&0u8); +} diff --git a/tests/ui-stable/transmute-mut-src-immutable.stderr b/tests/ui-stable/transmute-mut-src-immutable.stderr new file mode 100644 index 0000000..0115c79 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-immutable.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-src-immutable.rs:17:37 + | +17 | let _: &mut u8 = transmute_mut!(&0u8); + | ---------------^^^^- + | | | + | | types differ in mutability + | expected due to this + | + = note: expected mutable reference `&mut _` + found reference `&u8` diff --git a/tests/ui-stable/transmute-mut-src-not-a-reference.rs b/tests/ui-stable/transmute-mut-src-not-a-reference.rs new file mode 100644 index 0000000..bf8bc32 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); diff --git a/tests/ui-stable/transmute-mut-src-not-a-reference.stderr b/tests/ui-stable/transmute-mut-src-not-a-reference.stderr new file mode 100644 index 0000000..8c1d9b4 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-not-a-reference.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-mut-src-not-a-reference.rs:17:53 + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&mut _`, found `usize` + | expected due to this + | + = note: expected mutable reference `&mut _` + found type `usize` +help: consider mutably borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &mut u8 = transmute_mut!(&mut 0usize); + | ++++ diff --git a/tests/ui-stable/transmute-mut-src-not-asbytes.rs b/tests/ui-stable/transmute-mut-src-not-asbytes.rs new file mode 100644 index 0000000..6a14f12 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-not-asbytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-stable/transmute-mut-src-not-asbytes.stderr b/tests/ui-stable/transmute-mut-src-not-asbytes.stderr new file mode 100644 index 0000000..9fc9546 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-not-asbytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `Src: AsBytes` is not satisfied + --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `Src` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: AsBytes` is not satisfied + --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Src` + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-stable/transmute-mut-src-not-asbytes.rs:24:36 + | +24 | const SRC_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-src-not-frombytes.rs b/tests/ui-stable/transmute-mut-src-not-frombytes.rs new file mode 100644 index 0000000..2ebe036 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-not-frombytes.rs @@ -0,0 +1,24 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +#[derive(zerocopy::AsBytes)] +#[repr(C)] +struct Src; + +#[derive(zerocopy::FromZeroes, zerocopy::FromBytes, zerocopy::AsBytes)] +#[repr(C)] +struct Dst; + +// `transmute_mut` requires that the source type implements `FromBytes` +const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); diff --git a/tests/ui-stable/transmute-mut-src-not-frombytes.stderr b/tests/ui-stable/transmute-mut-src-not-frombytes.stderr new file mode 100644 index 0000000..cc4a19d --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-not-frombytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `Src` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `Src: FromBytes` is not satisfied + --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src` + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-stable/transmute-mut-src-not-frombytes.rs:24:38 + | +24 | const SRC_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-mut-src-unsized.rs b/tests/ui-stable/transmute-mut-src-unsized.rs new file mode 100644 index 0000000..413dd68 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-unsized.rs @@ -0,0 +1,16 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_mut; + +fn main() {} + +// `transmute_mut!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); diff --git a/tests/ui-stable/transmute-mut-src-unsized.stderr b/tests/ui-stable/transmute-mut-src-unsized.stderr new file mode 100644 index 0000000..7f6def9 --- /dev/null +++ b/tests/ui-stable/transmute-mut-src-unsized.stderr @@ -0,0 +1,195 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsFromBytes` + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertSrcIsAsBytes` + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsAsBytes` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-mut-src-unsized.rs:16:35 + | +16 | const SRC_UNSIZED: &mut [u8; 1] = transmute_mut!(&mut [0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_mut` + --> src/macro_util.rs + | + | pub unsafe fn transmute_mut<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_mut` + = note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ptr-to-usize.rs b/tests/ui-stable/transmute-ptr-to-usize.rs new file mode 100644 index 0000000..5af8859 --- /dev/null +++ b/tests/ui-stable/transmute-ptr-to-usize.rs @@ -0,0 +1,20 @@ +// Copyright 2022 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. + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// It is unclear whether we can or should support this transmutation, especially +// in a const context. This test ensures that even if such a transmutation +// becomes valid due to the requisite implementations of `FromBytes` being +// added, that we re-examine whether it should specifically be valid in a const +// context. +const POINTER_VALUE: usize = transmute!(&0usize as *const usize); diff --git a/tests/ui-stable/transmute-ptr-to-usize.stderr b/tests/ui-stable/transmute-ptr-to-usize.stderr new file mode 100644 index 0000000..4f4d583 --- /dev/null +++ b/tests/ui-stable/transmute-ptr-to-usize.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied + --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `*const usize` + | required by a bound introduced by this call + | + = help: the trait `AsBytes` is implemented for `usize` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied + --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize` + | + = help: the trait `AsBytes` is implemented for `usize` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ptr-to-usize.rs:20:30 + | +20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-alignment-increase.rs b/tests/ui-stable/transmute-ref-alignment-increase.rs new file mode 100644 index 0000000..bf1988c --- /dev/null +++ b/tests/ui-stable/transmute-ref-alignment-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a type of smaller +// alignment to one of larger alignment. +const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]); diff --git a/tests/ui-stable/transmute-ref-alignment-increase.stderr b/tests/ui-stable/transmute-ref-alignment-increase.stderr new file mode 100644 index 0000000..a34c406 --- /dev/null +++ b/tests/ui-stable/transmute-ref-alignment-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-alignment-increase.rs:19:35 + | +19 | const INCREASE_ALIGNMENT: &AU16 = transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf<[u8; 2]>` (8 bits) + = note: target type: `MaxAlignsOf<[u8; 2], AU16>` (16 bits) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-dst-generic.rs b/tests/ui-stable/transmute-ref-dst-generic.rs new file mode 100644 index 0000000..bf4a0f9 --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, FromBytes}; + +fn main() {} + +fn transmute_ref(u: &u8) -> &T { + // `transmute_ref!` requires the destination type to be concrete. + transmute_ref!(u) +} diff --git a/tests/ui-stable/transmute-ref-dst-generic.stderr b/tests/ui-stable/transmute-ref-dst-generic.stderr new file mode 100644 index 0000000..e30b9f6 --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-dst-generic.rs:17:5 + | +17 | transmute_ref!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `T` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-dst-generic.rs:17:5 + | +17 | transmute_ref!(u) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (8 bits) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-dst-mutable.rs b/tests/ui-stable/transmute-ref-dst-mutable.rs new file mode 100644 index 0000000..fa0e6e4 --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-mutable.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +fn ref_dst_mutable() { + // `transmute_ref!` requires that its destination type be an immutable + // reference. + let _: &mut u8 = transmute_ref!(&0u8); +} diff --git a/tests/ui-stable/transmute-ref-dst-mutable.stderr b/tests/ui-stable/transmute-ref-dst-mutable.stderr new file mode 100644 index 0000000..c70f6ea --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-mutable.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-mutable.rs:18:22 + | +18 | let _: &mut u8 = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | + = note: expected mutable reference `&mut u8` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-dst-not-a-reference.rs b/tests/ui-stable/transmute-ref-dst-not-a-reference.rs new file mode 100644 index 0000000..de55f9a --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into a non-reference +// destination type. +const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); diff --git a/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr b/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr new file mode 100644 index 0000000..ab3f90c --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-not-a-reference.stderr @@ -0,0 +1,29 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-dst-not-a-reference.rs:17:36 + | +17 | const DST_NOT_A_REFERENCE: usize = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-dst-not-frombytes.rs b/tests/ui-stable/transmute-ref-dst-not-frombytes.rs new file mode 100644 index 0000000..d81f64d --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-not-frombytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref` requires that the destination type implements `FromBytes` +const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); diff --git a/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr b/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr new file mode 100644 index 0000000..76d18c5 --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-not-frombytes.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied + --> tests/ui-stable/transmute-ref-dst-not-frombytes.rs:18:42 + | +18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `FromBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `FromBytes`: + isize + i8 + i16 + i32 + i64 + i128 + usize + u8 + and $N others +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-stable/transmute-ref-dst-not-frombytes.rs:18:42 + | +18 | const DST_NOT_FROM_BYTES: &NotZerocopy = transmute_ref!(&AU16(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-dst-unsized.rs b/tests/ui-stable/transmute-ref-dst-unsized.rs new file mode 100644 index 0000000..625f1fa --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting into an unsized destination +// type. +const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); diff --git a/tests/ui-stable/transmute-ref-dst-unsized.stderr b/tests/ui-stable/transmute-ref-dst-unsized.stderr new file mode 100644 index 0000000..8a0c761 --- /dev/null +++ b/tests/ui-stable/transmute-ref-dst-unsized.stderr @@ -0,0 +1,89 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-dst-unsized.rs:17:28 + | +17 | const DST_UNSIZED: &[u8] = transmute_ref!(&[0u8; 1]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-illegal-lifetime.rs b/tests/ui-stable/transmute-ref-illegal-lifetime.rs new file mode 100644 index 0000000..8dd191e --- /dev/null +++ b/tests/ui-stable/transmute-ref-illegal-lifetime.rs @@ -0,0 +1,15 @@ +// 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. + +fn main() {} + +fn increase_lifetime() { + let x = 0u64; + // It is illegal to increase the lifetime scope. + let _: &'static u64 = zerocopy::transmute_ref!(&x); +} diff --git a/tests/ui-stable/transmute-ref-illegal-lifetime.stderr b/tests/ui-stable/transmute-ref-illegal-lifetime.stderr new file mode 100644 index 0000000..1ef34fe --- /dev/null +++ b/tests/ui-stable/transmute-ref-illegal-lifetime.stderr @@ -0,0 +1,12 @@ +error[E0597]: `x` does not live long enough + --> tests/ui-stable/transmute-ref-illegal-lifetime.rs:14:52 + | +12 | let x = 0u64; + | - binding `x` declared here +13 | // It is illegal to increase the lifetime scope. +14 | let _: &'static u64 = zerocopy::transmute_ref!(&x); + | ------------ ^^ borrowed value does not live long enough + | | + | type annotation requires that `x` is borrowed for `'static` +15 | } + | - `x` dropped here while still borrowed diff --git a/tests/ui-stable/transmute-ref-size-decrease.rs b/tests/ui-stable/transmute-ref-size-decrease.rs new file mode 100644 index 0000000..1d66a54 --- /dev/null +++ b/tests/ui-stable/transmute-ref-size-decrease.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]); diff --git a/tests/ui-stable/transmute-ref-size-decrease.stderr b/tests/ui-stable/transmute-ref-size-decrease.stderr new file mode 100644 index 0000000..f353b26 --- /dev/null +++ b/tests/ui-stable/transmute-ref-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-size-decrease.rs:17:28 + | +17 | const DECREASE_SIZE: &u8 = transmute_ref!(&[0u8; 2]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `[u8; 2]` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-size-increase.rs b/tests/ui-stable/transmute-ref-size-increase.rs new file mode 100644 index 0000000..cdca560 --- /dev/null +++ b/tests/ui-stable/transmute-ref-size-increase.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8); diff --git a/tests/ui-stable/transmute-ref-size-increase.stderr b/tests/ui-stable/transmute-ref-size-increase.stderr new file mode 100644 index 0000000..f51eb63 --- /dev/null +++ b/tests/ui-stable/transmute-ref-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-size-increase.rs:17:33 + | +17 | const INCREASE_SIZE: &[u8; 2] = transmute_ref!(&0u8); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `[u8; 2]` (16 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-src-dst-generic.rs b/tests/ui-stable/transmute-ref-src-dst-generic.rs new file mode 100644 index 0000000..409d785 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-dst-generic.rs @@ -0,0 +1,19 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, AsBytes, FromBytes}; + +fn main() {} + +fn transmute_ref(t: &T) -> &U { + // `transmute_ref!` requires the source and destination types to be + // concrete. + transmute_ref!(t) +} diff --git a/tests/ui-stable/transmute-ref-src-dst-generic.stderr b/tests/ui-stable/transmute-ref-src-dst-generic.stderr new file mode 100644 index 0000000..0905dc6 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-dst-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-src-dst-generic.rs:18:5 + | +18 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `U` (this type does not have a fixed size) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-src-dst-generic.rs:18:5 + | +18 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-src-dst-not-references.rs b/tests/ui-stable/transmute-ref-src-dst-not-references.rs new file mode 100644 index 0000000..114e917 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-dst-not-references.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between non-reference source +// and destination types. +const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); diff --git a/tests/ui-stable/transmute-ref-src-dst-not-references.stderr b/tests/ui-stable/transmute-ref-src-dst-not-references.stderr new file mode 100644 index 0000000..8a80e99 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-dst-not-references.stderr @@ -0,0 +1,45 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:54 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(&0usize); + | + + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-dst-not-references.rs:17:39 + | +17 | const SRC_DST_NOT_REFERENCES: usize = transmute_ref!(0usize); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` + | + = note: expected type `usize` + found reference `&_` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-src-dst-unsized.rs b/tests/ui-stable/transmute-ref-src-dst-unsized.rs new file mode 100644 index 0000000..6bfe7ff --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-dst-unsized.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting between unsized source and +// destination types. +const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); diff --git a/tests/ui-stable/transmute-ref-src-dst-unsized.stderr b/tests/ui-stable/transmute-ref-src-dst-unsized.stderr new file mode 100644 index 0000000..ca62fcf --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-dst-unsized.stderr @@ -0,0 +1,240 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsFromBytes` + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-dst-unsized.rs:17:32 + | +17 | const SRC_DST_UNSIZED: &[u8] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-src-generic.rs b/tests/ui-stable/transmute-ref-src-generic.rs new file mode 100644 index 0000000..010281c --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-generic.rs @@ -0,0 +1,18 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::{transmute_ref, AsBytes}; + +fn main() {} + +fn transmute_ref(t: &T) -> &u8 { + // `transmute_ref!` requires the source type to be concrete. + transmute_ref!(t) +} diff --git a/tests/ui-stable/transmute-ref-src-generic.stderr b/tests/ui-stable/transmute-ref-src-generic.stderr new file mode 100644 index 0000000..b6bbd16 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-generic.stderr @@ -0,0 +1,19 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-src-generic.rs:17:5 + | +17 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `T` (this type does not have a fixed size) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-ref-src-generic.rs:17:5 + | +17 | transmute_ref!(t) + | ^^^^^^^^^^^^^^^^^ + | + = note: source type: `AlignOf` (size can vary because of T) + = note: target type: `MaxAlignsOf` (size can vary because of T) + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-src-not-a-reference.rs b/tests/ui-stable/transmute-ref-src-not-a-reference.rs new file mode 100644 index 0000000..90661b3 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-not-a-reference.rs @@ -0,0 +1,17 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from a non-reference source +// type. +const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); diff --git a/tests/ui-stable/transmute-ref-src-not-a-reference.stderr b/tests/ui-stable/transmute-ref-src-not-a-reference.stderr new file mode 100644 index 0000000..622c3db --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-not-a-reference.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> tests/ui-stable/transmute-ref-src-not-a-reference.rs:17:49 + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(0usize); + | ---------------^^^^^^- + | | | + | | expected `&_`, found `usize` + | expected due to this + | + = note: expected reference `&_` + found type `usize` +help: consider borrowing here + | +17 | const SRC_NOT_A_REFERENCE: &u8 = transmute_ref!(&0usize); + | + diff --git a/tests/ui-stable/transmute-ref-src-not-asbytes.rs b/tests/ui-stable/transmute-ref-src-not-asbytes.rs new file mode 100644 index 0000000..6ab19f3 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-not-asbytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); diff --git a/tests/ui-stable/transmute-ref-src-not-asbytes.stderr b/tests/ui-stable/transmute-ref-src-not-asbytes.stderr new file mode 100644 index 0000000..2ded6ba --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-not-asbytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ref-src-not-asbytes.rs:18:33 + | +18 | const SRC_NOT_AS_BYTES: &AU16 = transmute_ref!(&NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-ref-src-unsized.rs b/tests/ui-stable/transmute-ref-src-unsized.rs new file mode 100644 index 0000000..14e72b4 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-unsized.rs @@ -0,0 +1,16 @@ +// 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. + +extern crate zerocopy; + +use zerocopy::transmute_ref; + +fn main() {} + +// `transmute_ref!` does not support transmuting from an unsized source type. +const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); diff --git a/tests/ui-stable/transmute-ref-src-unsized.stderr b/tests/ui-stable/transmute-ref-src-unsized.stderr new file mode 100644 index 0000000..b194d67 --- /dev/null +++ b/tests/ui-stable/transmute-ref-src-unsized.stderr @@ -0,0 +1,164 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute` + --> $RUST/core/src/intrinsics.rs + | + | pub fn transmute(src: Src) -> Dst; + | ^^^ required by this bound in `transmute` + = note: this error originates in the macro `$crate::assert_size_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf::::into_t` + --> src/macro_util.rs + | + | impl AlignOf { + | ^ required by this bound in `AlignOf::::into_t` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn into_t(self) -> T { + | ------ required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: the left-hand-side of an assignment must have a statically known size + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf::::new` + --> src/macro_util.rs + | + | impl MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf::::new` + | #[inline(never)] // Make `missing_inline_in_public_items` happy. + | pub fn new(_t: T, _u: U) -> MaxAlignsOf { + | --- required by a bound in this associated function + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `MaxAlignsOf` + --> src/macro_util.rs + | + | pub union MaxAlignsOf { + | ^ required by this bound in `MaxAlignsOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `AlignOf` + --> src/macro_util.rs + | + | pub struct AlignOf { + | ^ required by this bound in `AlignOf` + = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> tests/ui-stable/transmute-ref-src-unsized.rs:16:31 + | +16 | const SRC_UNSIZED: &[u8; 1] = transmute_ref!(&[0u8][..]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | doesn't have a size known at compile-time + | required by a bound introduced by this call + | + = help: the trait `Sized` is not implemented for `[u8]` +note: required by a bound in `transmute_ref` + --> src/macro_util.rs + | + | pub const unsafe fn transmute_ref<'dst, 'src: 'dst, Src: 'src, Dst: 'dst>( + | ^^^ required by this bound in `transmute_ref` + = note: this error originates in the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-size-decrease.rs b/tests/ui-stable/transmute-size-decrease.rs new file mode 100644 index 0000000..1d56831 --- /dev/null +++ b/tests/ui-stable/transmute-size-decrease.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// Although this is not a soundness requirement, we currently require that the +// size of the destination type is not smaller than the size of the source type. +const DECREASE_SIZE: u8 = transmute!(AU16(0)); diff --git a/tests/ui-stable/transmute-size-decrease.stderr b/tests/ui-stable/transmute-size-decrease.stderr new file mode 100644 index 0000000..0241662 --- /dev/null +++ b/tests/ui-stable/transmute-size-decrease.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-size-decrease.rs:19:27 + | +19 | const DECREASE_SIZE: u8 = transmute!(AU16(0)); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `AU16` (16 bits) + = note: target type: `u8` (8 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-size-increase.rs b/tests/ui-stable/transmute-size-increase.rs new file mode 100644 index 0000000..32f9363 --- /dev/null +++ b/tests/ui-stable/transmute-size-increase.rs @@ -0,0 +1,19 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(0u8); diff --git a/tests/ui-stable/transmute-size-increase.stderr b/tests/ui-stable/transmute-size-increase.stderr new file mode 100644 index 0000000..87d82a2 --- /dev/null +++ b/tests/ui-stable/transmute-size-increase.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-size-increase.rs:19:29 + | +19 | const INCREASE_SIZE: AU16 = transmute!(0u8); + | ^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `AU16` (16 bits) + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui-stable/transmute-src-not-asbytes.rs b/tests/ui-stable/transmute-src-not-asbytes.rs new file mode 100644 index 0000000..dd73021 --- /dev/null +++ b/tests/ui-stable/transmute-src-not-asbytes.rs @@ -0,0 +1,18 @@ +// 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. + +include!("../../zerocopy-derive/tests/util.rs"); + +extern crate zerocopy; + +use zerocopy::transmute; + +fn main() {} + +// `transmute` requires that the source type implements `AsBytes` +const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); diff --git a/tests/ui-stable/transmute-src-not-asbytes.stderr b/tests/ui-stable/transmute-src-not-asbytes.stderr new file mode 100644 index 0000000..f2e834e --- /dev/null +++ b/tests/ui-stable/transmute-src-not-asbytes.stderr @@ -0,0 +1,48 @@ +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | the trait `AsBytes` is not implemented for `NotZerocopy` + | required by a bound introduced by this call + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `NotZerocopy: AsBytes` is not satisfied + --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `NotZerocopy` + | + = help: the following other types implement trait `AsBytes`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required by a bound in `AssertIsAsBytes` + --> tests/ui-stable/transmute-src-not-asbytes.rs:18:32 + | +18 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsAsBytes` + = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info) -- cgit v1.2.3