Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Error code E0793

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:

#![allow(unused)]
fn main() {
#[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.

#![allow(unused)]
fn main() {
#[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.

#![allow(unused)]
fn main() {
#[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.