Skip to content

Commit 4441f41

Browse files
committed
repr(int) fieldless enums are ABI-compatible with int
1 parent 6a2cd0d commit 4441f41

File tree

2 files changed

+64
-42
lines changed

2 files changed

+64
-42
lines changed

library/core/src/primitive_docs.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,8 @@ mod prim_ref {}
16671667
/// Pointee>::Metadata`).
16681668
/// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is
16691669
/// ABI-compatible with the `iN` integer type of the same size.
1670+
/// - A fieldless enum with `repr(u*)` or `repr(i*)` is ABI-compatible with the integer type given
1671+
/// in the `repr`.
16701672
/// - `char` is ABI-compatible with `u32`.
16711673
/// - Any two `fn` (function pointer) types are ABI-compatible with each other if they have the same
16721674
/// ABI string or the ABI string only differs in a trailing `-unwind`, independent of the rest of

tests/ui/abi/compatibility.rs

+62-42
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ mod prelude {
188188
#[cfg(not(host))]
189189
use prelude::*;
190190

191-
macro_rules! assert_abi_compatible {
191+
macro_rules! test_abi_compatible {
192192
($name:ident, $t1:ty, $t2:ty) => {
193193
mod $name {
194194
use super::*;
@@ -232,55 +232,75 @@ union ReprCUnion<T> {
232232
something: ManuallyDrop<T>,
233233
}
234234

235-
macro_rules! test_abi_compatible {
235+
macro_rules! test_abi_compatible_nested {
236236
($name:ident, $t1:ty, $t2:ty) => {
237237
mod $name {
238238
use super::*;
239-
assert_abi_compatible!(plain, $t1, $t2);
239+
test_abi_compatible!(plain, $t1, $t2);
240240
// We also do some tests with differences in fields of `repr(C)` types.
241-
assert_abi_compatible!(repr_c_1, ReprC1<$t1>, ReprC1<$t2>);
242-
assert_abi_compatible!(repr_c_2_int, ReprC2Int<$t1>, ReprC2Int<$t2>);
243-
assert_abi_compatible!(repr_c_2_float, ReprC2Float<$t1>, ReprC2Float<$t2>);
244-
assert_abi_compatible!(repr_c_4, ReprC4<$t1>, ReprC4<$t2>);
245-
assert_abi_compatible!(repr_c_4mixed, ReprC4Mixed<$t1>, ReprC4Mixed<$t2>);
246-
assert_abi_compatible!(repr_c_enum, ReprCEnum<$t1>, ReprCEnum<$t2>);
247-
assert_abi_compatible!(repr_c_union, ReprCUnion<$t1>, ReprCUnion<$t2>);
241+
// This is not guaranteed, but it's still good to know when there are differences here.
242+
test_abi_compatible!(repr_c_1, ReprC1<$t1>, ReprC1<$t2>);
243+
test_abi_compatible!(repr_c_2_int, ReprC2Int<$t1>, ReprC2Int<$t2>);
244+
test_abi_compatible!(repr_c_2_float, ReprC2Float<$t1>, ReprC2Float<$t2>);
245+
test_abi_compatible!(repr_c_4, ReprC4<$t1>, ReprC4<$t2>);
246+
test_abi_compatible!(repr_c_4mixed, ReprC4Mixed<$t1>, ReprC4Mixed<$t2>);
247+
test_abi_compatible!(repr_c_enum, ReprCEnum<$t1>, ReprCEnum<$t2>);
248+
test_abi_compatible!(repr_c_union, ReprCUnion<$t1>, ReprCUnion<$t2>);
248249
}
249250
};
250251
}
251252

252253
// Compatibility of pointers.
253-
test_abi_compatible!(ptr_mut, *const i32, *mut i32);
254-
test_abi_compatible!(ptr_pointee, *const i32, *const Vec<i32>);
255-
test_abi_compatible!(ref_mut, &i32, &mut i32);
256-
test_abi_compatible!(ref_ptr, &i32, *const i32);
257-
test_abi_compatible!(box_ptr, Box<i32>, *const i32);
258-
test_abi_compatible!(nonnull_ptr, NonNull<i32>, *const i32);
259-
test_abi_compatible!(fn_fn, fn(), fn(i32) -> i32);
254+
test_abi_compatible_nested!(ptr_mut, *const i32, *mut i32);
255+
test_abi_compatible_nested!(ptr_pointee, *const i32, *const Vec<i32>);
256+
test_abi_compatible_nested!(ref_mut, &i32, &mut i32);
257+
test_abi_compatible_nested!(ref_ptr, &i32, *const i32);
258+
test_abi_compatible_nested!(box_ptr, Box<i32>, *const i32);
259+
test_abi_compatible_nested!(nonnull_ptr, NonNull<i32>, *const i32);
260+
test_abi_compatible_nested!(fn_fn, fn(), fn(i32) -> i32);
260261

261262
// Compatibility of integer types.
262-
test_abi_compatible!(char_uint, char, u32);
263+
test_abi_compatible_nested!(char_uint, char, u32);
263264
#[cfg(target_pointer_width = "32")]
264-
test_abi_compatible!(isize_int, isize, i32);
265+
test_abi_compatible_nested!(isize_int, isize, i32);
265266
#[cfg(target_pointer_width = "64")]
266-
test_abi_compatible!(isize_int, isize, i64);
267+
test_abi_compatible_nested!(isize_int, isize, i64);
268+
269+
// Compatibility of enums with `repr($int)`.
270+
#[repr(i16)]
271+
enum I16 {
272+
Var1,
273+
Var2,
274+
}
275+
test_abi_compatible_nested!(enum_i16, I16, i16);
276+
#[repr(u64)]
277+
enum U64 {
278+
Var1,
279+
Var2,
280+
}
281+
#[cfg(not(target_arch = "m68k"))]
282+
test_abi_compatible_nested!(enum_u64, U64, u64);
283+
// On m68k, the nested case does not work out. We don't guarantee that case
284+
// so this is not a bug.
285+
#[cfg(target_arch = "m68k")]
286+
test_abi_compatible!(enum_u64, U64, u64);
267287

268288
// Compatibility of 1-ZST.
269-
test_abi_compatible!(zst_unit, Zst, ());
270-
#[cfg(not(any(target_arch = "sparc64")))]
271-
test_abi_compatible!(zst_array, Zst, [u8; 0]);
272-
test_abi_compatible!(nonzero_int, NonZero<i32>, i32);
289+
test_abi_compatible_nested!(zst_unit, Zst, ());
290+
#[cfg(not(target_arch = "sparc64"))]
291+
test_abi_compatible_nested!(zst_array, Zst, [u8; 0]);
292+
test_abi_compatible_nested!(nonzero_int, NonZero<i32>, i32);
273293

274294
// `#[repr(C)]` enums should not change ABI based on individual variant inhabitedness.
275295
// (However, this is *not* a guarantee. We only guarantee same layout, not same ABI.)
276296
enum Void {}
277-
test_abi_compatible!(repr_c_enum_void, ReprCEnum<Void>, ReprCEnum<ReprCUnion<Void>>);
297+
test_abi_compatible_nested!(repr_c_enum_void, ReprCEnum<Void>, ReprCEnum<ReprCUnion<Void>>);
278298

279299
// `DispatchFromDyn` relies on ABI compatibility.
280300
// This is interesting since these types are not `repr(transparent)`. So this is not part of our
281301
// public ABI guarantees, but is relied on by the compiler.
282-
test_abi_compatible!(rc, Rc<i32>, *mut i32);
283-
test_abi_compatible!(arc, Arc<i32>, *mut i32);
302+
test_abi_compatible_nested!(rc, Rc<i32>, *mut i32);
303+
test_abi_compatible_nested!(arc, Arc<i32>, *mut i32);
284304

285305
// `repr(transparent)` compatibility.
286306
#[repr(transparent)]
@@ -299,10 +319,10 @@ macro_rules! test_transparent {
299319
($name:ident, $t:ty) => {
300320
mod $name {
301321
use super::*;
302-
test_abi_compatible!(wrap1, $t, Wrapper1<$t>);
303-
test_abi_compatible!(wrap2, $t, Wrapper2<$t>);
304-
test_abi_compatible!(wrap3, $t, Wrapper3<$t>);
305-
test_abi_compatible!(wrap4, $t, WrapperUnion<$t>);
322+
test_abi_compatible_nested!(wrap1, $t, Wrapper1<$t>);
323+
test_abi_compatible_nested!(wrap2, $t, Wrapper2<$t>);
324+
test_abi_compatible_nested!(wrap3, $t, Wrapper3<$t>);
325+
test_abi_compatible_nested!(wrap4, $t, WrapperUnion<$t>);
306326
}
307327
};
308328
}
@@ -341,10 +361,10 @@ macro_rules! test_transparent_unsized {
341361
($name:ident, $t:ty) => {
342362
mod $name {
343363
use super::*;
344-
assert_abi_compatible!(wrap1, $t, Wrapper1<$t>);
345-
assert_abi_compatible!(wrap1_reprc, ReprC1<$t>, ReprC1<Wrapper1<$t>>);
346-
assert_abi_compatible!(wrap2, $t, Wrapper2<$t>);
347-
assert_abi_compatible!(wrap2_reprc, ReprC1<$t>, ReprC1<Wrapper2<$t>>);
364+
test_abi_compatible!(wrap1, $t, Wrapper1<$t>);
365+
test_abi_compatible!(wrap1_reprc, ReprC1<$t>, ReprC1<Wrapper1<$t>>);
366+
test_abi_compatible!(wrap2, $t, Wrapper2<$t>);
367+
test_abi_compatible!(wrap2_reprc, ReprC1<$t>, ReprC1<Wrapper2<$t>>);
348368
}
349369
};
350370
}
@@ -363,13 +383,13 @@ macro_rules! test_nonnull {
363383
($name:ident, $t:ty) => {
364384
mod $name {
365385
use super::*;
366-
test_abi_compatible!(option, Option<$t>, $t);
367-
test_abi_compatible!(result_err_unit, Result<$t, ()>, $t);
368-
test_abi_compatible!(result_ok_unit, Result<(), $t>, $t);
369-
test_abi_compatible!(result_err_zst, Result<$t, Zst>, $t);
370-
test_abi_compatible!(result_ok_zst, Result<Zst, $t>, $t);
371-
test_abi_compatible!(result_err_arr, Result<$t, [i8; 0]>, $t);
372-
test_abi_compatible!(result_ok_arr, Result<[i8; 0], $t>, $t);
386+
test_abi_compatible_nested!(option, Option<$t>, $t);
387+
test_abi_compatible_nested!(result_err_unit, Result<$t, ()>, $t);
388+
test_abi_compatible_nested!(result_ok_unit, Result<(), $t>, $t);
389+
test_abi_compatible_nested!(result_err_zst, Result<$t, Zst>, $t);
390+
test_abi_compatible_nested!(result_ok_zst, Result<Zst, $t>, $t);
391+
test_abi_compatible_nested!(result_err_arr, Result<$t, [i8; 0]>, $t);
392+
test_abi_compatible_nested!(result_ok_arr, Result<[i8; 0], $t>, $t);
373393
}
374394
}
375395
}

0 commit comments

Comments
 (0)