summaryrefslogtreecommitdiffstats
path: root/tests/ui/transmutability
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:58 +0000
commita4b7ed7a42c716ab9f05e351f003d589124fd55d (patch)
treeb620cd3f223850b28716e474e80c58059dca5dd4 /tests/ui/transmutability
parentAdding upstream version 1.67.1+dfsg1. (diff)
downloadrustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.tar.xz
rustc-a4b7ed7a42c716ab9f05e351f003d589124fd55d.zip
Adding upstream version 1.68.2+dfsg1.upstream/1.68.2+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/transmutability')
-rw-r--r--tests/ui/transmutability/abstraction/abstracted_assume.rs72
-rw-r--r--tests/ui/transmutability/abstraction/const_generic_fn.rs41
-rw-r--r--tests/ui/transmutability/arrays/issue-103783-array-length.rs24
-rw-r--r--tests/ui/transmutability/arrays/issue-103783-array-length.stderr9
-rw-r--r--tests/ui/transmutability/arrays/should_have_correct_length.rs44
-rw-r--r--tests/ui/transmutability/arrays/should_inherit_alignment.rs60
-rw-r--r--tests/ui/transmutability/arrays/should_require_well_defined_layout.rs66
-rw-r--r--tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr135
-rw-r--r--tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.rs156
-rw-r--r--tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr463
-rw-r--r--tests/ui/transmutability/enums/repr/should_require_well_defined_layout.rs124
-rw-r--r--tests/ui/transmutability/enums/repr/should_require_well_defined_layout.stderr141
-rw-r--r--tests/ui/transmutability/enums/should_order_correctly.rs36
-rw-r--r--tests/ui/transmutability/enums/should_pad_variants.rs45
-rw-r--r--tests/ui/transmutability/enums/should_pad_variants.stderr25
-rw-r--r--tests/ui/transmutability/enums/should_respect_endianness.rs37
-rw-r--r--tests/ui/transmutability/enums/should_respect_endianness.stderr25
-rw-r--r--tests/ui/transmutability/issue-101739-1.rs21
-rw-r--r--tests/ui/transmutability/issue-101739-1.stderr16
-rw-r--r--tests/ui/transmutability/issue-101739-2.rs37
-rw-r--r--tests/ui/transmutability/issue-101739-2.stderr14
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs9
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr21
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.rs21
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_dst.stderr14
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_src.rs21
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_src.stderr14
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.rs22
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr9
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs53
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr27
-rw-r--r--tests/ui/transmutability/primitives/bool.rs25
-rw-r--r--tests/ui/transmutability/primitives/bool.stderr19
-rw-r--r--tests/ui/transmutability/primitives/numbers.rs128
-rw-r--r--tests/ui/transmutability/primitives/numbers.stderr915
-rw-r--r--tests/ui/transmutability/primitives/unit.rs29
-rw-r--r--tests/ui/transmutability/primitives/unit.stderr25
-rw-r--r--tests/ui/transmutability/references.rs27
-rw-r--r--tests/ui/transmutability/references.stderr26
-rw-r--r--tests/ui/transmutability/structs/repr/should_handle_align.rs43
-rw-r--r--tests/ui/transmutability/structs/repr/should_handle_packed.rs42
-rw-r--r--tests/ui/transmutability/structs/repr/should_require_well_defined_layout.rs83
-rw-r--r--tests/ui/transmutability/structs/repr/should_require_well_defined_layout.stderr279
-rw-r--r--tests/ui/transmutability/structs/should_order_fields_correctly.rs36
-rw-r--r--tests/ui/transmutability/unions/boolish.rs31
-rw-r--r--tests/ui/transmutability/unions/repr/should_handle_align.rs47
-rw-r--r--tests/ui/transmutability/unions/repr/should_handle_packed.rs48
-rw-r--r--tests/ui/transmutability/unions/repr/should_require_well_defined_layout.rs44
-rw-r--r--tests/ui/transmutability/unions/repr/should_require_well_defined_layout.stderr49
-rw-r--r--tests/ui/transmutability/unions/should_pad_variants.rs45
-rw-r--r--tests/ui/transmutability/unions/should_pad_variants.stderr25
-rw-r--r--tests/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs38
-rw-r--r--tests/ui/transmutability/unions/should_reject_contraction.rs36
-rw-r--r--tests/ui/transmutability/unions/should_reject_contraction.stderr19
-rw-r--r--tests/ui/transmutability/unions/should_reject_disjoint.rs35
-rw-r--r--tests/ui/transmutability/unions/should_reject_disjoint.stderr35
-rw-r--r--tests/ui/transmutability/unions/should_reject_intersecting.rs38
-rw-r--r--tests/ui/transmutability/unions/should_reject_intersecting.stderr35
-rw-r--r--tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_field.rs38
-rw-r--r--tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_private_variant.rs39
-rw-r--r--tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_tricky_unreachable_field.rs46
-rw-r--r--tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.rs39
-rw-r--r--tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_field.stderr12
-rw-r--r--tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.rs40
-rw-r--r--tests/ui/transmutability/visibility/assume/should_accept_if_dst_has_unreachable_ty.stderr15
-rw-r--r--tests/ui/transmutability/visibility/should_accept_if_src_has_private_field.rs37
-rw-r--r--tests/ui/transmutability/visibility/should_accept_if_src_has_private_variant.rs38
-rw-r--r--tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.rs37
-rw-r--r--tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_field.stderr12
-rw-r--r--tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.rs38
-rw-r--r--tests/ui/transmutability/visibility/should_accept_if_src_has_unreachable_ty.stderr15
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.rs36
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_private_field.stderr19
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.rs37
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_private_variant.stderr19
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_tricky_unreachable_field.rs51
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.rs38
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_field.stderr19
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.rs41
-rw-r--r--tests/ui/transmutability/visibility/should_reject_if_dst_has_unreachable_ty.stderr32
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`.