1
1
use std:: mem;
2
2
use std:: num;
3
+ use std:: ptr;
3
4
4
5
#[ derive( Copy , Clone , Default ) ]
5
6
struct Zst ;
6
7
7
- fn test_abi_compat < T : Copy , U : Copy > ( t : T , u : U ) {
8
+ #[ repr( transparent) ]
9
+ #[ derive( Copy , Clone ) ]
10
+ struct Wrapper < T > ( T ) ;
11
+
12
+ fn id < T > ( x : T ) -> T { x }
13
+
14
+ fn test_abi_compat < T : Clone , U : Clone > ( t : T , u : U ) {
8
15
fn id < T > ( x : T ) -> T {
9
16
x
10
17
}
@@ -16,10 +23,10 @@ fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
16
23
// in both directions.
17
24
let f: fn ( T ) -> T = id;
18
25
let f: fn ( U ) -> U = unsafe { std:: mem:: transmute ( f) } ;
19
- let _val = f ( u) ;
26
+ let _val = f ( u. clone ( ) ) ;
20
27
let f: fn ( U ) -> U = id;
21
28
let f: fn ( T ) -> T = unsafe { std:: mem:: transmute ( f) } ;
22
- let _val = f ( t) ;
29
+ let _val = f ( t. clone ( ) ) ;
23
30
24
31
// And then we do the same for `extern "C"`.
25
32
let f: extern "C" fn ( T ) -> T = id_c;
@@ -32,9 +39,6 @@ fn test_abi_compat<T: Copy, U: Copy>(t: T, u: U) {
32
39
33
40
/// Ensure that `T` is compatible with various repr(transparent) wrappers around `T`.
34
41
fn test_abi_newtype < T : Copy + Default > ( ) {
35
- #[ repr( transparent) ]
36
- #[ derive( Copy , Clone ) ]
37
- struct Wrapper1 < T > ( T ) ;
38
42
#[ repr( transparent) ]
39
43
#[ derive( Copy , Clone ) ]
40
44
struct Wrapper2 < T > ( T , ( ) ) ;
@@ -46,31 +50,38 @@ fn test_abi_newtype<T: Copy + Default>() {
46
50
struct Wrapper3 < T > ( Zst , T , [ u8 ; 0 ] ) ;
47
51
48
52
let t = T :: default ( ) ;
49
- test_abi_compat ( t, Wrapper1 ( t) ) ;
53
+ test_abi_compat ( t, Wrapper ( t) ) ;
50
54
test_abi_compat ( t, Wrapper2 ( t, ( ) ) ) ;
51
55
test_abi_compat ( t, Wrapper2a ( ( ) , t) ) ;
52
56
test_abi_compat ( t, Wrapper3 ( Zst , t, [ ] ) ) ;
53
57
test_abi_compat ( t, mem:: MaybeUninit :: new ( t) ) ; // MaybeUninit is `repr(transparent)`
54
58
}
55
59
56
60
fn 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' ) ;
61
+ // Here we check some of the guaranteed ABI compatibilities.
62
+ // Different integer types of the same size and sign.
63
+ if cfg ! ( target_pointer_width = "32" ) {
64
+ test_abi_compat ( 0usize , 0u32 ) ;
65
+ test_abi_compat ( 0isize , 0i32 ) ;
66
+ } else {
67
+ test_abi_compat ( 0usize , 0u64 ) ;
68
+ test_abi_compat ( 0isize , 0i64 ) ;
69
+ }
70
70
test_abi_compat ( 42u32 , num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ;
71
- test_abi_compat ( 0u32 , Some ( num :: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ) ;
71
+ // Reference/pointer types with the same pointee.
72
72
test_abi_compat ( & 0u32 , & 0u32 as * const u32 ) ;
73
+ test_abi_compat ( & mut 0u32 as * mut u32 , Box :: new ( 0u32 ) ) ;
74
+ test_abi_compat ( & ( ) , ptr:: NonNull :: < ( ) > :: dangling ( ) ) ;
75
+ // Reference/pointer types with different but sized pointees.
73
76
test_abi_compat ( & 0u32 , & ( [ true ; 4 ] , [ 0u32 ; 0 ] ) ) ;
77
+ // `fn` types
78
+ test_abi_compat ( main as fn ( ) , id :: < i32 > as fn ( i32 ) -> i32 ) ;
79
+ // Guaranteed null-pointer-optimizations.
80
+ test_abi_compat ( & 0u32 as * const u32 , Some ( & 0u32 ) ) ;
81
+ test_abi_compat ( main as fn ( ) , Some ( main as fn ( ) ) ) ;
82
+ test_abi_compat ( 0u32 , Some ( num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ) ;
83
+ test_abi_compat ( & 0u32 as * const u32 , Some ( Wrapper ( & 0u32 ) ) ) ;
84
+ test_abi_compat ( 0u32 , Some ( Wrapper ( num:: NonZeroU32 :: new ( 1 ) . unwrap ( ) ) ) ) ;
74
85
75
86
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
76
87
// with the wrapped field.
0 commit comments