Skip to content

Commit 0b877de

Browse files
authoredAug 20, 2018
Merge pull request #376 from Havvy/really_empty_statements
Expand block expression section
2 parents d37b611 + bbcacbb commit 0b877de

File tree

1 file changed

+77
-24
lines changed

1 file changed

+77
-24
lines changed
 

‎src/expressions/block-expr.md

Lines changed: 77 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,85 @@
44
> _BlockExpression_ :\
55
>    `{`\
66
> &nbsp;&nbsp; &nbsp;&nbsp; [_InnerAttribute_]<sup>\*</sup>\
7-
> &nbsp;&nbsp; &nbsp;&nbsp; [_Statement_]<sup>\*</sup>\
7+
> &nbsp;&nbsp; &nbsp;&nbsp; _Statements_<sup>\*</sup>\
88
> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_]<sup>?</sup>\
99
> &nbsp;&nbsp; `}`
10+
>
11+
> _Statements_ :\
12+
> &nbsp;&nbsp; ( `;`\
13+
> &nbsp;&nbsp; | [_ItemDeclaration_]\
14+
> &nbsp;&nbsp; | [_LetStatement_] ;\
15+
> &nbsp;&nbsp; | [_NonControlFlowExpressionStatement_][expression statement] ;\
16+
> &nbsp;&nbsp; | [_FlowControlExpressionStatement_][expression statement] ;<sup>?</sup>\
17+
> &nbsp;&nbsp; )<sup>\*</sup>
18+
19+
A *block expression*, or *block*, is a control flow expression and anonymouse
20+
namespace scope for items and variable declarations. As a control flow
21+
expression, a block sequentially executes its component non-item declaration
22+
statements and then its final optional expression. As an anonymous namespace
23+
scope, item declarations are only in scope inside the block itself and variables
24+
declared by `let` statements are in scope from the next statement until the end
25+
of the block.
26+
27+
Blocks are written as `{`, then any [inner attributes], then [statements],
28+
then an optional expression, and finally a `}`. Statements are usually required
29+
to be followed a semicolon, with two exceptions. Item declaration statements do
30+
not need to be followed by a semicolon. Expression statements usually require
31+
a following semicolon except if its outer expression is a flow control
32+
expression. Furthermore, extra semicolons between statements are allowed, but
33+
these semicolons do not affect semantics.
34+
35+
> Note: The semicolon following a statement is not a part of the statement
36+
> itself. They are invalid when using the `stmt` macro matcher.
37+
38+
When evaluating a block expression, each statement, except for item declaration
39+
statements, is executed sequentially. Then the final expression is executed,
40+
if given.
41+
42+
The type of a block is the type of the final expression, or `()` if the final
43+
expression is omitted.
1044

11-
A _block expression_ is similar to a module in terms of the declarations that
12-
are possible, but can also contain [statements] and end with
13-
an [expression]. Each block conceptually introduces a new namespace scope. Use
14-
items can bring new names into scopes and declared items are in scope for only
15-
the block itself.
45+
```rust
46+
# fn fn_call() {}
47+
let _: () = {
48+
fn_call();
49+
};
1650

17-
A block will execute each statement sequentially, and then execute the
18-
expression, if given. If the block doesn't end in an expression, its value is
19-
`()`:
51+
let five: i32 = {
52+
fn_call();
53+
5
54+
};
2055

21-
```rust
22-
let x: () = { println!("Hello."); };
56+
assert_eq!(5, five);
2357
```
2458

25-
If it ends in an expression, its value and type are that of the expression:
59+
> Note: As a control flow expression, if a block expression is the outer
60+
> expression of an expression statement, the expected type is `()` unless it
61+
> is followed immediately by a semicolon.
2662
27-
```rust
28-
let x: i32 = { println!("Hello."); 5 };
63+
Blocks are always [value expressions] and evaluate the last expression in
64+
value expression context. This can be used to force moving a value if really
65+
needed. For example, the following example fails on the call to `consume_self`
66+
because the struct was moved out of `s` in the block expression.
2967

30-
assert_eq!(5, x);
31-
```
68+
```rust,compile_fail
69+
struct Struct;
3270
33-
Blocks are always [value expressions] and evaluate the last expression in
34-
value expression context. This can be used to force moving a value if really
35-
needed.
71+
impl Struct {
72+
fn consume_self(self) {}
73+
fn borrow_self(&self) {}
74+
}
75+
76+
fn move_by_block_expression() {
77+
let s = Struct;
78+
79+
// Move the value out of `s` in the block expreesion.
80+
(&{ s }).borrow_self();
81+
82+
// Fails to execute because `s` is moved out of.
83+
s.consume_self();
84+
}
85+
```
3686

3787
## `unsafe` blocks
3888

@@ -42,8 +92,8 @@ needed.
4292
4393
_See [`unsafe` block](unsafe-blocks.html) for more information on when to use `unsafe`_
4494

45-
A block of code can be prefixed with the `unsafe` keyword, to permit calling
46-
`unsafe` functions or dereferencing raw pointers within a safe function. Examples:
95+
A block of code can be prefixed with the `unsafe` keyword to permit [unsafe
96+
operations]. Examples:
4797

4898
```rust
4999
unsafe {
@@ -53,8 +103,8 @@ unsafe {
53103
assert_eq!(*a.offset(1), 17);
54104
}
55105

56-
# unsafe fn f() -> i32 { 10 }
57-
let a = unsafe { f() };
106+
# unsafe fn an_unsafe_fn() -> i32 { 10 }
107+
let a = unsafe { an_unsafe_fn() };
58108
```
59109

60110
## Attributes on block expressions
@@ -76,7 +126,9 @@ fn is_unix_platform() -> bool {
76126
```
77127

78128
[_InnerAttribute_]: attributes.html
79-
[_Statement_]: statements.html
129+
[_ItemDeclaration_]: items.html
130+
[_LetStatement_]: statements.html#let-statements
131+
[expression statement]: statements.html#expression-statements
80132
[_Expression_]: expressions.html
81133
[expression]: expressions.html
82134
[statements]: statements.html
@@ -86,3 +138,4 @@ fn is_unix_platform() -> bool {
86138
[expression statement]: statements.html#expression-statements
87139
[`cfg`]: attributes.html#conditional-compilation
88140
[the lint check attributes]: attributes.html#lint-check-attributes
141+
[unsafe operations]: unsafety.html

0 commit comments

Comments
 (0)