Skip to content

Commit

Permalink
Let Rust derive everything but Default for large arrays in 1.47 and l…
Browse files Browse the repository at this point in the history
…ater

Fixes #1977 as of rust-lang/rust#74060 is available since Rust 1.47
Fixes #2041.
Closes #2070.
  • Loading branch information
Ian P. Cooke authored and emilio committed Jul 16, 2021
1 parent f65f230 commit a380678
Show file tree
Hide file tree
Showing 35 changed files with 135 additions and 43 deletions.
4 changes: 3 additions & 1 deletion src/codegen/impl_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,9 @@ impl<'a> ImplDebug<'a> for Item {
format!("{}: Array with length {}", name, len),
vec![],
))
} else if len < RUST_DERIVE_IN_ARRAY_LIMIT {
} else if len < RUST_DERIVE_IN_ARRAY_LIMIT ||
ctx.options().rust_features().larger_arrays
{
// The simple case
debug_print(name, quote! { #name_ident })
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/codegen/impl_partialeq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ fn gen_field(
}

TypeKind::Array(_, len) => {
if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
if len <= RUST_DERIVE_IN_ARRAY_LIMIT ||
ctx.options().rust_features().larger_arrays
{
quote_equals(name_ident)
} else {
quote! {
Expand Down
7 changes: 5 additions & 2 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,8 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {

// We cannot generate any constructor if the underlying storage can't
// implement AsRef<[u8]> / AsMut<[u8]> / etc.
let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT;
let mut generate_ctor = layout.size <= RUST_DERIVE_IN_ARRAY_LIMIT ||
ctx.options().rust_features().larger_arrays;

let mut access_spec = !fields_should_be_private;
for bf in self.bitfields() {
Expand All @@ -1512,7 +1513,9 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
continue;
}

if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT {
if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT &&
!ctx.options().rust_features().larger_arrays
{
continue;
}

Expand Down
8 changes: 7 additions & 1 deletion src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ macro_rules! rust_target_base {
/// Rust stable 1.40
/// * `non_exhaustive` enums/structs ([Tracking issue](https://github.com/rust-lang/rust/issues/44109))
=> Stable_1_40 => 1.40;
/// Rust stable 1.47
/// * `larger_arrays` ([Tracking issue](https://github.com/rust-lang/rust/pull/74060))
=> Stable_1_47 => 1.47;
/// Nightly rust
/// * `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
=> Nightly => nightly;
Expand All @@ -134,7 +137,7 @@ rust_target_base!(rust_target_def);
rust_target_base!(rust_target_values_def);

/// Latest stable release of Rust
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_40;
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_47;

/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules! rust_feature_def {
Expand Down Expand Up @@ -222,6 +225,9 @@ rust_feature_def!(
Stable_1_40 {
=> non_exhaustive;
}
Stable_1_47 {
=> larger_arrays;
}
Nightly {
=> thiscall_abi;
}
Expand Down
21 changes: 14 additions & 7 deletions src/ir/analysis/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ impl<'ctx> CannotDerive<'ctx> {
return CanDerive::No;
}

if self.derive_trait.can_derive_large_array() {
if self.derive_trait.can_derive_large_array(&self.ctx) {
trace!(" array can derive {}", self.derive_trait);
return CanDerive::Yes;
}
Expand Down Expand Up @@ -377,7 +377,7 @@ impl<'ctx> CannotDerive<'ctx> {
// Bitfield units are always represented as arrays of u8, but
// they're not traced as arrays, so we need to check here
// instead.
if !self.derive_trait.can_derive_large_array() &&
if !self.derive_trait.can_derive_large_array(&self.ctx) &&
info.has_too_large_bitfield_unit() &&
!item.is_opaque(self.ctx, &())
{
Expand Down Expand Up @@ -496,10 +496,17 @@ impl DeriveTrait {
}
}

fn can_derive_large_array(&self) -> bool {
match self {
DeriveTrait::Copy => true,
_ => false,
fn can_derive_large_array(&self, ctx: &BindgenContext) -> bool {
if ctx.options().rust_features().larger_arrays {
match self {
DeriveTrait::Default => false,
_ => true,
}
} else {
match self {
DeriveTrait::Copy => true,
_ => false,
}
}
}

Expand Down Expand Up @@ -686,7 +693,7 @@ impl<'ctx> MonotoneFramework for CannotDerive<'ctx> {
Some(ty) => {
let mut can_derive = self.constrain_type(item, ty);
if let CanDerive::Yes = can_derive {
if !self.derive_trait.can_derive_large_array() &&
if !self.derive_trait.can_derive_large_array(&self.ctx) &&
ty.layout(self.ctx).map_or(false, |l| {
l.align > RUST_DERIVE_IN_ARRAY_LIMIT
})
Expand Down
1 change: 0 additions & 1 deletion src/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ pub struct Type {
/// traits, and so if we have a type containing an array with more than this
/// many items, we won't be able to derive common traits on that type.
///
/// We need type-level integers yesterday :'(
pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;

impl Type {
Expand Down
61 changes: 61 additions & 0 deletions tests/expectations/tests/issue-1977-larger-arrays.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
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 {
&(*(::std::ptr::null::<S>())).large_array as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(S),
"::",
stringify!(large_array)
)
);
}
impl Default for S {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
#[repr(C)]
#[derive(Debug, Hash, PartialEq, Eq)]
pub struct ST<T> {
pub large_array: [T; 33usize],
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
impl<T> Default for ST<T> {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
unsafe {
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
s.assume_init()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
)]

/// We emit a `[u8; 63usize]` padding field for this struct, which cannot derive
/// Debug/Hash because 63 is over the hard coded limit. (Yes, this struct doesn't end
/// up with the reight alignment, we're waiting on `#[repr(align="N")]` to land
/// in rustc).
/// Debug/Hash because 63 is over the hard coded limit.
#[repr(C)]
#[repr(align(64))]
#[derive(Copy, Clone)]
Expand Down Expand Up @@ -55,7 +53,7 @@ impl ::std::cmp::PartialEq for NoDebug {
/// This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive
/// Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because
/// we determine Debug derive-ability before we compute padding, which happens at
/// codegen. (Again, we expect to get the alignment wrong for similar reasons.)
/// codegen.
#[repr(C)]
#[repr(align(64))]
#[derive(Copy, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/class.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --with-derive-partialord --with-derive-ord
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --with-derive-partialord --with-derive-ord --rust-target 1.40
//
class C {
int a;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-bitfield-method-same-name.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-partialeq --impl-partialeq --impl-debug
// bindgen-flags: --with-derive-partialeq --impl-partialeq --impl-debug --rust-target 1.40

/// Because this struct have array larger than 32 items
/// and --with-derive-partialeq --impl-partialeq --impl-debug is provided,
Expand Down
2 changes: 2 additions & 0 deletions tests/headers/derive-clone.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// bindgen-flags: --rust-target 1.40
//

/// This struct should derive `Clone`.
struct ShouldDeriveClone {
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-debug-bitfield-core.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --impl-debug --use-core --raw-line "extern crate core;"
// bindgen-flags: --impl-debug --use-core --raw-line "extern crate core;" --rust-target 1.40

class C {
bool a: 1;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-debug-bitfield.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --impl-debug
// bindgen-flags: --impl-debug --rust-target 1.40

class C {
bool a: 1;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-debug-function-pointer.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --impl-debug
// bindgen-flags: --impl-debug --rust-target 1.40

class Nice {
typedef void (*Function) (int data);
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-debug-generic.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --impl-debug
// bindgen-flags: --impl-debug --rust-target 1.40

template<typename T>
class Generic {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --impl-debug
// bindgen-flags: --impl-debug --rust-target 1.40

// This type is opaque because the second template parameter
// is a non-type template parameter
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-debug-opaque.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --opaque-type "Opaque" --impl-debug
// bindgen-flags: --opaque-type "Opaque" --impl-debug --rust-target 1.40

class Opaque {
int i;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-partialeq-base.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-partialeq --impl-partialeq
// bindgen-flags: --with-derive-partialeq --impl-partialeq --rust-target 1.40

class Base {
int large[33];
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-partialeq-bitfield.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-partialeq --impl-partialeq
// bindgen-flags: --with-derive-partialeq --impl-partialeq --rust-target 1.40

class C {
bool a: 1;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/derive-partialeq-core.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-partialeq --impl-partialeq --use-core --raw-line "extern crate core;"
// bindgen-flags: --with-derive-partialeq --impl-partialeq --use-core --raw-line "extern crate core;" --rust-target 1.40

struct C {
int large_array[420];
Expand Down
2 changes: 2 additions & 0 deletions tests/headers/extern-const-struct.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// bindgen-flags: --rust-target 1.40

struct nsFoo {
float details[400];
};
Expand Down
9 changes: 9 additions & 0 deletions tests/headers/issue-1977-larger-arrays.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
//
struct S {
char large_array[33];
};

template<typename T> struct ST {
T large_array[33];
};
2 changes: 1 addition & 1 deletion tests/headers/issue-372.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --enable-cxx-namespaces --rustified-enum ".*"
// bindgen-flags: --enable-cxx-namespaces --rustified-enum ".*" --rust-target 1.40
template <typename a, int b> class c { a e[b]; };
class d;
template <typename g, g f> class C { c<d, f> h; };
Expand Down
8 changes: 3 additions & 5 deletions tests/headers/issue-648-derive-debug-with-padding.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rust-target 1.40
/**
* We emit a `[u8; 63usize]` padding field for this struct, which cannot derive
* Debug/Hash because 63 is over the hard coded limit. (Yes, this struct doesn't end
* up with the reight alignment, we're waiting on `#[repr(align="N")]` to land
* in rustc).
* Debug/Hash because 63 is over the hard coded limit.
*/
struct NoDebug {
char c;
Expand All @@ -14,7 +12,7 @@ struct NoDebug {
* This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive
* Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because
* we determine Debug derive-ability before we compute padding, which happens at
* codegen. (Again, we expect to get the alignment wrong for similar reasons.)
* codegen.
*/
struct ShouldDeriveDebugButDoesNot {
char c[32];
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/layout_array.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rust-target 1.40
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/layout_array_too_long.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rustified-enum ".*"
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rustified-enum ".*" --rust-target 1.40
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/layout_eth_conf.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*"
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" --rust-target 1.40
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
Expand Down
1 change: 1 addition & 0 deletions tests/headers/layout_kni_mbuf.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// bindgen-flags: --rust-target 1.40

#define RTE_CACHE_LINE_MIN_SIZE 64 /**< Minimum Cache line size. */

Expand Down
2 changes: 1 addition & 1 deletion tests/headers/layout_large_align_field.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --rustified-enum ".*"
// bindgen-flags: --rustified-enum ".*" --rust-target 1.40

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/no_debug_bypass_impl_debug.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --no-debug "NoDebug" --impl-debug
// bindgen-flags: --no-debug "NoDebug" --impl-debug --rust-target 1.40

template<typename T>
class Generic {
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/no_default_bypass_derive_default.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --no-default "NoDefault"
// bindgen-flags: --no-default "NoDefault" --rust-target 1.40

template<typename T>
class Generic {
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/opaque-template-inst-member.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --opaque-type 'OpaqueTemplate' --with-derive-hash --with-derive-partialeq --impl-partialeq --with-derive-eq
// bindgen-flags: --opaque-type 'OpaqueTemplate' --with-derive-hash --with-derive-partialeq --impl-partialeq --with-derive-eq --rust-target 1.40

template<typename T>
class OpaqueTemplate {
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/struct_with_derive_debug.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rust-target 1.40
//
struct LittleArray {
int a[32];
Expand Down
2 changes: 1 addition & 1 deletion tests/headers/struct_with_large_array.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rust-target 1.40
//
struct S {
char large_array[33];
Expand Down
2 changes: 2 additions & 0 deletions tests/headers/timex.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// bindgen-flags: --rust-target 1.40

struct timex {
int tai;

Expand Down

0 comments on commit a380678

Please sign in to comment.