@@ -112,26 +112,43 @@ assert_eq!(16, size_of::<MyReprOption<&u16>>());
112
112
113
113
This optimization still applies to fieldless enums with an explicit ` repr(u*) ` , ` repr(i*) ` , or ` repr(C) ` .
114
114
115
- ## repr(packed)
115
+ ## repr(packed(n) )
116
116
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).
120
124
121
125
In particular, most architectures * strongly* prefer values to be aligned. This
122
126
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:
127
133
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
+ }
130
139
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
+ ```
133
151
134
- This repr is a modifier on ` repr(C) ` and ` repr(Rust) ` .
135
152
136
153
## repr(align(n))
137
154
@@ -153,3 +170,4 @@ This is a modifier on `repr(C)` and `repr(Rust)`. It is incompatible with
153
170
[ really-tagged ] : https://github.com/rust-lang/rfcs/blob/master/text/2195-really-tagged-unions.md
154
171
[ rust-bindgen ] : https://rust-lang.github.io/rust-bindgen/
155
172
[ cbindgen ] : https://github.com/eqrion/cbindgen
173
+ [ rust-reference-type-layout ] : https://doc.rust-lang.org/reference/type-layout.html
0 commit comments