@@ -3,53 +3,89 @@ use std::mem;
33use std:: num;
44use std:: simd;
55
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 ) {
710 fn id < T > ( x : T ) -> T {
811 x
912 }
13+ extern "C" fn id_c < T > ( x : T ) -> T {
14+ x
15+ }
1016
1117 // This checks ABI compatibility both for arguments and return values,
1218 // in both directions.
1319 let f: fn ( T ) -> T = id;
1420 let f: fn ( U ) -> U = unsafe { std:: mem:: transmute ( f) } ;
15- drop ( f ( u) ) ;
16-
21+ let _val = f ( u) ;
1722 let f: fn ( U ) -> U = id;
1823 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) ;
2033}
2134
2235/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
2336fn test_abi_newtype < T : Copy > ( t : T ) {
2437 #[ repr( transparent) ]
38+ #[ derive( Copy , Clone ) ]
2539 struct Wrapper1 < T > ( T ) ;
2640 #[ repr( transparent) ]
41+ #[ derive( Copy , Clone ) ]
2742 struct Wrapper2 < T > ( T , ( ) ) ;
2843 #[ repr( transparent) ]
44+ #[ derive( Copy , Clone ) ]
2945 struct Wrapper2a < T > ( ( ) , T ) ;
3046 #[ repr( transparent) ]
31- struct Wrapper3 < T > ( T , [ u8 ; 0 ] ) ;
47+ #[ derive( Copy , Clone ) ]
48+ struct Wrapper3 < T > ( Zst , T , [ u8 ; 0 ] ) ;
3249
3350 test_abi_compat ( t, Wrapper1 ( t) ) ;
3451 test_abi_compat ( t, Wrapper2 ( t, ( ) ) ) ;
3552 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)`
3755}
3856
3957fn 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 ) ) ;
4070 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' ) ;
4372 test_abi_compat ( 42u32 , num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ;
4473 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 ] ) ) ;
4776 // Note that `bool` and `u8` are *not* compatible, at least on x86-64!
4877 // One of them has `arg_ext: Zext`, the other does not.
4978
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);
5083 test_abi_newtype ( 0u32 ) ;
5184 test_abi_newtype ( 0f32 ) ;
5285 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+ }
5591}
0 commit comments