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