Skip to content

Failed to generate Default impl for arrays larger than 32 entries #2803

Open

Description

Input C/C++ Header

#define CCHDEVICENAME 32
typedef long LONG;
typedef char CHAR;
typedef unsigned long DWORD;

typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT;
typedef struct tagMONITORINFO
{
    DWORD   cbSize;
    RECT    rcMonitor;
    RECT    rcWork;
    DWORD   dwFlags;
} MONITORINFO, *LPMONITORINFO;
typedef struct tagMONITORINFOEXA
{
    MONITORINFO;
    CHAR        szDevice[CCHDEVICENAME];
} MONITORINFOEXA, *LPMONITORINFOEXA;
        

Bindgen Invocation

use std::env;
use std::path::PathBuf;

fn main() {

    let bindings = bindgen::Builder::default()
        .header_contents(
            "input.h",
            r#"
#define CCHDEVICENAME 32
typedef long LONG;
typedef char CHAR;
typedef unsigned long DWORD;

typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT;
typedef struct tagMONITORINFO
{
    DWORD   cbSize;
    RECT    rcMonitor;
    RECT    rcWork;
    DWORD   dwFlags;
} MONITORINFO, *LPMONITORINFO;
typedef struct tagMONITORINFOEXA
{
    MONITORINFO;
    CHAR        szDevice[CCHDEVICENAME];
} MONITORINFOEXA, *LPMONITORINFOEXA;"#,
        )
        .derive_default(true)
        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

Actual Results

error[E0277]: the trait bound `[u8; 40]: Default` is not satisfied
   --> D:\git-repos\bindgen-test\target\debug\build\bindgen-test-39d5729a71a2ce1c\out/bindings.rs:140:5
    |
138 | #[derive(Debug, Default, Copy, Clone)]
    |                 ------- in this derive macro expansion
139 | pub struct tagMONITORINFOEXA {
140 |     pub __bindgen_padding_0: [u8; 40usize],
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `[u8; 40]`
    |
    = help: the following other types implement trait `Default`:
              [T; 0]
              [T; 1]
              [T; 2]
              [T; 3]
              [T; 4]
              [T; 5]
              [T; 6]
              [T; 7]
            and 27 others
    = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `bindgen-test` (lib) due to 1 previous error

Caused by:
  process didn't exit successfully: `sccache rustc --crate-name bindgen_test --edition=2021 src\lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --diagnostic-width=191 --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=dfb5b3ab9206c6f2 -C extra-filename=-dfb5b3ab9206c6f2 --out-dir D:\git-repos\bindgen-test\target\debug\deps -C incremental=D:\git-repos\bindgen-test\target\debug\incremental -L dependency=D:\git-repos\bindgen-test\target\debug\deps` (exit code: 1)

and/or

/* automatically generated by rust-bindgen 0.69.4 */

pub const CCHDEVICENAME: u32 = 32;
pub type LONG = ::std::os::raw::c_long;
pub type CHAR = ::std::os::raw::c_char;
pub type DWORD = ::std::os::raw::c_ulong;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct tagRECT {
    pub left: LONG,
    pub top: LONG,
    pub right: LONG,
    pub bottom: LONG,
}
#[test]
fn bindgen_test_layout_tagRECT() {
    const UNINIT: ::std::mem::MaybeUninit<tagRECT> = ::std::mem::MaybeUninit::uninit();
    let ptr = UNINIT.as_ptr();
    assert_eq!(
        ::std::mem::size_of::<tagRECT>(),
        16usize,
        concat!("Size of: ", stringify!(tagRECT))
    );
    assert_eq!(
        ::std::mem::align_of::<tagRECT>(),
        4usize,
        concat!("Alignment of ", stringify!(tagRECT))
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).left) as usize - ptr as usize },
        0usize,
        concat!(
            "Offset of field: ",
            stringify!(tagRECT),
            "::",
            stringify!(left)
        )
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).top) as usize - ptr as usize },
        4usize,
        concat!(
            "Offset of field: ",
            stringify!(tagRECT),
            "::",
            stringify!(top)
        )
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).right) as usize - ptr as usize },
        8usize,
        concat!(
            "Offset of field: ",
            stringify!(tagRECT),
            "::",
            stringify!(right)
        )
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).bottom) as usize - ptr as usize },
        12usize,
        concat!(
            "Offset of field: ",
            stringify!(tagRECT),
            "::",
            stringify!(bottom)
        )
    );
}
pub type RECT = tagRECT;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct tagMONITORINFO {
    pub cbSize: DWORD,
    pub rcMonitor: RECT,
    pub rcWork: RECT,
    pub dwFlags: DWORD,
}
#[test]
fn bindgen_test_layout_tagMONITORINFO() {
    const UNINIT: ::std::mem::MaybeUninit<tagMONITORINFO> = ::std::mem::MaybeUninit::uninit();
    let ptr = UNINIT.as_ptr();
    assert_eq!(
        ::std::mem::size_of::<tagMONITORINFO>(),
        40usize,
        concat!("Size of: ", stringify!(tagMONITORINFO))
    );
    assert_eq!(
        ::std::mem::align_of::<tagMONITORINFO>(),
        4usize,
        concat!("Alignment of ", stringify!(tagMONITORINFO))
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).cbSize) as usize - ptr as usize },
        0usize,
        concat!(
            "Offset of field: ",
            stringify!(tagMONITORINFO),
            "::",
            stringify!(cbSize)
        )
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).rcMonitor) as usize - ptr as usize },
        4usize,
        concat!(
            "Offset of field: ",
            stringify!(tagMONITORINFO),
            "::",
            stringify!(rcMonitor)
        )
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).rcWork) as usize - ptr as usize },
        20usize,
        concat!(
            "Offset of field: ",
            stringify!(tagMONITORINFO),
            "::",
            stringify!(rcWork)
        )
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).dwFlags) as usize - ptr as usize },
        36usize,
        concat!(
            "Offset of field: ",
            stringify!(tagMONITORINFO),
            "::",
            stringify!(dwFlags)
        )
    );
}
pub type MONITORINFO = tagMONITORINFO;
pub type LPMONITORINFO = *mut tagMONITORINFO;
#[repr(C)]
#[repr(align(4))]
#[derive(Debug, Default, Copy, Clone)]
pub struct tagMONITORINFOEXA {
    pub __bindgen_padding_0: [u8; 40usize],
    pub szDevice: [CHAR; 32usize],
}
#[test]
fn bindgen_test_layout_tagMONITORINFOEXA() {
    const UNINIT: ::std::mem::MaybeUninit<tagMONITORINFOEXA> = ::std::mem::MaybeUninit::uninit();
    let ptr = UNINIT.as_ptr();
    assert_eq!(
        ::std::mem::size_of::<tagMONITORINFOEXA>(),
        72usize,
        concat!("Size of: ", stringify!(tagMONITORINFOEXA))
    );
    assert_eq!(
        ::std::mem::align_of::<tagMONITORINFOEXA>(),
        4usize,
        concat!("Alignment of ", stringify!(tagMONITORINFOEXA))
    );
    assert_eq!(
        unsafe { ::std::ptr::addr_of!((*ptr).szDevice) as usize - ptr as usize },
        40usize,
        concat!(
            "Offset of field: ",
            stringify!(tagMONITORINFOEXA),
            "::",
            stringify!(szDevice)
        )
    );
}
pub type MONITORINFOEXA = tagMONITORINFOEXA;
pub type LPMONITORINFOEXA = *mut tagMONITORINFOEXA;

Expected Results

I expected it to generate a default implementation successfully. This seems to be another regression of #1718/#1719 and #2082, where it fails to generate a valid Default when the array has more than the 32 entries (where rust itself generates a Default for <=32 entries).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions