Skip to content

Commit b1946ee

Browse files
committed
Merge remote-tracking branch 'retep998/optimal-rabbit-packing'
2 parents 82a969b + cbb18a4 commit b1946ee

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

text/0000-repr-pack.md

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
- Feature Name: `repr_pack`
2+
- Start Date: 2015-12-06
3+
- RFC PR: (leave this empty)
4+
- Rust Issue: (leave this empty)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
Extend the existing `#[repr]` attribute on structs with a `pack = "N"` option to
10+
specify a custom packing for `struct` types.
11+
12+
# Motivation
13+
[motivation]: #motivation
14+
15+
Many C/C++ compilers allow a packing to be specified for structs which
16+
effectively lowers the alignment for a struct and its fields (for example with
17+
MSVC there is `#pragma pack(N)`). Such packing is used extensively in certain
18+
C/C++ libraries (such as Windows API which uses it pervasively making writing
19+
Rust libraries such as `winapi` challenging).
20+
21+
At the moment the only way to work around the lack of a proper
22+
`#[repr(pack = "N")]` attribute is to use `#[repr(packed)]` and then manually
23+
fill in padding which is a burdensome task. Even then that isn't quite right
24+
because the overall alignment of the struct would end up as 1 even though it
25+
needs to be N (or the default if that is smaller than N), so this fills in a gap
26+
which is impossible to do in Rust at the moment.
27+
28+
# Detailed design
29+
[design]: #detailed-design
30+
31+
The `#[repr]` attribute on `struct`s will be extended to include a form such as:
32+
33+
```rust
34+
#[repr(pack = "2")]
35+
struct LessAligned(i16, i32);
36+
```
37+
38+
This structure will have an alignment of 2 and a size of 6, as well as the
39+
second field having an offset of 2 instead of 4 from the base of the struct.
40+
This is in contrast to without the attribute where the structure would have an
41+
alignment of 4 and a size of 8, and the second field would have an offset of 4
42+
from the base of the struct.
43+
44+
Syntactically, the `repr` meta list will be extended to accept a meta item
45+
name/value pair with the name "pack" and the value as a string which can be
46+
parsed as a `u64`. The restrictions on where this attribute can be placed along
47+
with the accepted values are:
48+
49+
* Custom packing can only be specified on `struct` declarations for now.
50+
Specifying a different packing on perhaps `enum` or `type` definitions should
51+
be a backwards-compatible extension.
52+
* Packing values must be a power of two.
53+
54+
By specifying this attribute, the alignment of the struct would be the smaller
55+
of the specified packing and the default alignment of the struct. The alignments
56+
of each struct field for the purpose of positioning fields would also be the
57+
smaller of the specified packing and the alignment of the type of that field. If
58+
the specified packing is greater than or equal to the default alignment of the
59+
struct, then the alignment and layout of the struct should be unaffected.
60+
61+
When combined with `#[repr(C)]` the size alignment and layout of the struct
62+
should match the equivalent struct in C.
63+
64+
`#[repr(packed)]` and `#[repr(pack = "1")]` should have identical behavior.
65+
66+
Because this lowers the effective alignment of fields in the same way that
67+
`#[repr(packed)]` does (which caused [issue #27060][gh27060]), while accessing a
68+
field should be safe, borrowing a field should be unsafe.
69+
70+
Specifying `#[repr(packed)]` and `#[repr(pack = "N")]` where N is not 1 should
71+
result in an error.
72+
73+
Specifying `#[repr(pack = "A")]` and `#[repr(align = "B")]` should still pack
74+
together fields with the packing specified, but then increase the overall
75+
alignment to the alignment specified. Depends on [RFC #1358][rfc1358] landing.
76+
77+
# Drawbacks
78+
[drawbacks]: #drawbacks
79+
80+
Duplication in the language where `#[repr(packed)]` and `#[repr(pack = "1")]`
81+
have identical behavior.
82+
83+
# Alternatives
84+
[alternatives]: #alternatives
85+
86+
* The alternative is not doing this and forcing people to continue using
87+
`#[repr(packed)]` with manual padding, although such structs would always have
88+
an alignment of 1 which is often wrong.
89+
* Alternatively a new attribute could be used such as `#[pack]`.
90+
* `#[repr(packed)]` could be extended as either `#[repr(packed(N))]` or
91+
`#[repr(packed = "N")]`.
92+
93+
# Unresolved questions
94+
[unresolved]: #unresolved-questions
95+
96+
* The behavior specified here should match the behavior of MSVC at least. Does
97+
it match the behavior of other C/C++ compilers as well?
98+
* Should it still be safe to borrow fields whose alignment is less than or equal
99+
to the specified packing or should all field borrows be unsafe?
100+
101+
[gh27060]: https://github.com/rust-lang/rust/issues/27060
102+
[rfc1358]: https://github.com/rust-lang/rfcs/pull/1358

0 commit comments

Comments
 (0)