rust-lang / rust-lang/rust-bindgen

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

Open
#3,168 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Rust enum-generation path behind Builder::no_copy, no_hash, and no_partialeq, using the provided netlink.h and main.rs reproducer. Check how these options interact with EnumVariation::Rust and ParseCallbacks::add_attributes; done means the generated sinf_command has none of the unwanted derives while callback-added attributes remain possible.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.