Skip to content

Commit 1f900ee

Browse files
committed
docs: add comprehensive documentation for borrowing from repr(packed) arrays
- Add detailed explanation of alignment requirements when borrowing from packed structs - Document that array/slice ABI alignment equals element type alignment - Provide concrete examples showing allowed and forbidden borrowing patterns - Clarify that E0793 error prevents creation of misaligned references - Explain the conservative nature of alignment checks in generic contexts This documentation helps developers understand the safety constraints when working with packed structs containing arrays of different types.
1 parent 3279c0e commit 1f900ee

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

src/type-layout.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,40 @@ own, `packed` does not provide any guarantee about field ordering). An
595595
important consequence of these rules is that a type with `#[repr(packed(1))]`
596596
(or `#[repr(packed)]`) will have no inter-field padding.
597597

598+
[r[layout.repr.packed.borrowing]]
599+
When borrowing a field of a `repr(packed(...))` struct, Rust must not create a **misaligned reference** (which would be undefined behavior). Therefore:
600+
601+
- It is a **hard error** (E0793) to create a reference whose **ABI alignment requirement** is **greater** than the struct’s packed alignment.
602+
- Borrowing is **allowed** if the target’s ABI alignment is **less than or equal to** the struct’s packed alignment.
603+
604+
For array and slice fields `[T; N]` and `[T]`, the ABI alignment equals that of the element type `T` and **does not depend on the length `N`**. (Sketch: from `&[T]` one can obtain `&T`, hence `align([T]) ≥ align(T)`; from `&T` one can obtain `&[T; 1]` via `std::array::from_ref`, hence `align(T) ≥ align([T])`. Therefore `align([T]) == align(T)`.)
605+
606+
**Examples**
607+
608+
```rust
609+
// Allowed: `u8` has ABI alignment 1, which is ≤ the packed alignment (typically 1).
610+
#[repr(C, packed)]
611+
struct S<const N: usize> { buf: [u8; N] }
612+
613+
fn ok<const N: usize>(s: &S<N>) -> &[u8] {
614+
&s.buf[..]
615+
}
616+
617+
// Error (E0793): `u16` has ABI alignment 2, which is > the packed alignment.
618+
#[repr(C, packed)]
619+
struct T<const N: usize> { buf: [u16; N] }
620+
621+
fn err<const N: usize>(t: &T<N>) -> &[u16] {
622+
&t.buf[..] // creates a reference requiring alignment 2 from a packed(1) field
623+
}
624+
```
625+
626+
Note: This is a hard error, not a lint. Implementations may determine the
627+
target’s ABI alignment either directly from the borrowed type, or—when the full
628+
layout of an array is unavailable in generic contexts—by using the element type’s
629+
alignment (align([T]) == align(T)). The check must remain conservative and never
630+
permit creating misaligned references.
631+
598632
r[layout.repr.alignment.constraint-exclusive]
599633
The `align` and `packed` modifiers cannot be applied on the same type and a
600634
`packed` type cannot transitively contain another `align`ed type. `align` and

0 commit comments

Comments
 (0)