Skip to content

no_copy, no_hash, no_partialeq are ignored #3168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
gabi-250 opened this issue Feb 28, 2025 · 1 comment
Open

no_copy, no_hash, no_partialeq are ignored #3168

gabi-250 opened this issue Feb 28, 2025 · 1 comment

Comments

@gabi-250
Copy link

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
Copy link
Author

gabi-250 commented Mar 6, 2025

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant