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

`no_copy`, `no_hash`, `no_partialeq` are ignored

Open gabi-250 opened this issue 9 months ago • 1 comments

I am trying to generate bindings for a C enum, and make the resulting Rust type not derive Copy, Clone, Hash, PartialEq, Eq:

/* netlink.h */

#ifndef _SINF_NETLINK_H
#define _SINF_NETLINK_H

enum sinf_command {
        SINF_C_UNSPEC,
        SINF_C_GET,
};

#endif /* _SINF_NETLINK_H */

I tried using no_copy, no_hash etc, but they don't seem to work. Here is a small example that reproduces my issue:

/* main.rs */

use bindgen::callbacks::ParseCallbacks;
use bindgen::EnumVariation;

/// Helper for applying custom attributes to enums.
#[derive(Debug)]
struct NeliEnum;

impl ParseCallbacks for NeliEnum {
    /*
    fn add_attributes(&self, _info: &AttributeInfo<'_>) -> Vec<String> {
        // I want to apply neli::neli_enum, which derives Copy, Clone, etc.,
        // so I need to prevent bindgen from deriving them too.
        vec!["#[neli::neli_enum(serialized_type = \"u8\")]".into()]
    }
    */
}

fn main() {
    let bindings = bindgen::Builder::default()
        .default_enum_style(EnumVariation::Rust { non_exhaustive: false })
        .parse_callbacks(Box::new(NeliEnum))
        .header("./netlink.h")
        // This works
        .no_debug(".*")
        // This doesn't work quite as advertised: the docs say
        // this will suppress both Copy and Clone, but in this case,
        // it looks like it only suppresses Copy?
        .no_copy(".*")
        // Does not work, Hash is still derived for sinf_command
        .no_hash(".*")
        // Does not work, PartialEq is still derived for sinf_command
        .no_partialeq(".*")
        .generate()
        .expect("Unable to generate bindings");

    bindings
        .write_to_file("./src/netlink.rs")
        .expect("Couldn't write bindings!");
}

My Cargo.toml is:

[package]
name = "sinf"
version = "0.1.0"
edition = "2024"

[dependencies]
bindgen = "0.71.0"

Expected output

/* automatically generated by rust-bindgen 0.71.1 */

#[repr(u32)]
pub enum sinf_command {
    SINF_C_UNSPEC = 0,
    SINF_C_GET = 1,
}

Actual output

/* automatically generated by rust-bindgen 0.71.1 */

#[repr(u32)]
#[derive(Clone, Hash, PartialEq, Eq)]
pub enum sinf_command {
    SINF_C_UNSPEC = 0,
    SINF_C_GET = 1,
}

I am also confused by the derive_hash, etc. docs, which seem to suggest these traits shouldn't have been derived at all:

Set whether the Hash trait should be derived when possible.

Hash is not derived by default.

Are the docs wrong, or is this a separate bug? Or am I somehow misinterpreting them?


For context, I'm trying to generate bindings for some netlink types that are shared between a kernel module and my userspace application.

gabi-250 avatar Feb 28 '25 12:02 gabi-250

Ah, looks like this is by design. I think it's worth updating the builder docs to mention that some of these derives can't be disabled for enums.

Would you be open to adding a way to override this behavior?

gabi-250 avatar Mar 06 '25 00:03 gabi-250