Skip to content

Commit ecff956

Browse files
committed
Auto merge of #3046 - RalfJung:rustup, r=RalfJung
Rustup also more ABI compat tests
2 parents 09b78f3 + 7c7219c commit ecff956

18 files changed

+160
-19
lines changed

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
008c21c9779fd1e3632d9fe908b8afc0c421b26c
1+
dca2d1ff00bf96d244b1bb9a2117a92ec50ac71d
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#![feature(portable_simd)]
2+
3+
// Some targets treat arrays and structs very differently. We would probably catch that on those
4+
// targets since we check the `PassMode`; here we ensure that we catch it on *all* targets
5+
// (in particular, on x86-64 the pass mode is `Indirect` for both of these).
6+
struct S(i32, i32, i32, i32);
7+
type A = [i32; 4];
8+
9+
fn main() {
10+
fn f(_: S) {}
11+
12+
// These two types have the same size but are still not compatible.
13+
let g = unsafe { std::mem::transmute::<fn(S), fn(A)>(f) };
14+
15+
g(Default::default()) //~ ERROR: calling a function with argument of type S passing data of type [i32; 4]
16+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: calling a function with argument of type S passing data of type [i32; 4]
2+
--> $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
3+
|
4+
LL | g(Default::default())
5+
| ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S passing data of type [i32; 4]
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to previous error
15+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
fn f(_: f32) {}
3+
4+
let g = unsafe { std::mem::transmute::<fn(f32), fn(i32)>(f) };
5+
6+
g(42) //~ ERROR: calling a function with argument of type f32 passing data of type i32
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: calling a function with argument of type f32 passing data of type i32
2+
--> $DIR/abi_mismatch_int_vs_float.rs:LL:CC
3+
|
4+
LL | g(42)
5+
| ^^^^^ calling a function with argument of type f32 passing data of type i32
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to previous error
15+

tests/fail/function_pointers/cast_fn_ptr4.stderr renamed to tests/fail/function_pointers/abi_mismatch_raw_pointer.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: calling a function with argument of type *const [i32] passing data of type *const i32
2-
--> $DIR/cast_fn_ptr4.rs:LL:CC
2+
--> $DIR/abi_mismatch_raw_pointer.rs:LL:CC
33
|
44
LL | g(&42 as *const i32)
55
| ^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type *const [i32] passing data of type *const i32
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/cast_fn_ptr4.rs:LL:CC
10+
= note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC
1111

1212
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1313

tests/fail/function_pointers/cast_fn_ptr5.stderr renamed to tests/fail/function_pointers/abi_mismatch_return_type.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: calling a function with return type u32 passing return place of type ()
2-
--> $DIR/cast_fn_ptr5.rs:LL:CC
2+
--> $DIR/abi_mismatch_return_type.rs:LL:CC
33
|
44
LL | g()
55
| ^^^ calling a function with return type u32 passing return place of type ()
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/cast_fn_ptr5.rs:LL:CC
10+
= note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC
1111

1212
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1313

tests/fail/function_pointers/cast_fn_ptr2.stderr renamed to tests/fail/function_pointers/abi_mismatch_simple.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: calling a function with argument of type (i32, i32) passing data of type i32
2-
--> $DIR/cast_fn_ptr2.rs:LL:CC
2+
--> $DIR/abi_mismatch_simple.rs:LL:CC
33
|
44
LL | g(42)
55
| ^^^^^ calling a function with argument of type (i32, i32) passing data of type i32
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/cast_fn_ptr2.rs:LL:CC
10+
= note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC
1111

1212
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1313

tests/fail/function_pointers/cast_fn_ptr3.stderr renamed to tests/fail/function_pointers/abi_mismatch_too_few_args.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: calling a function with fewer arguments than it requires
2-
--> $DIR/cast_fn_ptr3.rs:LL:CC
2+
--> $DIR/abi_mismatch_too_few_args.rs:LL:CC
33
|
44
LL | g()
55
| ^^^ calling a function with fewer arguments than it requires
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/cast_fn_ptr3.rs:LL:CC
10+
= note: inside `main` at $DIR/abi_mismatch_too_few_args.rs:LL:CC
1111

1212
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1313

tests/fail/function_pointers/cast_fn_ptr1.stderr renamed to tests/fail/function_pointers/abi_mismatch_too_many_args.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: Undefined Behavior: calling a function with more arguments than it expected
2-
--> $DIR/cast_fn_ptr1.rs:LL:CC
2+
--> $DIR/abi_mismatch_too_many_args.rs:LL:CC
33
|
44
LL | g(42)
55
| ^^^^^ calling a function with more arguments than it expected
66
|
77
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
88
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
99
= note: BACKTRACE:
10-
= note: inside `main` at $DIR/cast_fn_ptr1.rs:LL:CC
10+
= note: inside `main` at $DIR/abi_mismatch_too_many_args.rs:LL:CC
1111

1212
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
1313

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(portable_simd)]
2+
use std::simd;
3+
4+
fn main() {
5+
fn f(_: simd::u32x8) {}
6+
7+
// These two vector types have the same size but are still not compatible.
8+
let g = unsafe { std::mem::transmute::<fn(simd::u32x8), fn(simd::u64x4)>(f) };
9+
10+
g(Default::default()) //~ ERROR: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
2+
--> $DIR/abi_mismatch_vector.rs:LL:CC
3+
|
4+
LL | g(Default::default())
5+
| ^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type std::simd::Simd<u32, 8> passing data of type std::simd::Simd<u64, 4>
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to previous error
15+
Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,91 @@
1+
#![feature(portable_simd)]
12
use std::mem;
23
use std::num;
4+
use std::simd;
35

4-
fn test_abi_compat<T, U>(t: T, u: U) {
6+
#[derive(Copy, Clone)]
7+
struct Zst;
8+
9+
fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
510
fn id<T>(x: T) -> T {
611
x
712
}
13+
extern "C" fn id_c<T>(x: T) -> T {
14+
x
15+
}
816

917
// This checks ABI compatibility both for arguments and return values,
1018
// in both directions.
1119
let f: fn(T) -> T = id;
1220
let f: fn(U) -> U = unsafe { std::mem::transmute(f) };
13-
drop(f(u));
14-
21+
let _val = f(u);
1522
let f: fn(U) -> U = id;
1623
let f: fn(T) -> T = unsafe { std::mem::transmute(f) };
17-
drop(f(t));
24+
let _val = f(t);
25+
26+
// And then we do the same for `extern "C"`.
27+
let f: extern "C" fn(T) -> T = id_c;
28+
let f: extern "C" fn(U) -> U = unsafe { std::mem::transmute(f) };
29+
let _val = f(u);
30+
let f: extern "C" fn(U) -> U = id_c;
31+
let f: extern "C" fn(T) -> T = unsafe { std::mem::transmute(f) };
32+
let _val = f(t);
33+
}
34+
35+
/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
36+
fn test_abi_newtype<T: Copy>(t: T) {
37+
#[repr(transparent)]
38+
#[derive(Copy, Clone)]
39+
struct Wrapper1<T>(T);
40+
#[repr(transparent)]
41+
#[derive(Copy, Clone)]
42+
struct Wrapper2<T>(T, ());
43+
#[repr(transparent)]
44+
#[derive(Copy, Clone)]
45+
struct Wrapper2a<T>((), T);
46+
#[repr(transparent)]
47+
#[derive(Copy, Clone)]
48+
struct Wrapper3<T>(Zst, T, [u8; 0]);
49+
50+
test_abi_compat(t, Wrapper1(t));
51+
test_abi_compat(t, Wrapper2(t, ()));
52+
test_abi_compat(t, Wrapper2a((), t));
53+
test_abi_compat(t, Wrapper3(Zst, t, []));
54+
test_abi_compat(t, mem::MaybeUninit::new(t)); // MaybeUninit is `repr(transparent)`
1855
}
1956

2057
fn main() {
58+
// Here we check:
59+
// - unsigned vs signed integer is allowed
60+
// - u32/i32 vs char is allowed
61+
// - u32 vs NonZeroU32/Option<NonZeroU32> is allowed
62+
// - reference vs raw pointer is allowed
63+
// - references to things of the same size and alignment are allowed
64+
// These are very basic tests that should work on all ABIs. However it is not clear that any of
65+
// these would be stably guaranteed. Code that relies on this is equivalent to code that relies
66+
// on the layout of `repr(Rust)` types. They are also fragile: the same mismatches in the fields
67+
// of a struct (even with `repr(C)`) will not always be accepted by Miri.
68+
test_abi_compat(0u32, 0i32);
69+
test_abi_compat(simd::u32x8::splat(1), simd::i32x8::splat(1));
2170
test_abi_compat(0u32, 'x');
22-
test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
23-
test_abi_compat(0u32, mem::MaybeUninit::new(0u32));
71+
test_abi_compat(0i32, 'x');
2472
test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
2573
test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
26-
test_abi_compat(0u32, 0i32);
27-
// Note that `bool` and `u8` are *not* compatible!
74+
test_abi_compat(&0u32, &0u32 as *const u32);
75+
test_abi_compat(&0u32, &([true; 4], [0u32; 0]));
76+
// Note that `bool` and `u8` are *not* compatible, at least on x86-64!
2877
// One of them has `arg_ext: Zext`, the other does not.
78+
79+
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
80+
// with the wrapped field.
81+
test_abi_newtype(());
82+
// FIXME: this still fails! test_abi_newtype(Zst);
83+
test_abi_newtype(0u32);
84+
test_abi_newtype(0f32);
85+
test_abi_newtype((0u32, 1u32, 2u32));
86+
// FIXME: skipping the array tests on mips64 due to https://github.com/rust-lang/rust/issues/115404
87+
if !cfg!(target_arch = "mips64") {
88+
test_abi_newtype([0u32, 1u32, 2u32]);
89+
test_abi_newtype([0i32; 0]);
90+
}
2991
}

0 commit comments

Comments
 (0)