rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

C union containing only flexible array members does not generate Rust union

Open tamird opened this issue 9 months ago • 1 comments

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<bpf_prog__bindgen_ty_1__bindgen_ty_1>,
    pub __bindgen_anon_2: __BindgenUnionField<bpf_prog__bindgen_ty_1__bindgen_ty_2>,
    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 https://github.com/rust-lang/rust-bindgen/blob/59a43e10b758bd86275aefceae29e874157087d8/bindgen/ir/comp.rs#L1756-L1758

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<bpf_prog__bindgen_ty_1__bindgen_ty_1>,
    pub __bindgen_anon_2: ::core::mem::ManuallyDrop<bpf_prog__bindgen_ty_1__bindgen_ty_2>,
}
...

This condition was introduced in https://github.com/rust-lang/rust-bindgen/commit/8ac787a9b4fab937533b964a3ee8d0bff840bf08 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

tamird avatar Feb 15 '25 03:02 tamird

I suggest providing expanded code; otherwise, the maintainers need to figure out what this may be referring to. For instance, from my comment https://github.com/Rust-for-Linux/linux/issues/1137#issuecomment-2596194034, reduced from struct bpf_array:

struct bpf_array {
    union {
        struct {
            struct {} __empty_value;
            char value[];
        };
    };
};

Related: https://github.com/Rust-for-Linux/linux/issues/1137 Related: https://github.com/Richardhongyu/rfl_empirical_tools/issues/1 Cc @pvdrz

ojeda avatar Feb 15 '25 19:02 ojeda