Skip to content

Support deriving copy for large array #874

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ impl<'a> CanDeriveCopy<'a> for Type {
fn can_derive_copy(&self, ctx: &BindgenContext, item: &Item) -> bool {
match self.kind {
TypeKind::Array(t, len) => {
len <= RUST_DERIVE_IN_ARRAY_LIMIT &&
len > 0 &&
t.can_derive_copy_in_array(ctx, ())
}
TypeKind::ResolvedTypeRef(t) |
Expand Down
4 changes: 4 additions & 0 deletions tests/expectations/tests/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl <T> ::std::fmt::Debug for __BindgenUnionField<T> {
}
}
#[repr(C)]
#[derive(Copy)]
pub struct C {
pub a: ::std::os::raw::c_int,
pub big_array: [::std::os::raw::c_char; 33usize],
Expand All @@ -82,6 +83,9 @@ fn bindgen_test_layout_C() {
"Alignment of field: " , stringify ! ( C ) , "::" , stringify
! ( big_array ) ));
}
impl Clone for C {
fn clone(&self) -> Self { *self }
}
impl Default for C {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down
5 changes: 1 addition & 4 deletions tests/expectations/tests/issue-643-inner-struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl <T> ::std::clone::Clone for __IncompleteArrayField<T> {
}
impl <T> ::std::marker::Copy for __IncompleteArrayField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
#[derive(Debug)]
pub struct rte_ring {
pub memzone: *mut rte_memzone,
pub prod: rte_ring_prod,
Expand Down Expand Up @@ -92,9 +92,6 @@ fn bindgen_test_layout_rte_ring() {
assert_eq! (::std::mem::align_of::<rte_ring>() , 8usize , concat ! (
"Alignment of " , stringify ! ( rte_ring ) ));
}
impl Clone for rte_ring {
fn clone(&self) -> Self { *self }
}
impl Default for rte_ring {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down
5 changes: 1 addition & 4 deletions tests/expectations/tests/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl <T> ::std::clone::Clone for __IncompleteArrayField<T> {
}
impl <T> ::std::marker::Copy for __IncompleteArrayField<T> { }
#[repr(C, packed)]
#[derive(Debug, Default, Copy)]
Copy link
Contributor Author

@WiSaGaN WiSaGaN Aug 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually bindgen derived Copy for incomplete array even before this change. The reason some of the structs with incomplete array in previous tests have not been deriving Copy is that they also contain large arrays...
This will disallow previous allowed deriving of Copy though if it contains an incomplete array.
So this pull requests now actually makes two conceptually different changes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then this was a pretty egregious bug; pretty sad we didn't catch that :(

Definitely shouldn't be deriving Copy for incomplete arrays, as we have no idea what the correct thing to do in the scenario is...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we could discern incomplete arrays vs zero-sized arrays that get used as a field separator, but seems safer to just avoid it for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think before variable length array (the name used for incomplete array) gets into C99, zero-sized array is used as a hack to achieve the same effect? If so, maybe we should not assume zero-sized array is not used as incomplete array?

#[derive(Debug, Default)]
pub struct header {
pub proto: ::std::os::raw::c_char,
pub size: ::std::os::raw::c_uint,
Expand All @@ -50,6 +50,3 @@ fn bindgen_test_layout_header() {
assert_eq!(::std::mem::size_of::<header>() , 16usize , concat ! (
"Size of: " , stringify ! ( header ) ));
}
impl Clone for header {
fn clone(&self) -> Self { *self }
}
5 changes: 1 addition & 4 deletions tests/expectations/tests/layout_align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl <T> ::std::clone::Clone for __IncompleteArrayField<T> {
}
impl <T> ::std::marker::Copy for __IncompleteArrayField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
#[derive(Debug)]
pub struct rte_kni_fifo {
/// < Next position to be written
pub write: ::std::os::raw::c_uint,
Expand All @@ -59,9 +59,6 @@ fn bindgen_test_layout_rte_kni_fifo() {
assert_eq! (::std::mem::align_of::<rte_kni_fifo>() , 8usize , concat ! (
"Alignment of " , stringify ! ( rte_kni_fifo ) ));
}
impl Clone for rte_kni_fifo {
fn clone(&self) -> Self { *self }
}
impl Default for rte_kni_fifo {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down
16 changes: 16 additions & 0 deletions tests/expectations/tests/layout_eth_conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ pub enum rte_eth_nb_pools {
/// A default pool may be used, if desired, to route all traffic which
/// does not match the vlan filter rules.
#[repr(C)]
#[derive(Copy)]
pub struct rte_eth_vmdq_dcb_conf {
/// < With DCB, 16 or 32 pools
pub nb_queue_pools: rte_eth_nb_pools,
Expand Down Expand Up @@ -814,6 +815,9 @@ fn bindgen_test_layout_rte_eth_vmdq_dcb_conf() {
"Alignment of field: " , stringify ! ( rte_eth_vmdq_dcb_conf )
, "::" , stringify ! ( dcb_tc ) ));
}
impl Clone for rte_eth_vmdq_dcb_conf {
fn clone(&self) -> Self { *self }
}
impl Default for rte_eth_vmdq_dcb_conf {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down Expand Up @@ -941,6 +945,7 @@ impl Default for rte_eth_vmdq_tx_conf {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
#[derive(Copy)]
pub struct rte_eth_vmdq_rx_conf {
/// < VMDq only mode, 8 or 64 pools
pub nb_queue_pools: rte_eth_nb_pools,
Expand Down Expand Up @@ -1036,6 +1041,9 @@ fn bindgen_test_layout_rte_eth_vmdq_rx_conf() {
"Alignment of field: " , stringify ! ( rte_eth_vmdq_rx_conf )
, "::" , stringify ! ( pool_map ) ));
}
impl Clone for rte_eth_vmdq_rx_conf {
fn clone(&self) -> Self { *self }
}
impl Default for rte_eth_vmdq_rx_conf {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down Expand Up @@ -1458,6 +1466,7 @@ impl Clone for rte_intr_conf {
/// Depending upon the RX multi-queue mode, extra advanced
/// configuration settings may be needed.
#[repr(C)]
#[derive(Copy)]
pub struct rte_eth_conf {
/// < bitmap of ETH_LINK_SPEED_XXX of speeds to be
/// used. ETH_LINK_SPEED_FIXED disables link
Expand Down Expand Up @@ -1490,6 +1499,7 @@ pub struct rte_eth_conf {
pub intr_conf: rte_intr_conf,
}
#[repr(C)]
#[derive(Copy)]
pub struct rte_eth_conf__bindgen_ty_1 {
/// < Port RSS configuration
pub rss_conf: rte_eth_rss_conf,
Expand Down Expand Up @@ -1531,6 +1541,9 @@ fn bindgen_test_layout_rte_eth_conf__bindgen_ty_1() {
rte_eth_conf__bindgen_ty_1 ) , "::" , stringify ! (
vmdq_rx_conf ) ));
}
impl Clone for rte_eth_conf__bindgen_ty_1 {
fn clone(&self) -> Self { *self }
}
impl Default for rte_eth_conf__bindgen_ty_1 {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down Expand Up @@ -1625,6 +1638,9 @@ fn bindgen_test_layout_rte_eth_conf() {
"Alignment of field: " , stringify ! ( rte_eth_conf ) , "::" ,
stringify ! ( intr_conf ) ));
}
impl Clone for rte_eth_conf {
fn clone(&self) -> Self { *self }
}
impl Default for rte_eth_conf {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
4 changes: 0 additions & 4 deletions tests/expectations/tests/layout_large_align_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ impl Default for ip_frag_tbl_stat {
}
/// fragmentation table
#[repr(C)]
#[derive(Copy)]
pub struct rte_ip_frag_tbl {
/// < ttl for table entries.
pub max_cycles: u64,
Expand Down Expand Up @@ -403,9 +402,6 @@ fn bindgen_test_layout_rte_ip_frag_tbl() {
"Alignment of field: " , stringify ! ( rte_ip_frag_tbl ) ,
"::" , stringify ! ( pkt ) ));
}
impl Clone for rte_ip_frag_tbl {
fn clone(&self) -> Self { *self }
}
impl Default for rte_ip_frag_tbl {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down
4 changes: 0 additions & 4 deletions tests/expectations/tests/layout_mbuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ impl Clone for rte_atomic16_t {
}
/// The generic rte_mbuf, containing a packet mbuf.
#[repr(C)]
#[derive(Copy)]
pub struct rte_mbuf {
pub cacheline0: MARKER,
/// < Virtual address of segment buffer.
Expand Down Expand Up @@ -1078,9 +1077,6 @@ fn bindgen_test_layout_rte_mbuf() {
"Alignment of field: " , stringify ! ( rte_mbuf ) , "::" ,
stringify ! ( timesync ) ));
}
impl Clone for rte_mbuf {
fn clone(&self) -> Self { *self }
}
impl Default for rte_mbuf {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand Down
8 changes: 8 additions & 0 deletions tests/expectations/tests/struct_with_derive_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ impl Clone for LittleArray {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Copy)]
pub struct BigArray {
pub a: [::std::os::raw::c_int; 33usize],
}
Expand All @@ -40,6 +41,9 @@ fn bindgen_test_layout_BigArray() {
"Alignment of field: " , stringify ! ( BigArray ) , "::" ,
stringify ! ( a ) ));
}
impl Clone for BigArray {
fn clone(&self) -> Self { *self }
}
impl Default for BigArray {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
Expand All @@ -64,6 +68,7 @@ impl Clone for WithLittleArray {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Copy)]
pub struct WithBigArray {
pub a: BigArray,
}
Expand All @@ -79,6 +84,9 @@ fn bindgen_test_layout_WithBigArray() {
"Alignment of field: " , stringify ! ( WithBigArray ) , "::" ,
stringify ! ( a ) ));
}
impl Clone for WithBigArray {
fn clone(&self) -> Self { *self }
}
impl Default for WithBigArray {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
37 changes: 37 additions & 0 deletions tests/expectations/tests/struct_with_large_array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Copy)]
pub struct S {
pub large_array: [::std::os::raw::c_char; 33usize],
}
#[test]
fn bindgen_test_layout_S() {
assert_eq!(::std::mem::size_of::<S>() , 33usize , concat ! (
"Size of: " , stringify ! ( S ) ));
assert_eq! (::std::mem::align_of::<S>() , 1usize , concat ! (
"Alignment of " , stringify ! ( S ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const S ) ) . large_array as * const _ as usize
} , 0usize , concat ! (
"Alignment of field: " , stringify ! ( S ) , "::" , stringify
! ( large_array ) ));
}
impl Clone for S {
fn clone(&self) -> Self { *self }
}
impl Default for S {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
#[repr(C)]
pub struct ST<T> {
pub large_array: [T; 33usize],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so why did this suddenly start working? There have been multiple refactors of the derive debug code, @fitzgen, do you know which one could cause this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emilio I'm unsure what "this" that suddenly started working is? We aren't deriving Debug here, which it seems like you're implying, so I am confused.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant that the length check was effectively fixing that, so it eventually became unneeded, and I wondered if you knew off-hand why :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my memory, deriving Copy was working before bindgen gained the ability to derive Debug. It may as well just be that the implementor treat all derive the same, while not knowing Copy is a special trait to the compiler in regard to large array derive. Should be able to verify this aginst the commit history, but a bit tedious...

pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
impl <T> Default for ST<T> {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
7 changes: 7 additions & 0 deletions tests/headers/struct_with_large_array.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
struct S {
char large_array[33];
};

template<typename T> struct ST {
T large_array[33];
};