C union containing only flexible array members does not generate Rust union · Issue #3130 · rust-lang/rust-bindgen (original) (raw)

Consider this type from Linux:

struct bpf_prog { ... /* Instructions for interpreter */ union { DECLARE_FLEX_ARRAY(struct sock_filter, insns); DECLARE_FLEX_ARRAY(struct bpf_insn, insnsi); }; };

This generates:

#[repr(C)] pub struct bpf_prog { ... pub __bindgen_anon_1: bpf_prog__bindgen_ty_1, } #[repr(C)] pub struct bpf_prog__bindgen_ty_1 { pub __bindgen_anon_1: __BindgenUnionField, pub __bindgen_anon_2: __BindgenUnionField, pub bindgen_union_field: [u32; 0usize], } ...

Note that bpf_prog__bindgen_ty_1 is a struct rather than a union and its fields are bindgen wrappers. This happens even in the presence of --default-non-copy-union-style manually_drop. This arises from

| if layout.is_some_and(|l| l.size == 0) { | | -------------------------------------------- | | return (false, false); | | } |

Removing that check generates what I expect:

#[repr(C)] pub struct bpf_prog { ... pub __bindgen_anon_1: bpf_prog__bindgen_ty_1, } #[repr(C)] pub union bpf_prog__bindgen_ty_1 { pub __bindgen_anon_1: ::core::mem::ManuallyDrop, pub __bindgen_anon_2: ::core::mem::ManuallyDrop, } ...

This condition was introduced in 8ac787a but it's not clear to me why. Perhaps this was meant to deal with the fact that unions without any fields are not accepted by the compiler?

cc @emilio