You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/divergence.md
+19-37Lines changed: 19 additions & 37 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,50 +6,32 @@ Divergence is the state where a particular section of code could never be encoun
6
6
7
7
Any expression of type [`!`](./types/never.md) is a _diverging expression_, but there are also diverging expressions which are not of type `!` (e.g. `Some(panic!())`).
8
8
9
-
r[divergence.diverging-expressions]
10
-
## Producing diverging expressions
11
-
12
-
r[divergence.diverging-expressions.unconditional]
13
-
The following language constructs unconditonally produce a _diverging expression_ of the type [`!`](./types/never.md):
14
-
15
-
*[A call to a function returning `!`.](./types/never.md#r-type.never.constraint)
16
-
*[A `loop` expression with no corresponding break.](./expressions/loop-expr.md#r-expr.loop.infinite.diverging)
Copy file name to clipboardExpand all lines: src/expressions/block-expr.md
+41-2Lines changed: 41 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,7 +44,7 @@ r[expr.block.result]
44
44
Then the final operand is executed, if given.
45
45
46
46
r[expr.block.type]
47
-
Typically, the type of a block is the type of the final operand, or `()` if the final operand is omitted.
47
+
Except in the case of divergence (see below), the type of a block is the type of the final operand, or `()` if the final operand is omitted.
48
48
49
49
```rust
50
50
# fnfn_call() {}
@@ -64,7 +64,46 @@ assert_eq!(5, five);
64
64
> As a control flow expression, if a block expression is the outer expression of an expression statement, the expected type is `()` unless it is followed immediately by a semicolon.
65
65
66
66
r[expr.block.type.diverging]
67
-
A block is itself considered to be [diverging](../divergence.md) if all reachable control flow paths contain a [diverging expression](../divergence.md#r-divergence.diverging-expressions).
67
+
A block is itself considered to be [diverging](../divergence.md) if all reachable control flow paths contain a [diverging expression](../divergence.md#r-divergence.diverging-expressions), unless that expression is a place expression that is not read from.
68
+
69
+
```rust
70
+
# #![ feature(never_type) ]
71
+
# fnmake<T>() ->T { loop {} }
72
+
letno_control_flow:!= {
73
+
// There are no conditional statements, so this entire block is diverging.
74
+
loop {}
75
+
};
76
+
77
+
letcontrol_flow_diverging:!= {
78
+
// All paths are diverging, so this entire block is diverging.
79
+
iftrue {
80
+
loop {}
81
+
} else {
82
+
loop {}
83
+
}
84
+
};
85
+
86
+
letcontrol_flow_not_diverging: () = {
87
+
// Some paths are not diverging, so this entire block is not diverging.
88
+
iftrue {
89
+
()
90
+
} else {
91
+
loop {}
92
+
}
93
+
};
94
+
95
+
structFoo {
96
+
x:!,
97
+
}
98
+
99
+
letfoo=Foo { x:make() };
100
+
letdiverging_place_not_read: () = {
101
+
let_: () = {
102
+
// Asssignment to `_` means the place is not read
103
+
let_=foo.x;
104
+
};
105
+
};
106
+
```
68
107
69
108
r[expr.block.value]
70
109
Blocks are always [value expressions] and evaluate the last operand in value expression context.
Copy file name to clipboardExpand all lines: src/expressions/loop-expr.md
+4-6Lines changed: 4 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -292,6 +292,8 @@ for x in 1..100 {
292
292
assert_eq!(last, 12);
293
293
```
294
294
295
+
Thus, the `break` expression itself is diverging and has a type of [`!`](../types/never.md).
296
+
295
297
r[expr.loop.break.label]
296
298
A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression,
297
299
but a [label](#loop-labels) can be used to specify which enclosing loop is affected.
@@ -308,9 +310,6 @@ Example:
308
310
r[expr.loop.break.value]
309
311
A `break` expression is only permitted in the body of a loop, and has one of the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) `break EXPR` or `break 'label EXPR`.
310
312
311
-
r[expr.loop.break.type]
312
-
A `break` expression itself has a type of [`!`](../types/never.md).
Copy file name to clipboardExpand all lines: src/expressions/return-expr.md
+2-3Lines changed: 2 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,6 +12,8 @@ Return expressions are denoted with the keyword `return`.
12
12
r[expr.return.behavior]
13
13
Evaluating a `return` expression moves its argument into the designated output location for the current function call, destroys the current function activation frame, and transfers control to the caller frame.
14
14
15
+
Thus, a `return` expression itself has a type of [`!`](../types/never.md).
16
+
15
17
An example of a `return` expression:
16
18
17
19
```rust
@@ -22,6 +24,3 @@ fn max(a: i32, b: i32) -> i32 {
22
24
returnb;
23
25
}
24
26
```
25
-
26
-
r[expr.return.type]
27
-
A `return` expression itself has a type of [`!`](../types/never.md).
0 commit comments