diff options
Diffstat (limited to 'src/test/ui/transmutability/unions')
14 files changed, 481 insertions, 0 deletions
diff --git a/src/test/ui/transmutability/unions/boolish.rs b/src/test/ui/transmutability/unions/boolish.rs new file mode 100644 index 000000000..975118b99 --- /dev/null +++ b/src/test/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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true> + {} +} + +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/src/test/ui/transmutability/unions/repr/should_handle_align.rs b/src/test/ui/transmutability/unions/repr/should_handle_align.rs new file mode 100644 index 000000000..e215799a2 --- /dev/null +++ b/src/test/ui/transmutability/unions/repr/should_handle_align.rs @@ -0,0 +1,40 @@ +// 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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, 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/src/test/ui/transmutability/unions/repr/should_handle_packed.rs b/src/test/ui/transmutability/unions/repr/should_handle_packed.rs new file mode 100644 index 000000000..34a53c7a8 --- /dev/null +++ b/src/test/ui/transmutability/unions/repr/should_handle_packed.rs @@ -0,0 +1,41 @@ +// 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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, 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/src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.rs b/src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.rs new file mode 100644 index 000000000..cec8e389f --- /dev/null +++ b/src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.rs @@ -0,0 +1,37 @@ +//! 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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, 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/src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr b/src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr new file mode 100644 index 000000000..2ed01b159 --- /dev/null +++ b/src/test/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr @@ -0,0 +1,35 @@ +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:23: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, true, true, true, 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, true, true, true, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:24: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, true, true, true, 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, true, true, true, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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/src/test/ui/transmutability/unions/should_pad_variants.rs b/src/test/ui/transmutability/unions/should_pad_variants.rs new file mode 100644 index 000000000..c4757900f --- /dev/null +++ b/src/test/ui/transmutability/unions/should_pad_variants.rs @@ -0,0 +1,40 @@ +//! 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::BikeshedIntrinsicFrom; + + pub fn is_transmutable<Src, Dst, Context>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, true, true, true, true> + {} +} + +#[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/src/test/ui/transmutability/unions/should_pad_variants.stderr b/src/test/ui/transmutability/unions/should_pad_variants.stderr new file mode 100644 index 000000000..429f7211d --- /dev/null +++ b/src/test/ui/transmutability/unions/should_pad_variants.stderr @@ -0,0 +1,19 @@ +error[E0277]: `Src` cannot be safely transmuted into `Dst` in the defining scope of `should_pad_variants::Context`. + --> $DIR/should_pad_variants.rs:39: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, true, true, true, 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, true, true, true, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs b/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs new file mode 100644 index 000000000..2493d7155 --- /dev/null +++ b/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs @@ -0,0 +1,39 @@ +// 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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true> + // validity IS 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_maybe_transmutable::<A, B>(); + assert::is_maybe_transmutable::<B, A>(); +} diff --git a/src/test/ui/transmutability/unions/should_reject_contraction.rs b/src/test/ui/transmutability/unions/should_reject_contraction.rs new file mode 100644 index 000000000..e8138d0e0 --- /dev/null +++ b/src/test/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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true> + {} +} + +#[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/src/test/ui/transmutability/unions/should_reject_contraction.stderr b/src/test/ui/transmutability/unions/should_reject_contraction.stderr new file mode 100644 index 000000000..99f589008 --- /dev/null +++ b/src/test/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, false, false, false, true>` 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, false, false, false, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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/src/test/ui/transmutability/unions/should_reject_disjoint.rs b/src/test/ui/transmutability/unions/should_reject_disjoint.rs new file mode 100644 index 000000000..16160e29a --- /dev/null +++ b/src/test/ui/transmutability/unions/should_reject_disjoint.rs @@ -0,0 +1,36 @@ +//! 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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_maybe_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, false, false, true, true> + // validity IS assumed --------------------------------^^^^ + {} +} + +#[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/src/test/ui/transmutability/unions/should_reject_disjoint.stderr b/src/test/ui/transmutability/unions/should_reject_disjoint.stderr new file mode 100644 index 000000000..5714e2bf3 --- /dev/null +++ b/src/test/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:34: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, false, false, true, 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, false, false, true, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:35: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, false, false, true, 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, false, false, true, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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/src/test/ui/transmutability/unions/should_reject_intersecting.rs b/src/test/ui/transmutability/unions/should_reject_intersecting.rs new file mode 100644 index 000000000..58e399fb9 --- /dev/null +++ b/src/test/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::BikeshedIntrinsicFrom; + pub struct Context; + + pub fn is_transmutable<Src, Dst>() + where + Dst: BikeshedIntrinsicFrom<Src, Context, false, false, false, true> + // 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/src/test/ui/transmutability/unions/should_reject_intersecting.stderr b/src/test/ui/transmutability/unions/should_reject_intersecting.stderr new file mode 100644 index 000000000..92689a5f8 --- /dev/null +++ b/src/test/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, false, false, false, true>` 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, false, false, false, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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, false, false, false, true>` 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, false, false, false, true> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. |