diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:03 +0000 |
commit | 64d98f8ee037282c35007b64c2649055c56af1db (patch) | |
tree | 5492bcf97fce41ee1c0b1cc2add283f3e66cdab0 /tests/ui/transmutability | |
parent | Adding debian version 1.67.1+dfsg1-1. (diff) | |
download | rustc-64d98f8ee037282c35007b64c2649055c56af1db.tar.xz rustc-64d98f8ee037282c35007b64c2649055c56af1db.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/transmutability')
80 files changed, 4702 insertions, 0 deletions
diff --git a/tests/ui/transmutability/abstraction/abstracted_assume.rs b/tests/ui/transmutability/abstraction/abstracted_assume.rs new file mode 100644 index 000000000..0225c4230 --- /dev/null +++ b/tests/ui/transmutability/abstraction/abstracted_assume.rs @@ -0,0 +1,72 @@ +// check-pass +//! The implementation should behave correctly when the `ASSUME` parameters are +//! provided indirectly through an abstraction. + +#![crate_type = "lib"] +#![feature(adt_const_params)] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable< + Src, + Dst, + Context, + const ASSUME: std::mem::Assume, + >() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + ASSUME, + >, + {} +} + +fn direct() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + assert::is_transmutable::<Src, Dst, Context, { std::mem::Assume::NOTHING }>(); +} + +fn via_const() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + const FALSE: bool = false; + + assert::is_transmutable::<Src, Dst, Context, { std::mem::Assume::NOTHING }>(); +} + +fn via_associated_const() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + trait Trait { + const FALSE: bool = true; + } + + struct Ty; + + impl Trait for Ty {} + + assert::is_transmutable::< + Src, + Dst, + Context, + { + std::mem::Assume { + alignment: {Ty::FALSE}, + lifetimes: {Ty::FALSE}, + safety: {Ty::FALSE}, + validity: {Ty::FALSE}, + } + } + >(); +} diff --git a/tests/ui/transmutability/abstraction/const_generic_fn.rs b/tests/ui/transmutability/abstraction/const_generic_fn.rs new file mode 100644 index 000000000..e693a0957 --- /dev/null +++ b/tests/ui/transmutability/abstraction/const_generic_fn.rs @@ -0,0 +1,41 @@ +// check-pass +//! An array must have the correct length. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn array_like<T, E, const N: usize>() + where + T: BikeshedIntrinsicFrom<[E; N], Context, { Assume::SAFETY }>, + [E; N]: BikeshedIntrinsicFrom<T, Context, { Assume::SAFETY }> + {} +} + +fn len_0() { + type Array = [u8; 0]; + #[repr(C)] struct Struct(); + assert::array_like::<Struct, u8, 0>(); +} + +fn len_1() { + type Array = [u8; 1]; + #[repr(C)] struct Struct(u8); + assert::array_like::<Struct, u8, 1>(); +} + +fn len_2() { + type Array = [u8; 2]; + #[repr(C)] struct Struct(u8, u8); + assert::array_like::<Struct, u8, 2>(); +} + +fn len_3() { + type Array = [u8; 3]; + #[repr(C)] struct Struct(u8, u8, u8); + assert::array_like::<Struct, u8, 3>(); +} diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.rs b/tests/ui/transmutability/arrays/issue-103783-array-length.rs new file mode 100644 index 000000000..cb36e539e --- /dev/null +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.rs @@ -0,0 +1,24 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { Assume { alignment: true, lifetimes: true, safety: true, validity: true } }, + >, + { + } +} + +fn test() { + type NaughtyLenArray = [u32; 3.14159]; //~ ERROR mismatched types + type JustUnit = (); + assert::is_maybe_transmutable::<JustUnit, NaughtyLenArray>(); +} diff --git a/tests/ui/transmutability/arrays/issue-103783-array-length.stderr b/tests/ui/transmutability/arrays/issue-103783-array-length.stderr new file mode 100644 index 000000000..37774c59e --- /dev/null +++ b/tests/ui/transmutability/arrays/issue-103783-array-length.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-103783-array-length.rs:21:34 + | +LL | type NaughtyLenArray = [u32; 3.14159]; + | ^^^^^^^ expected `usize`, found floating-point number + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/arrays/should_have_correct_length.rs b/tests/ui/transmutability/arrays/should_have_correct_length.rs new file mode 100644 index 000000000..353797d0c --- /dev/null +++ b/tests/ui/transmutability/arrays/should_have_correct_length.rs @@ -0,0 +1,44 @@ +// check-pass +//! An array must have the correct length. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }> + {} +} + +fn should_have_len_0() { + type Array = [u8; 0]; + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::<Array, Struct>(); + assert::is_maybe_transmutable::<Struct, Array>(); +} + +fn should_have_len_1() { + type Array = [u8; 1]; + #[repr(C)] struct Struct(u8); + assert::is_maybe_transmutable::<Array, Struct>(); + assert::is_maybe_transmutable::<Struct, Array>(); +} + +fn should_have_len_2() { + type Array = [u8; 2]; + #[repr(C)] struct Struct(u8, u8); + assert::is_maybe_transmutable::<Array, Struct>(); + assert::is_maybe_transmutable::<Struct, Array>(); +} + +fn should_have_len_3() { + type Array = [u8; 3]; + #[repr(C)] struct Struct(u8, u8, u8); + assert::is_maybe_transmutable::<Array, Struct>(); + assert::is_maybe_transmutable::<Struct, Array>(); +} diff --git a/tests/ui/transmutability/arrays/should_inherit_alignment.rs b/tests/ui/transmutability/arrays/should_inherit_alignment.rs new file mode 100644 index 000000000..b00e5c7e4 --- /dev/null +++ b/tests/ui/transmutability/arrays/should_inherit_alignment.rs @@ -0,0 +1,60 @@ +// check-pass +//! An array must inherit the alignment of its inner type. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox01 { V = 0x01 } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +#[repr(C)] +union Uninit { + a: (), + b: OxFF, +} + +#[repr(C, align(2))] struct align_2(Ox00); + +fn len_0() { + #[repr(C)] struct ImplicitlyPadded([align_2; 0], Ox01); + #[repr(C)] struct ExplicitlyPadded(Ox01, Uninit); + + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::<ImplicitlyPadded, ExplicitlyPadded>(); + assert::is_maybe_transmutable::<ExplicitlyPadded, ImplicitlyPadded>(); +} + +fn len_1() { + #[repr(C)] struct ImplicitlyPadded([align_2; 1], Ox01); + #[repr(C)] struct ExplicitlyPadded(Ox00, Uninit, Ox01, Uninit); + + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::<ImplicitlyPadded, ExplicitlyPadded>(); + assert::is_maybe_transmutable::<ExplicitlyPadded, ImplicitlyPadded>(); +} + +fn len_2() { + #[repr(C)] struct ImplicitlyPadded([align_2; 2], Ox01); + #[repr(C)] struct ExplicitlyPadded(Ox00, Uninit, Ox00, Uninit, Ox01, Uninit); + + #[repr(C)] struct Struct(); + assert::is_maybe_transmutable::<ImplicitlyPadded, ExplicitlyPadded>(); + assert::is_maybe_transmutable::<ExplicitlyPadded, ImplicitlyPadded>(); +} diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs new file mode 100644 index 000000000..853bd9cbc --- /dev/null +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.rs @@ -0,0 +1,66 @@ +//! An array must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +fn should_reject_repr_rust() +{ + fn unit() { + type repr_rust = [String; 0]; + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn singleton() { + type repr_rust = [String; 1]; + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn duplex() { + type repr_rust = [String; 2]; + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } +} + +fn should_accept_repr_C() +{ + fn unit() { + #[repr(C)] struct repr_c(u8, u16, u8); + type array = [repr_c; 0]; + assert::is_maybe_transmutable::<array, ()>(); + assert::is_maybe_transmutable::<i128, array>(); + } + + fn singleton() { + #[repr(C)] struct repr_c(u8, u16, u8); + type array = [repr_c; 1]; + assert::is_maybe_transmutable::<array, repr_c>(); + assert::is_maybe_transmutable::<repr_c, array>(); + } + + fn duplex() { + #[repr(C)] struct repr_c(u8, u16, u8); + #[repr(C)] struct duplex(repr_c, repr_c); + type array = [repr_c; 2]; + assert::is_maybe_transmutable::<array, duplex>(); + assert::is_maybe_transmutable::<duplex, array>(); + } +} diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..96a2fdc54 --- /dev/null +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr @@ -0,0 +1,135 @@ +error[E0277]: `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:26:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `[String; 0]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<[String; 0], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:27:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 0]` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 0]` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:32:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `[String; 1]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<[String; 1], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:33:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 1]` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 1]` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:38:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `[String; 2]` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<[String; 2], assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:39:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `[String; 2]` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[String; 2]` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs new file mode 100644 index 000000000..940f070e7 --- /dev/null +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs @@ -0,0 +1,156 @@ +//! An enum with a primitive repr should have exactly the size of that primitive. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +#[repr(C)] +struct Zst; + +#[derive(Clone, Copy)] +#[repr(i8)] enum V0i8 { V } +#[repr(u8)] enum V0u8 { V } +#[repr(i16)] enum V0i16 { V } +#[repr(u16)] enum V0u16 { V } +#[repr(i32)] enum V0i32 { V } +#[repr(u32)] enum V0u32 { V } +#[repr(i64)] enum V0i64 { V } +#[repr(u64)] enum V0u64 { V } +#[repr(isize)] enum V0isize { V } +#[repr(usize)] enum V0usize { V } + +fn n8() { + struct Context; + + type Smaller = Zst; + type Analog = u8; + type Larger = u16; + + fn i_should_have_correct_length() { + type Current = V0i8; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u8; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } +} + +fn n16() { + struct Context; + + type Smaller = u8; + type Analog = u16; + type Larger = u32; + + fn i_should_have_correct_length() { + type Current = V0i16; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u16; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } +} + +fn n32() { + struct Context; + + type Smaller = u16; + type Analog = u32; + type Larger = u64; + + fn i_should_have_correct_length() { + type Current = V0i32; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u32; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } +} + +fn n64() { + struct Context; + + type Smaller = u32; + type Analog = u64; + type Larger = u128; + + fn i_should_have_correct_length() { + type Current = V0i64; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0u64; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } +} + +fn nsize() { + struct Context; + + type Smaller = u8; + type Analog = usize; + type Larger = [usize; 2]; + + fn i_should_have_correct_length() { + type Current = V0isize; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } + + fn u_should_have_correct_length() { + type Current = V0usize; + + assert::is_transmutable::<Smaller, Current, Context>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<Current, Analog, Context>(); + assert::is_transmutable::<Current, Larger, Context>(); //~ ERROR cannot be safely transmuted + } +} diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr new file mode 100644 index 000000000..4da5fcea3 --- /dev/null +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr @@ -0,0 +1,463 @@ +error[E0277]: `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:48:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `Zst` cannot be safely transmuted into `V0i8` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i8` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:50:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0i8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0i8, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:56:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `Zst` cannot be safely transmuted into `V0u8` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Zst, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u8` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:58:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0u8` cannot be safely transmuted into `u16` in the defining scope of `n8::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0u8, n8::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:72:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0i16` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:74:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0i16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0i16, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:80:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0u16` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u16` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:82:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0u16` cannot be safely transmuted into `u32` in the defining scope of `n16::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0u16, n16::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:96:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u16` cannot be safely transmuted into `V0i32` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:98:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0i32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0i32, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:104:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u16` cannot be safely transmuted into `V0u32` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u32` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:106:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0u32` cannot be safely transmuted into `u64` in the defining scope of `n32::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0u32, n32::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:120:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u32` cannot be safely transmuted into `V0i64` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0i64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:122:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0i64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0i64, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:128:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u32` cannot be safely transmuted into `V0u64` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u32, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0u64` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:130:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0u64` cannot be safely transmuted into `u128` in the defining scope of `n64::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0u64, n64::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:144:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0isize` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0isize` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:146:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0isize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0isize, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[usize; 2]` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:152:44 + | +LL | assert::is_transmutable::<Smaller, Current, Context>(); + | ^^^^^^^ `u8` cannot be safely transmuted into `V0usize` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `V0usize` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error[E0277]: `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + --> $DIR/primitive_reprs_should_have_correct_length.rs:154:44 + | +LL | assert::is_transmutable::<Current, Larger, Context>(); + | ^^^^^^ `V0usize` cannot be safely transmuted into `[usize; 2]` in the defining scope of `nsize::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<V0usize, nsize::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `[usize; 2]` +note: required by a bound in `is_transmutable` + --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to 20 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs new file mode 100644 index 000000000..102111ae2 --- /dev/null +++ b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs @@ -0,0 +1,124 @@ +//! An enum must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(repr128)] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn should_reject_repr_rust() { + fn void() { + enum repr_rust {} + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn singleton() { + enum repr_rust { V } + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn duplex() { + enum repr_rust { A, B } + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } +} + +fn should_accept_primitive_reprs() +{ + fn should_accept_repr_i8() { + #[repr(i8)] enum repr_i8 { V } + assert::is_maybe_transmutable::<repr_i8, ()>(); + assert::is_maybe_transmutable::<i8, repr_i8>(); + } + + fn should_accept_repr_u8() { + #[repr(u8)] enum repr_u8 { V } + assert::is_maybe_transmutable::<repr_u8, ()>(); + assert::is_maybe_transmutable::<u8, repr_u8>(); + } + + fn should_accept_repr_i16() { + #[repr(i16)] enum repr_i16 { V } + assert::is_maybe_transmutable::<repr_i16, ()>(); + assert::is_maybe_transmutable::<i16, repr_i16>(); + } + + fn should_accept_repr_u16() { + #[repr(u16)] enum repr_u16 { V } + assert::is_maybe_transmutable::<repr_u16, ()>(); + assert::is_maybe_transmutable::<u16, repr_u16>(); + } + + fn should_accept_repr_i32() { + #[repr(i32)] enum repr_i32 { V } + assert::is_maybe_transmutable::<repr_i32, ()>(); + assert::is_maybe_transmutable::<i32, repr_i32>(); + } + + fn should_accept_repr_u32() { + #[repr(u32)] enum repr_u32 { V } + assert::is_maybe_transmutable::<repr_u32, ()>(); + assert::is_maybe_transmutable::<u32, repr_u32>(); + } + + fn should_accept_repr_i64() { + #[repr(i64)] enum repr_i64 { V } + assert::is_maybe_transmutable::<repr_i64, ()>(); + assert::is_maybe_transmutable::<i64, repr_i64>(); + } + + fn should_accept_repr_u64() { + #[repr(u64)] enum repr_u64 { V } + assert::is_maybe_transmutable::<repr_u64, ()>(); + assert::is_maybe_transmutable::<u64, repr_u64>(); + } + + fn should_accept_repr_i128() { + #[repr(i128)] enum repr_i128 { V } + assert::is_maybe_transmutable::<repr_i128, ()>(); + assert::is_maybe_transmutable::<i128, repr_i128>(); + } + + fn should_accept_repr_u128() { + #[repr(u128)] enum repr_u128 { V } + assert::is_maybe_transmutable::<repr_u128, ()>(); + assert::is_maybe_transmutable::<u128, repr_u128>(); + } + + fn should_accept_repr_isize() { + #[repr(isize)] enum repr_isize { V } + assert::is_maybe_transmutable::<repr_isize, ()>(); + assert::is_maybe_transmutable::<isize, repr_isize>(); + } + + fn should_accept_repr_usize() { + #[repr(usize)] enum repr_usize { V } + assert::is_maybe_transmutable::<repr_usize, ()>(); + assert::is_maybe_transmutable::<usize, repr_usize>(); + } +} + +fn should_accept_repr_C() { + #[repr(C)] enum repr_c { V } + assert::is_maybe_transmutable::<repr_c, ()>(); + assert::is_maybe_transmutable::<i128, repr_c>(); +} diff --git a/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..510b8c56e --- /dev/null +++ b/tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr @@ -0,0 +1,141 @@ +error[E0277]: `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:28:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `void::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<void::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:29:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `void::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `void::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:34:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `singleton::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<singleton::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:35:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `singleton::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `singleton::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:40:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `duplex::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<duplex::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:41:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `duplex::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `duplex::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:14:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/should_order_correctly.rs b/tests/ui/transmutability/enums/should_order_correctly.rs new file mode 100644 index 000000000..1335cc9d2 --- /dev/null +++ b/tests/ui/transmutability/enums/should_order_correctly.rs @@ -0,0 +1,36 @@ +// check-pass +//! The payloads of an enum variant should be ordered after its tag. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +#[repr(u8)] enum V0 { V = 0 } +#[repr(u8)] enum V1 { V = 1 } +#[repr(u8)] enum V2 { V = 2 } + +#[repr(u8)] enum E01 { V0(V1) = 0u8 } +#[repr(u8)] enum E012 { V0(V1, V2) = 0u8 } + +fn should_order_tag_and_fields_correctly() { + // An implementation that (incorrectly) arranges E01 as [0x01, 0x00] will, + // in principle, reject this transmutation. + assert::is_transmutable::<E01, V0>(); + // Again, but with one more field. + assert::is_transmutable::<E012, E01>(); +} diff --git a/tests/ui/transmutability/enums/should_pad_variants.rs b/tests/ui/transmutability/enums/should_pad_variants.rs new file mode 100644 index 000000000..c077c52a3 --- /dev/null +++ b/tests/ui/transmutability/enums/should_pad_variants.rs @@ -0,0 +1,45 @@ +//! The variants of an enum must be padded with uninit bytes such that they have +//! the same length (in bytes). + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +#[derive(Clone, Copy)] +#[repr(C)] struct Zst; + +#[derive(Clone, Copy)] +#[repr(u8)] enum V0 { V = 0 } + +#[derive(Clone, Copy)] +#[repr(u8)] enum V2 { V = 2 } + +#[repr(C, u8)] +enum Lopsided { + Smol(Zst), + Lorg(V0), +} + +#[repr(C)] struct Src(V0, Zst, V2); +#[repr(C)] struct Dst(Lopsided, V2); + +fn should_pad_variants() { + struct Context; + // If the implementation (incorrectly) fails to pad `Lopsided::Smol` with + // an uninitialized byte, this transmutation might be (wrongly) accepted: + assert::is_transmutable::<Src, Dst, Context>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/enums/should_pad_variants.stderr b/tests/ui/transmutability/enums/should_pad_variants.stderr new file mode 100644 index 000000000..a823503d5 --- /dev/null +++ b/tests/ui/transmutability/enums/should_pad_variants.stderr @@ -0,0 +1,25 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + --> $DIR/should_pad_variants.rs:44:36 + | +LL | assert::is_transmutable::<Src, Dst, Context>(); + | ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_pad_variants.rs:13:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/enums/should_respect_endianness.rs b/tests/ui/transmutability/enums/should_respect_endianness.rs new file mode 100644 index 000000000..f3567b405 --- /dev/null +++ b/tests/ui/transmutability/enums/should_respect_endianness.rs @@ -0,0 +1,37 @@ +//! The target endianness should be a consideration in computing the layout of +//! an enum with a multi-byte tag. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +#[repr(u16)] enum Src { V = 0xCAFE } + +#[repr(u8)] enum OxCA { V = 0xCA } +#[repr(u8)] enum OxFE { V = 0xFE } + +#[cfg(target_endian = "big")] #[repr(C)] struct Expected(OxCA, OxFE); +#[cfg(target_endian = "big")] #[repr(C)] struct Unexpected(OxFE, OxCA); + +#[cfg(target_endian = "little")] #[repr(C)] struct Expected(OxFE, OxCA); +#[cfg(target_endian = "little")] #[repr(C)] struct Unexpected(OxCA, OxFE); + +fn should_respect_endianness() { + assert::is_transmutable::<Src, Expected>(); + assert::is_transmutable::<Src, Unexpected>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/enums/should_respect_endianness.stderr b/tests/ui/transmutability/enums/should_respect_endianness.stderr new file mode 100644 index 000000000..0845a5edf --- /dev/null +++ b/tests/ui/transmutability/enums/should_respect_endianness.stderr @@ -0,0 +1,25 @@ +error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. + --> $DIR/should_respect_endianness.rs:36:36 + | +LL | assert::is_transmutable::<Src, Unexpected>(); + | ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Src, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Unexpected` +note: required by a bound in `is_transmutable` + --> $DIR/should_respect_endianness.rs:14:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/issue-101739-1.rs b/tests/ui/transmutability/issue-101739-1.rs new file mode 100644 index 000000000..bcb8b158e --- /dev/null +++ b/tests/ui/transmutability/issue-101739-1.rs @@ -0,0 +1,21 @@ +#![feature(transmutability)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Context, const ASSUME_ALIGNMENT: bool>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope + //~^ ERROR mismatched types + { + } +} + +fn via_const() { + struct Context; + struct Src; + + assert::is_transmutable::<Src, Context, false>(); +} + +fn main() {} diff --git a/tests/ui/transmutability/issue-101739-1.stderr b/tests/ui/transmutability/issue-101739-1.stderr new file mode 100644 index 000000000..5fa741f26 --- /dev/null +++ b/tests/ui/transmutability/issue-101739-1.stderr @@ -0,0 +1,16 @@ +error[E0412]: cannot find type `Dst` in this scope + --> $DIR/issue-101739-1.rs:8:9 + | +LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, + | ^^^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/issue-101739-1.rs:8:50 + | +LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, + | ^^^^^^^^^^^^^^^^ expected struct `Assume`, found `bool` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0308, E0412. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/issue-101739-2.rs b/tests/ui/transmutability/issue-101739-2.rs new file mode 100644 index 000000000..964a7e49e --- /dev/null +++ b/tests/ui/transmutability/issue-101739-2.rs @@ -0,0 +1,37 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable< + Src, + Dst, + Context, + const ASSUME_ALIGNMENT: bool, + const ASSUME_LIFETIMES: bool, + const ASSUME_VALIDITY: bool, + const ASSUME_VISIBILITY: bool, + >() + where + Dst: BikeshedIntrinsicFrom< //~ ERROR this trait takes at most 3 generic arguments but 6 generic arguments were supplied + Src, + Context, + ASSUME_ALIGNMENT, + ASSUME_LIFETIMES, + ASSUME_VALIDITY, + ASSUME_VISIBILITY, + >, + {} +} + +fn via_const() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + + const FALSE: bool = false; + + assert::is_transmutable::<Src, Dst, Context, FALSE, FALSE, FALSE, FALSE>(); +} diff --git a/tests/ui/transmutability/issue-101739-2.stderr b/tests/ui/transmutability/issue-101739-2.stderr new file mode 100644 index 000000000..1b3d20259 --- /dev/null +++ b/tests/ui/transmutability/issue-101739-2.stderr @@ -0,0 +1,14 @@ +error[E0107]: this trait takes at most 3 generic arguments but 6 generic arguments were supplied + --> $DIR/issue-101739-2.rs:18:14 + | +LL | Dst: BikeshedIntrinsicFrom< + | ^^^^^^^^^^^^^^^^^^^^^ expected at most 3 generic arguments +... +LL | / ASSUME_LIFETIMES, +LL | | ASSUME_VALIDITY, +LL | | ASSUME_VISIBILITY, + | |_____________________________- help: remove these generic arguments + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs new file mode 100644 index 000000000..30c381745 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs @@ -0,0 +1,9 @@ +// The trait must not be available if its feature flag is absent. + +#![crate_type = "lib"] + +use std::mem::BikeshedIntrinsicFrom; +//~^ ERROR use of unstable library feature 'transmutability' [E0658] + +use std::mem::Assume; +//~^ ERROR use of unstable library feature 'transmutability' [E0658] diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr new file mode 100644 index 000000000..ba8093f86 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr @@ -0,0 +1,21 @@ +error[E0658]: use of unstable library feature 'transmutability' + --> $DIR/feature-missing.rs:5:5 + | +LL | use std::mem::BikeshedIntrinsicFrom; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information + = help: add `#![feature(transmutability)]` to the crate attributes to enable + +error[E0658]: use of unstable library feature 'transmutability' + --> $DIR/feature-missing.rs:8:5 + | +LL | use std::mem::Assume; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #99571 <https://github.com/rust-lang/rust/issues/99571> for more information + = help: add `#![feature(transmutability)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs new file mode 100644 index 000000000..b3a1e13b8 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs @@ -0,0 +1,21 @@ +// An unknown destination type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> + {} +} + +fn should_gracefully_handle_unknown_dst() { + struct Context; + struct Src; + assert::is_transmutable::<Src, Dst, Context>(); //~ cannot find type +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr new file mode 100644 index 000000000..b4591778f --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Dst` in this scope + --> $DIR/unknown_dst.rs:20:36 + | +LL | assert::is_transmutable::<Src, Dst, Context>(); + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn should_gracefully_handle_unknown_dst<Dst>() { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs new file mode 100644 index 000000000..092b205b7 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs @@ -0,0 +1,21 @@ +// An unknown source type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> + {} +} + +fn should_gracefully_handle_unknown_src() { + struct Context; + #[repr(C)] struct Dst; + assert::is_transmutable::<Src, Dst, Context>(); //~ cannot find type +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr new file mode 100644 index 000000000..a55d71d80 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Src` in this scope + --> $DIR/unknown_src.rs:20:31 + | +LL | assert::is_transmutable::<Src, Dst, Context>(); + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | fn should_gracefully_handle_unknown_src<Src>() { + | +++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs new file mode 100644 index 000000000..ebe34e134 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs @@ -0,0 +1,22 @@ +// An unknown destination type should be gracefully handled. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> + {} +} + +fn should_gracefully_handle_unknown_dst_field() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst(Missing); //~ cannot find type + assert::is_transmutable::<Src, Dst, Context>(); +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr new file mode 100644 index 000000000..475e6f429 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unknown_src_field.rs:20:27 + | +LL | #[repr(C)] struct Dst(Missing); + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs new file mode 100644 index 000000000..52aa4bb31 --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs @@ -0,0 +1,53 @@ +//! The implementation must behave well if const values of wrong types are +//! provided. + +#![crate_type = "lib"] +#![feature(adt_const_params)] +#![feature(generic_const_exprs)] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable< + Src, + Dst, + Context, + const ASSUME_ALIGNMENT: bool, + const ASSUME_LIFETIMES: bool, + const ASSUME_SAFETY: bool, + const ASSUME_VALIDITY: bool, + >() + where + Dst: BikeshedIntrinsicFrom< + Src, + Context, + { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) } + >, + {} + + const fn from_options( + alignment: bool, + lifetimes: bool, + safety: bool, + validity: bool, + ) -> Assume { + Assume { + alignment, + lifetimes, + safety, + validity, + } + } +} + +fn test() { + struct Context; + #[repr(C)] struct Src; + #[repr(C)] struct Dst; + assert::is_transmutable::<Src, Dst, Context, {0u8}, false, false, false>(); //~ ERROR mismatched types + assert::is_transmutable::<Src, Dst, Context, false, {0u8}, false, false>(); //~ ERROR mismatched types + assert::is_transmutable::<Src, Dst, Context, false, false, {0u8}, false>(); //~ ERROR mismatched types + assert::is_transmutable::<Src, Dst, Context, false, false, false, {0u8}>(); //~ ERROR mismatched types +} diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr new file mode 100644 index 000000000..c6d93876c --- /dev/null +++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:49:51 + | +LL | assert::is_transmutable::<Src, Dst, Context, {0u8}, false, false, false>(); + | ^^^ expected `bool`, found `u8` + +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:50:58 + | +LL | assert::is_transmutable::<Src, Dst, Context, false, {0u8}, false, false>(); + | ^^^ expected `bool`, found `u8` + +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:51:65 + | +LL | assert::is_transmutable::<Src, Dst, Context, false, false, {0u8}, false>(); + | ^^^ expected `bool`, found `u8` + +error[E0308]: mismatched types + --> $DIR/wrong-type-assume.rs:52:72 + | +LL | assert::is_transmutable::<Src, Dst, Context, false, false, false, {0u8}>(); + | ^^^ expected `bool`, found `u8` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/transmutability/primitives/bool.rs b/tests/ui/transmutability/primitives/bool.rs new file mode 100644 index 000000000..eebb74fff --- /dev/null +++ b/tests/ui/transmutability/primitives/bool.rs @@ -0,0 +1,25 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + {} + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }> + {} +} + +fn contrast_with_u8() { + assert::is_transmutable::<u8, bool>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u8, bool>(); + assert::is_transmutable::<bool, u8>(); +} diff --git a/tests/ui/transmutability/primitives/bool.stderr b/tests/ui/transmutability/primitives/bool.stderr new file mode 100644 index 000000000..214b5e150 --- /dev/null +++ b/tests/ui/transmutability/primitives/bool.stderr @@ -0,0 +1,19 @@ +error[E0277]: `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`. + --> $DIR/bool.rs:22:35 + | +LL | assert::is_transmutable::<u8, bool>(); + | ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `bool` +note: required by a bound in `is_transmutable` + --> $DIR/bool.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs new file mode 100644 index 000000000..0df43d204 --- /dev/null +++ b/tests/ui/transmutability/primitives/numbers.rs @@ -0,0 +1,128 @@ +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> + {} +} + +fn should_accept_identity() { + assert::is_transmutable::< i8, i8>(); + assert::is_transmutable::< u8, u8>(); + assert::is_transmutable::< i16, i16>(); + assert::is_transmutable::< u16, u16>(); + assert::is_transmutable::< i32, i32>(); + assert::is_transmutable::< f32, f32>(); + assert::is_transmutable::< u32, u32>(); + assert::is_transmutable::< i64, i64>(); + assert::is_transmutable::< f64, f64>(); + assert::is_transmutable::< u64, u64>(); + assert::is_transmutable::< i128, i128>(); + assert::is_transmutable::< u128, u128>(); + assert::is_transmutable::<isize, isize>(); + assert::is_transmutable::<usize, usize>(); +} + +fn should_be_bitransmutable() { + assert::is_transmutable::< i8, u8>(); + assert::is_transmutable::< u8, i8>(); + + assert::is_transmutable::< i16, u16>(); + assert::is_transmutable::< u16, i16>(); + + assert::is_transmutable::< i32, f32>(); + assert::is_transmutable::< i32, u32>(); + assert::is_transmutable::< f32, i32>(); + assert::is_transmutable::< f32, u32>(); + assert::is_transmutable::< u32, i32>(); + assert::is_transmutable::< u32, f32>(); + + assert::is_transmutable::< u64, i64>(); + assert::is_transmutable::< u64, f64>(); + assert::is_transmutable::< i64, u64>(); + assert::is_transmutable::< i64, f64>(); + assert::is_transmutable::< f64, u64>(); + assert::is_transmutable::< f64, i64>(); + + assert::is_transmutable::< u128, i128>(); + assert::is_transmutable::< i128, u128>(); + + assert::is_transmutable::<isize, usize>(); + assert::is_transmutable::<usize, isize>(); +} + +fn should_reject_extension() { + assert::is_transmutable::< i8, i16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i8, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u8, i16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u16>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u8, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< i16, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i16, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u16, i32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, f32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, u32>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u16, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< i32, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i32, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< f32, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f32, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u32, u64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, i64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, f64>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u32, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< u64, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< u64, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< i64, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< i64, i128>(); //~ ERROR cannot be safely transmuted + + assert::is_transmutable::< f64, u128>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::< f64, i128>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/primitives/numbers.stderr b/tests/ui/transmutability/primitives/numbers.stderr new file mode 100644 index 000000000..7cb7ca8e6 --- /dev/null +++ b/tests/ui/transmutability/primitives/numbers.stderr @@ -0,0 +1,915 @@ +error[E0277]: `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:62:40 + | +LL | assert::is_transmutable::< i8, i16>(); + | ^^^ `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:63:40 + | +LL | assert::is_transmutable::< i8, u16>(); + | ^^^ `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:64:40 + | +LL | assert::is_transmutable::< i8, i32>(); + | ^^^ `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:65:40 + | +LL | assert::is_transmutable::< i8, f32>(); + | ^^^ `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:66:40 + | +LL | assert::is_transmutable::< i8, u32>(); + | ^^^ `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:67:40 + | +LL | assert::is_transmutable::< i8, u64>(); + | ^^^ `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:68:40 + | +LL | assert::is_transmutable::< i8, i64>(); + | ^^^ `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:69:40 + | +LL | assert::is_transmutable::< i8, f64>(); + | ^^^ `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:70:39 + | +LL | assert::is_transmutable::< i8, u128>(); + | ^^^^ `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:71:39 + | +LL | assert::is_transmutable::< i8, i128>(); + | ^^^^ `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:73:40 + | +LL | assert::is_transmutable::< u8, i16>(); + | ^^^ `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:74:40 + | +LL | assert::is_transmutable::< u8, u16>(); + | ^^^ `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:75:40 + | +LL | assert::is_transmutable::< u8, i32>(); + | ^^^ `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:76:40 + | +LL | assert::is_transmutable::< u8, f32>(); + | ^^^ `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:77:40 + | +LL | assert::is_transmutable::< u8, u32>(); + | ^^^ `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:78:40 + | +LL | assert::is_transmutable::< u8, u64>(); + | ^^^ `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:79:40 + | +LL | assert::is_transmutable::< u8, i64>(); + | ^^^ `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:80:40 + | +LL | assert::is_transmutable::< u8, f64>(); + | ^^^ `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:81:39 + | +LL | assert::is_transmutable::< u8, u128>(); + | ^^^^ `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:82:39 + | +LL | assert::is_transmutable::< u8, i128>(); + | ^^^^ `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:84:40 + | +LL | assert::is_transmutable::< i16, i32>(); + | ^^^ `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:85:40 + | +LL | assert::is_transmutable::< i16, f32>(); + | ^^^ `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:86:40 + | +LL | assert::is_transmutable::< i16, u32>(); + | ^^^ `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:87:40 + | +LL | assert::is_transmutable::< i16, u64>(); + | ^^^ `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:88:40 + | +LL | assert::is_transmutable::< i16, i64>(); + | ^^^ `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:89:40 + | +LL | assert::is_transmutable::< i16, f64>(); + | ^^^ `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:90:39 + | +LL | assert::is_transmutable::< i16, u128>(); + | ^^^^ `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:91:39 + | +LL | assert::is_transmutable::< i16, i128>(); + | ^^^^ `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:93:40 + | +LL | assert::is_transmutable::< u16, i32>(); + | ^^^ `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:94:40 + | +LL | assert::is_transmutable::< u16, f32>(); + | ^^^ `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:95:40 + | +LL | assert::is_transmutable::< u16, u32>(); + | ^^^ `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:96:40 + | +LL | assert::is_transmutable::< u16, u64>(); + | ^^^ `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:97:40 + | +LL | assert::is_transmutable::< u16, i64>(); + | ^^^ `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:98:40 + | +LL | assert::is_transmutable::< u16, f64>(); + | ^^^ `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:99:39 + | +LL | assert::is_transmutable::< u16, u128>(); + | ^^^^ `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:100:39 + | +LL | assert::is_transmutable::< u16, i128>(); + | ^^^^ `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:102:40 + | +LL | assert::is_transmutable::< i32, u64>(); + | ^^^ `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:103:40 + | +LL | assert::is_transmutable::< i32, i64>(); + | ^^^ `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:104:40 + | +LL | assert::is_transmutable::< i32, f64>(); + | ^^^ `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:105:39 + | +LL | assert::is_transmutable::< i32, u128>(); + | ^^^^ `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:106:39 + | +LL | assert::is_transmutable::< i32, i128>(); + | ^^^^ `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:108:40 + | +LL | assert::is_transmutable::< f32, u64>(); + | ^^^ `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:109:40 + | +LL | assert::is_transmutable::< f32, i64>(); + | ^^^ `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:110:40 + | +LL | assert::is_transmutable::< f32, f64>(); + | ^^^ `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:111:39 + | +LL | assert::is_transmutable::< f32, u128>(); + | ^^^^ `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:112:39 + | +LL | assert::is_transmutable::< f32, i128>(); + | ^^^^ `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:114:40 + | +LL | assert::is_transmutable::< u32, u64>(); + | ^^^ `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:115:40 + | +LL | assert::is_transmutable::< u32, i64>(); + | ^^^ `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:116:40 + | +LL | assert::is_transmutable::< u32, f64>(); + | ^^^ `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:117:39 + | +LL | assert::is_transmutable::< u32, u128>(); + | ^^^^ `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:118:39 + | +LL | assert::is_transmutable::< u32, i128>(); + | ^^^^ `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:120:39 + | +LL | assert::is_transmutable::< u64, u128>(); + | ^^^^ `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:121:39 + | +LL | assert::is_transmutable::< u64, i128>(); + | ^^^^ `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:123:39 + | +LL | assert::is_transmutable::< i64, u128>(); + | ^^^^ `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:124:39 + | +LL | assert::is_transmutable::< i64, i128>(); + | ^^^^ `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:126:39 + | +LL | assert::is_transmutable::< f64, u128>(); + | ^^^^ `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + --> $DIR/numbers.rs:127:39 + | +LL | assert::is_transmutable::< f64, i128>(); + | ^^^^ `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128` +note: required by a bound in `is_transmutable` + --> $DIR/numbers.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 57 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/primitives/unit.rs b/tests/ui/transmutability/primitives/unit.rs new file mode 100644 index 000000000..1975a61de --- /dev/null +++ b/tests/ui/transmutability/primitives/unit.rs @@ -0,0 +1,29 @@ +//! The unit type, `()`, should be one byte. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +#[repr(C)] +struct Zst; + +fn should_have_correct_size() { + struct Context; + assert::is_transmutable::<(), Zst, Context>(); + assert::is_transmutable::<Zst, (), Context>(); + assert::is_transmutable::<(), u8, Context>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/primitives/unit.stderr b/tests/ui/transmutability/primitives/unit.stderr new file mode 100644 index 000000000..8cabe44a0 --- /dev/null +++ b/tests/ui/transmutability/primitives/unit.stderr @@ -0,0 +1,25 @@ +error[E0277]: `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`. + --> $DIR/unit.rs:28:35 + | +LL | assert::is_transmutable::<(), u8, Context>(); + | ^^ `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u8` +note: required by a bound in `is_transmutable` + --> $DIR/unit.rs:12:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/references.rs b/tests/ui/transmutability/references.rs new file mode 100644 index 000000000..af3ff0ec1 --- /dev/null +++ b/tests/ui/transmutability/references.rs @@ -0,0 +1,27 @@ +//! Transmutations involving references are not yet supported. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn not_yet_implemented() { + #[repr(C)] struct Unit; + assert::is_maybe_transmutable::<&'static Unit, &'static Unit>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/references.stderr b/tests/ui/transmutability/references.stderr new file mode 100644 index 000000000..e9c7b144a --- /dev/null +++ b/tests/ui/transmutability/references.stderr @@ -0,0 +1,26 @@ +error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`. + --> $DIR/references.rs:26:52 + | +LL | assert::is_maybe_transmutable::<&'static Unit, &'static Unit>(); + | ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `&'static Unit` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/references.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/structs/repr/should_handle_align.rs b/tests/ui/transmutability/structs/repr/should_handle_align.rs new file mode 100644 index 000000000..ea9bf2a23 --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_handle_align.rs @@ -0,0 +1,43 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn should_pad_explicitly_aligned_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V0u8, + } + + #[repr(C, align(2))] struct align_2(V0u8); + + #[repr(C)] struct ImplicitlyPadded(align_2, V0u8); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V0u8); + + // An implementation that (incorrectly) does not place a padding byte after + // `align_2` will, incorrectly, reject the following transmutations. + assert::is_maybe_transmutable::<ImplicitlyPadded, ExplicitlyPadded>(); + assert::is_maybe_transmutable::<ExplicitlyPadded, ImplicitlyPadded>(); +} diff --git a/tests/ui/transmutability/structs/repr/should_handle_packed.rs b/tests/ui/transmutability/structs/repr/should_handle_packed.rs new file mode 100644 index 000000000..17dc995fc --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_handle_packed.rs @@ -0,0 +1,42 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn should_pad_explicitly_packed_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + #[derive(Clone, Copy)] #[repr(u32)] enum V0u32 { V = 0 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V0u8, + } + + #[repr(C, packed(2))] struct ImplicitlyPadded(V0u8, V0u32); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V0u8, V0u8, V0u8, V0u8); + + // An implementation that (incorrectly) does not place a padding byte after + // `align_2` will, incorrectly, reject the following transmutations. + assert::is_maybe_transmutable::<ImplicitlyPadded, ExplicitlyPadded>(); + assert::is_maybe_transmutable::<ExplicitlyPadded, ImplicitlyPadded>(); +} diff --git a/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs new file mode 100644 index 000000000..9a65b4d70 --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs @@ -0,0 +1,83 @@ +//! A struct must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn should_reject_repr_rust() +{ + fn unit() { + struct repr_rust; + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn tuple() { + struct repr_rust(); + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn braces() { + struct repr_rust{} + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn aligned() { + #[repr(align(1))] struct repr_rust{} + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn packed() { + #[repr(packed)] struct repr_rust{} + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted + } + + fn nested() { + struct repr_rust; + #[repr(C)] struct repr_c(repr_rust); + assert::is_maybe_transmutable::<repr_c, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_c>(); //~ ERROR cannot be safely transmuted + } +} + +fn should_accept_repr_C() +{ + fn unit() { + #[repr(C)] struct repr_c; + assert::is_maybe_transmutable::<repr_c, ()>(); + assert::is_maybe_transmutable::<i128, repr_c>(); + } + + fn tuple() { + #[repr(C)] struct repr_c(); + assert::is_maybe_transmutable::<repr_c, ()>(); + assert::is_maybe_transmutable::<i128, repr_c>(); + } + + fn braces() { + #[repr(C)] struct repr_c{} + assert::is_maybe_transmutable::<repr_c, ()>(); + assert::is_maybe_transmutable::<i128, repr_c>(); + } +} diff --git a/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..621dbee84 --- /dev/null +++ b/tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr @@ -0,0 +1,279 @@ +error[E0277]: `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:28:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `should_reject_repr_rust::unit::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::unit::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:29:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::unit::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::unit::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:34:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `should_reject_repr_rust::tuple::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::tuple::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:35:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::tuple::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::tuple::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:40:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `should_reject_repr_rust::braces::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::braces::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:41:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::braces::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::braces::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:46:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `aligned::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<aligned::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:47:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `aligned::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `aligned::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:52:52 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `packed::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<packed::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:53:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `packed::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `packed::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:59:49 + | +LL | assert::is_maybe_transmutable::<repr_c, ()>(); + | ^^ `nested::repr_c` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<nested::repr_c, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:60:47 + | +LL | assert::is_maybe_transmutable::<u128, repr_c>(); + | ^^^^^^ `u128` cannot be safely transmuted into `nested::repr_c` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `nested::repr_c` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/structs/should_order_fields_correctly.rs b/tests/ui/transmutability/structs/should_order_fields_correctly.rs new file mode 100644 index 000000000..28724562b --- /dev/null +++ b/tests/ui/transmutability/structs/should_order_fields_correctly.rs @@ -0,0 +1,36 @@ +// check-pass +//! The fields of a struct should be laid out in lexical order. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +#[repr(u8)] enum V0 { V = 0 } +#[repr(u8)] enum V1 { V = 1 } +#[repr(u8)] enum V2 { V = 2 } + +#[repr(C)] struct S01(V0, V1); +#[repr(C)] struct S012(V0, V1, V2); + +fn should_order_tag_and_fields_correctly() { + // An implementation that (incorrectly) arranges S01 as [0x01, 0x00] will, + // in principle, reject this transmutation. + assert::is_transmutable::<S01, V0>(); + // Again, but with one more field. + assert::is_transmutable::<S012, S01>(); +} diff --git a/tests/ui/transmutability/unions/boolish.rs b/tests/ui/transmutability/unions/boolish.rs new file mode 100644 index 000000000..e469c4973 --- /dev/null +++ b/tests/ui/transmutability/unions/boolish.rs @@ -0,0 +1,31 @@ +// check-pass + +#![crate_type = "lib"] +#![feature(transmutability)] +#![feature(marker_trait_attr)] +#![allow(dead_code)] +#![allow(incomplete_features)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + {} +} + +fn should_match_bool() { + #[derive(Copy, Clone)] #[repr(u8)] pub enum False { V = 0 } + #[derive(Copy, Clone)] #[repr(u8)] pub enum True { V = 1 } + + #[repr(C)] + pub union Bool { + pub f: False, + pub t: True, + } + + assert::is_transmutable::<Bool, bool>(); + assert::is_transmutable::<bool, Bool>(); +} diff --git a/tests/ui/transmutability/unions/repr/should_handle_align.rs b/tests/ui/transmutability/unions/repr/should_handle_align.rs new file mode 100644 index 000000000..09c13cc4d --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_handle_align.rs @@ -0,0 +1,47 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn should_pad_explicitly_aligned_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + #[derive(Clone, Copy)] #[repr(u8)] enum V1u8 { V = 1 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V1u8, + } + + #[repr(C, align(2))] + pub union align_2 { + a: V0u8, + } + + #[repr(C)] struct ImplicitlyPadded(align_2, V0u8); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V0u8); + + // An implementation that (incorrectly) does not place a padding byte after + // `align_2` will, incorrectly, reject the following transmutations. + assert::is_maybe_transmutable::<ImplicitlyPadded, ExplicitlyPadded>(); + assert::is_maybe_transmutable::<ExplicitlyPadded, ImplicitlyPadded>(); +} diff --git a/tests/ui/transmutability/unions/repr/should_handle_packed.rs b/tests/ui/transmutability/unions/repr/should_handle_packed.rs new file mode 100644 index 000000000..24c2abd69 --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_handle_packed.rs @@ -0,0 +1,48 @@ +// check-pass +//! The presence of an `align(X)` annotation must be accounted for. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn should_pad_explicitly_packed_field() { + #[derive(Clone, Copy)] #[repr(u8)] enum V0u8 { V = 0 } + #[derive(Clone, Copy)] #[repr(u8)] enum V1u8 { V = 1 } + #[derive(Clone, Copy)] #[repr(u8)] enum V2u8 { V = 2 } + #[derive(Clone, Copy)] #[repr(u32)] enum V3u32 { V = 3 } + + #[repr(C)] + pub union Uninit { + a: (), + b: V1u8, + } + + #[repr(C, packed(2))] + pub union Packed { + a: [V3u32; 0], + b: V0u8, + } + + #[repr(C)] struct ImplicitlyPadded(Packed, V2u8); + #[repr(C)] struct ExplicitlyPadded(V0u8, Uninit, V2u8); + + assert::is_maybe_transmutable::<ImplicitlyPadded, ExplicitlyPadded>(); + assert::is_maybe_transmutable::<ExplicitlyPadded, ImplicitlyPadded>(); +} diff --git a/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs new file mode 100644 index 000000000..b1d5f71dc --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs @@ -0,0 +1,44 @@ +//! A struct must have a well-defined layout to participate in a transmutation. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume { + alignment: true, + lifetimes: true, + safety: true, + validity: true, + } + }> + {} +} + +fn should_reject_repr_rust() +{ + union repr_rust { + a: u8 + } + + assert::is_maybe_transmutable::<repr_rust, ()>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<u128, repr_rust>(); //~ ERROR cannot be safely transmuted +} + +fn should_accept_repr_C() +{ + #[repr(C)] + union repr_c { + a: u8 + } + + struct repr_rust; + assert::is_maybe_transmutable::<repr_c, ()>(); + assert::is_maybe_transmutable::<u128, repr_c>(); +} diff --git a/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..523bde85a --- /dev/null +++ b/tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr @@ -0,0 +1,49 @@ +error[E0277]: `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:30:48 + | +LL | assert::is_maybe_transmutable::<repr_rust, ()>(); + | ^^ `should_reject_repr_rust::repr_rust` cannot be safely transmuted into `()` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<should_reject_repr_rust::repr_rust, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `()` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`. + --> $DIR/should_require_well_defined_layout.rs:31:43 + | +LL | assert::is_maybe_transmutable::<u128, repr_rust>(); + | ^^^^^^^^^ `u128` cannot be safely transmuted into `should_reject_repr_rust::repr_rust` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<u128, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `should_reject_repr_rust::repr_rust` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_require_well_defined_layout.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume { +LL | | alignment: true, +LL | | lifetimes: true, +... | +LL | | } +LL | | }> + | |__________^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_pad_variants.rs b/tests/ui/transmutability/unions/should_pad_variants.rs new file mode 100644 index 000000000..cabe54467 --- /dev/null +++ b/tests/ui/transmutability/unions/should_pad_variants.rs @@ -0,0 +1,45 @@ +//! The variants of a union must be padded with uninit bytes such that they have +//! the same length (in bytes). + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { + Assume::ALIGNMENT + .and(Assume::LIFETIMES) + .and(Assume::SAFETY) + .and(Assume::VALIDITY) + }> + {} +} + +#[derive(Clone, Copy)] +#[repr(C)] struct Zst; + +#[derive(Clone, Copy)] +#[repr(u8)] enum V0 { V = 0 } + +#[derive(Clone, Copy)] +#[repr(u8)] enum V2 { V = 2 } + +#[repr(C)] +union Lopsided { + smol: Zst, + lorg: V0, +} + +#[repr(C)] struct Src(V0, Zst, V2); +#[repr(C)] struct Dst(V0, Lopsided, V2); + +fn should_pad_variants() { + struct Context; + // If the implementation (incorrectly) fails to pad `Lopsided::smol` with + // an uninitialized byte, this transmutation might be (wrongly) accepted: + assert::is_transmutable::<Src, Dst, Context>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_pad_variants.stderr b/tests/ui/transmutability/unions/should_pad_variants.stderr new file mode 100644 index 000000000..a823503d5 --- /dev/null +++ b/tests/ui/transmutability/unions/should_pad_variants.stderr @@ -0,0 +1,25 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + --> $DIR/should_pad_variants.rs:44:36 + | +LL | assert::is_transmutable::<Src, Dst, Context>(); + | ^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Src, should_pad_variants::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_pad_variants.rs:13:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { + | ______________^ +LL | | Assume::ALIGNMENT +LL | | .and(Assume::LIFETIMES) +LL | | .and(Assume::SAFETY) +LL | | .and(Assume::VALIDITY) +LL | | }> + | |__________^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs b/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs new file mode 100644 index 000000000..1007fdd79 --- /dev/null +++ b/tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs @@ -0,0 +1,38 @@ +// check-pass +//! If validity is assumed, there need only be one matching bit-pattern between +//! the source and destination types. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }> + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox7F { V = 0x7F } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union A { + a: Ox00, + b: Ox7F, + } + + #[repr(C)] + union B { + a: Ox7F, + b: OxFF, + } + + assert::is_maybe_transmutable::<A, B>(); + assert::is_maybe_transmutable::<B, A>(); +} diff --git a/tests/ui/transmutability/unions/should_reject_contraction.rs b/tests/ui/transmutability/unions/should_reject_contraction.rs new file mode 100644 index 000000000..a24dfccd3 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_contraction.rs @@ -0,0 +1,36 @@ +//! Validity may not be contracted, unless validity is assumed. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox01 { V = 0x01 } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union Subset { + a: Ox00, + b: OxFF, + } + + #[repr(C)] + union Superset { + a: Ox00, + b: OxFF, + c: Ox01, + } + + assert::is_transmutable::<Superset, Subset>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_reject_contraction.stderr b/tests/ui/transmutability/unions/should_reject_contraction.stderr new file mode 100644 index 000000000..41f0cedc3 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_contraction.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Superset` cannot be safely transmuted into `Subset` in the defining scope of `assert::Context`. + --> $DIR/should_reject_contraction.rs:35:41 + | +LL | assert::is_transmutable::<Superset, Subset>(); + | ^^^^^^ `Superset` cannot be safely transmuted into `Subset` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Superset, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `Subset` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_contraction.rs:13:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.rs b/tests/ui/transmutability/unions/should_reject_disjoint.rs new file mode 100644 index 000000000..43aaa6905 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_disjoint.rs @@ -0,0 +1,35 @@ +//! Validity must be satisfiable, even if validity is assumed. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }> + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox01 { V = 0x01 } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union A { + a: Ox00, + b: OxFF, + } + + #[repr(C)] + union B { + c: Ox01, + } + + assert::is_maybe_transmutable::<A, B>(); //~ ERROR cannot be safely transmuted + assert::is_maybe_transmutable::<B, A>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.stderr b/tests/ui/transmutability/unions/should_reject_disjoint.stderr new file mode 100644 index 000000000..4323f9740 --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_disjoint.stderr @@ -0,0 +1,35 @@ +error[E0277]: `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + --> $DIR/should_reject_disjoint.rs:33:40 + | +LL | assert::is_maybe_transmutable::<A, B>(); + | ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: true }>` is not implemented for `B` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_reject_disjoint.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` + +error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + --> $DIR/should_reject_disjoint.rs:34:40 + | +LL | assert::is_maybe_transmutable::<B, A>(); + | ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: true }>` is not implemented for `A` +note: required by a bound in `is_maybe_transmutable` + --> $DIR/should_reject_disjoint.rs:13:14 + | +LL | pub fn is_maybe_transmutable<Src, Dst>() + | --------------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY.and(Assume::VALIDITY) }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.rs b/tests/ui/transmutability/unions/should_reject_intersecting.rs new file mode 100644 index 000000000..9cd4233ee --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_intersecting.rs @@ -0,0 +1,38 @@ +//! ALL valid bit patterns of the source must be valid bit patterns of the +//! destination type, unless validity is assumed. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code, incomplete_features, non_camel_case_types)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + // validity is NOT assumed --------------^^^^^^^^^^^^^^^^^^ + {} +} + +#[derive(Clone, Copy)] #[repr(u8)] enum Ox00 { V = 0x00 } +#[derive(Clone, Copy)] #[repr(u8)] enum Ox7F { V = 0x7F } +#[derive(Clone, Copy)] #[repr(u8)] enum OxFF { V = 0xFF } + +fn test() { + #[repr(C)] + union A { + a: Ox00, + b: Ox7F, + } + + #[repr(C)] + union B { + a: Ox7F, + b: OxFF, + } + + assert::is_transmutable::<A, B>(); //~ ERROR cannot be safely transmuted + assert::is_transmutable::<B, A>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.stderr b/tests/ui/transmutability/unions/should_reject_intersecting.stderr new file mode 100644 index 000000000..e009888ae --- /dev/null +++ b/tests/ui/transmutability/unions/should_reject_intersecting.stderr @@ -0,0 +1,35 @@ +error[E0277]: `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + --> $DIR/should_reject_intersecting.rs:36:34 + | +LL | assert::is_transmutable::<A, B>(); + | ^ `A` cannot be safely transmuted into `B` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<A, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `B` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_intersecting.rs:14:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error[E0277]: `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + --> $DIR/should_reject_intersecting.rs:37:34 + | +LL | assert::is_transmutable::<B, A>(); + | ^ `B` cannot be safely transmuted into `A` in the defining scope of `assert::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `A` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_intersecting.rs:14:14 + | +LL | pub fn is_transmutable<Src, Dst>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs new file mode 100644 index 000000000..8a41669c6 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs @@ -0,0 +1,38 @@ +// check-pass +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains a private field. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(self) field: Zst, // <- private field + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs new file mode 100644 index 000000000..dd57b877d --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs @@ -0,0 +1,39 @@ +// check-pass +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains a private variant. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[derive(Copy, Clone)] + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) union Dst { + pub(self) field: Zst, // <- private variant + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs new file mode 100644 index 000000000..ebce8ce87 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs @@ -0,0 +1,46 @@ +// check-pass +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) +//! +//! This test exercises a tricky-to-implement instance of this principle: the +//! "pub-in-priv trick". In the below example, the type `dst::private::Zst` is +//! unreachable from `Context`. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + mod private { + #[repr(C)] pub struct Zst; // <- unreachable type + } + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: private::Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs new file mode 100644 index 000000000..546fcbaa3 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs @@ -0,0 +1,39 @@ +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(self) struct Zst; // <- unreachable type + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, //~ ERROR private type + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr new file mode 100644 index 000000000..be83b7ce3 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `dst::Zst` in public interface + --> $DIR/should_accept_if_dst_has_unreachable_field.rs:32:9 + | +LL | #[repr(C)] pub(self) struct Zst; // <- unreachable type + | -------------------- `dst::Zst` declared as private +... +LL | pub(in super) field: Zst, + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs new file mode 100644 index 000000000..b9b74d183 --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs @@ -0,0 +1,40 @@ +//! If visibility is assumed, a transmutation should be accepted even if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::{Assume, BikeshedIntrinsicFrom}; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }> + // safety IS assumed --------------------^^^^^^^^^^^^^^^^^^ + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + // unreachable type + #[repr(C)] pub(self) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); //~ ERROR `Dst` is private +} diff --git a/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr new file mode 100644 index 000000000..827df05de --- /dev/null +++ b/tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr @@ -0,0 +1,15 @@ +error[E0603]: struct `Dst` is private + --> $DIR/should_accept_if_dst_has_unreachable_ty.rs:39:46 + | +LL | assert::is_transmutable::<src::Src, dst::Dst, Context>(); + | ^^^ private struct + | +note: the struct `Dst` is defined here + --> $DIR/should_accept_if_dst_has_unreachable_ty.rs:32:16 + | +LL | #[repr(C)] pub(self) struct Dst { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs new file mode 100644 index 000000000..5a0df09d4 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs @@ -0,0 +1,37 @@ +// check-pass +//! The presence of a private field in the source type does not affect +//! transmutability. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(self) field: Zst, // <- private field + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs new file mode 100644 index 000000000..0f69630cc --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs @@ -0,0 +1,38 @@ +// check-pass +//! The presence of a private variant in the source type does not affect +//! transmutability. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[derive(Copy, Clone)] + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) union Src { + pub(self) field: Zst, // <- private variant + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs new file mode 100644 index 000000000..9c8345a8e --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs @@ -0,0 +1,37 @@ +//! The presence of an unreachable field in the source type (e.g., a public +//! field with a private type does not affect transmutability. (This rule is +//! distinct from type privacy, which still may forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(self) struct Zst; // <- unreachable type + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, //~ ERROR private type + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr new file mode 100644 index 000000000..39b73302e --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr @@ -0,0 +1,12 @@ +error[E0446]: private type `src::Zst` in public interface + --> $DIR/should_accept_if_src_has_unreachable_field.rs:22:9 + | +LL | #[repr(C)] pub(self) struct Zst; // <- unreachable type + | -------------------- `src::Zst` declared as private +... +LL | pub(in super) field: Zst, + | ^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs new file mode 100644 index 000000000..acf9f2302 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs @@ -0,0 +1,38 @@ +//! The presence of an unreachable source type (i.e., the source type is +//! private) does not affect transmutability. (This rule is distinct from type +//! privacy, which still may forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + // unreachable type + #[repr(C)] pub(self) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); //~ ERROR `Src` is private +} diff --git a/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr new file mode 100644 index 000000000..76dc7f340 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr @@ -0,0 +1,15 @@ +error[E0603]: struct `Src` is private + --> $DIR/should_accept_if_src_has_unreachable_ty.rs:37:36 + | +LL | assert::is_transmutable::<src::Src, dst::Dst, Context>(); + | ^^^ private struct + | +note: the struct `Src` is defined here + --> $DIR/should_accept_if_src_has_unreachable_ty.rs:22:16 + | +LL | #[repr(C)] pub(self) struct Src { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs new file mode 100644 index 000000000..e8c3fbc9a --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs @@ -0,0 +1,36 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains a private field. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Dst { + pub(self) field: Zst, // <- private field + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr new file mode 100644 index 000000000..d5d6d431b --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_private_field.rs:35:41 + | +LL | assert::is_transmutable::<src::Src, dst::Dst, Context>(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_private_field.rs:13:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs new file mode 100644 index 000000000..47bca27ab --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs @@ -0,0 +1,37 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains a private variant. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[derive(Copy, Clone)] + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) union Dst { + pub(self) field: Zst, // <- private variant + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr new file mode 100644 index 000000000..a1ca2ced5 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_private_variant.rs:36:41 + | +LL | assert::is_transmutable::<src::Src, dst::Dst, Context>(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_private_variant.rs:13:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs new file mode 100644 index 000000000..662c32af1 --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs @@ -0,0 +1,51 @@ +// check-pass +//! NOTE: This test documents a known-bug in the implementation of the +//! transmutability trait. Once fixed, the above "check-pass" header should be +//! removed, and an "ERROR cannot be safely transmuted" annotation should be added at the end +//! of the line starting with `assert::is_transmutable`. +//! +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) +//! +//! This test exercises a tricky-to-implement instance of this principle: the +//! "pub-in-priv trick". In the below example, the type `dst::private::Zst` is +//! unreachable from `Context`. Consequently, the transmute from `Src` to `Dst` +//! SHOULD be rejected. + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + mod private { + #[repr(C)] pub struct Zst; // <- unreachable type + } + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: private::Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs new file mode 100644 index 000000000..d7e21676f --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs @@ -0,0 +1,38 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(self) struct Zst; // <- unreachable type + + #[repr(C)] pub(in super) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); //~ ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr new file mode 100644 index 000000000..4e648664d --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_unreachable_field.rs:37:41 + | +LL | assert::is_transmutable::<src::Src, dst::Dst, Context>(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_unreachable_field.rs:15:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs new file mode 100644 index 000000000..c7b59f15b --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs @@ -0,0 +1,41 @@ +//! Unless visibility is assumed, a transmutation should be rejected if the +//! destination type contains an unreachable field (e.g., a public field with a +//! private type). (This rule is distinct from type privacy, which still may +//! forbid naming such types.) + +#![crate_type = "lib"] +#![feature(transmutability)] +#![allow(dead_code)] + +mod assert { + use std::mem::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + {} +} + +mod src { + #[repr(C)] pub(in super) struct Zst; + + #[repr(C)] pub(in super) struct Src { + pub(in super) field: Zst, + } +} + +mod dst { + #[repr(C)] pub(in super) struct Zst; + + // unreachable type + #[repr(C)] pub(self) struct Dst { + pub(in super) field: Zst, + } +} + +fn test() { + struct Context; + assert::is_transmutable::<src::Src, dst::Dst, Context>(); + //~^ ERROR `Dst` is private + //~| ERROR cannot be safely transmuted +} diff --git a/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr new file mode 100644 index 000000000..bd72d64cc --- /dev/null +++ b/tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr @@ -0,0 +1,32 @@ +error[E0603]: struct `Dst` is private + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:46 + | +LL | assert::is_transmutable::<src::Src, dst::Dst, Context>(); + | ^^^ private struct + | +note: the struct `Dst` is defined here + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:31:16 + | +LL | #[repr(C)] pub(self) struct Dst { + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:38:41 + | +LL | assert::is_transmutable::<src::Src, dst::Dst, Context>(); + | ^^^^^^^^ `Src` cannot be safely transmuted into `Dst` in the defining scope of `test::Context`. + | + = help: the trait `BikeshedIntrinsicFrom<Src, test::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `Dst` +note: required by a bound in `is_transmutable` + --> $DIR/should_reject_if_dst_has_unreachable_ty.rs:15:14 + | +LL | pub fn is_transmutable<Src, Dst, Context>() + | --------------- required by a bound in this +LL | where +LL | Dst: BikeshedIntrinsicFrom<Src, Context> // safety is NOT assumed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0603. +For more information about an error, try `rustc --explain E0277`. |