Skip to content

Commit

Permalink
Derive from any other trait only when deriving from Copy
Browse files Browse the repository at this point in the history
It's impossible to #[derive] from any other trair when not deriving from
Copy when using the newest Rust nightly. Any attempt to do that results
in the following error:

  error: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)

Fixes: rust-lang#2083
Signed-off-by: Michal Rostecki <vadorovsky@gmail.com>
  • Loading branch information
vadorovsky committed May 4, 2022
1 parent ee6ff69 commit ab7e3c3
Show file tree
Hide file tree
Showing 34 changed files with 419 additions and 100 deletions.
47 changes: 23 additions & 24 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,6 @@ bitflags! {
fn derives_of_item(item: &Item, ctx: &BindgenContext) -> DerivableTraits {
let mut derivable_traits = DerivableTraits::empty();

if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() {
derivable_traits |= DerivableTraits::DEBUG;
}

if item.can_derive_default(ctx) && !item.annotations().disallow_default() {
derivable_traits |= DerivableTraits::DEFAULT;
}

let all_template_params = item.all_template_params(ctx);

if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
Expand All @@ -137,26 +129,34 @@ fn derives_of_item(item: &Item, ctx: &BindgenContext) -> DerivableTraits {
// It's not hard to fix though.
derivable_traits |= DerivableTraits::CLONE;
}
}

if item.can_derive_hash(ctx) {
derivable_traits |= DerivableTraits::HASH;
}
if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() {
derivable_traits |= DerivableTraits::DEBUG;
}

if item.can_derive_partialord(ctx) {
derivable_traits |= DerivableTraits::PARTIAL_ORD;
}
if item.can_derive_default(ctx) && !item.annotations().disallow_default() {
derivable_traits |= DerivableTraits::DEFAULT;
}

if item.can_derive_ord(ctx) {
derivable_traits |= DerivableTraits::ORD;
}
if item.can_derive_hash(ctx) {
derivable_traits |= DerivableTraits::HASH;
}

if item.can_derive_partialeq(ctx) {
derivable_traits |= DerivableTraits::PARTIAL_EQ;
}
if item.can_derive_partialord(ctx) {
derivable_traits |= DerivableTraits::PARTIAL_ORD;
}

if item.can_derive_eq(ctx) {
derivable_traits |= DerivableTraits::EQ;
if item.can_derive_ord(ctx) {
derivable_traits |= DerivableTraits::ORD;
}

if item.can_derive_partialeq(ctx) {
derivable_traits |= DerivableTraits::PARTIAL_EQ;
}

if item.can_derive_eq(ctx) {
derivable_traits |= DerivableTraits::EQ;
}
}

derivable_traits
Expand Down Expand Up @@ -4554,7 +4554,6 @@ pub mod utils {

let incomplete_array_decl = quote! {
#[repr(C)]
#[derive(Default)]
pub struct __IncompleteArrayField<T>(
::#prefix::marker::PhantomData<T>, [T; 0]);
};
Expand Down
20 changes: 18 additions & 2 deletions tests/expectations/tests/allowlisted_item_references_no_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)]

#[repr(C)]
#[derive(Debug, Default)]
pub struct NoCopy {
pub _address: u8,
}
Expand All @@ -23,8 +22,16 @@ fn bindgen_test_layout_NoCopy() {
concat!("Alignment of ", stringify!(NoCopy))
);
}
impl Default for NoCopy {
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, Default)]
pub struct AllowlistMe {
pub a: NoCopy,
}
Expand Down Expand Up @@ -53,3 +60,12 @@ fn bindgen_test_layout_AllowlistMe() {
)
);
}
impl Default for AllowlistMe {
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()
}
}
}
2 changes: 0 additions & 2 deletions tests/expectations/tests/class_with_dtor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)]

#[repr(C)]
#[derive(Debug, Hash, PartialEq, Eq)]
pub struct HandleWithDtor<T> {
pub ptr: *mut T,
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
Expand All @@ -22,7 +21,6 @@ impl<T> Default for HandleWithDtor<T> {
}
pub type HandleValue = HandleWithDtor<::std::os::raw::c_int>;
#[repr(C)]
#[derive(Debug, Hash, PartialEq, Eq)]
pub struct WithoutDtor {
pub shouldBeWithDtor: HandleValue,
}
Expand Down
20 changes: 18 additions & 2 deletions tests/expectations/tests/crtp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,19 @@ fn bindgen_test_layout_Derived() {
);
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct BaseWithDestructor {
pub _address: u8,
}
impl Default for BaseWithDestructor {
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, Default)]
pub struct DerivedFromBaseWithDestructor {
pub _address: u8,
}
Expand All @@ -51,6 +58,15 @@ fn bindgen_test_layout_DerivedFromBaseWithDestructor() {
concat!("Alignment of ", stringify!(DerivedFromBaseWithDestructor))
);
}
impl Default for DerivedFromBaseWithDestructor {
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()
}
}
}
#[test]
fn __bindgen_test_layout_Base_open0_Derived_close0_instantiation() {
assert_eq!(
Expand Down
106 changes: 102 additions & 4 deletions tests/expectations/tests/derive-custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,119 @@
)]

/// <div rustbindgen derive="Debug"></div>
/// <div rustbindgen derive="Copy"></div>
#[repr(C)]
#[derive(Default, Debug)]
#[derive(Debug, Copy)]
pub struct my_type {
pub a: ::std::os::raw::c_int,
}
#[test]
fn bindgen_test_layout_my_type() {
assert_eq!(
::std::mem::size_of::<my_type>(),
4usize,
concat!("Size of: ", stringify!(my_type))
);
assert_eq!(
::std::mem::align_of::<my_type>(),
4usize,
concat!("Alignment of ", stringify!(my_type))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<my_type>())).a as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(my_type),
"::",
stringify!(a)
)
);
}
impl Default for my_type {
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()
}
}
}
/// <div rustbindgen derive="Debug"></div>
/// <div rustbindgen derive="Copy"></div>
/// <div rustbindgen derive="Clone"></div>
#[repr(C)]
#[derive(Default, Debug, Clone)]
#[derive(Debug, Copy, Clone)]
pub struct my_type2 {
pub a: ::std::os::raw::c_uint,
}
/// <div rustbindgen derive="Debug" derive="Clone"></div>
#[test]
fn bindgen_test_layout_my_type2() {
assert_eq!(
::std::mem::size_of::<my_type2>(),
4usize,
concat!("Size of: ", stringify!(my_type2))
);
assert_eq!(
::std::mem::align_of::<my_type2>(),
4usize,
concat!("Alignment of ", stringify!(my_type2))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<my_type2>())).a as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(my_type2),
"::",
stringify!(a)
)
);
}
impl Default for my_type2 {
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()
}
}
}
/// <div rustbindgen derive="Debug" derive="Copy" derive="Clone"></div>
#[repr(C)]
#[derive(Default, Debug, Clone)]
#[derive(Debug, Copy, Clone)]
pub struct my_type3 {
pub a: ::std::os::raw::c_ulong,
}
#[test]
fn bindgen_test_layout_my_type3() {
assert_eq!(
::std::mem::size_of::<my_type3>(),
8usize,
concat!("Size of: ", stringify!(my_type3))
);
assert_eq!(
::std::mem::align_of::<my_type3>(),
8usize,
concat!("Alignment of ", stringify!(my_type3))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<my_type3>())).a as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(my_type3),
"::",
stringify!(a)
)
);
}
impl Default for my_type3 {
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()
}
}
}
10 changes: 9 additions & 1 deletion tests/expectations/tests/do-not-derive-copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)]

#[repr(C)]
#[derive(Debug, Default)]
pub struct WouldBeCopyButWeAreNotDerivingCopy {
pub x: ::std::os::raw::c_int,
}
Expand Down Expand Up @@ -39,3 +38,12 @@ fn bindgen_test_layout_WouldBeCopyButWeAreNotDerivingCopy() {
)
);
}
impl Default for WouldBeCopyButWeAreNotDerivingCopy {
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()
}
}
}
10 changes: 9 additions & 1 deletion tests/expectations/tests/gen-destructors-neg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)]

#[repr(C)]
#[derive(Debug, Default)]
pub struct Foo {
pub bar: ::std::os::raw::c_int,
}
Expand All @@ -28,3 +27,12 @@ fn bindgen_test_layout_Foo() {
concat!("Offset of field: ", stringify!(Foo), "::", stringify!(bar))
);
}
impl Default for Foo {
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()
}
}
}
10 changes: 9 additions & 1 deletion tests/expectations/tests/gen-destructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)]

#[repr(C)]
#[derive(Debug, Default)]
pub struct Foo {
pub bar: ::std::os::raw::c_int,
}
Expand All @@ -32,6 +31,15 @@ extern "C" {
#[link_name = "\u{1}_ZN3FooD1Ev"]
pub fn Foo_Foo_destructor(this: *mut Foo);
}
impl Default for Foo {
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()
}
}
}
impl Foo {
#[inline]
pub unsafe fn destruct(&mut self) {
Expand Down
2 changes: 0 additions & 2 deletions tests/expectations/tests/inline_namespace_no_ns_enabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)]

#[repr(C)]
#[derive(Debug)]
pub struct std_basic_string<CharT> {
pub hider: std_basic_string_Alloc_hider,
pub length: ::std::os::raw::c_ulong,
Expand All @@ -28,7 +27,6 @@ impl Default for std_basic_string_Alloc_hider {
}
}
#[repr(C)]
#[derive(Debug)]
pub struct std_basic_string__bindgen_ty_1<CharT> {
pub inline_storage: [CharT; 4usize],
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<CharT>>,
Expand Down
1 change: 0 additions & 1 deletion tests/expectations/tests/issue-1197-pure-virtual-stuff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#[repr(C)]
pub struct Foo__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
#[derive(Debug)]
pub struct Foo {
pub vtable_: *const Foo__bindgen_vtable,
}
Expand Down
1 change: 0 additions & 1 deletion tests/expectations/tests/issue-1238-fwd-no-copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)]

#[repr(C)]
#[derive(Debug)]
pub struct MyType {
_unused: [u8; 0],
}
Expand Down
1 change: 0 additions & 1 deletion tests/expectations/tests/issue-1454.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
pub struct extern_type;

#[repr(C)]
#[derive(Debug)]
pub struct local_type {
pub inner: extern_type,
}
Expand Down

0 comments on commit ab7e3c3

Please sign in to comment.