Rust errors / Everything else
Rust compiler error · checked with rustc 1.99.0
Rust error E0793: reference to field of packed struct is unaligned
What it meansAn unaligned reference to a field of a [packed] struct or union was created.
What rustc prints
error[E0793]: reference to field of packed struct is unaligned --> main.rs:14:15 | 14 | let val = &foo.field1; // ERROR | ^^^^^^^^^^^ | = note: this struct is 1-byte aligned, but the type of this field may require higher alignment = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers)
Real output of rustc 1.99.0 compiling the official example below (2021 edition). Your names and line numbers will differ; the first line is the part to match.
The compiler team's explanation
An unaligned reference to a field of a packed struct or union was created.
The #[repr(packed)] attribute removes padding between fields, which can cause fields to be stored at unaligned memory addresses. Creating references to such fields violates Rust's memory safety guarantees and can lead to undefined behavior in optimized code.
Erroneous code example:
#[repr(packed)]
pub struct Foo {
field1: u64,
field2: u8,
}
unsafe {
let foo = Foo { field1: 0, field2: 0 };
// Accessing the field directly is fine.
let val = foo.field1;
// A reference to a packed field causes a error.
let val = &foo.field1; // ERROR
// An implicit `&` is added in format strings, causing the same error.
println!("{}", foo.field1); // ERROR
}
Creating a reference to an insufficiently aligned packed field is undefined behavior and therefore disallowed. Using an unsafe block does not change anything about this. Instead, the code should do a copy of the data in the packed field or use raw pointers and unaligned accesses.
#[repr(packed)]
pub struct Foo {
field1: u64,
field2: u8,
}
unsafe {
let foo = Foo { field1: 0, field2: 0 };
// Instead of a reference, we can create a raw pointer...
let ptr = std::ptr::addr_of!(foo.field1);
// ... and then (crucially!) access it in an explicitly unaligned way.
let val = unsafe { ptr.read_unaligned() };
// This would *NOT* be correct:
// let val = unsafe { *ptr }; // Undefined Behavior due to unaligned load!
// For formatting, we can create a copy to avoid the direct reference.
let copy = foo.field1;
println!("{}", copy);
// Creating a copy can be written in a single line with curly braces.
// (This is equivalent to the two lines above.)
println!("{}", { foo.field1 });
// A reference to a field that will always be sufficiently aligned is safe:
println!("{}", foo.field2);
}
Unions
Although creating a reference to a union field is unsafe, this error will still be triggered if the referenced field is not sufficiently aligned. Use addr_of! and raw pointers in the same way as for struct fields.
#[repr(packed)]
pub union Foo {
field1: u64,
field2: u8,
}
unsafe {
let foo = Foo { field1: 0 };
// Accessing the field directly is fine.
let val = foo.field1;
// A reference to a packed union field causes an error.
let val = &foo.field1; // ERROR
}
Additional information
Note that this error is specifically about *references* to packed fields. Direct by-value access of those fields is fine, since then the compiler has enough information to generate the correct kind of access.
See issue #82523 for more information.
From rustc --explain E0793 (1.99.0), part of the Rust project, MIT or Apache-2.0. Official page.
Related errors
- E0061this function takes N arguments but M were supplied
- E0412cannot find type in this scope
- E0515cannot return reference to local variable
- E0728await is only allowed inside async functions and blocks
- E0786A metadata file was invalid
- E0787naked functions must contain a single `naked_asm!` invocation
- E0797base expression required after `..`
- E0798arguments for `"cmse-nonsecure-call"` function too large to pass via registers
Up next
Often hit nextE0061: this function takes N arguments but M were suppliedA related error from the same family.Read it next →Did this answer your question?