Skip to content

Commit 751ecde

Browse files
committed
rustc_target/riscv: Fix passing of transparent unions with only one non-ZST member
This ensures that `MaybeUninit<T>` has the same ABI as `T` when passed through an `extern "C"` function. Fixes #115481.
1 parent ae9c330 commit 751ecde

File tree

3 files changed

+23
-0
lines changed

3 files changed

+23
-0
lines changed

compiler/rustc_middle/src/ty/layout.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,10 @@ where
11181118
fn is_unit(this: TyAndLayout<'tcx>) -> bool {
11191119
matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
11201120
}
1121+
1122+
fn is_transparent(this: TyAndLayout<'tcx>) -> bool {
1123+
matches!(this.ty.kind(), ty::Adt(def, _) if def.repr().transparent())
1124+
}
11211125
}
11221126

11231127
/// Calculates whether a function's ABI can unwind or not.

compiler/rustc_target/src/abi/call/riscv.rs

+11
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ where
8989
}
9090
FieldsShape::Union(_) => {
9191
if !arg_layout.is_zst() {
92+
if arg_layout.is_transparent() {
93+
let non_1zst_elem = arg_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in non-ZST repr(transparent) union").1;
94+
return should_use_fp_conv_helper(
95+
cx,
96+
&non_1zst_elem,
97+
xlen,
98+
flen,
99+
field1_kind,
100+
field2_kind,
101+
);
102+
}
92103
return Err(CannotUseFpConv);
93104
}
94105
}

compiler/rustc_target/src/abi/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
6666
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
6767
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
6868
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
69+
fn is_transparent(this: TyAndLayout<'a, Self>) -> bool;
6970
}
7071

7172
impl<'a, Ty> TyAndLayout<'a, Ty> {
@@ -136,6 +137,13 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
136137
Ty::is_unit(self)
137138
}
138139

140+
pub fn is_transparent<C>(self) -> bool
141+
where
142+
Ty: TyAbiInterface<'a, C>,
143+
{
144+
Ty::is_transparent(self)
145+
}
146+
139147
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
140148
where
141149
Ty: TyAbiInterface<'a, C>,

0 commit comments

Comments
 (0)