1
1
// check-pass
2
- #![ feature( rustc_attrs, transparent_unions) ]
3
- #![ allow( unused, improper_ctypes_definitions) ]
2
+ #![ feature( rustc_attrs, unsized_fn_params , transparent_unions) ]
3
+ #![ allow( unused, improper_ctypes_definitions, internal_features ) ]
4
4
use std:: marker:: PhantomData ;
5
5
use std:: mem:: ManuallyDrop ;
6
6
use std:: num:: NonZeroI32 ;
7
7
use std:: ptr:: NonNull ;
8
8
9
+ // FIXME: a bunch of targets are broken in various ways.
10
+ // Hence there are `cfg` throughout this test to disable parts of it on those targets.
11
+ // sparc64: https://github.com/rust-lang/rust/issues/115336
12
+ // mips64: https://github.com/rust-lang/rust/issues/115404
13
+ // riscv64: https://github.com/rust-lang/rust/issues/115481
14
+ // loongarch64: https://github.com/rust-lang/rust/issues/115509
15
+
9
16
macro_rules! assert_abi_compatible {
10
17
( $name: ident, $t1: ty, $t2: ty) => {
11
18
mod $name {
12
19
use super :: * ;
20
+ // Declaring a `type` doesn't even check well-formedness, so we also declare a function.
21
+ fn check_wf( _x: $t1, _y: $t2) { }
13
22
// Test argument and return value, `Rust` and `C` ABIs.
14
23
#[ rustc_abi( assert_eq) ]
15
24
type TestRust = ( fn ( $t1) -> $t1, fn ( $t2) -> $t2) ;
@@ -23,7 +32,7 @@ macro_rules! assert_abi_compatible {
23
32
struct Zst ;
24
33
25
34
#[ repr( C ) ]
26
- struct ReprC1 < T > ( T ) ;
35
+ struct ReprC1 < T : ? Sized > ( T ) ;
27
36
#[ repr( C ) ]
28
37
struct ReprC2Int < T > ( i32 , T ) ;
29
38
#[ repr( C ) ]
@@ -72,14 +81,20 @@ test_abi_compatible!(fn_fn, fn(), fn(i32) -> i32);
72
81
73
82
// Some further guarantees we will likely (have to) make.
74
83
test_abi_compatible ! ( zst_unit, Zst , ( ) ) ;
84
+ #[ cfg( not( any( target_arch = "sparc64" ) ) ) ]
75
85
test_abi_compatible ! ( zst_array, Zst , [ u8 ; 0 ] ) ;
76
86
test_abi_compatible ! ( nonzero_int, NonZeroI32 , i32 ) ;
77
87
88
+ // `DispatchFromDyn` relies on ABI compatibility.
89
+ // This is interesting since these types are not `repr(transparent)`.
90
+ test_abi_compatible ! ( rc, std:: rc:: Rc <i32 >, * mut i32 ) ;
91
+ test_abi_compatible ! ( arc, std:: sync:: Arc <i32 >, * mut i32 ) ;
92
+
78
93
// `repr(transparent)` compatibility.
79
94
#[ repr( transparent) ]
80
- struct Wrapper1 < T > ( T ) ;
95
+ struct Wrapper1 < T : ? Sized > ( T ) ;
81
96
#[ repr( transparent) ]
82
- struct Wrapper2 < T > ( ( ) , Zst , T ) ;
97
+ struct Wrapper2 < T : ? Sized > ( ( ) , Zst , T ) ;
83
98
#[ repr( transparent) ]
84
99
struct Wrapper3 < T > ( T , [ u8 ; 0 ] , PhantomData < u64 > ) ;
85
100
#[ repr( transparent) ]
@@ -95,6 +110,7 @@ macro_rules! test_transparent {
95
110
test_abi_compatible!( wrap1, $t, Wrapper1 <$t>) ;
96
111
test_abi_compatible!( wrap2, $t, Wrapper2 <$t>) ;
97
112
test_abi_compatible!( wrap3, $t, Wrapper3 <$t>) ;
113
+ #[ cfg( not( any( target_arch = "riscv64" , target_arch = "loongarch64" ) ) ) ]
98
114
test_abi_compatible!( wrap4, $t, WrapperUnion <$t>) ;
99
115
}
100
116
} ;
@@ -104,17 +120,51 @@ test_transparent!(simple, i32);
104
120
test_transparent ! ( reference, & ' static i32 ) ;
105
121
test_transparent ! ( zst, Zst ) ;
106
122
test_transparent ! ( unit, ( ) ) ;
107
- test_transparent ! ( pair, ( i32 , f32 ) ) ; // mixing in some floats since they often get special treatment
108
- test_transparent ! ( triple, ( i8 , i16 , f32 ) ) ; // chosen to fit into 64bit
109
- test_transparent ! ( triple_f32, ( f32 , f32 , f32 ) ) ; // homogeneous case
110
- test_transparent ! ( triple_f64, ( f64 , f64 , f64 ) ) ;
111
- test_transparent ! ( tuple, ( i32 , f32 , i64 , f64 ) ) ;
112
- test_transparent ! ( empty_array, [ u32 ; 0 ] ) ;
113
- test_transparent ! ( empty_1zst_array, [ u8 ; 0 ] ) ;
114
- test_transparent ! ( small_array, [ i32 ; 2 ] ) ; // chosen to fit into 64bit
115
- test_transparent ! ( large_array, [ i32 ; 16 ] ) ;
116
123
test_transparent ! ( enum_, Option <i32 >) ;
117
124
test_transparent ! ( enum_niched, Option <& ' static i32 >) ;
125
+ #[ cfg( not( any( target_arch = "mips64" , target_arch = "sparc64" ) ) ) ]
126
+ mod tuples {
127
+ use super :: * ;
128
+ // mixing in some floats since they often get special treatment
129
+ test_transparent ! ( pair, ( i32 , f32 ) ) ;
130
+ // chosen to fit into 64bit
131
+ test_transparent ! ( triple, ( i8 , i16 , f32 ) ) ;
132
+ // Pure-float types that are not ScalarPair seem to be tricky.
133
+ test_transparent ! ( triple_f32, ( f32 , f32 , f32 ) ) ;
134
+ test_transparent ! ( triple_f64, ( f64 , f64 , f64 ) ) ;
135
+ // and also something that's larger than 2 pointers
136
+ test_transparent ! ( tuple, ( i32 , f32 , i64 , f64 ) ) ;
137
+ }
138
+ // Some targets have special rules for arrays.
139
+ #[ cfg( not( any( target_arch = "mips64" , target_arch = "sparc64" ) ) ) ]
140
+ mod arrays {
141
+ use super :: * ;
142
+ test_transparent ! ( empty_array, [ u32 ; 0 ] ) ;
143
+ test_transparent ! ( empty_1zst_array, [ u8 ; 0 ] ) ;
144
+ test_transparent ! ( small_array, [ i32 ; 2 ] ) ; // chosen to fit into 64bit
145
+ test_transparent ! ( large_array, [ i32 ; 16 ] ) ;
146
+ }
147
+
148
+ // Some tests with unsized types (not all wrappers are compatible with that).
149
+ macro_rules! test_transparent_unsized {
150
+ ( $name: ident, $t: ty) => {
151
+ mod $name {
152
+ use super :: * ;
153
+ assert_abi_compatible!( wrap1, $t, Wrapper1 <$t>) ;
154
+ assert_abi_compatible!( wrap1_reprc, ReprC1 <$t>, ReprC1 <Wrapper1 <$t>>) ;
155
+ assert_abi_compatible!( wrap2, $t, Wrapper2 <$t>) ;
156
+ assert_abi_compatible!( wrap2_reprc, ReprC1 <$t>, ReprC1 <Wrapper2 <$t>>) ;
157
+ }
158
+ } ;
159
+ }
160
+
161
+ #[ cfg( not( any( target_arch = "mips64" , target_arch = "sparc64" ) ) ) ]
162
+ mod unsized_ {
163
+ use super :: * ;
164
+ test_transparent_unsized ! ( str_, str ) ;
165
+ test_transparent_unsized ! ( slice, [ u8 ] ) ;
166
+ test_transparent_unsized ! ( dyn_trait, dyn std:: any:: Any ) ;
167
+ }
118
168
119
169
// RFC 3391 <https://rust-lang.github.io/rfcs/3391-result_ffi_guarantees.html>.
120
170
macro_rules! test_nonnull {
0 commit comments