Skip to content

Commit a380678

Browse files
Ian P. Cookeemilio
Ian P. Cooke
authored andcommitted
Let Rust derive everything but Default for large arrays in 1.47 and later
Fixes #1977 as of rust-lang/rust#74060 is available since Rust 1.47 Fixes #2041. Closes #2070.
1 parent f65f230 commit a380678

35 files changed

+135
-43
lines changed

src/codegen/impl_debug.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ impl<'a> ImplDebug<'a> for Item {
181181
format!("{}: Array with length {}", name, len),
182182
vec![],
183183
))
184-
} else if len < RUST_DERIVE_IN_ARRAY_LIMIT {
184+
} else if len < RUST_DERIVE_IN_ARRAY_LIMIT ||
185+
ctx.options().rust_features().larger_arrays
186+
{
185187
// The simple case
186188
debug_print(name, quote! { #name_ident })
187189
} else {

src/codegen/impl_partialeq.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ fn gen_field(
114114
}
115115

116116
TypeKind::Array(_, len) => {
117-
if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
117+
if len <= RUST_DERIVE_IN_ARRAY_LIMIT ||
118+
ctx.options().rust_features().larger_arrays
119+
{
118120
quote_equals(name_ident)
119121
} else {
120122
quote! {

src/codegen/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1503,7 +1503,8 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
15031503

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

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

1515-
if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT {
1516+
if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT &&
1517+
!ctx.options().rust_features().larger_arrays
1518+
{
15161519
continue;
15171520
}
15181521

src/features.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ macro_rules! rust_target_base {
123123
/// Rust stable 1.40
124124
/// * `non_exhaustive` enums/structs ([Tracking issue](https://github.com/rust-lang/rust/issues/44109))
125125
=> Stable_1_40 => 1.40;
126+
/// Rust stable 1.47
127+
/// * `larger_arrays` ([Tracking issue](https://github.com/rust-lang/rust/pull/74060))
128+
=> Stable_1_47 => 1.47;
126129
/// Nightly rust
127130
/// * `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
128131
=> Nightly => nightly;
@@ -134,7 +137,7 @@ rust_target_base!(rust_target_def);
134137
rust_target_base!(rust_target_values_def);
135138

136139
/// Latest stable release of Rust
137-
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_40;
140+
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_47;
138141

139142
/// Create RustFeatures struct definition, new(), and a getter for each field
140143
macro_rules! rust_feature_def {
@@ -222,6 +225,9 @@ rust_feature_def!(
222225
Stable_1_40 {
223226
=> non_exhaustive;
224227
}
228+
Stable_1_47 {
229+
=> larger_arrays;
230+
}
225231
Nightly {
226232
=> thiscall_abi;
227233
}

src/ir/analysis/derive.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl<'ctx> CannotDerive<'ctx> {
255255
return CanDerive::No;
256256
}
257257

258-
if self.derive_trait.can_derive_large_array() {
258+
if self.derive_trait.can_derive_large_array(&self.ctx) {
259259
trace!(" array can derive {}", self.derive_trait);
260260
return CanDerive::Yes;
261261
}
@@ -377,7 +377,7 @@ impl<'ctx> CannotDerive<'ctx> {
377377
// Bitfield units are always represented as arrays of u8, but
378378
// they're not traced as arrays, so we need to check here
379379
// instead.
380-
if !self.derive_trait.can_derive_large_array() &&
380+
if !self.derive_trait.can_derive_large_array(&self.ctx) &&
381381
info.has_too_large_bitfield_unit() &&
382382
!item.is_opaque(self.ctx, &())
383383
{
@@ -496,10 +496,17 @@ impl DeriveTrait {
496496
}
497497
}
498498

499-
fn can_derive_large_array(&self) -> bool {
500-
match self {
501-
DeriveTrait::Copy => true,
502-
_ => false,
499+
fn can_derive_large_array(&self, ctx: &BindgenContext) -> bool {
500+
if ctx.options().rust_features().larger_arrays {
501+
match self {
502+
DeriveTrait::Default => false,
503+
_ => true,
504+
}
505+
} else {
506+
match self {
507+
DeriveTrait::Copy => true,
508+
_ => false,
509+
}
503510
}
504511
}
505512

@@ -686,7 +693,7 @@ impl<'ctx> MonotoneFramework for CannotDerive<'ctx> {
686693
Some(ty) => {
687694
let mut can_derive = self.constrain_type(item, ty);
688695
if let CanDerive::Yes = can_derive {
689-
if !self.derive_trait.can_derive_large_array() &&
696+
if !self.derive_trait.can_derive_large_array(&self.ctx) &&
690697
ty.layout(self.ctx).map_or(false, |l| {
691698
l.align > RUST_DERIVE_IN_ARRAY_LIMIT
692699
})

src/ir/ty.rs

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ pub struct Type {
3939
/// traits, and so if we have a type containing an array with more than this
4040
/// many items, we won't be able to derive common traits on that type.
4141
///
42-
/// We need type-level integers yesterday :'(
4342
pub const RUST_DERIVE_IN_ARRAY_LIMIT: usize = 32;
4443

4544
impl Type {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#![allow(
2+
dead_code,
3+
non_snake_case,
4+
non_camel_case_types,
5+
non_upper_case_globals
6+
)]
7+
8+
#[repr(C)]
9+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
10+
pub struct S {
11+
pub large_array: [::std::os::raw::c_char; 33usize],
12+
}
13+
#[test]
14+
fn bindgen_test_layout_S() {
15+
assert_eq!(
16+
::std::mem::size_of::<S>(),
17+
33usize,
18+
concat!("Size of: ", stringify!(S))
19+
);
20+
assert_eq!(
21+
::std::mem::align_of::<S>(),
22+
1usize,
23+
concat!("Alignment of ", stringify!(S))
24+
);
25+
assert_eq!(
26+
unsafe {
27+
&(*(::std::ptr::null::<S>())).large_array as *const _ as usize
28+
},
29+
0usize,
30+
concat!(
31+
"Offset of field: ",
32+
stringify!(S),
33+
"::",
34+
stringify!(large_array)
35+
)
36+
);
37+
}
38+
impl Default for S {
39+
fn default() -> Self {
40+
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
41+
unsafe {
42+
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
43+
s.assume_init()
44+
}
45+
}
46+
}
47+
#[repr(C)]
48+
#[derive(Debug, Hash, PartialEq, Eq)]
49+
pub struct ST<T> {
50+
pub large_array: [T; 33usize],
51+
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
52+
}
53+
impl<T> Default for ST<T> {
54+
fn default() -> Self {
55+
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
56+
unsafe {
57+
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
58+
s.assume_init()
59+
}
60+
}
61+
}

tests/expectations/tests/issue-648-derive-debug-with-padding.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
)]
77

88
/// We emit a `[u8; 63usize]` padding field for this struct, which cannot derive
9-
/// Debug/Hash because 63 is over the hard coded limit. (Yes, this struct doesn't end
10-
/// up with the reight alignment, we're waiting on `#[repr(align="N")]` to land
11-
/// in rustc).
9+
/// Debug/Hash because 63 is over the hard coded limit.
1210
#[repr(C)]
1311
#[repr(align(64))]
1412
#[derive(Copy, Clone)]
@@ -55,7 +53,7 @@ impl ::std::cmp::PartialEq for NoDebug {
5553
/// This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive
5654
/// Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because
5755
/// we determine Debug derive-ability before we compute padding, which happens at
58-
/// codegen. (Again, we expect to get the alignment wrong for similar reasons.)
56+
/// codegen.
5957
#[repr(C)]
6058
#[repr(align(64))]
6159
#[derive(Copy, Clone)]

tests/headers/class.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --with-derive-partialord --with-derive-ord
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --with-derive-partialord --with-derive-ord --rust-target 1.40
22
//
33
class C {
44
int a;

tests/headers/derive-bitfield-method-same-name.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-partialeq --impl-partialeq --impl-debug
1+
// bindgen-flags: --with-derive-partialeq --impl-partialeq --impl-debug --rust-target 1.40
22

33
/// Because this struct have array larger than 32 items
44
/// and --with-derive-partialeq --impl-partialeq --impl-debug is provided,

tests/headers/derive-clone.h

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// bindgen-flags: --rust-target 1.40
2+
//
13

24
/// This struct should derive `Clone`.
35
struct ShouldDeriveClone {

tests/headers/derive-debug-bitfield-core.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --impl-debug --use-core --raw-line "extern crate core;"
1+
// bindgen-flags: --impl-debug --use-core --raw-line "extern crate core;" --rust-target 1.40
22

33
class C {
44
bool a: 1;

tests/headers/derive-debug-bitfield.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --impl-debug
1+
// bindgen-flags: --impl-debug --rust-target 1.40
22

33
class C {
44
bool a: 1;

tests/headers/derive-debug-function-pointer.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --impl-debug
1+
// bindgen-flags: --impl-debug --rust-target 1.40
22

33
class Nice {
44
typedef void (*Function) (int data);

tests/headers/derive-debug-generic.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --impl-debug
1+
// bindgen-flags: --impl-debug --rust-target 1.40
22

33
template<typename T>
44
class Generic {

tests/headers/derive-debug-opaque-template-instantiation.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --impl-debug
1+
// bindgen-flags: --impl-debug --rust-target 1.40
22

33
// This type is opaque because the second template parameter
44
// is a non-type template parameter

tests/headers/derive-debug-opaque.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --opaque-type "Opaque" --impl-debug
1+
// bindgen-flags: --opaque-type "Opaque" --impl-debug --rust-target 1.40
22

33
class Opaque {
44
int i;

tests/headers/derive-partialeq-base.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-partialeq --impl-partialeq
1+
// bindgen-flags: --with-derive-partialeq --impl-partialeq --rust-target 1.40
22

33
class Base {
44
int large[33];

tests/headers/derive-partialeq-bitfield.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-partialeq --impl-partialeq
1+
// bindgen-flags: --with-derive-partialeq --impl-partialeq --rust-target 1.40
22

33
class C {
44
bool a: 1;

tests/headers/derive-partialeq-core.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-partialeq --impl-partialeq --use-core --raw-line "extern crate core;"
1+
// bindgen-flags: --with-derive-partialeq --impl-partialeq --use-core --raw-line "extern crate core;" --rust-target 1.40
22

33
struct C {
44
int large_array[420];

tests/headers/extern-const-struct.h

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// bindgen-flags: --rust-target 1.40
2+
13
struct nsFoo {
24
float details[400];
35
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
2+
//
3+
struct S {
4+
char large_array[33];
5+
};
6+
7+
template<typename T> struct ST {
8+
T large_array[33];
9+
};

tests/headers/issue-372.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --enable-cxx-namespaces --rustified-enum ".*"
1+
// bindgen-flags: --enable-cxx-namespaces --rustified-enum ".*" --rust-target 1.40
22
template <typename a, int b> class c { a e[b]; };
33
class d;
44
template <typename g, g f> class C { c<d, f> h; };

tests/headers/issue-648-derive-debug-with-padding.h

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rust-target 1.40
22
/**
33
* We emit a `[u8; 63usize]` padding field for this struct, which cannot derive
4-
* Debug/Hash because 63 is over the hard coded limit. (Yes, this struct doesn't end
5-
* up with the reight alignment, we're waiting on `#[repr(align="N")]` to land
6-
* in rustc).
4+
* Debug/Hash because 63 is over the hard coded limit.
75
*/
86
struct NoDebug {
97
char c;
@@ -14,7 +12,7 @@ struct NoDebug {
1412
* This should derive Debug/Hash/PartialEq/Eq because the padding size is less than the max derive
1513
* Debug/Hash/PartialEq/Eq impl for arrays. However, we conservatively don't derive Debug/Hash because
1614
* we determine Debug derive-ability before we compute padding, which happens at
17-
* codegen. (Again, we expect to get the alignment wrong for similar reasons.)
15+
* codegen.
1816
*/
1917
struct ShouldDeriveDebugButDoesNot {
2018
char c[32];

tests/headers/layout_array.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rust-target 1.40
22
typedef unsigned char uint8_t;
33
typedef unsigned short uint16_t;
44
typedef unsigned int uint32_t;

tests/headers/layout_array_too_long.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rustified-enum ".*"
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq --rustified-enum ".*" --rust-target 1.40
22
typedef unsigned char uint8_t;
33
typedef unsigned short uint16_t;
44
typedef unsigned int uint32_t;

tests/headers/layout_eth_conf.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*"
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rustified-enum ".*" --rust-target 1.40
22
typedef unsigned char uint8_t;
33
typedef unsigned short uint16_t;
44
typedef unsigned int uint32_t;

tests/headers/layout_kni_mbuf.h

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// bindgen-flags: --rust-target 1.40
12

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

tests/headers/layout_large_align_field.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --rustified-enum ".*"
1+
// bindgen-flags: --rustified-enum ".*" --rust-target 1.40
22

33
typedef unsigned char uint8_t;
44
typedef unsigned short uint16_t;

tests/headers/no_debug_bypass_impl_debug.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --no-debug "NoDebug" --impl-debug
1+
// bindgen-flags: --no-debug "NoDebug" --impl-debug --rust-target 1.40
22

33
template<typename T>
44
class Generic {

tests/headers/no_default_bypass_derive_default.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --no-default "NoDefault"
1+
// bindgen-flags: --no-default "NoDefault" --rust-target 1.40
22

33
template<typename T>
44
class Generic {

tests/headers/opaque-template-inst-member.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --opaque-type 'OpaqueTemplate' --with-derive-hash --with-derive-partialeq --impl-partialeq --with-derive-eq
1+
// bindgen-flags: --opaque-type 'OpaqueTemplate' --with-derive-hash --with-derive-partialeq --impl-partialeq --with-derive-eq --rust-target 1.40
22

33
template<typename T>
44
class OpaqueTemplate {

tests/headers/struct_with_derive_debug.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rust-target 1.40
22
//
33
struct LittleArray {
44
int a[32];

tests/headers/struct_with_large_array.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
1+
// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --rust-target 1.40
22
//
33
struct S {
44
char large_array[33];

tests/headers/timex.h

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// bindgen-flags: --rust-target 1.40
2+
13
struct timex {
24
int tai;
35

0 commit comments

Comments
 (0)