Closed
Description
Example:
#[derive(Copy, Clone, derivative::Derivative)]
#[derivative(Debug)]
#[repr(C, packed)]
struct Test {
a: u8,
b: u32
}
warning: borrow of packed field is unsafe and requires unsafe function or block (error E0133)
--> src/lib.rs:1:23
|
1 | #[derive(Copy, Clone, derivative::Derivative)]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(safe_packed_borrows)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
= note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
Default #[derive(Debug)]
requires that the struct also derives Copy
and Clone
:
warning: `#[derive]` can't be used on a `#[repr(packed)]` struct that does not derive Copy (error E0133)
--> src/main.rs:1:10
|
1 | #[derive(Debug)]
| ^^^^^
|
= note: `#[warn(safe_packed_borrows)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
= note: this warning originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
After adding #[derive(Copy, Clone)]
, default Debug
expands to the following (notice the copying of the fields):
impl ::core::fmt::Debug for Test {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match *self {
Test {
a: __self_0_0,
b: __self_0_1,
} => {
let mut debug_trait_builder = f.debug_struct("Test");
let _ = debug_trait_builder.field("a", &&(__self_0_0));
let _ = debug_trait_builder.field("b", &&(__self_0_1));
debug_trait_builder.finish()
}
}
}
}
#[derivative(Debug)]
just always references the fields instead, and referencing fields in a packed struct is -- as far as I can tell -- bad:
impl ::std::fmt::Debug for Test {
fn fmt(&self, __f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Test {
a: ref __arg_0,
b: ref __arg_1,
} => {
let mut __debug_trait_builder = __f.debug_struct("Test");
let _ = __debug_trait_builder.field("a", &__arg_0);
let _ = __debug_trait_builder.field("b", &__arg_1);
__debug_trait_builder.finish()
}
}
}
}