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.
diff --git a/src/codegen/impl_debug.rs b/src/codegen/impl_debug.rs
index b8fdd0d..661711e 100644
--- a/src/codegen/impl_debug.rs
+++ b/src/codegen/impl_debug.rs
@@ -181,7 +181,9 @@
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 {
diff --git a/src/codegen/impl_partialeq.rs b/src/codegen/impl_partialeq.rs
index 5f2600e..5a1ba3f 100644
--- a/src/codegen/impl_partialeq.rs
+++ b/src/codegen/impl_partialeq.rs
@@ -114,7 +114,9 @@
}
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! {
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index c70c106..d49d324 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1503,7 +1503,8 @@
// 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() {
@@ -1512,7 +1513,9 @@
continue;
}
- if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT {
+ if layout.size > RUST_DERIVE_IN_ARRAY_LIMIT &&
+ !ctx.options().rust_features().larger_arrays
+ {
continue;
}
diff --git a/src/features.rs b/src/features.rs
index 4ec9dee..99b789e 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -123,6 +123,9 @@
/// 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;
@@ -134,7 +137,7 @@
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 {
@@ -222,6 +225,9 @@
Stable_1_40 {
=> non_exhaustive;
}
+ Stable_1_47 {
+ => larger_arrays;
+ }
Nightly {
=> thiscall_abi;
}
diff --git a/src/ir/analysis/derive.rs b/src/ir/analysis/derive.rs
index be62666..44e6702 100644
--- a/src/ir/analysis/derive.rs
+++ b/src/ir/analysis/derive.rs
@@ -255,7 +255,7 @@
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;
}
@@ -377,7 +377,7 @@
// 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, &())
{
@@ -496,10 +496,17 @@
}
}
- 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,
+ }
}
}
@@ -686,7 +693,7 @@
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
})
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index e6eecc3..e049ed6 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -39,7 +39,6 @@
/// 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 {
diff --git a/tests/expectations/tests/issue-1977-larger-arrays.rs b/tests/expectations/tests/issue-1977-larger-arrays.rs
new file mode 100644
index 0000000..54e5b43
--- /dev/null
+++ b/tests/expectations/tests/issue-1977-larger-arrays.rs
@@ -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()
+ }
+ }
+}
diff --git a/tests/expectations/tests/issue-648-derive-debug-with-padding.rs b/tests/expectations/tests/issue-648-derive-debug-with-padding.rs
index 15822b5..4355486 100644
--- a/tests/expectations/tests/issue-648-derive-debug-with-padding.rs
+++ b/tests/expectations/tests/issue-648-derive-debug-with-padding.rs
@@ -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)]
@@ -55,7 +53,7 @@
/// 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)]
diff --git a/tests/headers/class.hpp b/tests/headers/class.hpp
index f77ac92..a90e373 100644
--- a/tests/headers/class.hpp
+++ b/tests/headers/class.hpp
@@ -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;
diff --git a/tests/headers/derive-bitfield-method-same-name.hpp b/tests/headers/derive-bitfield-method-same-name.hpp
index 4b7b21e..ea9d801 100644
--- a/tests/headers/derive-bitfield-method-same-name.hpp
+++ b/tests/headers/derive-bitfield-method-same-name.hpp
@@ -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,
diff --git a/tests/headers/derive-clone.h b/tests/headers/derive-clone.h
index a84d35c..aacbcaf 100644
--- a/tests/headers/derive-clone.h
+++ b/tests/headers/derive-clone.h
@@ -1,3 +1,5 @@
+// bindgen-flags: --rust-target 1.40
+//
/// This struct should derive `Clone`.
struct ShouldDeriveClone {
diff --git a/tests/headers/derive-debug-bitfield-core.hpp b/tests/headers/derive-debug-bitfield-core.hpp
index 5d78e74..2073cc2 100644
--- a/tests/headers/derive-debug-bitfield-core.hpp
+++ b/tests/headers/derive-debug-bitfield-core.hpp
@@ -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;
diff --git a/tests/headers/derive-debug-bitfield.hpp b/tests/headers/derive-debug-bitfield.hpp
index df43e6a..b689190 100644
--- a/tests/headers/derive-debug-bitfield.hpp
+++ b/tests/headers/derive-debug-bitfield.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --impl-debug
+// bindgen-flags: --impl-debug --rust-target 1.40
class C {
bool a: 1;
diff --git a/tests/headers/derive-debug-function-pointer.hpp b/tests/headers/derive-debug-function-pointer.hpp
index a370dee..147097f 100644
--- a/tests/headers/derive-debug-function-pointer.hpp
+++ b/tests/headers/derive-debug-function-pointer.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --impl-debug
+// bindgen-flags: --impl-debug --rust-target 1.40
class Nice {
typedef void (*Function) (int data);
diff --git a/tests/headers/derive-debug-generic.hpp b/tests/headers/derive-debug-generic.hpp
index d515851..50122fa 100644
--- a/tests/headers/derive-debug-generic.hpp
+++ b/tests/headers/derive-debug-generic.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --impl-debug
+// bindgen-flags: --impl-debug --rust-target 1.40
template<typename T>
class Generic {
diff --git a/tests/headers/derive-debug-opaque-template-instantiation.hpp b/tests/headers/derive-debug-opaque-template-instantiation.hpp
index 0dead78..0c70fcc 100644
--- a/tests/headers/derive-debug-opaque-template-instantiation.hpp
+++ b/tests/headers/derive-debug-opaque-template-instantiation.hpp
@@ -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
diff --git a/tests/headers/derive-debug-opaque.hpp b/tests/headers/derive-debug-opaque.hpp
index 0ce1d63..715d3c8 100644
--- a/tests/headers/derive-debug-opaque.hpp
+++ b/tests/headers/derive-debug-opaque.hpp
@@ -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;
diff --git a/tests/headers/derive-partialeq-base.hpp b/tests/headers/derive-partialeq-base.hpp
index 989cbe6..2a57dca 100644
--- a/tests/headers/derive-partialeq-base.hpp
+++ b/tests/headers/derive-partialeq-base.hpp
@@ -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];
diff --git a/tests/headers/derive-partialeq-bitfield.hpp b/tests/headers/derive-partialeq-bitfield.hpp
index ac2cac6..f6dd82e 100644
--- a/tests/headers/derive-partialeq-bitfield.hpp
+++ b/tests/headers/derive-partialeq-bitfield.hpp
@@ -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;
diff --git a/tests/headers/derive-partialeq-core.h b/tests/headers/derive-partialeq-core.h
index 6da5b78..18eed8b 100644
--- a/tests/headers/derive-partialeq-core.h
+++ b/tests/headers/derive-partialeq-core.h
@@ -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];
diff --git a/tests/headers/extern-const-struct.h b/tests/headers/extern-const-struct.h
index 10006e8..1027127 100644
--- a/tests/headers/extern-const-struct.h
+++ b/tests/headers/extern-const-struct.h
@@ -1,3 +1,5 @@
+// bindgen-flags: --rust-target 1.40
+
struct nsFoo {
float details[400];
};
diff --git a/tests/headers/issue-1977-larger-arrays.hpp b/tests/headers/issue-1977-larger-arrays.hpp
new file mode 100644
index 0000000..58e8e4d
--- /dev/null
+++ b/tests/headers/issue-1977-larger-arrays.hpp
@@ -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];
+};
diff --git a/tests/headers/issue-372.hpp b/tests/headers/issue-372.hpp
index 7127be2..a2a5d45 100644
--- a/tests/headers/issue-372.hpp
+++ b/tests/headers/issue-372.hpp
@@ -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; };
diff --git a/tests/headers/issue-648-derive-debug-with-padding.h b/tests/headers/issue-648-derive-debug-with-padding.h
index f528c10..0860ce9 100644
--- a/tests/headers/issue-648-derive-debug-with-padding.h
+++ b/tests/headers/issue-648-derive-debug-with-padding.h
@@ -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;
@@ -14,7 +12,7 @@
* 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];
diff --git a/tests/headers/layout_array.h b/tests/headers/layout_array.h
index 239e52b..e6a57f7 100644
--- a/tests/headers/layout_array.h
+++ b/tests/headers/layout_array.h
@@ -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;
diff --git a/tests/headers/layout_array_too_long.h b/tests/headers/layout_array_too_long.h
index d0d34ba..53e4d8b 100644
--- a/tests/headers/layout_array_too_long.h
+++ b/tests/headers/layout_array_too_long.h
@@ -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;
diff --git a/tests/headers/layout_eth_conf.h b/tests/headers/layout_eth_conf.h
index 93ab840..9446bff 100644
--- a/tests/headers/layout_eth_conf.h
+++ b/tests/headers/layout_eth_conf.h
@@ -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;
diff --git a/tests/headers/layout_kni_mbuf.h b/tests/headers/layout_kni_mbuf.h
index ff16114..4d604aa 100644
--- a/tests/headers/layout_kni_mbuf.h
+++ b/tests/headers/layout_kni_mbuf.h
@@ -1,3 +1,4 @@
+// bindgen-flags: --rust-target 1.40
#define RTE_CACHE_LINE_MIN_SIZE 64 /**< Minimum Cache line size. */
diff --git a/tests/headers/layout_large_align_field.h b/tests/headers/layout_large_align_field.h
index f292bb7..63aea90 100644
--- a/tests/headers/layout_large_align_field.h
+++ b/tests/headers/layout_large_align_field.h
@@ -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;
diff --git a/tests/headers/no_debug_bypass_impl_debug.hpp b/tests/headers/no_debug_bypass_impl_debug.hpp
index a586441..d934d2c 100644
--- a/tests/headers/no_debug_bypass_impl_debug.hpp
+++ b/tests/headers/no_debug_bypass_impl_debug.hpp
@@ -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 {
diff --git a/tests/headers/no_default_bypass_derive_default.hpp b/tests/headers/no_default_bypass_derive_default.hpp
index 0f83390..ab0fdfa 100644
--- a/tests/headers/no_default_bypass_derive_default.hpp
+++ b/tests/headers/no_default_bypass_derive_default.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --no-default "NoDefault"
+// bindgen-flags: --no-default "NoDefault" --rust-target 1.40
template<typename T>
class Generic {
diff --git a/tests/headers/opaque-template-inst-member.hpp b/tests/headers/opaque-template-inst-member.hpp
index 6516aa5..9b32791 100644
--- a/tests/headers/opaque-template-inst-member.hpp
+++ b/tests/headers/opaque-template-inst-member.hpp
@@ -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 {
diff --git a/tests/headers/struct_with_derive_debug.h b/tests/headers/struct_with_derive_debug.h
index 201748d..4dc816b 100644
--- a/tests/headers/struct_with_derive_debug.h
+++ b/tests/headers/struct_with_derive_debug.h
@@ -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];
diff --git a/tests/headers/struct_with_large_array.hpp b/tests/headers/struct_with_large_array.hpp
index 58e8e4d..974ca52 100644
--- a/tests/headers/struct_with_large_array.hpp
+++ b/tests/headers/struct_with_large_array.hpp
@@ -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];
diff --git a/tests/headers/timex.h b/tests/headers/timex.h
index 1add26c..099be61 100644
--- a/tests/headers/timex.h
+++ b/tests/headers/timex.h
@@ -1,3 +1,5 @@
+// bindgen-flags: --rust-target 1.40
+
struct timex {
int tai;