rust-bindgen
rust-bindgen copied to clipboard
packed type cannot transitively contain a `#[repr(align)]` type
Input C/C++ Header
#include <stdint.h>
#pragma pack(push, 2)
typedef struct _UART_SETTINGS
{
uint16_t Baudrate;
uint16_t spbrg;
uint16_t brgh;
uint16_t parity;
uint16_t stop_bits;
uint8_t flow_control; /* 0- off, 1 - Simple CTS RTS */
uint8_t reserved_1;
union {
uint32_t bOptions;
struct
{
unsigned invert_tx : 1;
unsigned invert_rx : 1;
unsigned half_duplex : 1;
unsigned reserved_bits : 13;
unsigned reserved_bits2 : 16;
} opts;
} options;
} UART_SETTINGS;
#pragma pack(pop)
Bindgen Invocation
$ bindgen test.h >> test.rs
Actual Results
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> src\main.rs:149:1
|
149 | / pub union _UART_SETTINGS__bindgen_ty_1 {
150 | | pub bOptions: u32,
151 | | pub opts: _UART_SETTINGS__bindgen_ty_1__bindgen_ty_1,
152 | | }
| |_^
|
note: `_UART_SETTINGS__bindgen_ty_1__bindgen_ty_1` has a `#[repr(align)]` attribute
--> src\main.rs:156:1
|
156 | / pub struct _UART_SETTINGS__bindgen_ty_1__bindgen_ty_1 {
157 | | pub _bitfield_align_1: [u8; 0],
158 | | pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>,
159 | | }
| |_^
Expected Results
compile successfully. If bitfields are removed and or packed is removed this work.
I'm getting a similar error when trying to build https://github.com/nviennot/tinyusb-sys-rs.git
I'm building with: cargo build --verbose --features device,cdc,rp2040 --target thumbv6m-none-eabi
I get these errors
Running `rustc --crate-name tinyusb_sys --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="cdc"' --cfg 'feature="device"' --cfg 'feature="rp2040"' -C metadata=222396e23cc7c407 -C extra-filename=-222396e23cc7c407 --out-dir /Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/deps --target thumbv6m-none-eabi -C incremental=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/incremental -L dependency=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/deps -L dependency=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/debug/deps --extern cty=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/deps/libcty-539500295d24c90b.rmeta -L native=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/build/tinyusb-sys-d484e22ceeda2732/out -l static=tinyusb`
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> /Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/build/tinyusb-sys-d484e22ceeda2732/out/bindings.rs:3910:1
|
3910 | / pub struct cdc_desc_func_telephone_call_state_reporting_capabilities_t {
3911 | | #[doc = "< Size of this descriptor in bytes."]
3912 | | pub bLength: u8,
3913 | | #[doc = "< Descriptor Type, must be Class-Specific"]
... |
3917 | | pub bmCapabilities: cdc_desc_func_telephone_call_state_reporting_capabilities_t__bindgen_ty_1,
3918 | | }
| |_^
|
note: `cdc_desc_func_telephone_call_state_reporting_capabilities_t__bindgen_ty_1` has a `#[repr(align)]` attribute
--> /Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/build/tinyusb-sys-d484e22ceeda2732/out/bindings.rs:3922:1
|
3922 | / pub struct cdc_desc_func_telephone_call_state_reporting_capabilities_t__bindgen_ty_1 {
3923 | | pub _bitfield_align_1: [u32; 0],
3924 | | pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>,
3925 | | }
| |_^
For more information about this error, try `rustc --explain E0588`.
error: could not compile `tinyusb-sys` due to previous error
Caused by:
process didn't exit successfully: `rustc --crate-name tinyusb_sys --edition=2021 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 --cfg 'feature="cdc"' --cfg 'feature="device"' --cfg 'feature="rp2040"' -C metadata=222396e23cc7c407 -C extra-filename=-222396e23cc7c407 --out-dir /Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/deps --target thumbv6m-none-eabi -C incremental=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/incremental -L dependency=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/deps -L dependency=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/debug/deps --extern cty=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/deps/libcty-539500295d24c90b.rmeta -L native=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/tinyusb-sys-rs/target/thumbv6m-none-eabi/debug/build/tinyusb-sys-d484e22ceeda2732/out -l static=tinyusb` (exit status: 1)
Where the source looks like
/// \brief Telephone Call and Line State Reporting Capabilities Descriptor
/// \details The Telephone Call and Line State Reporting Capabilities functional descriptor describes the abilities of a
/// telephone device to report optional call and line states.
typedef struct TU_ATTR_PACKED
{
uint8_t bLength ; ///< Size of this descriptor in bytes.
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
struct {
uint32_t interrupted_dialtone : 1; ///< 0 : Reports only dialtone (does not differentiate between normal and interrupted dialtone). 1 : R
eports interrupted dialtone in addition to normal dialtone
uint32_t ringback_busy_fastbusy : 1; ///< 0 : Reports only dialing state. 1 : Reports ringback, busy, and fast busy states.
uint32_t caller_id : 1; ///< 0 : Does not report caller ID. 1 : Reports caller ID information.
uint32_t incoming_distinctive : 1; ///< 0 : Reports only incoming ringing. 1 : Reports incoming distinctive ringing patterns.
uint32_t dual_tone_multi_freq : 1; ///< 0 : Cannot report dual tone multi-frequency (DTMF) digits input remotely over the telephone line.
1 : Can report DTMF digits input remotely over the telephone line.
uint32_t line_state_change : 1; ///< 0 : Does not support line state change notification. 1 : Does support line state change notificat
ion
uint32_t TU_RESERVED : 26;
} bmCapabilities;
}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
Seen by the kernel as well at: https://lore.kernel.org/all/[email protected]/
struct alt_instr {
s32 instr_offset; /* original instruction */
s32 repl_offset; /* offset to replacement instruction */
union {
struct {
u32 cpuid: 16; /* CPUID bit set for replacement */
u32 flags: 16; /* patching control flags */
};
u32 ft_flgs;
};
u8 instrlen; /* length of original instruction */
u8 replacementlen; /* length of new instruction */
} __packed;
Encountered the same problem when binding spdk.
#include <stdint.h>
struct __attribute__((packed)) spdk_nvme_sgl_descriptor {
uint64_t address;
union {
struct {
uint8_t reserved[7];
uint8_t subtype : 4;
uint8_t type : 4;
} generic;
struct {
uint32_t length;
uint8_t reserved[3];
uint8_t subtype : 4;
uint8_t type : 4;
} unkeyed;
struct {
uint64_t length : 24;
uint64_t key : 32;
uint64_t subtype : 4;
uint64_t type : 4;
} keyed;
};
};
Any solution?
Here is a simple breakdown of the actual issue at hand. It looks the rust compiler can't align and pack at the same time which is causing the issue.
#[derive(Debug, Clone, Copy)]
#[repr(C, packed(2))]
struct PackedAlignedTest {
a: u32,
b: u16,
inner: PackedAlignedInnerTest,
}
#[derive(Debug, Clone, Copy)]
#[repr(C, align(2))]
struct PackedAlignedInnerTest {
c: u32,
d: u16,
}
fn main() {
let packed_aligned_test = PackedAlignedTest {
a: 0,
b: 1,
inner: PackedAlignedInnerTest {
c: 2,
d: 3
}
};
println!("{packed_aligned_test:#?}");
}
error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
--> src/main.rs:3:1
|
3 | struct PackedAlignedTest {
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `PackedAlignedInnerTest` has a `#[repr(align)]` attribute
--> src/main.rs:11:1
|
11 | struct PackedAlignedInnerTest {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0588`.
error: could not compile `playground` (bin "playground") due to previous error
From what I can tell there was an oversight in this issue: https://github.com/rust-lang/rust/issues/33158
Currently #[repr(packed())] structs cannot transitively contain #[repr(align())] structs due to differing behavior between msvc and gcc. Do we want to keep this a hard error, pick one behavior over the other, or provide some way to choose which behavior is desired?
This was never resolved and missed in review.