Skip to content

Commit 20d86cd

Browse files
committed
doc: fix deprecated doc of attribute packed
The Rust language reference (and my experience, proofed by tests) says, that `packed(n)` gives you the ability to align the struct too. https://doc.rust-lang.org/reference/type-layout.html
1 parent 2d66852 commit 20d86cd

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

src/other-reprs.md

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,26 +112,43 @@ assert_eq!(16, size_of::<MyReprOption<&u16>>());
112112

113113
This optimization still applies to fieldless enums with an explicit `repr(u*)`, `repr(i*)`, or `repr(C)`.
114114

115-
## repr(packed)
115+
## repr(packed(n))
116116

117-
`repr(packed)` forces Rust to strip any padding, and only align the type to a
118-
byte. This may improve the memory footprint, but will likely have other negative
119-
side-effects.
117+
`repr(packed(n))` forces the Rust compiler to strip any padding between fields, and align the type, hence,
118+
the first field, at least to a [`n`-byte boundary][rust-reference-type-layout] (where `n` is a power of two).
119+
`repr(packed)` is equivalent to `repr(packed(1))`.
120+
121+
This `repr`-attribute is a modifier on `repr(C)` and `repr(Rust)`, but is incompatible with `align(n)`. It may improve
122+
the memory footprint and is useful in scenarios, where you need exact control over the memory layout
123+
(such as constructing network packets).
120124

121125
In particular, most architectures *strongly* prefer values to be aligned. This
122126
may mean the unaligned loads are penalized (x86), or even fault (some ARM
123-
chips). For simple cases like directly loading or storing a packed field, the
124-
compiler might be able to paper over alignment issues with shifts and masks.
125-
However if you take a reference to a packed field, it's unlikely that the
126-
compiler will be able to emit code to avoid an unaligned load.
127+
chips). Fields of packed structs are not guaranteed to be properly aligned, and creating a reference to them is
128+
undefined behavior (even if that reference is never dereferenced). [As this can cause undefined behavior][ub loads],
129+
the lint has been implemented and it will become a hard error in the future (not yet in Rust nightly 1.58).
130+
131+
The workaround is either to implement unsafe functionality on top of pointers or to copy the value. See the example
132+
below:
127133

128-
[As this can cause undefined behavior][ub loads], the lint has been implemented
129-
and it will become a hard error.
134+
```rust
135+
#[repr(C, packed(2))]
136+
struct Foo {
137+
a: u32,
138+
}
130139

131-
`repr(packed)` is not to be used lightly. Unless you have extreme requirements,
132-
this should not be used.
140+
impl Foo {
141+
/// Okay because it's a safe copy
142+
fn a(&self) -> u32 {
143+
self.a
144+
}
145+
/// Warning and future hard error
146+
fn a_ref(&self) -> &u32 {
147+
&self.a
148+
}
149+
}
150+
```
133151

134-
This repr is a modifier on `repr(C)` and `repr(Rust)`.
135152

136153
## repr(align(n))
137154

@@ -153,3 +170,4 @@ This is a modifier on `repr(C)` and `repr(Rust)`. It is incompatible with
153170
[really-tagged]: https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md
154171
[rust-bindgen]: https://rust-lang.github.io/rust-bindgen/
155172
[cbindgen]: https://github.com/eqrion/cbindgen
173+
[rust-reference-type-layout]: https://doc.rust-lang.org/reference/type-layout.html

0 commit comments

Comments
 (0)