25
25
> _ EnumItemDiscriminant_ :
26
26
>   ;  ; ` = ` [ _ Expression_ ]
27
27
28
- An _ enumeration_ is a simultaneous definition of a nominal [ enumerated type] as
29
- well as a set of * constructors* , that can be used to create or pattern-match
30
- values of the corresponding enumerated type.
31
-
32
- [ enumerated type ] : types.html#enumerated-types
28
+ An * enumeration* , also referred to as * 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.
33
31
34
32
Enumerations are declared with the keyword ` enum ` .
35
33
@@ -45,11 +43,11 @@ let mut a: Animal = Animal::Dog;
45
43
a = Animal :: Cat ;
46
44
```
47
45
48
- Enumeration constructors can have either named or unnamed fields:
46
+ Enum constructors can have either named or unnamed fields:
49
47
50
48
``` rust
51
49
enum Animal {
52
- Dog (String , f64 ),
50
+ Dog (String , f64 ),
53
51
Cat { name : String , weight : f64 },
54
52
}
55
53
@@ -59,45 +57,87 @@ a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 };
59
57
60
58
In this example, ` Cat ` is a _ struct-like enum variant_ , whereas ` Dog ` is simply
61
59
called an enum variant. Each enum instance has a _ discriminant_ which is an
62
- integer associated to it that is used to determine which variant it holds.
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
63
64
64
## Custom Discriminant Values for Field-Less Enumerations
65
65
66
66
If there is no data attached to * any* of the variants of an enumeration,
67
67
then the discriminant can be directly chosen and accessed.
68
68
69
- If a discriminant isn't specified, they start at zero, and add one for each
70
- variant, in order. Each enum value is just its discriminant which you can
71
- specify explicitly:
69
+ These enumerations can be cast to integer types with the ` as ` operator by a
70
+ [ numeric cast] . The enumeration can optionaly specify which integer each
71
+ discriminant gets by following the variant name with ` = ` and then an integer
72
+ literal. If the first variant in the declaration is unspecified, then it is set
73
+ to zero. For every unspecified discriminant, it is set to one higher than the
74
+ previous variant in the declaration.
72
75
73
76
``` rust
74
77
enum Foo {
75
78
Bar , // 0
76
- Baz = 123 ,
79
+ Baz = 123 , // 123
77
80
Quux , // 124
78
81
}
82
+
83
+ let baz_discriminant = Foo :: Baz as u32 ;
84
+ assert_eq! (baz_discriminant , 123 );
79
85
```
80
86
81
- The right hand side of the specification is interpreted as an ` isize ` value,
82
- but the compiler is allowed to use a smaller type in the actual memory layout.
83
- The [ ` repr ` attribute ] can be added in order to change the type of the right
84
- hand side and specify the memory layout .
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 ] .
85
91
86
- [ `repr` attribute ] : attributes.html#ffi-attributes
92
+ It is an error when two variants share the same discriminant.
87
93
88
- You can also cast a field-less enum to get its discriminant:
94
+ ``` rust,ignore
95
+ enum SharedDiscriminantError {
96
+ SharedA = 1,
97
+ SharedB = 1
98
+ }
89
99
90
- ``` rust
91
- # enum Foo { Baz = 123 }
92
- let x = Foo :: Baz as u32 ; // x is now 123u32
100
+ enum SharedDiscriminantError2 {
101
+ Zero, // 0
102
+ One, // 1
103
+ OneToo = 1 // 1 (collision with previous!)
104
+ }
93
105
```
94
106
95
- This only works as long as none of the variants have data attached. If it were
96
- ` Baz(i32) ` , this is disallowed.
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,ignore
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
+ ```
97
133
98
134
[ IDENTIFIER ] : identifiers.html
99
135
[ _Generics_ ] : items.html#type-parameters
100
136
[ _WhereClause_ ] : items.html#type-parameters
101
137
[ _Expression_ ] : expressions.html
102
138
[ _TupleFields_ ] : items/structs.html
103
139
[ _StructFields_ ] : items/structs.html
140
+ [ enumerated type ] : types.html#enumerated-types
141
+ [ `mem::discriminant` ] : std/mem/fn.discriminant.html
142
+ [ numeric cast ] : expressions/operator-expr.html#semantics
143
+ [ `repr` attribute ] : attributes.html#ffi-attributes
0 commit comments