Skip to content

Commit 94a3b9b

Browse files
author
Kyle Strand
committed
Merge branch 'master' of https://github.com/rust-lang/reference into c-unwind-documentation
2 parents e9afd5a + b9ccb09 commit 94a3b9b

12 files changed

+177
-33
lines changed

src/behavior-considered-undefined.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ code.
2525
* Data races.
2626
* Evaluating a [dereference expression] (`*expr`) on a raw pointer that is
2727
[dangling] or unaligned, even in [place expression context]
28-
(e.g. `addr_of!(&*expr)`).
28+
(e.g. `addr_of!(*expr)`).
2929
* Breaking the [pointer aliasing rules]. `Box<T>`, `&mut T` and `&T` follow
3030
LLVM’s scoped [noalias] model, except if the `&T` contains an
3131
[`UnsafeCell<U>`]. References and boxes must not be [dangling] while they are

src/const_eval.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ Conversely, the following are possible in a const function, but not in a const c
113113
[Const parameters]: items/generics.md
114114
[dereference operator]: expressions/operator-expr.md#the-dereference-operator
115115
[destructors]: destructors.md
116-
[enum discriminants]: items/enumerations.md#custom-discriminant-values-for-fieldless-enumerations
116+
[enum discriminants]: items/enumerations.md#discriminants
117117
[expression statements]: statements.md#expression-statements
118118
[expressions]: expressions.md
119119
[field]: expressions/field-expr.md

src/destructors.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ smallest scope that contains the expression and is one of the following:
162162
* The `else` block of an `if` expression.
163163
* The condition expression of an `if` or `while` expression, or a `match`
164164
guard.
165-
* The expression for a match arm.
165+
* The body expression for a match arm.
166166
* The second operand of a [lazy boolean expression].
167167

168168
> **Notes**:
@@ -272,8 +272,9 @@ let x = &mut 0;
272272
println!("{}", x);
273273
```
274274

275-
If a borrow, dereference, field, or tuple indexing expression has an extended
276-
temporary scope then so does its operand. If an indexing expression has an
275+
If a [borrow][borrow expression], [dereference][dereference expression],
276+
[field][field expression], or [tuple indexing expression] has an extended
277+
temporary scope then so does its operand. If an [indexing expression] has an
277278
extended temporary scope then the indexed expression also has an extended
278279
temporary scope.
279280

@@ -386,8 +387,12 @@ variable or field from being dropped automatically.
386387
[block expression]: expressions/block-expr.md
387388
[borrow expression]: expressions/operator-expr.md#borrow-operators
388389
[cast expression]: expressions/operator-expr.md#type-cast-expressions
390+
[dereference expression]: expressions/operator-expr.md#the-dereference-operator
391+
[field expression]: expressions/field-expr.md
392+
[indexing expression]: expressions/array-expr.md#array-and-slice-indexing-expressions
389393
[struct expression]: expressions/struct-expr.md
390394
[tuple expression]: expressions/tuple-expr.md#tuple-expressions
395+
[tuple indexing expression]: expressions/tuple-expr.md#tuple-indexing-expressions
391396

392397
[`for`]: expressions/loop-expr.md#iterator-loops
393398
[`if let`]: expressions/if-expr.md#if-let-expressions

src/expressions/field-expr.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ foo().x;
3737
## Automatic dereferencing
3838

3939
If the type of the container operand implements [`Deref`] or [`DerefMut`][`Deref`] depending on whether the operand is [mutable], it is *automatically dereferenced* as many times as necessary to make the field access possible.
40-
This processes is also called *autoderef* for short.
40+
This process is also called *autoderef* for short.
4141

4242
## Borrowing
4343

src/expressions/if-expr.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperat
129129
Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]).
130130
When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below:
131131

132-
<!-- ignore: psuedo code -->
132+
<!-- ignore: pseudo code -->
133133
```rust,ignore
134134
// Before...
135135
if let PAT = EXPR && EXPR { .. }

src/expressions/operator-expr.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ reference types and `mut` or `const` in pointer types.
368368
| Type of `e` | `U` | Cast performed by `e as U` |
369369
|-----------------------|-----------------------|----------------------------------|
370370
| Integer or Float type | Integer or Float type | Numeric cast |
371-
| C-like enum | Integer type | Enum cast |
371+
| Enumeration | Integer type | Enum cast |
372372
| `bool` or `char` | Integer type | Primitive to integer cast |
373373
| `u8` | `char` | `u8` to `char` cast |
374374
| `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast |
@@ -430,6 +430,10 @@ halfway between two floating point numbers.
430430
#### Enum cast
431431

432432
Casts an enum to its discriminant, then uses a numeric cast if needed.
433+
Casting is limited to the following kinds of enumerations:
434+
435+
* [Unit-only enums]
436+
* [Field-less enums] without [explicit discriminants], or where only unit-variants have explicit discriminants
433437

434438
#### Primitive to integer cast
435439

@@ -596,7 +600,7 @@ It will then set the value of the assigned operand's place to the value of perfo
596600

597601
> **Note**: This is different than other expressions in that the right operand is evaluated before the left one.
598602
599-
Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assigment trait of the operator (see the table earlier in this chapter).
603+
Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assignment trait of the operator (see the table earlier in this chapter).
600604
A mutable borrow of the assigned operand is automatically taken.
601605

602606
For example, the following expression statements in `example` are equivalent:
@@ -632,6 +636,8 @@ See [this test] for an example of using this dependency.
632636

633637
[copies or moves]: ../expressions.md#moved-and-copied-types
634638
[dropping]: ../destructors.md
639+
[explicit discriminants]: ../items/enumerations.md#explicit-discriminants
640+
[field-less enums]: ../items/enumerations.md#field-less-enum
635641
[grouped expression]: grouped-expr.md
636642
[literal expression]: literal-expr.md#integer-literal-expressions
637643
[logical and]: ../types/boolean.md#logical-and
@@ -643,6 +649,7 @@ See [this test] for an example of using this dependency.
643649
[assignee expression]: ../expressions.md#place-expressions-and-value-expressions
644650
[undefined behavior]: ../behavior-considered-undefined.md
645651
[unit]: ../types/tuple.md
652+
[Unit-only enums]: ../items/enumerations.md#unit-only-enum
646653
[value expression]: ../expressions.md#place-expressions-and-value-expressions
647654
[temporary value]: ../expressions.md#temporaries
648655
[this test]: https://github.com/rust-lang/rust/blob/1.58.0/src/test/ui/expr/compound-assignment/eval-order.rs

src/items/enumerations.md

Lines changed: 150 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
>
1414
> _EnumItem_ :\
1515
> &nbsp;&nbsp; _OuterAttribute_<sup>\*</sup> [_Visibility_]<sup>?</sup>\
16-
> &nbsp;&nbsp; [IDENTIFIER]&nbsp;( _EnumItemTuple_ | _EnumItemStruct_
17-
> | _EnumItemDiscriminant_ )<sup>?</sup>
16+
> &nbsp;&nbsp; [IDENTIFIER]&nbsp;( _EnumItemTuple_ | _EnumItemStruct_ )<sup>?</sup>
17+
> _EnumItemDiscriminant_<sup>?</sup>
1818
>
1919
> _EnumItemTuple_ :\
2020
> &nbsp;&nbsp; `(` [_TupleFields_]<sup>?</sup> `)`
@@ -56,22 +56,71 @@ a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 };
5656
```
5757

5858
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.
59+
called an enum variant.
6360

64-
## Custom Discriminant Values for Fieldless Enumerations
61+
An enum where no constructors contain fields are called a
62+
*<span id="field-less-enum">field-less enum</span>*. For example, this is a fieldless enum:
6563

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.
64+
```rust
65+
enum Fieldless {
66+
Tuple(),
67+
Struct{},
68+
Unit,
69+
}
70+
```
71+
72+
If a field-less enum only contains unit variants, the enum is called an
73+
*<span id="unit-only-enum">unit-only enum</span>*. For example:
74+
75+
```rust
76+
enum Enum {
77+
Foo = 3,
78+
Bar = 2,
79+
Baz = 1,
80+
}
81+
```
82+
83+
<span id="custom-discriminant-values-for-fieldless-enumerations"></span>
84+
## Discriminants
85+
86+
Each enum instance has a _discriminant_: an integer logically associated to it
87+
that is used to determine which variant it holds.
88+
89+
Under the [default representation], the discriminant is interpreted as
90+
an `isize` value. However, the compiler is allowed to use a smaller type (or
91+
another means of distinguishing variants) in its actual memory layout.
92+
93+
### Assigning discriminant values
94+
95+
#### Explicit discriminants
6896

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.
97+
In two circumstances, the discriminant of a variant may be explicitly set by
98+
following the variant name with `=` and a [constant expression]:
99+
100+
101+
1. if the enumeration is "[unit-only]".
102+
103+
104+
2. if a [primitive representation] is used. For example:
105+
106+
```rust
107+
#[repr(u8)]
108+
enum Enum {
109+
Unit = 3,
110+
Tuple(u16),
111+
Struct {
112+
a: u8,
113+
b: u16,
114+
} = 1,
115+
}
116+
```
117+
118+
#### Implicit discriminants
119+
120+
If a discriminant for a variant is not specified, then it is set to one higher
121+
than the discriminant of the previous variant in the declaration. If the
122+
discriminant of the first variant in the declaration is unspecified, then
123+
it is set to zero.
75124

76125
```rust
77126
enum Foo {
@@ -84,10 +133,7 @@ let baz_discriminant = Foo::Baz as u32;
84133
assert_eq!(baz_discriminant, 123);
85134
```
86135

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].
136+
#### Restrictions
91137

92138
It is an error when two variants share the same discriminant.
93139

@@ -122,7 +168,89 @@ enum OverflowingDiscriminantError2 {
122168
}
123169
```
124170

125-
## Zero-variant Enums
171+
### Accessing discriminant
172+
173+
#### Via `mem::discriminant`
174+
175+
[`mem::discriminant`] returns an opaque reference to the discriminant of
176+
an enum value which can be compared. This cannot be used to get the value
177+
of the discriminant.
178+
179+
#### Casting
180+
181+
If an enumeration is [unit-only] (with no tuple and struct variants), then its
182+
discriminant can be directly accessed with a [numeric cast]; e.g.:
183+
184+
```rust
185+
enum Enum {
186+
Foo,
187+
Bar,
188+
Baz,
189+
}
190+
191+
assert_eq!(0, Enum::Foo as isize);
192+
assert_eq!(1, Enum::Bar as isize);
193+
assert_eq!(2, Enum::Baz as isize);
194+
```
195+
196+
[Field-less enums] can be casted if they do not have explicit discriminants, or where only unit variants are explicit.
197+
198+
```rust
199+
enum Fieldless {
200+
Tuple(),
201+
Struct{},
202+
Unit,
203+
}
204+
205+
assert_eq!(0, Fieldless::Tuple() as isize);
206+
assert_eq!(1, Fieldless::Struct{} as isize);
207+
assert_eq!(2, Fieldless::Unit as isize);
208+
209+
#[repr(u8)]
210+
enum FieldlessWithDiscrimants {
211+
First = 10,
212+
Tuple(),
213+
Second = 20,
214+
Struct{},
215+
Unit,
216+
}
217+
218+
assert_eq!(10, FieldlessWithDiscrimants::First as u8);
219+
assert_eq!(11, FieldlessWithDiscrimants::Tuple() as u8);
220+
assert_eq!(20, FieldlessWithDiscrimants::Second as u8);
221+
assert_eq!(21, FieldlessWithDiscrimants::Struct{} as u8);
222+
assert_eq!(22, FieldlessWithDiscrimants::Unit as u8);
223+
```
224+
225+
#### Pointer casting
226+
227+
If the enumeration specifies a [primitive representation], then the
228+
discriminant may be reliably accessed via unsafe pointer casting:
229+
230+
```rust
231+
#[repr(u8)]
232+
enum Enum {
233+
Unit,
234+
Tuple(bool),
235+
Struct{a: bool},
236+
}
237+
238+
impl Enum {
239+
fn discriminant(&self) -> u8 {
240+
unsafe { *(self as *const Self as *const u8) }
241+
}
242+
}
243+
244+
let unit_like = Enum::Unit;
245+
let tuple_like = Enum::Tuple(true);
246+
let struct_like = Enum::Struct{a: false};
247+
248+
assert_eq!(0, unit_like.discriminant());
249+
assert_eq!(1, tuple_like.discriminant());
250+
assert_eq!(2, struct_like.discriminant());
251+
```
252+
253+
## Zero-variant enums
126254

127255
Enums with zero variants are known as *zero-variant enums*. As they have
128256
no valid values, they cannot be instantiated.
@@ -181,8 +309,10 @@ enum E {
181309
[enumerated type]: ../types/enum.md
182310
[`mem::discriminant`]: ../../std/mem/fn.discriminant.html
183311
[never type]: ../types/never.md
312+
[unit-only]: #unit-only-enum
184313
[numeric cast]: ../expressions/operator-expr.md#semantics
185314
[constant expression]: ../const_eval.md#constant-expressions
186315
[default representation]: ../type-layout.md#the-default-representation
187316
[primitive representation]: ../type-layout.md#primitive-representations
188317
[`C` representation]: ../type-layout.md#the-c-representation
318+
[Field-less enums]: #field-less-enum

src/linkage.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ be ignored in favor of only building the artifacts specified by command line.
7373
being built for a different target.
7474

7575
Note that these outputs are stackable in the sense that if multiple are
76-
specified, then the compiler will produce each form of output at once without
76+
specified, then the compiler will produce each form of output without
7777
having to recompile. However, this only applies for outputs specified by the
7878
same method. If only `crate_type` attributes are specified, then they will all
7979
be built, but if one or more `--crate-type` command line flags are specified,

src/patterns.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ The bounds can be literals or paths that point to constant values.
429429

430430
A half open range with only an upper bound is written as `..=` followed by its upper bound.
431431
These range patterns will match on any value less than or equal to the upper bound.
432-
For example, `..=10` will match 10, 1, 0, and for signed interger types, all negative values.
432+
For example, `..=10` will match 10, 1, 0, and for signed integer types, all negative values.
433433

434434
Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
435435

src/trait-bounds.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ provided on any type in a [where clause]. There are also shorter forms for
2727
certain common cases:
2828

2929
* Bounds written after declaring a [generic parameter][generic]:
30-
`fn f<A: Copy>() {}` is the same as `fn f<A> where A: Copy () {}`.
30+
`fn f<A: Copy>() {}` is the same as `fn f<A>() where A: Copy {}`.
3131
* In trait declarations as [supertraits]: `trait Circle : Shape {}` is
3232
equivalent to `trait Circle where Self : Shape {}`.
3333
* In trait declarations as bounds on [associated types]:

0 commit comments

Comments
 (0)