diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-09-11 21:16:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-11 21:16:22 +0200 |
| commit | 279e2576a0f8e9667d2e7ee82bd8edaadf1c0999 (patch) | |
| tree | cbc7f0868c052c412db0a5ff893f0a73eba64c1a | |
| parent | 5a2b589ac7bfcc86f17c6b2947ebe99ff292615c (diff) | |
| parent | 254e13d9f9dd38817a28880b99acd29a2fcc5613 (diff) | |
| download | rust-279e2576a0f8e9667d2e7ee82bd8edaadf1c0999.tar.gz rust-279e2576a0f8e9667d2e7ee82bd8edaadf1c0999.zip | |
Rollup merge of #115708 - RalfJung:homogeneous, r=davidtwco
fix homogeneous_aggregate not ignoring some ZST This is an ABI-breaking change, because it fixes bugs in our ABI code. I'm not sure what that means for this PR, we don't really have a process for such changes, do we? I can only hope nobody relied on the old buggy behavior. Fixes https://github.com/rust-lang/rust/issues/115664
| -rw-r--r-- | compiler/rustc_target/src/abi/call/mod.rs | 13 | ||||
| -rw-r--r-- | tests/ui/abi/compatibility.rs | 10 | ||||
| -rw-r--r-- | tests/ui/layout/homogeneous-aggr-transparent.rs | 44 | ||||
| -rw-r--r-- | tests/ui/layout/homogeneous-aggr-transparent.stderr | 32 |
4 files changed, 87 insertions, 12 deletions
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 5d75974279e..1a4a46ceb40 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -382,8 +382,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// only a single type (e.g., `(u32, u32)`). Such aggregates are often /// special-cased in ABIs. /// - /// Note: We generally ignore fields of zero-sized type when computing - /// this value (see #56877). + /// Note: We generally ignore 1-ZST fields when computing this value (see #56877). /// /// This is public so that it can be used in unit tests, but /// should generally only be relevant to the ABI details of @@ -441,12 +440,18 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { let mut total = start; for i in 0..layout.fields.count() { + let field = layout.field(cx, i); + if field.is_1zst() { + // No data here and no impact on layout, can be ignored. + // (We might be able to also ignore all aligned ZST but that's less clear.) + continue; + } + if !is_union && total != layout.fields.offset(i) { + // This field isn't just after the previous one we considered, abort. return Err(Heterogeneous); } - let field = layout.field(cx, i); - result = result.merge(field.homogeneous_aggregate(cx)?)?; // Keep track of the offset (without padding). diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 86fb365507a..bfe0a5cf81d 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -106,6 +106,8 @@ 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]); @@ -113,14 +115,6 @@ test_transparent!(small_array, [i32; 2]); // chosen to fit into 64bit test_transparent!(large_array, [i32; 16]); test_transparent!(enum_, Option<i32>); test_transparent!(enum_niched, Option<&'static i32>); -// Pure-float types that are not ScalarPair seem to be tricky. -// FIXME: <https://github.com/rust-lang/rust/issues/115664> -#[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))] -mod tricky { - use super::*; - test_transparent!(triple_f32, (f32, f32, f32)); - test_transparent!(triple_f64, (f64, f64, f64)); -} // RFC 3391 <https://rust-lang.github.io/rfcs/3391-result_ffi_guarantees.html>. macro_rules! test_nonnull { diff --git a/tests/ui/layout/homogeneous-aggr-transparent.rs b/tests/ui/layout/homogeneous-aggr-transparent.rs new file mode 100644 index 00000000000..9703d2bf294 --- /dev/null +++ b/tests/ui/layout/homogeneous-aggr-transparent.rs @@ -0,0 +1,44 @@ +#![feature(rustc_attrs)] +#![feature(transparent_unions)] +use std::marker::PhantomData; + +// Regression test for #115664. We want to ensure that `repr(transparent)` wrappers do not affect +// the result of `homogeneous_aggregate`. + +type Tuple = (f32, f32, f32); + +struct Zst; + +#[repr(transparent)] +struct Wrapper1<T>(T); +#[repr(transparent)] +struct Wrapper2<T>((), Zst, T); +#[repr(transparent)] +struct Wrapper3<T>(T, [u8; 0], PhantomData<u64>); +#[repr(transparent)] +union WrapperUnion<T: Copy> { + nothing: (), + something: T, +} + +#[rustc_layout(homogeneous_aggregate)] +pub type Test0 = Tuple; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test1 = Wrapper1<Tuple>; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test2 = Wrapper2<Tuple>; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test3 = Wrapper3<Tuple>; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +#[rustc_layout(homogeneous_aggregate)] +pub type Test4 = WrapperUnion<Tuple>; +//~^ ERROR homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + +fn main() {} diff --git a/tests/ui/layout/homogeneous-aggr-transparent.stderr b/tests/ui/layout/homogeneous-aggr-transparent.stderr new file mode 100644 index 00000000000..99eb703ac82 --- /dev/null +++ b/tests/ui/layout/homogeneous-aggr-transparent.stderr @@ -0,0 +1,32 @@ +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-transparent.rs:25:1 + | +LL | pub type Test0 = Tuple; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-transparent.rs:29:1 + | +LL | pub type Test1 = Wrapper1<Tuple>; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-transparent.rs:33:1 + | +LL | pub type Test2 = Wrapper2<Tuple>; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-transparent.rs:37:1 + | +LL | pub type Test3 = Wrapper3<Tuple>; + | ^^^^^^^^^^^^^^ + +error: homogeneous_aggregate: Ok(Homogeneous(Reg { kind: Float, size: Size(4 bytes) })) + --> $DIR/homogeneous-aggr-transparent.rs:41:1 + | +LL | pub type Test4 = WrapperUnion<Tuple>; + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + |
