Skip to content

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

Open
@tamird

Description

@tamird

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

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<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 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    rust-for-linuxIssues relevant to the Rust for Linux project

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions