rust-lang / rust-lang/rust-bindgen

Packed structures with 0-sized arrays are not deriving clone/copy

Open
#1,333 3 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

I think bindgen does this for any packed struct that doesn't contain a 0-sized array.

Input C/C++ Header
// test.h
#ifdef __cplusplus
extern "C" {
#endif

typedef struct {

        unsigned char data[0];

       // rustc will not complain about the generating bindings if the struct is "0-sized"
        unsigned short more_data;

}__attribute__((packed)) test_struct;


#ifdef __cplusplus
}
#endif

Bindgen Invocation
let bindings = bindgen::builder()
    .header("test.h")
    .generate()
    .unwrap();
Actual Results

Generated bindings:

 1  /* automatically generated by rust-bindgen */
 2
 3  #[repr(C)]
 4  #[derive(Default)]
 5  pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
 6  impl<T> __IncompleteArrayField<T> {
 7      #[inline]
 8      pub fn new() -> Self {
 9          __IncompleteArrayField(::std::marker::PhantomData)
10      }
11      #[inline]
12      pub unsafe fn as_ptr(&self) -> *const T {
13          ::std::mem::transmute(self)
14      }
15      #[inline]
16      pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
17          ::std::mem::transmute(self)
18      }
19      #[inline]
20      pub unsafe fn as_slice(&self, len: usize) -> &[T] {
21          ::std::slice::from_raw_parts(self.as_ptr(), len)
22      }
23      #[inline]
24      pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
25          ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
26      }
27  }
28  impl<T> ::std::fmt::Debug for __IncompleteArrayField<T> {
29      fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
30          fmt.write_str("__IncompleteArrayField")
31      }
32  }
33  impl<T> ::std::clone::Clone for __IncompleteArrayField<T> {
34      #[inline]
35      fn clone(&self) -> Self {
36          Self::new()
37      }
38  }
39  impl<T> ::std::marker::Copy for __IncompleteArrayField<T> {}
40  #[repr(C, packed)]
41  #[derive(Debug)]
42  pub struct test_struct {
43      pub data: __IncompleteArrayField<::std::os::raw::c_uchar>,
44      pub more_data: ::std::os::raw::c_ushort,
45  }
46 // removed test

Rust warning about this

  --> src/bindings.rs:41:10
   |
41 | #[derive(Debug)]
   |          ^^^^^
   |
   = note: #[warn(safe_packed_borrows)] on by default
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
Expected Results

test_struct should derive both clone & copy to get rid of the safe_packed_borrows rustc warning

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

Reproduce the issue with the test.h header and the bindgen::Builder invocation, then inspect the generated src/bindings.rs output for test_struct. Confirm that the packed structure derives Clone and Copy and that the safe_packed_borrows warning no longer appears.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, cpp, rust
Domain
build-system, devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 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.