Skip to content

Commit 969e45e

Browse files
committed
update union field type rules
1 parent d4d5dfd commit 969e45e

File tree

2 files changed

+22
-30
lines changed

2 files changed

+22
-30
lines changed

src/items/unions.md

+14-23
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ The key property of unions is that all fields of a union share common storage.
2020
As a result, writes to one field of a union can overwrite its other fields, and
2121
size of a union is determined by the size of its largest field.
2222

23+
Union field types are restricted to the following subset of types:
24+
- `Copy` types
25+
- References (`&T` and `&mut T` for arbitrary `T`)
26+
- `ManuallyDrop<T>` (for arbitrary `T`)
27+
- Tuples and arrays containing only allowed union field types
28+
29+
This restriction ensures, in particular, that union fields never need to be
30+
dropped. Like for structs and enums, it is possible to `impl Drop` for a union
31+
to manually define what happens when it gets dropped.
32+
2333
## Initialization of a union
2434

2535
A value of a union type can be created using the same syntax that is used for
@@ -67,32 +77,13 @@ unsafe {
6777
}
6878
```
6979

70-
Writes to [`Copy`] or [`ManuallyDrop`][ManuallyDrop] union fields do not
71-
require reads for running destructors, so these writes don't have to be placed
72-
in `unsafe` blocks
73-
74-
```rust
75-
# use std::mem::ManuallyDrop;
76-
union MyUnion { f1: u32, f2: ManuallyDrop<String> }
77-
let mut u = MyUnion { f1: 1 };
78-
79-
// These do not require `unsafe`.
80-
u.f1 = 2;
81-
u.f2 = ManuallyDrop::new(String::from("example"));
82-
```
83-
8480
Commonly, code using unions will provide safe wrappers around unsafe union
8581
field accesses.
8682

87-
## Unions and `Drop`
88-
89-
When a union is dropped, it cannot know which of its fields needs to be dropped.
90-
For this reason, all union fields must either be of a [`Copy`] type or of the
91-
shape [`ManuallyDrop<_>`][ManuallyDrop]. This ensures that a union does not
92-
need to drop anything when it goes out of scope.
93-
94-
Like for structs and enums, it is possible to `impl Drop` for a union to
95-
manually define what happens when it gets dropped.
83+
In contrast, writes to union fields are safe, since they just overwrite
84+
arbitrary data, but cannot cause undefined behavior. (Note that union field
85+
types can never have drop glue, so a union field write will never implicitly
86+
drop anything.)
9687

9788
## Pattern matching on unions
9889

src/types/union.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ A *union type* is a nominal, heterogeneous C-like union, denoted by the name of
44
a [`union` item][item].
55

66
Unions have no notion of an "active field". Instead, every union access
7-
transmutes parts of the content of the union to the type of the accessed
8-
field. Since transmutes can cause unexpected or undefined behaviour, `unsafe`
9-
is required to read from a union field, or to write to a field that doesn't
10-
implement [`Copy`] or has a [`ManuallyDrop`] type. See the [item] documentation
11-
for further details.
7+
transmutes parts of the content of the union to the type of the accessed field.
8+
Since transmutes can cause unexpected or undefined behaviour, `unsafe` is
9+
required to read from a union field. Union field types are also restricted to a
10+
subset of types which ensures that they never need dropping. See the [item]
11+
documentation for further details.
1212

13-
The memory layout of a `union` is undefined by default, but the `#[repr(...)]`
14-
attribute can be used to fix a layout.
13+
The memory layout of a `union` is undefined by default (in particular, fields do
14+
*not* have to be at offset 0), but the `#[repr(...)]` attribute can be used to
15+
fix a layout.
1516

1617
[`Copy`]: ../special-types-and-traits.md#copy
1718
[`ManuallyDrop`]: ../../std/mem/struct.ManuallyDrop.html

0 commit comments

Comments
 (0)