From 10951f350070c9aace60fd945897365f780974da Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 8 Sep 2023 16:13:24 +0200 Subject: [PATCH 1/4] make sure the types in the ABI compat test actually type-check --- tests/ui/abi/compatibility.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index bfe0a5cf81d19..8cb16812c1fe7 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -5,11 +5,14 @@ use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::num::NonZeroI32; use std::ptr::NonNull; +use std::mem::ManuallyDrop; macro_rules! assert_abi_compatible { ($name:ident, $t1:ty, $t2:ty) => { mod $name { use super::*; + // Declaring a `type` doesn't even check well-formedness, so we also declare a function. + fn check_wf(_x: $t1, _y: $t2) {} // Test argument and return value, `Rust` and `C` ABIs. #[rustc_abi(assert_eq)] type TestRust = (fn($t1) -> $t1, fn($t2) -> $t2); @@ -77,9 +80,9 @@ test_abi_compatible!(nonzero_int, NonZeroI32, i32); // `repr(transparent)` compatibility. #[repr(transparent)] -struct Wrapper1(T); +struct Wrapper1(T); #[repr(transparent)] -struct Wrapper2((), Zst, T); +struct Wrapper2((), Zst, T); #[repr(transparent)] struct Wrapper3(T, [u8; 0], PhantomData); #[repr(transparent)] From 721dfc5994bcad5d8b4bd0ea86338fd5d0790b41 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 8 Sep 2023 16:21:53 +0200 Subject: [PATCH 2/4] also test ABI-compatibility for some unsized types --- tests/ui/abi/compatibility.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 8cb16812c1fe7..6edec5ddf3ac2 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(rustc_attrs, transparent_unions)] +#![feature(rustc_attrs, unsized_fn_params, transparent_unions)] #![allow(unused, improper_ctypes_definitions)] use std::marker::PhantomData; use std::mem::ManuallyDrop; @@ -26,7 +26,7 @@ macro_rules! assert_abi_compatible { struct Zst; #[repr(C)] -struct ReprC1(T); +struct ReprC1(T); #[repr(C)] struct ReprC2Int(i32, T); #[repr(C)] @@ -119,6 +119,23 @@ test_transparent!(large_array, [i32; 16]); test_transparent!(enum_, Option); test_transparent!(enum_niched, Option<&'static i32>); +// Some tests with unsized types (not all wrappers are compatible with that). +macro_rules! test_transparent_unsized { + ($name:ident, $t:ty) => { + mod $name { + use super::*; + assert_abi_compatible!(wrap1, $t, Wrapper1<$t>); + assert_abi_compatible!(wrap1_reprc, ReprC1<$t>, ReprC1>); + assert_abi_compatible!(wrap2, $t, Wrapper2<$t>); + assert_abi_compatible!(wrap2_reprc, ReprC1<$t>, ReprC1>); + } + }; +} + +test_transparent_unsized!(str_, str); +test_transparent_unsized!(slice, [u8]); +test_transparent_unsized!(dyn_trait, dyn std::any::Any); + // RFC 3391 . macro_rules! test_nonnull { ($name:ident, $t:ty) => { From 4f606eb423b0fcbd68e1b72325fcd0f42bf740b2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 8 Sep 2023 17:25:37 +0200 Subject: [PATCH 3/4] add enough cfg to make the test pass on problematic targets --- tests/ui/abi/compatibility.rs | 53 ++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 6edec5ddf3ac2..8b7236bf42f92 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -1,11 +1,17 @@ // check-pass #![feature(rustc_attrs, unsized_fn_params, transparent_unions)] -#![allow(unused, improper_ctypes_definitions)] +#![allow(unused, improper_ctypes_definitions, internal_features)] use std::marker::PhantomData; use std::mem::ManuallyDrop; use std::num::NonZeroI32; use std::ptr::NonNull; -use std::mem::ManuallyDrop; + +// FIXME: a bunch of targets are broken in various ways. +// Hence there are `cfg` throughout this test to disable parts of it on those targets. +// sparc64: https://github.com/rust-lang/rust/issues/115336 +// mips64: https://github.com/rust-lang/rust/issues/115404 +// riscv64: https://github.com/rust-lang/rust/issues/115481 +// loongarch64: https://github.com/rust-lang/rust/issues/115509 macro_rules! assert_abi_compatible { ($name:ident, $t1:ty, $t2:ty) => { @@ -75,6 +81,7 @@ test_abi_compatible!(fn_fn, fn(), fn(i32) -> i32); // Some further guarantees we will likely (have to) make. test_abi_compatible!(zst_unit, Zst, ()); +#[cfg(not(any(target_arch = "sparc64")))] test_abi_compatible!(zst_array, Zst, [u8; 0]); test_abi_compatible!(nonzero_int, NonZeroI32, i32); @@ -98,6 +105,7 @@ macro_rules! test_transparent { test_abi_compatible!(wrap1, $t, Wrapper1<$t>); test_abi_compatible!(wrap2, $t, Wrapper2<$t>); test_abi_compatible!(wrap3, $t, Wrapper3<$t>); + #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] test_abi_compatible!(wrap4, $t, WrapperUnion<$t>); } }; @@ -107,17 +115,30 @@ test_transparent!(simple, i32); test_transparent!(reference, &'static i32); test_transparent!(zst, Zst); test_transparent!(unit, ()); -test_transparent!(pair, (i32, f32)); // mixing in some floats since they often get special treatment -test_transparent!(triple, (i8, i16, f32)); // chosen to fit into 64bit -test_transparent!(triple_f32, (f32, f32, f32)); // homogeneous case -test_transparent!(triple_f64, (f64, f64, f64)); -test_transparent!(tuple, (i32, f32, i64, f64)); -test_transparent!(empty_array, [u32; 0]); -test_transparent!(empty_1zst_array, [u8; 0]); -test_transparent!(small_array, [i32; 2]); // chosen to fit into 64bit -test_transparent!(large_array, [i32; 16]); test_transparent!(enum_, Option); test_transparent!(enum_niched, Option<&'static i32>); +#[cfg(not(any(target_arch = "mips64", target_arch = "sparc64")))] +mod tuples { + use super::*; + // mixing in some floats since they often get special treatment + test_transparent!(pair, (i32, f32)); + // chosen to fit into 64bit + test_transparent!(triple, (i8, i16, f32)); + // Pure-float types that are not ScalarPair seem to be tricky. + test_transparent!(triple_f32, (f32, f32, f32)); + test_transparent!(triple_f64, (f64, f64, f64)); + // and also something that's larger than 2 pointers + test_transparent!(tuple, (i32, f32, i64, f64)); +} +// Some targets have special rules for arrays. +#[cfg(not(any(target_arch = "mips64", target_arch = "sparc64")))] +mod arrays { + use super::*; + test_transparent!(empty_array, [u32; 0]); + test_transparent!(empty_1zst_array, [u8; 0]); + test_transparent!(small_array, [i32; 2]); // chosen to fit into 64bit + test_transparent!(large_array, [i32; 16]); +} // Some tests with unsized types (not all wrappers are compatible with that). macro_rules! test_transparent_unsized { @@ -132,9 +153,13 @@ macro_rules! test_transparent_unsized { }; } -test_transparent_unsized!(str_, str); -test_transparent_unsized!(slice, [u8]); -test_transparent_unsized!(dyn_trait, dyn std::any::Any); +#[cfg(not(any(target_arch = "mips64", target_arch = "sparc64")))] +mod unsized_ { + use super::*; + test_transparent_unsized!(str_, str); + test_transparent_unsized!(slice, [u8]); + test_transparent_unsized!(dyn_trait, dyn std::any::Any); +} // RFC 3391 . macro_rules! test_nonnull { From 6f2c051aba7d40b260ec6de4298f801164f569e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Sep 2023 13:05:12 +0200 Subject: [PATCH 4/4] add some DispatchFromDyn ABI compatibility tests --- tests/ui/abi/compatibility.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 8b7236bf42f92..b3e75bb8233e3 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -85,6 +85,11 @@ test_abi_compatible!(zst_unit, Zst, ()); test_abi_compatible!(zst_array, Zst, [u8; 0]); test_abi_compatible!(nonzero_int, NonZeroI32, i32); +// `DispatchFromDyn` relies on ABI compatibility. +// This is interesting since these types are not `repr(transparent)`. +test_abi_compatible!(rc, std::rc::Rc, *mut i32); +test_abi_compatible!(arc, std::sync::Arc, *mut i32); + // `repr(transparent)` compatibility. #[repr(transparent)] struct Wrapper1(T);