11use std:: mem;
22use std:: num;
3+ use std:: ptr;
34
45#[ derive( Copy , Clone , Default ) ]
56struct Zst ;
67
7- fn test_abi_compat < T : Copy , U : Copy > ( t : T , u : U ) {
8+ fn test_abi_compat < T : Clone , U : Clone > ( t : T , u : U ) {
89 fn id < T > ( x : T ) -> T {
910 x
1011 }
@@ -16,10 +17,10 @@ fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
1617 // in both directions.
1718 let f: fn ( T ) -> T = id;
1819 let f: fn ( U ) -> U = unsafe { std:: mem:: transmute ( f) } ;
19- let _val = f ( u) ;
20+ let _val = f ( u. clone ( ) ) ;
2021 let f: fn ( U ) -> U = id;
2122 let f: fn ( T ) -> T = unsafe { std:: mem:: transmute ( f) } ;
22- let _val = f ( t) ;
23+ let _val = f ( t. clone ( ) ) ;
2324
2425 // And then we do the same for `extern "C"`.
2526 let f: extern "C" fn ( T ) -> T = id_c;
@@ -54,23 +55,25 @@ fn test_abi_newtype<T: Copy + Default>() {
5455}
5556
5657fn main ( ) {
57- // Here we check:
58- // - u32 vs char is allowed
59- // - u32 vs NonZeroU32/Option<NonZeroU32> is allowed
60- // - reference vs raw pointer is allowed
61- // - references to things of the same size and alignment are allowed
62- // These are very basic tests that should work on all ABIs. However it is not clear that any of
63- // these would be stably guaranteed. Code that relies on this is equivalent to code that relies
64- // on the layout of `repr(Rust)` types. They are also fragile: the same mismatches in the fields
65- // of a struct (even with `repr(C)`) will not always be accepted by Miri.
66- // Note that `bool` and `u8` are *not* compatible, at least on x86-64!
67- // One of them has `arg_ext: Zext`, the other does not.
68- // Similarly, `i32` and `u32` are not compatible on s390x due to different `arg_ext`.
69- test_abi_compat ( 0u32 , 'x' ) ;
70- test_abi_compat ( 42u32 , num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ;
71- test_abi_compat ( 0u32 , Some ( num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ) ;
58+ // Here we check some of the guaranteed ABI compatibilities.
59+ // Different integer types of the same size and sign.
60+ if cfg ! ( target_pointer_width = "32" ) {
61+ test_abi_compat ( 0usize , 0u32 ) ;
62+ test_abi_compat ( 0isize , 0i32 ) ;
63+ } else {
64+ test_abi_compat ( 0usize , 0u64 ) ;
65+ test_abi_compat ( 0isize , 0i64 ) ;
66+ }
67+ // Reference/pointer types with the same pointee.
7268 test_abi_compat ( & 0u32 , & 0u32 as * const u32 ) ;
69+ test_abi_compat ( & mut 0u32 as * mut u32 , Box :: new ( 0u32 ) ) ;
70+ test_abi_compat ( & ( ) , ptr:: NonNull :: < ( ) > :: dangling ( ) ) ;
71+ // Reference/pointer types with different but sized pointees.
7372 test_abi_compat ( & 0u32 , & ( [ true ; 4 ] , [ 0u32 ; 0 ] ) ) ;
73+ // Guaranteed null-pointer-optimizations.
74+ test_abi_compat ( & 0u32 as * const u32 , Some ( & 0u32 ) ) ;
75+ test_abi_compat ( 42u32 , num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ;
76+ test_abi_compat ( 0u32 , Some ( num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ) ;
7477
7578 // These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
7679 // with the wrapped field.
0 commit comments