From 1f900ee90ae11aceab3476e8ede3a68c9b742067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Wed, 27 Aug 2025 11:50:48 +0800 Subject: [PATCH 1/5] 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. --- src/type-layout.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/type-layout.md b/src/type-layout.md index 425f82d5c9..3ba15d6f9e 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -595,6 +595,40 @@ own, `packed` does not provide any guarantee about field ordering). An important consequence of these rules is that a type with `#[repr(packed(1))]` (or `#[repr(packed)]`) will have no inter-field padding. +[r[layout.repr.packed.borrowing]] +When borrowing a field of a `repr(packed(...))` struct, Rust must not create a **misaligned reference** (which would be undefined behavior). Therefore: + +- It is a **hard error** (E0793) to create a reference whose **ABI alignment requirement** is **greater** than the struct’s packed alignment. +- Borrowing is **allowed** if the target’s ABI alignment is **less than or equal to** the struct’s packed alignment. + +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)`.) + +**Examples** + +```rust +// Allowed: `u8` has ABI alignment 1, which is ≤ the packed alignment (typically 1). +#[repr(C, packed)] +struct S { buf: [u8; N] } + +fn ok(s: &S) -> &[u8] { + &s.buf[..] +} + +// Error (E0793): `u16` has ABI alignment 2, which is > the packed alignment. +#[repr(C, packed)] +struct T { buf: [u16; N] } + +fn err(t: &T) -> &[u16] { + &t.buf[..] // creates a reference requiring alignment 2 from a packed(1) field +} +``` + +Note: This is a hard error, not a lint. Implementations may determine the +target’s ABI alignment either directly from the borrowed type, or—when the full +layout of an array is unavailable in generic contexts—by using the element type’s +alignment (align([T]) == align(T)). The check must remain conservative and never +permit creating misaligned references. + r[layout.repr.alignment.constraint-exclusive] The `align` and `packed` modifiers cannot be applied on the same type and a `packed` type cannot transitively contain another `align`ed type. `align` and From 8de5f2be7b16e0a7c65ded7f401bff650fb00d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Wed, 27 Aug 2025 12:15:49 +0800 Subject: [PATCH 2/5] modify example for check --- src/type-layout.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type-layout.md b/src/type-layout.md index 3ba15d6f9e..8da7070498 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -605,7 +605,7 @@ For array and slice fields `[T; N]` and `[T]`, the ABI alignment equals that of **Examples** -```rust +```rust,ignore // Allowed: `u8` has ABI alignment 1, which is ≤ the packed alignment (typically 1). #[repr(C, packed)] struct S { buf: [u8; N] } From cc4c14bb826f362c66b46f3ff1b0686a35843fd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Wed, 27 Aug 2025 12:26:21 +0800 Subject: [PATCH 3/5] modify style problem --- src/type-layout.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index 8da7070498..95674b8836 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -624,8 +624,8 @@ fn err(t: &T) -> &[u16] { ``` Note: This is a hard error, not a lint. Implementations may determine the -target’s ABI alignment either directly from the borrowed type, or—when the full -layout of an array is unavailable in generic contexts—by using the element type’s +target's ABI alignment either directly from the borrowed type, or---when the full +layout of an array is unavailable in generic contexts---by using the element type's alignment (align([T]) == align(T)). The check must remain conservative and never permit creating misaligned references. From 242b2d2065d37b26353cee4e26784b40de8a3385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Thu, 28 Aug 2025 11:58:26 +0800 Subject: [PATCH 4/5] modify style for check --- src/type-layout.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/type-layout.md b/src/type-layout.md index 95674b8836..2603791c84 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -601,7 +601,10 @@ When borrowing a field of a `repr(packed(...))` struct, Rust must not create a * - It is a **hard error** (E0793) to create a reference whose **ABI alignment requirement** is **greater** than the struct’s packed alignment. - Borrowing is **allowed** if the target’s ABI alignment is **less than or equal to** the struct’s packed alignment. -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)`.) +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)` ``.)* **Examples** From 950102085777a49c3697949eea3115e79884e462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=AE=81=E7=A4=BE?= <524395609@qq.com> Date: Thu, 28 Aug 2025 12:22:18 +0800 Subject: [PATCH 5/5] modify style for check --- src/type-layout.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index 2603791c84..afc83d42bd 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -595,7 +595,7 @@ own, `packed` does not provide any guarantee about field ordering). An important consequence of these rules is that a type with `#[repr(packed(1))]` (or `#[repr(packed)]`) will have no inter-field padding. -[r[layout.repr.packed.borrowing]] +r[layout.repr.packed.borrowing] When borrowing a field of a `repr(packed(...))` struct, Rust must not create a **misaligned reference** (which would be undefined behavior). Therefore: - It is a **hard error** (E0793) to create a reference whose **ABI alignment requirement** is **greater** than the struct’s packed alignment. @@ -629,7 +629,7 @@ fn err(t: &T) -> &[u16] { Note: This is a hard error, not a lint. Implementations may determine the target's ABI alignment either directly from the borrowed type, or---when the full layout of an array is unavailable in generic contexts---by using the element type's -alignment (align([T]) == align(T)). The check must remain conservative and never +alignment (`align([T])` == `align(T)`). The check must remain conservative and never permit creating misaligned references. r[layout.repr.alignment.constraint-exclusive]