]> git.proxmox.com Git - rustc.git/blob - src/doc/reference/src/items/enumerations.md
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / src / doc / reference / src / items / enumerations.md
1 # Enumerations
2
3 > **<sup>Syntax</sup>**\
4 > _Enumeration_ :\
5 > &nbsp;&nbsp; `enum`
6 > [IDENTIFIER]&nbsp;
7 > [_GenericParams_]<sup>?</sup>
8 > [_WhereClause_]<sup>?</sup>
9 > `{` _EnumItems_<sup>?</sup> `}`
10 >
11 > _EnumItems_ :\
12 > &nbsp;&nbsp; _EnumItem_ ( `,` _EnumItem_ )<sup>\*</sup> `,`<sup>?</sup>
13 >
14 > _EnumItem_ :\
15 > &nbsp;&nbsp; _OuterAttribute_<sup>\*</sup> [_Visibility_]<sup>?</sup>\
16 > &nbsp;&nbsp; [IDENTIFIER]&nbsp;( _EnumItemTuple_ | _EnumItemStruct_
17 > | _EnumItemDiscriminant_ )<sup>?</sup>
18 >
19 > _EnumItemTuple_ :\
20 > &nbsp;&nbsp; `(` [_TupleFields_]<sup>?</sup> `)`
21 >
22 > _EnumItemStruct_ :\
23 > &nbsp;&nbsp; `{` [_StructFields_]<sup>?</sup> `}`
24 >
25 > _EnumItemDiscriminant_ :\
26 > &nbsp;&nbsp; `=` [_Expression_]
27
28 An *enumeration*, also referred to as an *enum*, is a simultaneous definition of a
29 nominal [enumerated type] as well as a set of *constructors*, that can be used
30 to create or pattern-match values of the corresponding enumerated type.
31
32 Enumerations are declared with the keyword `enum`.
33
34 An example of an `enum` item and its use:
35
36 ```rust
37 enum Animal {
38 Dog,
39 Cat,
40 }
41
42 let mut a: Animal = Animal::Dog;
43 a = Animal::Cat;
44 ```
45
46 Enum constructors can have either named or unnamed fields:
47
48 ```rust
49 enum Animal {
50 Dog(String, f64),
51 Cat { name: String, weight: f64 },
52 }
53
54 let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2);
55 a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 };
56 ```
57
58 In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply
59 called an enum variant. Each enum instance has a _discriminant_ which is an
60 integer associated to it that is used to determine which variant it holds. An
61 opaque reference to this discriminant can be obtained with the
62 [`mem::discriminant`] function.
63
64 ## Custom Discriminant Values for Fieldless Enumerations
65
66 If there is no data attached to *any* of the variants of an enumeration,
67 then the discriminant can be directly chosen and accessed.
68
69 These enumerations can be cast to integer types with the `as` operator by a
70 [numeric cast]. The enumeration can optionally specify which integer each
71 discriminant gets by following the variant name with `=` followed by a [constant
72 expression]. If the first variant in the declaration is unspecified, then it is
73 set to zero. For every other unspecified discriminant, it is set to one higher
74 than the previous variant in the declaration.
75
76 ```rust
77 enum Foo {
78 Bar, // 0
79 Baz = 123, // 123
80 Quux, // 124
81 }
82
83 let baz_discriminant = Foo::Baz as u32;
84 assert_eq!(baz_discriminant, 123);
85 ```
86
87 Under the [default representation], the specified discriminant is interpreted as
88 an `isize` value although the compiler is allowed to use a smaller type in the
89 actual memory layout. The size and thus acceptable values can be changed by
90 using a [primitive representation] or the [`C` representation].
91
92 It is an error when two variants share the same discriminant.
93
94 ```rust,compile_fail
95 enum SharedDiscriminantError {
96 SharedA = 1,
97 SharedB = 1
98 }
99
100 enum SharedDiscriminantError2 {
101 Zero, // 0
102 One, // 1
103 OneToo = 1 // 1 (collision with previous!)
104 }
105 ```
106
107 It is also an error to have an unspecified discriminant where the previous
108 discriminant is the maximum value for the size of the discriminant.
109
110 ```rust,compile_fail
111 #[repr(u8)]
112 enum OverflowingDiscriminantError {
113 Max = 255,
114 MaxPlusOne // Would be 256, but that overflows the enum.
115 }
116
117 #[repr(u8)]
118 enum OverflowingDiscriminantError2 {
119 MaxMinusOne = 254, // 254
120 Max, // 255
121 MaxPlusOne // Would be 256, but that overflows the enum.
122 }
123 ```
124
125 ## Zero-variant Enums
126
127 Enums with zero variants are known as *zero-variant enums*. As they have
128 no valid values, they cannot be instantiated.
129
130 ```rust
131 enum ZeroVariants {}
132 ```
133
134 Zero-variant enums are equivalent to the [never type], but they cannot be
135 coerced into other types.
136
137 ```rust,compile_fail
138 # enum ZeroVariants {}
139 let x: ZeroVariants = panic!();
140 let y: u32 = x; // mismatched type error
141 ```
142
143 ## Variant visibility
144
145 Enum variants syntactically allow a [_Visibility_] annotation, but this is
146 rejected when the enum is validated. This allows items to be parsed with a
147 unified syntax across different contexts where they are used.
148
149 ```rust
150 macro_rules! mac_variant {
151 ($vis:vis $name:ident) => {
152 enum $name {
153 $vis Unit,
154
155 $vis Tuple(u8, u16),
156
157 $vis Struct { f: u8 },
158 }
159 }
160 }
161
162 // Empty `vis` is allowed.
163 mac_variant! { E }
164
165 // This is allowed, since it is removed before being validated.
166 #[cfg(FALSE)]
167 enum E {
168 pub U,
169 pub(crate) T(u8),
170 pub(super) T { f: String }
171 }
172 ```
173
174 [IDENTIFIER]: ../identifiers.md
175 [_GenericParams_]: generics.md
176 [_WhereClause_]: generics.md#where-clauses
177 [_Expression_]: ../expressions.md
178 [_TupleFields_]: structs.md
179 [_StructFields_]: structs.md
180 [_Visibility_]: ../visibility-and-privacy.md
181 [enumerated type]: ../types/enum.md
182 [`mem::discriminant`]: ../../std/mem/fn.discriminant.html
183 [never type]: ../types/never.md
184 [numeric cast]: ../expressions/operator-expr.md#semantics
185 [constant expression]: ../const_eval.md#constant-expressions
186 [default representation]: ../type-layout.md#the-default-representation
187 [primitive representation]: ../type-layout.md#primitive-representations
188 [`C` representation]: ../type-layout.md#the-c-representation