diff --git a/src/macros.rs b/src/macros.rs index 6de6eea01f..441c9de56f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -35,6 +35,17 @@ /// original `Src` will be forgotten, and the value of type `Dst` will be /// returned. /// +/// # `#![allow(shrink)]` +/// +/// If `#![allow(shrink)]` is provided, `transmute!` additionally supports +/// transmutations that shrink the size of the value; e.g.: +/// +/// ``` +/// # use zerocopy::transmute; +/// let u: u32 = transmute!(#![allow(shrink)] 0u64); +/// assert_eq!(u, 0u32); +/// ``` +/// /// # Examples /// /// ``` @@ -51,39 +62,117 @@ /// This macro can be invoked in `const` contexts. #[macro_export] macro_rules! transmute { - ($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. `core::mem::transmute` uses compiler magic - // to enforce this so long as the types are concrete. + // 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. `core::mem::transmute` uses compiler magic to enforce + // this so long as the types are concrete. + (#![allow(shrink)] $e:expr) => {{ + let mut e = $e; + if false { + // This branch, though never taken, ensures that the type of `e` is + // `IntoBytes` and that the type of the outer macro invocation + // expression is `FromBytes`. + + fn transmute(src: Src) -> Dst + where + Src: $crate::IntoBytes, + Dst: $crate::FromBytes, + { + let _ = src; + loop {} + } + loop {} + #[allow(unreachable_code)] + transmute(e) + } else { + use $crate::util::macro_util::core_reexport::mem::ManuallyDrop; + + // NOTE: `repr(packed)` is important! It ensures that the size of + // `Transmute` won't be rounded up to accomodate `Src`'s or `Dst`'s + // alignment, which would break the size comparison logic below. + // + // As an example of why this is problematic, consider `Src = [u8; + // 5]`, `Dst = u32`. The total size of `Transmute` would + // be 8, and so we would reject a `[u8; 5]` to `u32` transmute as + // being size-increasing, which it isn't. + #[repr(C, packed)] + union Transmute { + src: ManuallyDrop, + dst: ManuallyDrop, + } + // SAFETY: `Transmute` is a `reper(C)` union whose `src` field has + // type `ManuallyDrop`. Thus, the `src` field starts at byte + // offset 0 within `Transmute` [1]. `ManuallyDrop` has the same + // layout and bit validity as `T`, so it is sound to transmute `Src` + // to `Transmute`. + // + // [1] https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions + // + // [2] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html: + // + // `ManuallyDrop` is guaranteed to have the same layout and bit + // validity as `T` + let u: Transmute<_, _> = unsafe { + // Clippy: We can't annotate the types; this macro is designed + // to infer the types from the calling context. + #[allow(clippy::missing_transmute_annotations)] + $crate::util::macro_util::core_reexport::mem::transmute(e) + }; + + if false { + // SAFETY: This code is never executed. + e = ManuallyDrop::into_inner(unsafe { u.src }); + // Suppress the `unused_assignments` lint on the previous line. + let _ = e; + loop {} + } else { + // SAFETY: Per the safety comment on `let u` above, the `dst` + // field in `Transmute` starts at byte offset 0, and has the + // same layout and bit validity as `Dst`. + // + // Transmuting `Src` to `Transmute` above using + // `core::mem::transmute` ensures that `size_of::() == + // size_of::>()`. A `#[repr(C, packed)]` + // union has the maximum size of all of its fields [1], so this + // is equivalent to `size_of::() >= size_of::()`. + // + // The outer `if`'s `false` branch ensures that `Src: IntoBytes` + // and `Dst: FromBytes`. This, combined with the size bound, + // ensures that this transmute is sound. + // + // [1] Per https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions: + // + // The union will have a size of the maximum size of all of + // its fields rounded to its alignment + let dst = unsafe { u.dst }; + $crate::util::macro_util::must_use(ManuallyDrop::into_inner(dst)) + } + } + }}; + ($e:expr) => {{ let e = $e; if false { // This branch, though never taken, ensures that the type of `e` is - // `IntoBytes` and that the type of this macro invocation expression - // is `FromBytes`. - - struct AssertIsIntoBytes(T); - let _ = AssertIsIntoBytes(e); + // `IntoBytes` and that the type of the outer macro invocation + // expression is `FromBytes`. - struct AssertIsFromBytes(U); - #[allow(unused, unreachable_code)] - let u = AssertIsFromBytes(loop {}); - u.0 + fn transmute(src: Src) -> Dst + where + Src: $crate::IntoBytes, + Dst: $crate::FromBytes, + { + let _ = src; + loop {} + } + loop {} + #[allow(unreachable_code)] + transmute(e) } else { // SAFETY: `core::mem::transmute` ensures that the type of `e` and // the type of this macro invocation expression have the same size. // We know this transmute is safe thanks to the `IntoBytes` and // `FromBytes` bounds enforced by the `false` branch. - // - // We use this reexport of `core::mem::transmute` because we know it - // will always be available for crates which are using the 2015 - // edition of Rust. By contrast, if we were to use - // `std::mem::transmute`, this macro would not work for such crates - // in `no_std` contexts, and if we were to use - // `core::mem::transmute`, this macro would not work in `std` - // contexts in which `core` was not manually imported. This is not a - // problem for 2018 edition crates. let u = unsafe { // Clippy: We can't annotate the types; this macro is designed // to infer the types from the calling context. @@ -92,7 +181,7 @@ macro_rules! transmute { }; $crate::util::macro_util::must_use(u) } - }} + }}; } /// Safely transmutes a mutable or immutable reference of one type to an @@ -1046,6 +1135,10 @@ mod tests { let x: [u8; 8] = transmute!(array_of_arrays); assert_eq!(x, array_of_u8s); + // Test that memory is transmuted as expected when shrinking. + let x: [[u8; 2]; 3] = transmute!(#![allow(shrink)] array_of_u8s); + assert_eq!(x, [[0u8, 1], [2, 3], [4, 5]]); + // Test that the source expression's value is forgotten rather than // dropped. #[derive(IntoBytes)] @@ -1058,12 +1151,16 @@ mod tests { } #[allow(clippy::let_unit_value)] let _: () = transmute!(PanicOnDrop(())); + #[allow(clippy::let_unit_value)] + let _: () = transmute!(#![allow(shrink)] PanicOnDrop(())); // Test that `transmute!` 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]]; const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S); assert_eq!(X, ARRAY_OF_ARRAYS); + const X_SHRINK: [[u8; 2]; 3] = transmute!(#![allow(shrink)] ARRAY_OF_U8S); + assert_eq!(X_SHRINK, [[0u8, 1], [2, 3], [4, 5]]); // Test that `transmute!` works with `!Immutable` types. let x: usize = transmute!(UnsafeCell::new(1usize)); diff --git a/tests/ui-msrv/include_value_not_from_bytes.stderr b/tests/ui-msrv/include_value_not_from_bytes.stderr index 14dd22a71a..dea5dd1fe4 100644 --- a/tests/ui-msrv/include_value_not_from_bytes.stderr +++ b/tests/ui-msrv/include_value_not_from_bytes.stderr @@ -4,9 +4,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not sat 19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` | -note: required by `AssertIsFromBytes` +note: required by a bound in `NOT_FROM_BYTES::transmute` --> tests/ui-msrv/include_value_not_from_bytes.rs:19:42 | 19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this + | required by this bound in `NOT_FROM_BYTES::transmute` = 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/transmute-dst-not-frombytes.stderr b/tests/ui-msrv/transmute-dst-not-frombytes.stderr index 744cb48da0..e3f7f5d630 100644 --- a/tests/ui-msrv/transmute-dst-not-frombytes.stderr +++ b/tests/ui-msrv/transmute-dst-not-frombytes.stderr @@ -4,9 +4,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfie 19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); | ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` | -note: required by `AssertIsFromBytes` +note: required by a bound in `DST_NOT_FROM_BYTES::transmute` --> tests/ui-msrv/transmute-dst-not-frombytes.rs:19:41 | 19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); | ^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this + | required by this bound in `DST_NOT_FROM_BYTES::transmute` = 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-ptr-to-usize.stderr b/tests/ui-msrv/transmute-ptr-to-usize.stderr index 81d60c71a1..c57f7cdce3 100644 --- a/tests/ui-msrv/transmute-ptr-to-usize.stderr +++ b/tests/ui-msrv/transmute-ptr-to-usize.stderr @@ -4,22 +4,12 @@ error[E0277]: the trait bound `*const usize: IntoBytes` is not satisfied 20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `*const usize` | -note: required by `AssertIsIntoBytes` +note: required by a bound in `POINTER_VALUE::transmute` --> tests/ui-msrv/transmute-ptr-to-usize.rs:20:30 | 20 | const POINTER_VALUE: usize = transmute!(&0usize as *const usize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = 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: IntoBytes` 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 `IntoBytes` is not implemented for `*const usize` - | -note: required by a bound in `AssertIsIntoBytes` - --> 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 `AssertIsIntoBytes` + | | + | required by a bound in this + | required by this bound in `POINTER_VALUE::transmute` = 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-allow-shrink.rs b/tests/ui-msrv/transmute-size-increase-allow-shrink.rs new file mode 120000 index 0000000000..93b5e6db67 --- /dev/null +++ b/tests/ui-msrv/transmute-size-increase-allow-shrink.rs @@ -0,0 +1 @@ +../ui-nightly/transmute-size-increase-allow-shrink.rs \ No newline at end of file diff --git a/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr b/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr new file mode 100644 index 0000000000..9d03a36302 --- /dev/null +++ b/tests/ui-msrv/transmute-size-increase-allow-shrink.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-msrv/transmute-size-increase-allow-shrink.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `Transmute` (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-intobytes.stderr b/tests/ui-msrv/transmute-src-not-intobytes.stderr index 6382be909c..1a96a1364c 100644 --- a/tests/ui-msrv/transmute-src-not-intobytes.stderr +++ b/tests/ui-msrv/transmute-src-not-intobytes.stderr @@ -4,22 +4,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not sa 19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` | -note: required by `AssertIsIntoBytes` +note: required by a bound in `SRC_NOT_AS_BYTES::transmute` --> tests/ui-msrv/transmute-src-not-intobytes.rs:19:32 | 19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = 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: zerocopy::IntoBytes` is not satisfied - --> tests/ui-msrv/transmute-src-not-intobytes.rs:19:32 - | -19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` - | -note: required by a bound in `AssertIsIntoBytes` - --> tests/ui-msrv/transmute-src-not-intobytes.rs:19:32 - | -19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsIntoBytes` + | | + | required by a bound in this + | required by this bound in `SRC_NOT_AS_BYTES::transmute` = 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.stderr b/tests/ui-nightly/include_value_not_from_bytes.stderr index a990f1fa49..a84b34961a 100644 --- a/tests/ui-nightly/include_value_not_from_bytes.stderr +++ b/tests/ui-nightly/include_value_not_from_bytes.stderr @@ -2,10 +2,7 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not sat --> tests/ui-nightly/include_value_not_from_bytes.rs:19:42 | 19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` = help: the following other types implement trait `zerocopy::FromBytes`: @@ -18,9 +15,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not sat AtomicIsize AtomicU16 and $N others -note: required by a bound in `AssertIsFromBytes` +note: required by a bound in `NOT_FROM_BYTES::transmute` --> tests/ui-nightly/include_value_not_from_bytes.rs:19:42 | 19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = 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/transmute-dst-not-frombytes.stderr b/tests/ui-nightly/transmute-dst-not-frombytes.stderr index dfb2ea2b23..c5214a7986 100644 --- a/tests/ui-nightly/transmute-dst-not-frombytes.stderr +++ b/tests/ui-nightly/transmute-dst-not-frombytes.stderr @@ -2,10 +2,7 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfie --> tests/ui-nightly/transmute-dst-not-frombytes.rs:19:41 | 19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^ - | | - | the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` = help: the following other types implement trait `zerocopy::FromBytes`: @@ -18,9 +15,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfie AtomicIsize AtomicU16 and $N others -note: required by a bound in `AssertIsFromBytes` +note: required by a bound in `DST_NOT_FROM_BYTES::transmute` --> tests/ui-nightly/transmute-dst-not-frombytes.rs:19:41 | 19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + | ^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = 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-ptr-to-usize.stderr b/tests/ui-nightly/transmute-ptr-to-usize.stderr index 6dd1a0deab..783b45ff92 100644 --- a/tests/ui-nightly/transmute-ptr-to-usize.stderr +++ b/tests/ui-nightly/transmute-ptr-to-usize.stderr @@ -9,24 +9,12 @@ error[E0277]: the trait bound `*const usize: IntoBytes` is not satisfied | = note: Consider adding `#[derive(IntoBytes)]` to `*const usize` = help: the trait `IntoBytes` is implemented for `usize` -note: required by a bound in `AssertIsIntoBytes` +note: required by a bound in `POINTER_VALUE::transmute` --> 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 `AssertIsIntoBytes` - = 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: IntoBytes` 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 `IntoBytes` is not implemented for `*const usize` - | - = note: Consider adding `#[derive(IntoBytes)]` to `*const usize` - = help: the trait `IntoBytes` is implemented for `usize` -note: required by a bound in `AssertIsIntoBytes` - --> 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 `AssertIsIntoBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = 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-allow-shrink.rs b/tests/ui-nightly/transmute-size-increase-allow-shrink.rs new file mode 100644 index 0000000000..4922373ff9 --- /dev/null +++ b/tests/ui-nightly/transmute-size-increase-allow-shrink.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/include.rs"); + +extern crate zerocopy; + +use util::AU16; +use zerocopy::transmute; + +fn main() {} + +// `transmute!` does not support transmuting from a smaller type to a larger +// one. +const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); diff --git a/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr b/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr new file mode 100644 index 0000000000..48b51ab814 --- /dev/null +++ b/tests/ui-nightly/transmute-size-increase-allow-shrink.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-nightly/transmute-size-increase-allow-shrink.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `Transmute` (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-intobytes.stderr b/tests/ui-nightly/transmute-src-not-intobytes.stderr index 67398fc732..5633dad6ca 100644 --- a/tests/ui-nightly/transmute-src-not-intobytes.stderr +++ b/tests/ui-nightly/transmute-src-not-intobytes.stderr @@ -18,33 +18,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not sa AtomicI8 AtomicIsize and $N others -note: required by a bound in `AssertIsIntoBytes` +note: required by a bound in `SRC_NOT_AS_BYTES::transmute` --> tests/ui-nightly/transmute-src-not-intobytes.rs:19:32 | 19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsIntoBytes` - = 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: zerocopy::IntoBytes` is not satisfied - --> tests/ui-nightly/transmute-src-not-intobytes.rs:19:32 - | -19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` - | - = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` - = help: the following other types implement trait `zerocopy::IntoBytes`: - () - AU16 - AtomicBool - AtomicI16 - AtomicI32 - AtomicI64 - AtomicI8 - AtomicIsize - and $N others -note: required by a bound in `AssertIsIntoBytes` - --> tests/ui-nightly/transmute-src-not-intobytes.rs:19:32 - | -19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsIntoBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = 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.stderr b/tests/ui-stable/include_value_not_from_bytes.stderr index 3f569ac971..dce1560f39 100644 --- a/tests/ui-stable/include_value_not_from_bytes.stderr +++ b/tests/ui-stable/include_value_not_from_bytes.stderr @@ -2,10 +2,7 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not sat --> tests/ui-stable/include_value_not_from_bytes.rs:19:42 | 19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` = help: the following other types implement trait `zerocopy::FromBytes`: @@ -18,9 +15,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not sat AtomicIsize AtomicU16 and $N others -note: required by a bound in `AssertIsFromBytes` +note: required by a bound in `NOT_FROM_BYTES::transmute` --> tests/ui-stable/include_value_not_from_bytes.rs:19:42 | 19 | const NOT_FROM_BYTES: NotZerocopy = include_value!("../../testdata/include_value/data"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = 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/transmute-dst-not-frombytes.stderr b/tests/ui-stable/transmute-dst-not-frombytes.stderr index bc3eac2da8..d5335ceeda 100644 --- a/tests/ui-stable/transmute-dst-not-frombytes.stderr +++ b/tests/ui-stable/transmute-dst-not-frombytes.stderr @@ -2,10 +2,7 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfie --> tests/ui-stable/transmute-dst-not-frombytes.rs:19:41 | 19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^ - | | - | the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` - | required by a bound introduced by this call + | ^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::FromBytes` is not implemented for `NotZerocopy` | = note: Consider adding `#[derive(FromBytes)]` to `NotZerocopy` = help: the following other types implement trait `zerocopy::FromBytes`: @@ -18,9 +15,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::FromBytes` is not satisfie AtomicIsize AtomicU16 and $N others -note: required by a bound in `AssertIsFromBytes` +note: required by a bound in `DST_NOT_FROM_BYTES::transmute` --> tests/ui-stable/transmute-dst-not-frombytes.rs:19:41 | 19 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0)); - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes` + | ^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = 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-ptr-to-usize.stderr b/tests/ui-stable/transmute-ptr-to-usize.stderr index 3a1c79d804..a3b9f995d1 100644 --- a/tests/ui-stable/transmute-ptr-to-usize.stderr +++ b/tests/ui-stable/transmute-ptr-to-usize.stderr @@ -9,24 +9,12 @@ error[E0277]: the trait bound `*const usize: IntoBytes` is not satisfied | = note: Consider adding `#[derive(IntoBytes)]` to `*const usize` = help: the trait `IntoBytes` is implemented for `usize` -note: required by a bound in `AssertIsIntoBytes` +note: required by a bound in `POINTER_VALUE::transmute` --> 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 `AssertIsIntoBytes` - = 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: IntoBytes` 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 `IntoBytes` is not implemented for `*const usize` - | - = note: Consider adding `#[derive(IntoBytes)]` to `*const usize` - = help: the trait `IntoBytes` is implemented for `usize` -note: required by a bound in `AssertIsIntoBytes` - --> 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 `AssertIsIntoBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = 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-allow-shrink.rs b/tests/ui-stable/transmute-size-increase-allow-shrink.rs new file mode 120000 index 0000000000..93b5e6db67 --- /dev/null +++ b/tests/ui-stable/transmute-size-increase-allow-shrink.rs @@ -0,0 +1 @@ +../ui-nightly/transmute-size-increase-allow-shrink.rs \ No newline at end of file diff --git a/tests/ui-stable/transmute-size-increase-allow-shrink.stderr b/tests/ui-stable/transmute-size-increase-allow-shrink.stderr new file mode 100644 index 0000000000..9ad2760b91 --- /dev/null +++ b/tests/ui-stable/transmute-size-increase-allow-shrink.stderr @@ -0,0 +1,9 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> tests/ui-stable/transmute-size-increase-allow-shrink.rs:20:29 + | +20 | const INCREASE_SIZE: AU16 = transmute!(#![allow(shrink)] 0u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `u8` (8 bits) + = note: target type: `Transmute` (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-intobytes.stderr b/tests/ui-stable/transmute-src-not-intobytes.stderr index 41fc51f767..76af81eece 100644 --- a/tests/ui-stable/transmute-src-not-intobytes.stderr +++ b/tests/ui-stable/transmute-src-not-intobytes.stderr @@ -18,33 +18,12 @@ error[E0277]: the trait bound `NotZerocopy: zerocopy::IntoBytes` is not sa AtomicI8 AtomicIsize and $N others -note: required by a bound in `AssertIsIntoBytes` +note: required by a bound in `SRC_NOT_AS_BYTES::transmute` --> tests/ui-stable/transmute-src-not-intobytes.rs:19:32 | 19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsIntoBytes` - = 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: zerocopy::IntoBytes` is not satisfied - --> tests/ui-stable/transmute-src-not-intobytes.rs:19:32 - | -19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy` - | - = note: Consider adding `#[derive(IntoBytes)]` to `NotZerocopy` - = help: the following other types implement trait `zerocopy::IntoBytes`: - () - AU16 - AtomicBool - AtomicI16 - AtomicI32 - AtomicI64 - AtomicI8 - AtomicIsize - and $N others -note: required by a bound in `AssertIsIntoBytes` - --> tests/ui-stable/transmute-src-not-intobytes.rs:19:32 - | -19 | const SRC_NOT_AS_BYTES: AU16 = transmute!(NotZerocopy(AU16(0))); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsIntoBytes` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | required by a bound in this function + | required by this bound in `transmute` = note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)