From ca46564f958bdd71dd923f05f9eb29e0260888df Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Aug 2023 11:11:02 +0200 Subject: [PATCH 1/6] interpret: make sure we accept transparent newtypes as ABI-compatible also we were missing the case for Vector arguments, so handle those as well --- tests/pass/function_calls/abi_compat.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/pass/function_calls/abi_compat.rs b/tests/pass/function_calls/abi_compat.rs index 67b87b46bd..1be29992f2 100644 --- a/tests/pass/function_calls/abi_compat.rs +++ b/tests/pass/function_calls/abi_compat.rs @@ -1,5 +1,7 @@ +#![feature(portable_simd)] use std::num; use std::mem; +use std::simd; fn test_abi_compat(t: T, u: U) { fn id(x: T) -> T { x } @@ -15,6 +17,20 @@ fn test_abi_compat(t: T, u: U) { drop(f(t)); } +/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`. +fn test_abi_newtype(t: T) { + #[repr(transparent)] + struct Wrapper1(T); + #[repr(transparent)] + struct Wrapper2(T, ()); + #[repr(transparent)] + struct Wrapper3(T, [u8; 0]); + + test_abi_compat(t, Wrapper1(t)); + test_abi_compat(t, Wrapper2(t, ())); + test_abi_compat(t, Wrapper3(t, [])); +} + fn main() { test_abi_compat(0u32, 'x'); test_abi_compat(&0u32, &([true; 4], [0u32; 0])); @@ -22,6 +38,12 @@ fn main() { test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap()); test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap())); test_abi_compat(0u32, 0i32); - // Note that `bool` and `u8` are *not* compatible! + test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1)); + // Note that `bool` and `u8` are *not* compatible, at least on x86-64! // One of them has `arg_ext: Zext`, the other does not. + + test_abi_newtype(0u32); + test_abi_newtype(0f32); + test_abi_newtype((0u32, 1u32, 2u32)); + test_abi_newtype([0u32, 1u32, 2u32]); } From 7225fbef17f43dff109c167a27fb9e7aa1eb7f83 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Aug 2023 08:43:20 +0200 Subject: [PATCH 2/6] organize failing ABI compat tests and add some more --- .../abi_mismatch_int_vs_float.rs | 7 +++++++ .../abi_mismatch_int_vs_float.stderr | 15 +++++++++++++++ ...ast_fn_ptr4.rs => abi_mismatch_raw_pointer.rs} | 0 ...tr4.stderr => abi_mismatch_raw_pointer.stderr} | 4 ++-- ...ast_fn_ptr5.rs => abi_mismatch_return_type.rs} | 0 ...tr5.stderr => abi_mismatch_return_type.stderr} | 4 ++-- .../{cast_fn_ptr2.rs => abi_mismatch_simple.rs} | 0 ..._fn_ptr2.stderr => abi_mismatch_simple.stderr} | 4 ++-- ...st_fn_ptr3.rs => abi_mismatch_too_few_args.rs} | 0 ...r3.stderr => abi_mismatch_too_few_args.stderr} | 4 ++-- ...t_fn_ptr1.rs => abi_mismatch_too_many_args.rs} | 0 ...1.stderr => abi_mismatch_too_many_args.stderr} | 4 ++-- .../fail/function_pointers/abi_mismatch_vector.rs | 11 +++++++++++ .../function_pointers/abi_mismatch_vector.stderr | 15 +++++++++++++++ 14 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 tests/fail/function_pointers/abi_mismatch_int_vs_float.rs create mode 100644 tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr rename tests/fail/function_pointers/{cast_fn_ptr4.rs => abi_mismatch_raw_pointer.rs} (100%) rename tests/fail/function_pointers/{cast_fn_ptr4.stderr => abi_mismatch_raw_pointer.stderr} (85%) rename tests/fail/function_pointers/{cast_fn_ptr5.rs => abi_mismatch_return_type.rs} (100%) rename tests/fail/function_pointers/{cast_fn_ptr5.stderr => abi_mismatch_return_type.stderr} (84%) rename tests/fail/function_pointers/{cast_fn_ptr2.rs => abi_mismatch_simple.rs} (100%) rename tests/fail/function_pointers/{cast_fn_ptr2.stderr => abi_mismatch_simple.stderr} (85%) rename tests/fail/function_pointers/{cast_fn_ptr3.rs => abi_mismatch_too_few_args.rs} (100%) rename tests/fail/function_pointers/{cast_fn_ptr3.stderr => abi_mismatch_too_few_args.stderr} (83%) rename tests/fail/function_pointers/{cast_fn_ptr1.rs => abi_mismatch_too_many_args.rs} (100%) rename tests/fail/function_pointers/{cast_fn_ptr1.stderr => abi_mismatch_too_many_args.stderr} (83%) create mode 100644 tests/fail/function_pointers/abi_mismatch_vector.rs create mode 100644 tests/fail/function_pointers/abi_mismatch_vector.stderr diff --git a/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs b/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs new file mode 100644 index 0000000000..a1fda329e8 --- /dev/null +++ b/tests/fail/function_pointers/abi_mismatch_int_vs_float.rs @@ -0,0 +1,7 @@ +fn main() { + fn f(_: f32) {} + + let g = unsafe { std::mem::transmute::(f) }; + + g(42) //~ ERROR: calling a function with argument of type f32 passing data of type i32 +} diff --git a/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr b/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr new file mode 100644 index 0000000000..a53126c733 --- /dev/null +++ b/tests/fail/function_pointers/abi_mismatch_int_vs_float.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: calling a function with argument of type f32 passing data of type i32 + --> $DIR/abi_mismatch_int_vs_float.rs:LL:CC + | +LL | g(42) + | ^^^^^ calling a function with argument of type f32 passing data of type i32 + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/tests/fail/function_pointers/cast_fn_ptr4.rs b/tests/fail/function_pointers/abi_mismatch_raw_pointer.rs similarity index 100% rename from tests/fail/function_pointers/cast_fn_ptr4.rs rename to tests/fail/function_pointers/abi_mismatch_raw_pointer.rs diff --git a/tests/fail/function_pointers/cast_fn_ptr4.stderr b/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr similarity index 85% rename from tests/fail/function_pointers/cast_fn_ptr4.stderr rename to tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr index 610425658f..6eacfeece1 100644 --- a/tests/fail/function_pointers/cast_fn_ptr4.stderr +++ b/tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: calling a function with argument of type *const [i32] passing data of type *const i32 - --> $DIR/cast_fn_ptr4.rs:LL:CC + --> $DIR/abi_mismatch_raw_pointer.rs:LL:CC | LL | g(&42 as *const i32) | ^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type *const [i32] passing data of type *const i32 @@ -7,7 +7,7 @@ LL | g(&42 as *const i32) = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/cast_fn_ptr4.rs:LL:CC + = note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/tests/fail/function_pointers/cast_fn_ptr5.rs b/tests/fail/function_pointers/abi_mismatch_return_type.rs similarity index 100% rename from tests/fail/function_pointers/cast_fn_ptr5.rs rename to tests/fail/function_pointers/abi_mismatch_return_type.rs diff --git a/tests/fail/function_pointers/cast_fn_ptr5.stderr b/tests/fail/function_pointers/abi_mismatch_return_type.stderr similarity index 84% rename from tests/fail/function_pointers/cast_fn_ptr5.stderr rename to tests/fail/function_pointers/abi_mismatch_return_type.stderr index c4e08b5843..eedc123577 100644 --- a/tests/fail/function_pointers/cast_fn_ptr5.stderr +++ b/tests/fail/function_pointers/abi_mismatch_return_type.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: calling a function with return type u32 passing return place of type () - --> $DIR/cast_fn_ptr5.rs:LL:CC + --> $DIR/abi_mismatch_return_type.rs:LL:CC | LL | g() | ^^^ calling a function with return type u32 passing return place of type () @@ -7,7 +7,7 @@ LL | g() = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/cast_fn_ptr5.rs:LL:CC + = note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/tests/fail/function_pointers/cast_fn_ptr2.rs b/tests/fail/function_pointers/abi_mismatch_simple.rs similarity index 100% rename from tests/fail/function_pointers/cast_fn_ptr2.rs rename to tests/fail/function_pointers/abi_mismatch_simple.rs diff --git a/tests/fail/function_pointers/cast_fn_ptr2.stderr b/tests/fail/function_pointers/abi_mismatch_simple.stderr similarity index 85% rename from tests/fail/function_pointers/cast_fn_ptr2.stderr rename to tests/fail/function_pointers/abi_mismatch_simple.stderr index 086712e0d1..bc500a90b7 100644 --- a/tests/fail/function_pointers/cast_fn_ptr2.stderr +++ b/tests/fail/function_pointers/abi_mismatch_simple.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: calling a function with argument of type (i32, i32) passing data of type i32 - --> $DIR/cast_fn_ptr2.rs:LL:CC + --> $DIR/abi_mismatch_simple.rs:LL:CC | LL | g(42) | ^^^^^ calling a function with argument of type (i32, i32) passing data of type i32 @@ -7,7 +7,7 @@ LL | g(42) = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/cast_fn_ptr2.rs:LL:CC + = note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/tests/fail/function_pointers/cast_fn_ptr3.rs b/tests/fail/function_pointers/abi_mismatch_too_few_args.rs similarity index 100% rename from tests/fail/function_pointers/cast_fn_ptr3.rs rename to tests/fail/function_pointers/abi_mismatch_too_few_args.rs diff --git a/tests/fail/function_pointers/cast_fn_ptr3.stderr b/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr similarity index 83% rename from tests/fail/function_pointers/cast_fn_ptr3.stderr rename to tests/fail/function_pointers/abi_mismatch_too_few_args.stderr index 55fd7d6072..558d83bcfd 100644 --- a/tests/fail/function_pointers/cast_fn_ptr3.stderr +++ b/tests/fail/function_pointers/abi_mismatch_too_few_args.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: calling a function with fewer arguments than it requires - --> $DIR/cast_fn_ptr3.rs:LL:CC + --> $DIR/abi_mismatch_too_few_args.rs:LL:CC | LL | g() | ^^^ calling a function with fewer arguments than it requires @@ -7,7 +7,7 @@ LL | g() = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/cast_fn_ptr3.rs:LL:CC + = note: inside `main` at $DIR/abi_mismatch_too_few_args.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/tests/fail/function_pointers/cast_fn_ptr1.rs b/tests/fail/function_pointers/abi_mismatch_too_many_args.rs similarity index 100% rename from tests/fail/function_pointers/cast_fn_ptr1.rs rename to tests/fail/function_pointers/abi_mismatch_too_many_args.rs diff --git a/tests/fail/function_pointers/cast_fn_ptr1.stderr b/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr similarity index 83% rename from tests/fail/function_pointers/cast_fn_ptr1.stderr rename to tests/fail/function_pointers/abi_mismatch_too_many_args.stderr index bb2a263795..dc12073952 100644 --- a/tests/fail/function_pointers/cast_fn_ptr1.stderr +++ b/tests/fail/function_pointers/abi_mismatch_too_many_args.stderr @@ -1,5 +1,5 @@ error: Undefined Behavior: calling a function with more arguments than it expected - --> $DIR/cast_fn_ptr1.rs:LL:CC + --> $DIR/abi_mismatch_too_many_args.rs:LL:CC | LL | g(42) | ^^^^^ calling a function with more arguments than it expected @@ -7,7 +7,7 @@ LL | g(42) = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: BACKTRACE: - = note: inside `main` at $DIR/cast_fn_ptr1.rs:LL:CC + = note: inside `main` at $DIR/abi_mismatch_too_many_args.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/tests/fail/function_pointers/abi_mismatch_vector.rs b/tests/fail/function_pointers/abi_mismatch_vector.rs new file mode 100644 index 0000000000..80f357b61b --- /dev/null +++ b/tests/fail/function_pointers/abi_mismatch_vector.rs @@ -0,0 +1,11 @@ +#![feature(portable_simd)] +use std::simd; + +fn main() { + fn f(_: simd::u32x8) {} + + // These two vector types have the same size but are still not compatible. + let g = unsafe { std::mem::transmute::(f) }; + + g(Default::default()) //~ ERROR: calling a function with argument of type std::simd::Simd passing data of type std::simd::Simd +} diff --git a/tests/fail/function_pointers/abi_mismatch_vector.stderr b/tests/fail/function_pointers/abi_mismatch_vector.stderr new file mode 100644 index 0000000000..7dcca1e85b --- /dev/null +++ b/tests/fail/function_pointers/abi_mismatch_vector.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: calling a function with argument of type std::simd::Simd passing data of type std::simd::Simd + --> $DIR/abi_mismatch_vector.rs:LL:CC + | +LL | g(Default::default()) + | ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type std::simd::Simd passing data of type std::simd::Simd + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + From 07eff4ae29b582fc544b10039a183fcac14366b8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Aug 2023 12:26:17 +0200 Subject: [PATCH 3/6] miri function ABI check: specifically look for repr(transparent) --- .../abi_mismatch_array_vs_struct.rs | 16 ++++++++++++++++ .../abi_mismatch_array_vs_struct.stderr | 15 +++++++++++++++ tests/pass/function_calls/abi_compat.rs | 4 ++++ 3 files changed, 35 insertions(+) create mode 100644 tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs create mode 100644 tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr diff --git a/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs b/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs new file mode 100644 index 0000000000..415e91b250 --- /dev/null +++ b/tests/fail/function_pointers/abi_mismatch_array_vs_struct.rs @@ -0,0 +1,16 @@ +#![feature(portable_simd)] + +// Some targets treat arrays and structs very differently. We would probably catch that on those +// targets since we check the `PassMode`; here we ensure that we catch it on *all* targets +// (in particular, on x86-64 the pass mode is `Indirect` for both of these). +struct S(i32, i32, i32, i32); +type A = [i32; 4]; + +fn main() { + fn f(_: S) {} + + // These two types have the same size but are still not compatible. + let g = unsafe { std::mem::transmute::(f) }; + + g(Default::default()) //~ ERROR: calling a function with argument of type S passing data of type [i32; 4] +} diff --git a/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr b/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr new file mode 100644 index 0000000000..50d4228c11 --- /dev/null +++ b/tests/fail/function_pointers/abi_mismatch_array_vs_struct.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: calling a function with argument of type S passing data of type [i32; 4] + --> $DIR/abi_mismatch_array_vs_struct.rs:LL:CC + | +LL | g(Default::default()) + | ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S passing data of type [i32; 4] + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/tests/pass/function_calls/abi_compat.rs b/tests/pass/function_calls/abi_compat.rs index 1be29992f2..0786450f75 100644 --- a/tests/pass/function_calls/abi_compat.rs +++ b/tests/pass/function_calls/abi_compat.rs @@ -24,10 +24,13 @@ fn test_abi_newtype(t: T) { #[repr(transparent)] struct Wrapper2(T, ()); #[repr(transparent)] + struct Wrapper2a((), T); + #[repr(transparent)] struct Wrapper3(T, [u8; 0]); test_abi_compat(t, Wrapper1(t)); test_abi_compat(t, Wrapper2(t, ())); + test_abi_compat(t, Wrapper2a((), t)); test_abi_compat(t, Wrapper3(t, [])); } @@ -46,4 +49,5 @@ fn main() { test_abi_newtype(0f32); test_abi_newtype((0u32, 1u32, 2u32)); test_abi_newtype([0u32, 1u32, 2u32]); + test_abi_newtype([0i32; 0]); } From f06fe9258e12c6c463c5ee66a588f2cdb8b1ea44 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Aug 2023 11:32:11 +0200 Subject: [PATCH 4/6] Preparing for merge from rustc --- rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-version b/rust-version index 88a4ddfba6..f173cc37e8 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -008c21c9779fd1e3632d9fe908b8afc0c421b26c +dca2d1ff00bf96d244b1bb9a2117a92ec50ac71d From 2b1ff76524f3a9df8ce47a4ef6bcd30695d7b2fd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Aug 2023 11:34:43 +0200 Subject: [PATCH 5/6] fmt --- tests/pass/function_calls/abi_compat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pass/function_calls/abi_compat.rs b/tests/pass/function_calls/abi_compat.rs index 4821a50916..30ab2d0588 100644 --- a/tests/pass/function_calls/abi_compat.rs +++ b/tests/pass/function_calls/abi_compat.rs @@ -1,6 +1,6 @@ #![feature(portable_simd)] -use std::num; use std::mem; +use std::num; use std::simd; fn test_abi_compat(t: T, u: U) { From 7c7219cec183e9f4442b97836495eab4a6e01121 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 31 Aug 2023 11:35:31 +0200 Subject: [PATCH 6/6] more ABI compat tests --- tests/pass/function_calls/abi_compat.rs | 60 ++++++++++++++++++++----- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/tests/pass/function_calls/abi_compat.rs b/tests/pass/function_calls/abi_compat.rs index 30ab2d0588..dc1e1f0ba8 100644 --- a/tests/pass/function_calls/abi_compat.rs +++ b/tests/pass/function_calls/abi_compat.rs @@ -3,53 +3,89 @@ use std::mem; use std::num; use std::simd; -fn test_abi_compat(t: T, u: U) { +#[derive(Copy, Clone)] +struct Zst; + +fn test_abi_compat(t: T, u: U) { fn id(x: T) -> T { x } + extern "C" fn id_c(x: T) -> T { + x + } // This checks ABI compatibility both for arguments and return values, // in both directions. let f: fn(T) -> T = id; let f: fn(U) -> U = unsafe { std::mem::transmute(f) }; - drop(f(u)); - + let _val = f(u); let f: fn(U) -> U = id; let f: fn(T) -> T = unsafe { std::mem::transmute(f) }; - drop(f(t)); + let _val = f(t); + + // And then we do the same for `extern "C"`. + let f: extern "C" fn(T) -> T = id_c; + let f: extern "C" fn(U) -> U = unsafe { std::mem::transmute(f) }; + let _val = f(u); + let f: extern "C" fn(U) -> U = id_c; + let f: extern "C" fn(T) -> T = unsafe { std::mem::transmute(f) }; + let _val = f(t); } /// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`. fn test_abi_newtype(t: T) { #[repr(transparent)] + #[derive(Copy, Clone)] struct Wrapper1(T); #[repr(transparent)] + #[derive(Copy, Clone)] struct Wrapper2(T, ()); #[repr(transparent)] + #[derive(Copy, Clone)] struct Wrapper2a((), T); #[repr(transparent)] - struct Wrapper3(T, [u8; 0]); + #[derive(Copy, Clone)] + struct Wrapper3(Zst, T, [u8; 0]); test_abi_compat(t, Wrapper1(t)); test_abi_compat(t, Wrapper2(t, ())); test_abi_compat(t, Wrapper2a((), t)); - test_abi_compat(t, Wrapper3(t, [])); + test_abi_compat(t, Wrapper3(Zst, t, [])); + test_abi_compat(t, mem::MaybeUninit::new(t)); // MaybeUninit is `repr(transparent)` } fn main() { + // Here we check: + // - unsigned vs signed integer is allowed + // - u32/i32 vs char is allowed + // - u32 vs NonZeroU32/Option is allowed + // - reference vs raw pointer is allowed + // - references to things of the same size and alignment are allowed + // These are very basic tests that should work on all ABIs. However it is not clear that any of + // these would be stably guaranteed. Code that relies on this is equivalent to code that relies + // on the layout of `repr(Rust)` types. They are also fragile: the same mismatches in the fields + // of a struct (even with `repr(C)`) will not always be accepted by Miri. + test_abi_compat(0u32, 0i32); + test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1)); test_abi_compat(0u32, 'x'); - test_abi_compat(&0u32, &([true; 4], [0u32; 0])); - test_abi_compat(0u32, mem::MaybeUninit::new(0u32)); + test_abi_compat(0i32, 'x'); test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap()); test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap())); - test_abi_compat(0u32, 0i32); - test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1)); + test_abi_compat(&0u32, &0u32 as *const u32); + test_abi_compat(&0u32, &([true; 4], [0u32; 0])); // Note that `bool` and `u8` are *not* compatible, at least on x86-64! // One of them has `arg_ext: Zext`, the other does not. + // These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible + // with the wrapped field. + test_abi_newtype(()); + // FIXME: this still fails! test_abi_newtype(Zst); test_abi_newtype(0u32); test_abi_newtype(0f32); test_abi_newtype((0u32, 1u32, 2u32)); - test_abi_newtype([0u32, 1u32, 2u32]); - test_abi_newtype([0i32; 0]); + // FIXME: skipping the array tests on mips64 due to https://github.com/rust-lang/rust/issues/115404 + if !cfg!(target_arch = "mips64") { + test_abi_newtype([0u32, 1u32, 2u32]); + test_abi_newtype([0i32; 0]); + } }