Actually I found a counterexample:
opened 07:34AM - 29 Aug 23 UTC
needs-triage
I tried the following code:
```rust
#![feature(rustc_attrs)]
#[rustc_abi(de… bug)]
extern "C" fn test1(_x: [u8; 0]) {}
#[repr(transparent)]
struct Wrap<T>(T);
#[rustc_abi(debug)]
extern "C" fn test2(_x: Wrap<[u8; 0]>) {}
```
When running this with `--target sparc64-unknown-linux-gnu` (using Miri), the first function reports an argument pass mode of
```
mode: Indirect {
attrs: ArgAttributes {
regular: NoAlias | NoCapture | NonNull | NoUndef,
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: Some(
Align(1 bytes),
),
},
extra_attrs: None,
on_stack: false,
},
```
but the 2nd function reports
```
mode: Cast(
CastTarget {
prefix: [
None,
None,
None,
None,
None,
None,
None,
None,
],
rest: Uniform {
unit: Reg {
kind: Integer,
size: Size(8 bytes),
},
total: Size(0 bytes),
},
attrs: ArgAttributes {
regular: (empty),
arg_ext: None,
pointee_size: Size(0 bytes),
pointee_align: None,
},
},
false,
),
```
I'm not an expert in interpreting PassMode, but `Indirect` and `Cast` are not compatible, are they?
Cc @bjorn3 @eddyb @psumbera
Maybe we have to say that empty arrays do not count as 1-ZST... at that point we should probably find a new name for this. E.g. a type is "ABI-trivial" if it has the same ABI as ()
. And repr(transparent)
only allows any number of ABI-trivial fields plus one extra field.
There are more targets in this scary list though and I've not checked at all how they treat various kinds of 1-ZST:
// For some forsaken reason, x86_64-pc-windows-gnu
// doesn't ignore zero-sized struct arguments.
// The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}.
if is_return
|| rust_abi
|| (!win_x64_gnu
&& !linux_s390x_gnu_like
&& !linux_sparc64_gnu_like
&& !linux_powerpc_gnu_like)
{
arg.mode = PassMode::Ignore;
}
2 Likes