Skip to content

Commit 308c474

Browse files
authored
Merge pull request #164 from gnzlbg/single_field_struct
Guarantee the layout of structs with a single non-zero-sized field
2 parents bf597b9 + 054361b commit 308c474

File tree

1 file changed

+47
-20
lines changed

1 file changed

+47
-20
lines changed

Diff for: reference/src/layout/structs-and-tuples.md

+47-20
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,17 @@ Structs can have various `#[repr]` flags that influence their layout:
8484

8585
### Default layout ("repr rust")
8686

87-
**The default layout of structs is not specified.** As of this
88-
writing, we have not reached a full consensus on what limitations
89-
should exist on possible field struct layouts, so effectively one must
90-
assume that the compiler can select any layout it likes for each
91-
struct on each compilation, and it is not required to select the same
92-
layout across two compilations. This implies that (among other things)
93-
two structs with the same field types may not be laid out in the same
94-
way (for example, the hypothetical struct representing tuples may be
95-
laid out differently from user-declared structs).
87+
With the exception of the guarantees provided below, **the default layout of
88+
structs is not specified.**
89+
90+
As of this writing, we have not reached a full consensus on what limitations
91+
should exist on possible field struct layouts, so effectively one must assume
92+
that the compiler can select any layout it likes for each struct on each
93+
compilation, and it is not required to select the same layout across two
94+
compilations. This implies that (among other things) two structs with the same
95+
field types may not be laid out in the same way (for example, the hypothetical
96+
struct representing tuples may be laid out differently from user-declared
97+
structs).
9698

9799
Known things that can influence layout (non-exhaustive):
98100

@@ -123,9 +125,10 @@ unsizing. E.g., `struct Foo { x: u16, y: u32 }` and `struct Foo<T> {
123125
x: u16, y: T }` where `T = u32` are not guaranteed to be identical.
124126

125127
#### Zero-sized structs
128+
[zero-sized structs]: #zero-sized-structs
126129

127-
For `repr(Rust)`, `repr(packed(N))`, `repr(align(N))`, and `repr(C)`
128-
structs: if all fields of a struct have size 0, then the struct has size 0.
130+
For `repr(Rust)`, `repr(packed(N))`, `repr(align(N))`, and `repr(C)` structs: if
131+
all fields of a struct have size 0, then the struct has size 0.
129132

130133
For example, all these types are zero-sized:
131134

@@ -141,6 +144,37 @@ struct Zst2(Zst1, Zst0);
141144
# }
142145
```
143146

147+
In particular, a struct with no fields is a ZST, and if it has no repr attribute
148+
it is moreover a 1-ZST as it also has no alignment requirements.
149+
150+
#### Single-field structs
151+
[single-field structs]: #single-field-structs
152+
153+
A struct with only one field has the same layout as that field.
154+
155+
#### Structs with 1-ZST fields
156+
157+
For the purposes of struct layout [1-ZST] fields are ignored.
158+
159+
In particular, if all but one field are 1-ZST, then the struct is equivalent to
160+
a [single-field struct][single-field structs]. In other words, if all but one
161+
field is a 1-ZST, then the entire struct has the same layout as that one field.
162+
163+
Similarly, if all fields are 1-ZST, then the struct has the same layout as a
164+
[struct with no fields][zero-sized structs], and is itself a 1-ZST.
165+
166+
For example:
167+
168+
```rust
169+
type Zst1 = ();
170+
struct S1(i32, Zst1); // same layout as i32
171+
172+
type Zst2 = [u16; 0];
173+
struct S2(Zst2, Zst1); // same layout as Zst2
174+
175+
struct S3(Zst1); // same layout as Zst1
176+
```
177+
144178
#### Unresolved questions
145179

146180
During the course of the discussion in [#11] and [#12], various
@@ -150,15 +184,6 @@ issue has been opened for further discussion on the repository. This
150184
section documents the questions and gives a few light details, but the
151185
reader is referred to the issues for further discussion.
152186

153-
**Single-field structs ([#34]).** If you have a struct with single field
154-
(`struct Foo { x: T }`), should we guarantee that the memory layout of
155-
`Foo` is identical to the memory layout of `T` (note that ABI details
156-
around function calls may still draw a distinction, which is why
157-
`#[repr(transparent)]` is needed). What about zero-sized types like
158-
`PhantomData`?
159-
160-
[#34]: https://github.com/rust-rfcs/unsafe-code-guidelines/issues/34
161-
162187
**Homogeneous structs ([#36]).** If you have homogeneous structs, where all
163188
the `N` fields are of a single type `T`, can we guarantee a mapping to
164189
the memory layout of `[T; N]`? How do we map between the field names
@@ -400,3 +425,5 @@ proposal (and -- further -- it does not match our existing behavior):
400425
thread](https://github.com/rust-rfcs/unsafe-code-guidelines/pull/31#discussion_r224955817)).
401426
- Many people would prefer the name ordering to be chosen for
402427
"readability" and not optimal layout.
428+
429+
[1-ZST]: ../glossary.md#zero-sized-type--zst

0 commit comments

Comments
 (0)