-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BorshSerialize derive fails for structs with packed attribute #261
Comments
Seems to work out of the box in serde for this example: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=2005b735ca5ca80559abf53f03b36475 |
(it would be It works fine for #[derive(serde::Serialize)]
#[repr(packed)]
struct Bar {
x: u8,
y: u64,
} and is a compilation error for non- #[derive(serde::Serialize)]
#[repr(packed)]
struct Foo {
x: RefCell<u8>,
y: u64,
} 1 error[E0507]: cannot move out of `self.x` which is behind a shared reference
--> src/main.rs:12:10
|
12 | #[derive(serde::Serialize)]
| ^^^^^^^^^^^^^^^^ move occurs because `self.x` has type `RefCell<u8>`, which does not implement the `Copy` trait
|
= note: `#[derive(serde::Serialize)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
= note: this error originates in the derive macro `serde::Serialize` (in Nightly builds, run with -Z macro-backtrace for more info)
imo replicating |
a more versatile template for derives, allowing to work with non- use core::mem;
use core::ops::Deref;
use core::ptr;
use std::rc::Rc;
#[repr(packed)]
struct Foo {
x: Rc<u8>,
y: u64,
}
impl borsh::ser::BorshSerialize for Foo {
fn serialize<W: borsh::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh::io::Error> {
borsh::BorshSerialize::serialize(
mem::ManuallyDrop::new(unsafe { ptr::read_unaligned(ptr::addr_of!(self.x)) }).deref(),
writer,
)?;
borsh::BorshSerialize::serialize(
mem::ManuallyDrop::new(unsafe { ptr::read_unaligned(ptr::addr_of!(self.y)) }).deref(),
writer,
)?;
Ok(())
}
}
fn main() {
let foo = Foo {
x: Rc::new(42),
y: 182,
};
println!("{:?}", borsh::to_vec(&foo).unwrap());
} |
src/main.rs
:Cargo.toml
:Trying to build this fails with:
The macro itself expands to:
The work-around is to write a manual implementation that copies the underlying value first and uses a reference to that, like this:
I'm not sure what the best way forward/workaround is, but I thought I'd open a ticket anyway.
The text was updated successfully, but these errors were encountered: