]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | # Block expressions |
2 | ||
8faf50e0 XL |
3 | > **<sup>Syntax</sup>**\ |
4 | > _BlockExpression_ :\ | |
5 | > `{`\ | |
6 | > [_InnerAttribute_]<sup>\*</sup>\ | |
13cf67c4 | 7 | > _Statements_<sup>?</sup>\ |
8faf50e0 | 8 | > `}` |
b7449926 XL |
9 | > |
10 | > _Statements_ :\ | |
13cf67c4 XL |
11 | > [_Statement_]<sup>\+</sup>\ |
12 | > | [_Statement_]<sup>\+</sup> [_ExpressionWithoutBlock_]\ | |
13 | > | [_ExpressionWithoutBlock_] | |
14 | ||
15 | A *block expression*, or *block*, is a control flow expression and anonymous | |
b7449926 XL |
16 | namespace scope for items and variable declarations. As a control flow |
17 | expression, a block sequentially executes its component non-item declaration | |
18 | statements and then its final optional expression. As an anonymous namespace | |
19 | scope, item declarations are only in scope inside the block itself and variables | |
20 | declared by `let` statements are in scope from the next statement until the end | |
21 | of the block. | |
22 | ||
23 | Blocks are written as `{`, then any [inner attributes], then [statements], | |
24 | then an optional expression, and finally a `}`. Statements are usually required | |
25 | to be followed a semicolon, with two exceptions. Item declaration statements do | |
26 | not need to be followed by a semicolon. Expression statements usually require | |
27 | a following semicolon except if its outer expression is a flow control | |
28 | expression. Furthermore, extra semicolons between statements are allowed, but | |
29 | these semicolons do not affect semantics. | |
30 | ||
31 | > Note: The semicolon following a statement is not a part of the statement | |
32 | > itself. They are invalid when using the `stmt` macro matcher. | |
33 | ||
34 | When evaluating a block expression, each statement, except for item declaration | |
35 | statements, is executed sequentially. Then the final expression is executed, | |
36 | if given. | |
37 | ||
38 | The type of a block is the type of the final expression, or `()` if the final | |
39 | expression is omitted. | |
abe05a73 | 40 | |
b7449926 XL |
41 | ```rust |
42 | # fn fn_call() {} | |
43 | let _: () = { | |
44 | fn_call(); | |
45 | }; | |
ea8adc8c | 46 | |
b7449926 XL |
47 | let five: i32 = { |
48 | fn_call(); | |
49 | 5 | |
50 | }; | |
ea8adc8c | 51 | |
b7449926 | 52 | assert_eq!(5, five); |
ea8adc8c XL |
53 | ``` |
54 | ||
b7449926 XL |
55 | > Note: As a control flow expression, if a block expression is the outer |
56 | > expression of an expression statement, the expected type is `()` unless it | |
57 | > is followed immediately by a semicolon. | |
ea8adc8c | 58 | |
13cf67c4 | 59 | Blocks are always [value expressions] and evaluate the last expression in |
b7449926 XL |
60 | value expression context. This can be used to force moving a value if really |
61 | needed. For example, the following example fails on the call to `consume_self` | |
62 | because the struct was moved out of `s` in the block expression. | |
ea8adc8c | 63 | |
b7449926 XL |
64 | ```rust,compile_fail |
65 | struct Struct; | |
ea8adc8c | 66 | |
b7449926 XL |
67 | impl Struct { |
68 | fn consume_self(self) {} | |
69 | fn borrow_self(&self) {} | |
70 | } | |
71 | ||
72 | fn move_by_block_expression() { | |
73 | let s = Struct; | |
74 | ||
13cf67c4 | 75 | // Move the value out of `s` in the block expression. |
b7449926 XL |
76 | (&{ s }).borrow_self(); |
77 | ||
78 | // Fails to execute because `s` is moved out of. | |
79 | s.consume_self(); | |
80 | } | |
81 | ``` | |
ea8adc8c XL |
82 | |
83 | ## `unsafe` blocks | |
84 | ||
8faf50e0 XL |
85 | > **<sup>Syntax</sup>**\ |
86 | > _UnsafeBlockExpression_ :\ | |
abe05a73 XL |
87 | > `unsafe` _BlockExpression_ |
88 | ||
416331ca | 89 | _See [`unsafe` block](../unsafe-blocks.md) for more information on when to use `unsafe`_ |
ea8adc8c | 90 | |
b7449926 XL |
91 | A block of code can be prefixed with the `unsafe` keyword to permit [unsafe |
92 | operations]. Examples: | |
abe05a73 XL |
93 | |
94 | ```rust | |
95 | unsafe { | |
96 | let b = [13u8, 17u8]; | |
97 | let a = &b[0] as *const u8; | |
98 | assert_eq!(*a, 13); | |
99 | assert_eq!(*a.offset(1), 17); | |
100 | } | |
101 | ||
b7449926 XL |
102 | # unsafe fn an_unsafe_fn() -> i32 { 10 } |
103 | let a = unsafe { an_unsafe_fn() }; | |
abe05a73 XL |
104 | ``` |
105 | ||
8faf50e0 XL |
106 | ## Attributes on block expressions |
107 | ||
13cf67c4 XL |
108 | [Inner attributes] are allowed directly after the opening brace of a block |
109 | expression in the following situations: | |
110 | ||
111 | * [Function] and [method] bodies. | |
112 | * Loop bodies ([`loop`], [`while`], [`while let`], and [`for`]). | |
113 | * Block expressions used as a [statement]. | |
114 | * Block expressions as elements of [array expressions], [tuple expressions], | |
115 | [call expressions], tuple-style [struct] and [enum variant] expressions. | |
116 | * A block expression as the tail expression of another block expression. | |
117 | <!-- Keep list in sync with expressions.md --> | |
118 | ||
119 | The attributes that have meaning on a block expression are [`cfg`] and [the | |
120 | lint check attributes]. | |
8faf50e0 XL |
121 | |
122 | For example, this function returns `true` on unix platforms and `false` on other | |
123 | platforms. | |
124 | ||
125 | ```rust | |
126 | fn is_unix_platform() -> bool { | |
127 | #[cfg(unix)] { true } | |
128 | #[cfg(not(unix))] { false } | |
129 | } | |
130 | ``` | |
131 | ||
416331ca XL |
132 | [_ExpressionWithoutBlock_]: ../expressions.md |
133 | [_InnerAttribute_]: ../attributes.md | |
134 | [_Statement_]: ../statements.md | |
135 | [`cfg`]: ../conditional-compilation.md | |
136 | [`for`]: loop-expr.md#iterator-loops | |
137 | [`loop`]: loop-expr.md#infinite-loops | |
138 | [`while let`]: loop-expr.md#predicate-pattern-loops | |
139 | [`while`]: loop-expr.md#predicate-loops | |
140 | [array expressions]: array-expr.md | |
141 | [call expressions]: call-expr.md | |
142 | [enum variant]: enum-variant-expr.md | |
143 | [function]: ../items/functions.md | |
144 | [inner attributes]: ../attributes.md | |
145 | [method]: ../items/associated-items.md#methods | |
146 | [statement]: ../statements.md | |
147 | [statements]: ../statements.md | |
148 | [struct]: struct-expr.md | |
149 | [the lint check attributes]: ../attributes/diagnostics.md#lint-check-attributes | |
150 | [tuple expressions]: tuple-expr.md | |
151 | [unsafe operations]: ../unsafety.md | |
152 | [value expressions]: ../expressions.md#place-expressions-and-value-expressions |