rust-lang / rust-lang/rust-bindgen

Nested packed struct containing incomplete array declaration results in compilation failure due to non-present Debug impl

Open
#3,341 0 comments 1 reaction 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

example.h:

struct nested_struct {
  char *name;
  unsigned char more_data[];
} __attribute__((packed));

struct {
  struct nested_struct meow;
} cat;

After running bindgen -o example.rs example.h, we get

/* automatically generated by rust-bindgen 0.72.1 */

#[repr(C)]
#[derive(Default)]
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>, [T; 0]);
impl<T> __IncompleteArrayField<T> {
    #[inline]
    pub const fn new() -> Self {
        __IncompleteArrayField(::std::marker::PhantomData, [])
    }
    #[inline]
    pub fn as_ptr(&self) -> *const T {
        self as *const _ as *const T
    }
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T {
        self as *mut _ as *mut T
    }
    #[inline]
    pub unsafe fn as_slice(&self, len: usize) -> &[T] {
        ::std::slice::from_raw_parts(self.as_ptr(), len)
    }
    #[inline]
    pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
        ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
    }
}
impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
        fmt.write_str("__IncompleteArrayField")
    }
}
#[repr(C, packed)]
pub struct nested_struct {
    pub name: *mut ::std::os::raw::c_char,
    pub more_data: __IncompleteArrayField<::std::os::raw::c_uchar>,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of nested_struct"][::std::mem::size_of::<nested_struct>() - 8usize];
    ["Alignment of nested_struct"][::std::mem::align_of::<nested_struct>() - 1usize];
    ["Offset of field: nested_struct::name"][::std::mem::offset_of!(nested_struct, name) - 0usize];
    ["Offset of field: nested_struct::more_data"]
        [::std::mem::offset_of!(nested_struct, more_data) - 8usize];
};
#[repr(C)]
#[derive(Debug)]
pub struct _bindgen_ty_1 {
    pub meow: nested_struct,
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
    ["Size of _bindgen_ty_1"][::std::mem::size_of::<_bindgen_ty_1>() - 8usize];
    ["Alignment of _bindgen_ty_1"][::std::mem::align_of::<_bindgen_ty_1>() - 1usize];
    ["Offset of field: _bindgen_ty_1::meow"][::std::mem::offset_of!(_bindgen_ty_1, meow) - 0usize];
};
unsafe extern "C" {
    pub static mut cat: _bindgen_ty_1;
}

Trying to compile example.rs with rustc --crate-type staticlib -A nonstandard_style example.rs produces

error[E0277]: `nested_struct` doesn't implement `Debug`
  --> example_manual.rs:49:5
   |
47 | #[derive(Debug)]
   |          ----- in this derive macro expansion
48 | pub struct _bindgen_ty_1 {
49 |     pub meow: nested_struct,
   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `nested_struct`
   |
   = note: add `#[derive(Debug)]` to `nested_struct` or manually `impl Debug for nested_struct`
help: consider annotating `nested_struct` with `#[derive(Debug)]`
   |
34 + #[derive(Debug)]
35 | pub struct nested_struct {
   |

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.

It seems like the combination of the incomplete array field and the struct nesting results in a #[derive(Debug)] line being incorrectly generated for the anonymous struct even though nested_struct lacks it.

Tested with bindgen 0.72.1 and master (74a5f30c14769891e12de53ba275233ef2616819 as of the time of writing) using Rust 1.93

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 example.h and reproduce the generated example.rs using bindgen 0.72.1 or master, then compile it with the reported rustc command. Inspect the generated derives for nested_struct and _bindgen_ty_1; done means the binding compiles without the incorrect Debug requirement while preserving the reported layout checks.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, rust
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.