fix homogeneous_aggregate not ignoring some 1-ZST
This commit is contained in:
parent
38bbc2ce03
commit
254e13d9f9
@ -382,8 +382,7 @@ fn is_aggregate(&self) -> bool {
|
|||||||
/// only a single type (e.g., `(u32, u32)`). Such aggregates are often
|
/// only a single type (e.g., `(u32, u32)`). Such aggregates are often
|
||||||
/// special-cased in ABIs.
|
/// special-cased in ABIs.
|
||||||
///
|
///
|
||||||
/// Note: We generally ignore fields of zero-sized type when computing
|
/// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
|
||||||
/// this value (see #56877).
|
|
||||||
///
|
///
|
||||||
/// This is public so that it can be used in unit tests, but
|
/// This is public so that it can be used in unit tests, but
|
||||||
/// should generally only be relevant to the ABI details of
|
/// should generally only be relevant to the ABI details of
|
||||||
@ -441,11 +440,17 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H
|
|||||||
let mut total = start;
|
let mut total = start;
|
||||||
|
|
||||||
for i in 0..layout.fields.count() {
|
for i in 0..layout.fields.count() {
|
||||||
if !is_union && total != layout.fields.offset(i) {
|
let field = layout.field(cx, i);
|
||||||
return Err(Heterogeneous);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
let field = layout.field(cx, i);
|
if !is_union && total != layout.fields.offset(i) {
|
||||||
|
// This field isn't just after the previous one we considered, abort.
|
||||||
|
return Err(Heterogeneous);
|
||||||
|
}
|
||||||
|
|
||||||
result = result.merge(field.homogeneous_aggregate(cx)?)?;
|
result = result.merge(field.homogeneous_aggregate(cx)?)?;
|
||||||
|
|
||||||
|
@ -105,6 +105,8 @@ mod $name {
|
|||||||
test_transparent!(unit, ());
|
test_transparent!(unit, ());
|
||||||
test_transparent!(pair, (i32, f32)); // mixing in some floats since they often get special treatment
|
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, (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!(tuple, (i32, f32, i64, f64));
|
||||||
test_transparent!(empty_array, [u32; 0]);
|
test_transparent!(empty_array, [u32; 0]);
|
||||||
test_transparent!(empty_1zst_array, [u8; 0]);
|
test_transparent!(empty_1zst_array, [u8; 0]);
|
||||||
@ -112,14 +114,6 @@ mod $name {
|
|||||||
test_transparent!(large_array, [i32; 16]);
|
test_transparent!(large_array, [i32; 16]);
|
||||||
test_transparent!(enum_, Option<i32>);
|
test_transparent!(enum_, Option<i32>);
|
||||||
test_transparent!(enum_niched, Option<&'static 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>.
|
// RFC 3391 <https://rust-lang.github.io/rfcs/3391-result_ffi_guarantees.html>.
|
||||||
macro_rules! test_nonnull {
|
macro_rules! test_nonnull {
|
||||||
|
44
tests/ui/layout/homogeneous-aggr-transparent.rs
Normal file
44
tests/ui/layout/homogeneous-aggr-transparent.rs
Normal file
@ -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() {}
|
32
tests/ui/layout/homogeneous-aggr-transparent.stderr
Normal file
32
tests/ui/layout/homogeneous-aggr-transparent.stderr
Normal file
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user