rust-lang / rust-lang/rust-bindgen

Derive analysis manual selection is too conservative

Open
#2,005 0 comments 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

Input C/C++ Header
typedef struct {
    int (*foo) (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13);
} a;

typedef struct {
    int foo[4096];
} b;

typedef struct {
    a a;
    b b;
} combined;
Bindgen Invocation
bindgen::Builder::default()
    .header("input.h")
    .trust_clang_mangling(false)
    .derive_copy(false)
    .derive_debug(true)
    .impl_debug(true)
    .derive_default(true)
    .layout_tests(false)
    .generate()
    .unwrap()
Actual Results

I'm omitting output for struct a and struct b but please note that they do already implement Debug and Default.

#[repr(C)]
pub struct combined {
    pub a: a,
    pub b: b,
}
impl Default for combined {
    fn default() -> Self {
        unsafe { ::std::mem::zeroed() }
    }
}
impl ::std::fmt::Debug for combined {
    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        write!(f, "combined {{ a: {:?}, b: {:?} }}", self.a, self.b)
    }
}
Expected Results

Since struct a and struct b do get a manual implementation of Debug and Default, it should just be possible to derive them for struct combined. However, a manual implementation is generated by bindgen instead of just doing:

#[repr(C)]
#[derive(Debug, Default)]
pub struct combined {
    pub a: a,
    pub b: b,
}
Cause

The monotone constraint analysis for derive is too conservative. CanDerive::Manually means both that a type needs a manual implementation of a trait, as well as that the type, when included as a member of another type, requires manual implementations of a trait in the containing type. Since we use this one value to mean both things, if a type needs manual implementation due to one of its members, that is then automatically interpreted as that type triggering manual implementation in its containing types as well.

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 at the bindgen::Builder invocation and trace derive analysis for combined, including its a and b fields. Done means generated combined can use #[derive(Debug, Default)] when those member types have manual implementations, without incorrectly forcing a manual implementation in the containing type; verify the behavior with the supplied C++ header.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, rust
Domain
compilers, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.