block-expr: add new rule expr.block.result-value#2174
block-expr: add new rule expr.block.result-value#2174traviscross merged 3 commits intorust-lang:masterfrom
Conversation
Document that the value of a block expression is based on the final operand (if present), just like the type.
e4ab033 to
24a2ca3
Compare
|
Discovered while working on a conference talk about rust, I couldn't find any rule saying that a block expression had a value equal to the final operand, so I added such a rule fn main () {
let result: String = { panic!("test") };
let result: bool = { panic!("test") };
let result: Vec<String> = { panic!("test") };
}also, rule name could be improved, I originally was going to use
@rustbot label A-expressions |
|
From the review policy
Not sure if this is a new guarantee or just documenting a long-standing reality, @traviscross does this need to go through the lang team? |
When there is no final operand to a block (i.e. nothing or nothing after the final semicolon) and the block diverges, we need to say that there is no value as the type is uninhabited. Let's say that.
|
We talked about this on the lang-docs call today. Revised as we discussed on the call. With that, look good to me. Thanks @DanielEScherzer for the PR. |
An earlier commit added a single rule, `r[expr.block.result-value]`,
that documented the value of a block expression in one compound
sentence. While correct, that sentence carried a lot of weight -- the
three cases it described (final operand present, final operand absent,
and diverging) are different enough that each deserves its own rule
and example.
This commit replaces `r[expr.block.result-value]` and
`r[expr.block.type]` with three rules that each describe the type and
value together for one case:
- `r[expr.block.value-trailing-expr]`: when the block has a final
operand, it has that operand's type and value.
- `r[expr.block.value-no-trailing-expr]`: when the block has no final
operand and doesn't diverge, it has unit type and unit value.
- `r[expr.block.value-diverges-no-trailing-expr]`: when the block has
no final operand and diverges, it has the never type and has no
final value (because its type is uninhabited).
The existing example demonstrated type and value together in one
block. We replace it with focused examples for each rule, each
demonstrating the specific case that rule describes. A note after the
third rule highlights the distinction between omitting the final
operand and having an explicit unit final operand -- the diverging
case makes this difference visible, since `{ loop {}; }` has never
type while `{ loop {}; () }` has unit type.
Document that the value of a block expression is based on the final operand (if present), just like the type.