]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/items/unions.md
New upstream version 1.49.0~beta.4+dfsg1
[rustc.git] / src / doc / reference / src / items / unions.md
CommitLineData
ea8adc8c
XL
1# Unions
2
8faf50e0
XL
3> **<sup>Syntax</sup>**\
4> _Union_ :\
ff7c6d11
XL
5> &nbsp;&nbsp; `union` [IDENTIFIER]&nbsp;[_Generics_]<sup>?</sup> [_WhereClause_]<sup>?</sup>
6> `{`[_StructFields_] `}`
7
ea8adc8c
XL
8A union declaration uses the same syntax as a struct declaration, except with
9`union` in place of `struct`.
10
11```rust
12#[repr(C)]
13union MyUnion {
14 f1: u32,
15 f2: f32,
16}
17```
18
19The key property of unions is that all fields of a union share common storage.
ba9703b0 20As a result, writes to one field of a union can overwrite its other fields, and
ea8adc8c
XL
21size of a union is determined by the size of its largest field.
22
416331ca
XL
23## Initialization of a union
24
ea8adc8c
XL
25A value of a union type can be created using the same syntax that is used for
26struct types, except that it must specify exactly one field:
27
28```rust
29# union MyUnion { f1: u32, f2: f32 }
30#
31let u = MyUnion { f1: 1 };
32```
33
532ac7d7
XL
34The expression above creates a value of type `MyUnion` and initializes the
35storage using field `f1`. The union can be accessed using the same syntax as
36struct fields:
ea8adc8c 37
60c5eb7d
XL
38```rust
39# union MyUnion { f1: u32, f2: f32 }
40#
41# let u = MyUnion { f1: 1 };
42let f = unsafe { u.f1 };
ea8adc8c
XL
43```
44
416331ca
XL
45## Reading and writing union fields
46
532ac7d7
XL
47Unions have no notion of an "active field". Instead, every union access just
48interprets the storage at the type of the field used for the access. Reading a
416331ca
XL
49union field reads the bits of the union at the field's type. Fields might have a
50non-zero offset (except when `#[repr(C)]` is used); in that case the bits
51starting at the offset of the fields are read. It is the programmer's
52responsibility to make sure that the data is valid at the field's type. Failing
53to do so results in undefined behavior. For example, reading the value `3` at
54type `bool` is undefined behavior. Effectively, writing to and then reading from
55a `#[repr(C)]` union is analogous to a [`transmute`] from the type used for
532ac7d7
XL
56writing to the type used for reading.
57
58Consequently, all reads of union fields have to be placed in `unsafe` blocks:
ea8adc8c
XL
59
60```rust
61# union MyUnion { f1: u32, f2: f32 }
62# let u = MyUnion { f1: 1 };
63#
64unsafe {
65 let f = u.f1;
66}
67```
68
69Writes to `Copy` union fields do not require reads for running destructors, so
70these writes don't have to be placed in `unsafe` blocks
71
72```rust
73# union MyUnion { f1: u32, f2: f32 }
74# let mut u = MyUnion { f1: 1 };
75#
76u.f1 = 2;
77```
78
79Commonly, code using unions will provide safe wrappers around unsafe union
80field accesses.
81
29967ef6
XL
82## Unions and `Drop`
83
84When a union is dropped, it cannot know which of its fields needs to be dropped.
85For this reason, all union fields must either be of a `Copy` type or of the
86shape [`ManuallyDrop<_>`]. This ensures that a union does not need to drop
87anything when it goes out of scope.
88
89Like for structs and enums, it is possible to `impl Drop` for a union to
90manually define what happens when it gets dropped.
91
416331ca
XL
92## Pattern matching on unions
93
ea8adc8c 94Another way to access union fields is to use pattern matching. Pattern matching
532ac7d7
XL
95on union fields uses the same syntax as struct patterns, except that the pattern
96must specify exactly one field. Since pattern matching is like reading the union
97with a particular field, it has to be placed in `unsafe` blocks as well.
ea8adc8c
XL
98
99```rust
100# union MyUnion { f1: u32, f2: f32 }
101#
102fn f(u: MyUnion) {
103 unsafe {
104 match u {
105 MyUnion { f1: 10 } => { println!("ten"); }
106 MyUnion { f2 } => { println!("{}", f2); }
107 }
108 }
109}
110```
111
112Pattern matching may match a union as a field of a larger structure. In
113particular, when using a Rust union to implement a C tagged union via FFI, this
114allows matching on the tag and the corresponding field simultaneously:
115
116```rust
117#[repr(u32)]
118enum Tag { I, F }
119
120#[repr(C)]
121union U {
122 i: i32,
123 f: f32,
124}
125
126#[repr(C)]
127struct Value {
128 tag: Tag,
129 u: U,
130}
131
132fn is_zero(v: Value) -> bool {
133 unsafe {
134 match v {
e74abb32
XL
135 Value { tag: Tag::I, u: U { i: 0 } } => true,
136 Value { tag: Tag::F, u: U { f: num } } if num == 0.0 => true,
ea8adc8c
XL
137 _ => false,
138 }
139 }
140}
141```
142
416331ca
XL
143## References to union fields
144
ea8adc8c
XL
145Since union fields share common storage, gaining write access to one field of a
146union can give write access to all its remaining fields. Borrow checking rules
147have to be adjusted to account for this fact. As a result, if one field of a
148union is borrowed, all its remaining fields are borrowed as well for the same
149lifetime.
150
60c5eb7d
XL
151```rust,compile_fail
152# union MyUnion { f1: u32, f2: f32 }
ea8adc8c
XL
153// ERROR: cannot borrow `u` (via `u.f2`) as mutable more than once at a time
154fn test() {
155 let mut u = MyUnion { f1: 1 };
156 unsafe {
157 let b1 = &mut u.f1;
60c5eb7d 158// ---- first mutable borrow occurs here (via `u.f1`)
ea8adc8c 159 let b2 = &mut u.f2;
60c5eb7d 160// ^^^^ second mutable borrow occurs here (via `u.f2`)
ea8adc8c
XL
161 *b1 = 5;
162 }
60c5eb7d 163// - first borrow ends here
ea8adc8c
XL
164 assert_eq!(unsafe { u.f1 }, 5);
165}
166```
167
e1599b0c 168As you could see, in many aspects (except for layouts, safety, and ownership)
ea8adc8c
XL
169unions behave exactly like structs, largely as a consequence of inheriting
170their syntactic shape from structs. This is also true for many unmentioned
171aspects of Rust language (such as privacy, name resolution, type inference,
172generics, trait implementations, inherent implementations, coherence, pattern
173checking, etc etc etc).
174
416331ca
XL
175[IDENTIFIER]: ../identifiers.md
176[_Generics_]: generics.md
177[_WhereClause_]: generics.md#where-clauses
178[_StructFields_]: structs.md
179[`transmute`]: ../../std/mem/fn.transmute.html
29967ef6 180[`ManuallyDrop<_>`]: ../../std/mem/struct.ManuallyDrop.html