@@ -3,53 +3,89 @@ use std::mem;
3
3
use std:: num;
4
4
use std:: simd;
5
5
6
- 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 ) {
7
10
fn id < T > ( x : T ) -> T {
8
11
x
9
12
}
13
+ extern "C" fn id_c < T > ( x : T ) -> T {
14
+ x
15
+ }
10
16
11
17
// This checks ABI compatibility both for arguments and return values,
12
18
// in both directions.
13
19
let f: fn ( T ) -> T = id;
14
20
let f: fn ( U ) -> U = unsafe { std:: mem:: transmute ( f) } ;
15
- drop ( f ( u) ) ;
16
-
21
+ let _val = f ( u) ;
17
22
let f: fn ( U ) -> U = id;
18
23
let f: fn ( T ) -> T = unsafe { std:: mem:: transmute ( f) } ;
19
- 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) ;
20
33
}
21
34
22
35
/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
23
36
fn test_abi_newtype < T : Copy > ( t : T ) {
24
37
#[ repr( transparent) ]
38
+ #[ derive( Copy , Clone ) ]
25
39
struct Wrapper1 < T > ( T ) ;
26
40
#[ repr( transparent) ]
41
+ #[ derive( Copy , Clone ) ]
27
42
struct Wrapper2 < T > ( T , ( ) ) ;
28
43
#[ repr( transparent) ]
44
+ #[ derive( Copy , Clone ) ]
29
45
struct Wrapper2a < T > ( ( ) , T ) ;
30
46
#[ repr( transparent) ]
31
- struct Wrapper3 < T > ( T , [ u8 ; 0 ] ) ;
47
+ #[ derive( Copy , Clone ) ]
48
+ struct Wrapper3 < T > ( Zst , T , [ u8 ; 0 ] ) ;
32
49
33
50
test_abi_compat ( t, Wrapper1 ( t) ) ;
34
51
test_abi_compat ( t, Wrapper2 ( t, ( ) ) ) ;
35
52
test_abi_compat ( t, Wrapper2a ( ( ) , t) ) ;
36
- test_abi_compat ( t, Wrapper3 ( t, [ ] ) ) ;
53
+ test_abi_compat ( t, Wrapper3 ( Zst , t, [ ] ) ) ;
54
+ test_abi_compat ( t, mem:: MaybeUninit :: new ( t) ) ; // MaybeUninit is `repr(transparent)`
37
55
}
38
56
39
57
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 ) ) ;
40
70
test_abi_compat ( 0u32 , 'x' ) ;
41
- test_abi_compat ( & 0u32 , & ( [ true ; 4 ] , [ 0u32 ; 0 ] ) ) ;
42
- test_abi_compat ( 0u32 , mem:: MaybeUninit :: new ( 0u32 ) ) ;
71
+ test_abi_compat ( 0i32 , 'x' ) ;
43
72
test_abi_compat ( 42u32 , num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ;
44
73
test_abi_compat ( 0u32 , Some ( num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ) ;
45
- test_abi_compat ( 0u32 , 0i32 ) ;
46
- test_abi_compat ( simd :: u32x8 :: splat ( 1 ) , simd :: i32x8 :: splat ( 1 ) ) ;
74
+ test_abi_compat ( & 0u32 , & 0u32 as * const u32 ) ;
75
+ test_abi_compat ( & 0u32 , & ( [ true ; 4 ] , [ 0u32 ; 0 ] ) ) ;
47
76
// Note that `bool` and `u8` are *not* compatible, at least on x86-64!
48
77
// One of them has `arg_ext: Zext`, the other does not.
49
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);
50
83
test_abi_newtype ( 0u32 ) ;
51
84
test_abi_newtype ( 0f32 ) ;
52
85
test_abi_newtype ( ( 0u32 , 1u32 , 2u32 ) ) ;
53
- test_abi_newtype ( [ 0u32 , 1u32 , 2u32 ] ) ;
54
- test_abi_newtype ( [ 0i32 ; 0 ] ) ;
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
+ }
55
91
}
0 commit comments