Skip to content

Commit 457b072

Browse files
Merge pull request #427 from ehuss/grammar-statements
Grammar: Statements.
2 parents b9fb838 + 3512dc8 commit 457b072

File tree

9 files changed

+199
-61
lines changed

9 files changed

+199
-61
lines changed

src/attributes.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ Attributes may be applied to many things in the language:
4444

4545
* All [item declarations] accept outer attributes while [external blocks],
4646
[functions], [implementations], and [modules] accept inner attributes.
47-
* [Statements] accept outer attributes.
47+
* Most [statements] accept outer attributes (see [Expression Attributes] for
48+
limitations on expression statements).
4849
* [Block expressions] accept outer and inner attributes, but only when they are
4950
the outer expression of an [expression statement] or the final expression of
5051
another block expression.
5152
* [Enum] variants and [struct] and [union] fields accept outer attributes.
5253
* [Match expression arms][match expressions] accept outer attributes.
5354
* [Generic lifetime or type parameter][generics] accept outer attributes.
55+
* Expressions accept outer attributes in limited situations, see [Expression
56+
Attributes] for details.
5457

5558
Some examples of attributes:
5659

@@ -600,3 +603,4 @@ You can implement `derive` for your own traits through [procedural macros].
600603
[`Termination`]: ../std/process/trait.Termination.html
601604
[where clause]: items/where-clauses.html
602605
[trait or lifetime bounds]: trait-bounds.html
606+
[Expression Attributes]: expressions.html#expression-attributes

src/expressions.md

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,42 @@
22

33
> **<sup>Syntax</sup>**\
44
> _Expression_ :\
5-
> &nbsp;&nbsp; &nbsp;&nbsp; [_LiteralExpression_]\
6-
> &nbsp;&nbsp; | [_PathExpression_]\
7-
> &nbsp;&nbsp; | [_BlockExpression_]\
8-
> &nbsp;&nbsp; | [_OperatorExpression_]\
9-
> &nbsp;&nbsp; | [_GroupedExpression_]\
10-
> &nbsp;&nbsp; | [_ArrayExpression_]\
11-
> &nbsp;&nbsp; | [_IndexExpression_]\
12-
> &nbsp;&nbsp; | [_TupleExpression_]\
13-
> &nbsp;&nbsp; | [_TupleIndexingExpression_]\
14-
> &nbsp;&nbsp; | [_StructExpression_]\
15-
> &nbsp;&nbsp; | [_EnumerationVariantExpression_]\
16-
> &nbsp;&nbsp; | [_CallExpression_]\
17-
> &nbsp;&nbsp; | [_MethodCallExpression_]\
18-
> &nbsp;&nbsp; | [_FieldExpression_]\
19-
> &nbsp;&nbsp; | [_ClosureExpression_]\
20-
> &nbsp;&nbsp; | [_LoopExpression_]\
21-
> &nbsp;&nbsp; | [_ContinueExpression_]\
22-
> &nbsp;&nbsp; | [_BreakExpression_]\
23-
> &nbsp;&nbsp; | [_RangeExpression_]\
24-
> &nbsp;&nbsp; | [_IfExpression_]\
25-
> &nbsp;&nbsp; | [_IfLetExpression_]\
26-
> &nbsp;&nbsp; | [_MatchExpression_]\
27-
> &nbsp;&nbsp; | [_ReturnExpression_]
5+
> &nbsp;&nbsp; &nbsp;&nbsp; _ExpressionWithoutBlock_\
6+
> &nbsp;&nbsp; | _ExpressionWithBlock_
7+
>
8+
> _ExpressionWithoutBlock_ :\
9+
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[](#expression-attributes)\
10+
> &nbsp;&nbsp; (\
11+
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_LiteralExpression_]\
12+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PathExpression_]\
13+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_OperatorExpression_]\
14+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_GroupedExpression_]\
15+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ArrayExpression_]\
16+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IndexExpression_]\
17+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_TupleExpression_]\
18+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_TupleIndexingExpression_]\
19+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_StructExpression_]\
20+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_EnumerationVariantExpression_]\
21+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_CallExpression_]\
22+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MethodCallExpression_]\
23+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_FieldExpression_]\
24+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ClosureExpression_]\
25+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ContinueExpression_]\
26+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_BreakExpression_]\
27+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_RangeExpression_]\
28+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ReturnExpression_]\
29+
> &nbsp;&nbsp; )
30+
>
31+
> _ExpressionWithBlock_ :\
32+
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[](#expression-attributes)\
33+
> &nbsp;&nbsp; (\
34+
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]\
35+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_UnsafeBlockExpression_]\
36+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_LoopExpression_]\
37+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfExpression_]\
38+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfLetExpression_]\
39+
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MatchExpression_]\
40+
> &nbsp;&nbsp; )
2841
2942
An expression may have two roles: it always produces a *value*, and it may have
3043
*effects* (otherwise known as "side effects"). An expression *evaluates to* a
@@ -235,6 +248,31 @@ Many of the following operators and expressions can also be overloaded for
235248
other types using traits in `std::ops` or `std::cmp`. These traits also
236249
exist in `core::ops` and `core::cmp` with the same names.
237250

251+
## Expression Attributes
252+
253+
[Outer attributes][_OuterAttribute_] before an expression are allowed only in
254+
a few specific cases:
255+
256+
* Before an expression used as a [statement].
257+
* Elements of [array expressions], [tuple expressions], [call expressions],
258+
tuple-style [struct] and [enum variant] expressions.
259+
<!--
260+
These were likely stabilized inadvertently.
261+
See https://github.com/rust-lang/rust/issues/32796 and
262+
https://github.com/rust-lang/rust/issues/15701
263+
-->
264+
* The tail expression of [block expressions].
265+
<!-- Keep list in sync with block-expr.md -->
266+
267+
They are never allowed before:
268+
269+
* [`if`][_IfExpression_] and [`if let`][_IfLetExpression_] expressions.
270+
* [Range][_RangeExpression_] expressions.
271+
* Binary operator expressions ([_ArithmeticOrLogicalExpression_],
272+
[_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_],
273+
[_AssignmentExpression_], [_CompoundAssignmentExpression_]).
274+
275+
238276
[block expressions]: expressions/block-expr.html
239277
[call expressions]: expressions/call-expr.html
240278
[closure expressions]: expressions/closure-expr.html
@@ -278,30 +316,40 @@ exist in `core::ops` and `core::cmp` with the same names.
278316
[Mutable `static` items]: items/static-items.html#mutable-statics
279317
[const contexts]: const_eval.html
280318
[slice]: types.html#array-and-slice-types
319+
[statement]: statements.html
281320
[static variables]: items/static-items.html
282321
[Temporary values]: #temporary-lifetimes
283322
[Variables]: variables.html
284323

324+
325+
[_ArithmeticOrLogicalExpression_]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators
285326
[_ArrayExpression_]: expressions/array-expr.html
327+
[_AssignmentExpression_]: expressions/operator-expr.html#assignment-expressions
286328
[_BlockExpression_]: expressions/block-expr.html
287329
[_BreakExpression_]: expressions/loop-expr.html#break-expressions
288330
[_CallExpression_]: expressions/call-expr.html
289331
[_ClosureExpression_]: expressions/closure-expr.html
332+
[_ComparisonExpression_]: expressions/operator-expr.html#comparison-operators
333+
[_CompoundAssignmentExpression_]: expressions/operator-expr.html#compound-assignment-expressions
290334
[_ContinueExpression_]: expressions/loop-expr.html#continue-expressions
291335
[_EnumerationVariantExpression_]: expressions/enum-variant-expr.html
292336
[_FieldExpression_]: expressions/field-expr.html
293337
[_GroupedExpression_]: expressions/grouped-expr.html
294338
[_IfExpression_]: expressions/if-expr.html#if-expressions
295339
[_IfLetExpression_]: expressions/if-expr.html#if-let-expressions
296340
[_IndexExpression_]: expressions/array-expr.html#array-and-slice-indexing-expressions
341+
[_LazyBooleanExpression_]: expressions/operator-expr.html#lazy-boolean-operators
297342
[_LiteralExpression_]: expressions/literal-expr.html
298343
[_LoopExpression_]: expressions/loop-expr.html
299344
[_MatchExpression_]: expressions/match-expr.html
300345
[_MethodCallExpression_]: expressions/method-call-expr.html
301346
[_OperatorExpression_]: expressions/operator-expr.html
347+
[_OuterAttribute_]: attributes.html
302348
[_PathExpression_]: expressions/path-expr.html
303349
[_RangeExpression_]: expressions/range-expr.html
304350
[_ReturnExpression_]: expressions/return-expr.html
305351
[_StructExpression_]: expressions/struct-expr.html
306352
[_TupleExpression_]: expressions/tuple-expr.html
307353
[_TupleIndexingExpression_]: expressions/tuple-expr.html#tuple-indexing-expressions
354+
[_TypeCastExpression_]: expressions/operator-expr.html#type-cast-expressions
355+
[_UnsafeBlockExpression_]: expressions/block-expr.html#unsafe-blocks

src/expressions/array-expr.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
> **<sup>Syntax</sup>**\
66
> _ArrayExpression_ :\
7-
> &nbsp;&nbsp; &nbsp;&nbsp; `[` `]`\
8-
> &nbsp;&nbsp; | `[` [_Expression_] ( `,` [_Expression_] )<sup>\*</sup> `,`<sup>?</sup> `]`\
9-
> &nbsp;&nbsp; | `[` [_Expression_] `;` [_Expression_] `]`
7+
> &nbsp;&nbsp; `[` [_InnerAttribute_]<sup>\*</sup> _ArrayElements_<sup>?</sup> `]`
8+
>
9+
> _ArrayElements_ :\
10+
> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] ( `,` [_Expression_] )<sup>\*</sup> `,`<sup>?</sup>\
11+
> &nbsp;&nbsp; | [_Expression_] `;` [_Expression_]
1012
1113
An _[array](types.html#array-and-slice-types) expression_ can be written by
1214
enclosing zero or more comma-separated expressions of uniform type in square
@@ -30,6 +32,12 @@ greater than 1 then this requires that the type of `a` is
3032
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D array
3133
```
3234

35+
### Array expression attributes
36+
37+
[Inner attributes] are allowed directly after the opening bracket of an array
38+
expression in the same expression contexts as [attributes on block
39+
expressions].
40+
3341
## Array and slice indexing expressions
3442

3543
> **<sup>Syntax</sup>**\
@@ -73,8 +81,11 @@ arr[10]; // warning: index out of bounds
7381
The array index expression can be implemented for types other than arrays and slices
7482
by implementing the [Index] and [IndexMut] traits.
7583

76-
[_Expression_]: expressions.html
77-
[memory location]: expressions.html#place-expressions-and-value-expressions
78-
[Index]: ../std/ops/trait.Index.html
7984
[IndexMut]: ../std/ops/trait.IndexMut.html
85+
[Index]: ../std/ops/trait.Index.html
86+
[Inner attributes]: attributes.html
87+
[_Expression_]: expressions.html
88+
[_InnerAttribute_]: attributes.html
89+
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions
8090
[constant expression]: const_eval.html#constant-expressions
91+
[memory location]: expressions.html#place-expressions-and-value-expressions

src/expressions/block-expr.md

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,15 @@
44
> _BlockExpression_ :\
55
> &nbsp;&nbsp; `{`\
66
> &nbsp;&nbsp; &nbsp;&nbsp; [_InnerAttribute_]<sup>\*</sup>\
7-
> &nbsp;&nbsp; &nbsp;&nbsp; _Statements_<sup>\*</sup>\
8-
> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_]<sup>?</sup>\
7+
> &nbsp;&nbsp; &nbsp;&nbsp; _Statements_<sup>?</sup>\
98
> &nbsp;&nbsp; `}`
109
>
1110
> _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
11+
> &nbsp;&nbsp; &nbsp;&nbsp; [_Statement_]<sup>\+</sup>\
12+
> &nbsp;&nbsp; | [_Statement_]<sup>\+</sup> [_ExpressionWithoutBlock_]\
13+
> &nbsp;&nbsp; | [_ExpressionWithoutBlock_]
14+
15+
A *block expression*, or *block*, is a control flow expression and anonymous
2016
namespace scope for items and variable declarations. As a control flow
2117
expression, a block sequentially executes its component non-item declaration
2218
statements and then its final optional expression. As an anonymous namespace
@@ -60,7 +56,7 @@ assert_eq!(5, five);
6056
> expression of an expression statement, the expected type is `()` unless it
6157
> is followed immediately by a semicolon.
6258
63-
Blocks are always [value expressions] and evaluate the last expression in
59+
Blocks are always [value expressions] and evaluate the last expression in
6460
value expression context. This can be used to force moving a value if really
6561
needed. For example, the following example fails on the call to `consume_self`
6662
because the struct was moved out of `s` in the block expression.
@@ -109,11 +105,19 @@ let a = unsafe { an_unsafe_fn() };
109105

110106
## Attributes on block expressions
111107

112-
Block expressions allow [outer attributes] and [inner attributes] directly after
113-
the opening brace when the block expression is the outer expression of an
114-
[expression statement] or the final expression of another block expression. The
115-
attributes that have meaning on a block expression are [`cfg`] and [the lint
116-
check attributes].
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].
117121

118122
For example, this function returns `true` on unix platforms and `false` on other
119123
platforms.
@@ -125,17 +129,26 @@ fn is_unix_platform() -> bool {
125129
}
126130
```
127131

132+
[_ExpressionWithoutBlock_]: expressions.html
128133
[_InnerAttribute_]: attributes.html
129-
[_ItemDeclaration_]: items.html
130-
[_LetStatement_]: statements.html#let-statements
131-
[expression statement]: statements.html#expression-statements
132-
[_Expression_]: expressions.html
134+
[_Statement_]: statements.html
135+
[`cfg`]: conditional-compilation.html
136+
[`for`]: expressions/loop-expr.html#iterator-loops
137+
[`loop`]: expressions/loop-expr.html#infinite-loops
138+
[`while let`]: expressions/loop-expr.html#predicate-pattern-loops
139+
[`while`]: expressions/loop-expr.html#predicate-loops
140+
[array expressions]: expressions/array-expr.html
141+
[call expressions]: expressions/call-expr.html
142+
[enum variant]: expressions/enum-variant-expr.html
143+
[expression attributes]: expressions.html#expression-attributes
133144
[expression]: expressions.html
134-
[statements]: statements.html
135-
[value expressions]: expressions.html#place-expressions-and-value-expressions
136-
[outer attributes]: attributes.html
145+
[function]: items/functions.html
137146
[inner attributes]: attributes.html
138-
[expression statement]: statements.html#expression-statements
139-
[`cfg`]: conditional-compilation.html
147+
[method]: items/associated-items.html#methods
148+
[statement]: statements.html
149+
[statements]: statements.html
150+
[struct]: expressions/struct-expr.html
140151
[the lint check attributes]: attributes.html#lint-check-attributes
152+
[tuple expressions]: expressions/tuple-expr.html
141153
[unsafe operations]: unsafety.html
154+
[value expressions]: expressions.html#place-expressions-and-value-expressions

src/expressions/grouped-expr.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> **<sup>Syntax</sup>**\
44
> _GroupedExpression_ :\
5-
> &nbsp;&nbsp; `(` [_Expression_] `)`
5+
> &nbsp;&nbsp; `(` [_InnerAttribute_]<sup>\*</sup> [_Expression_] `)`
66
77
An expression enclosed in parentheses evaluates to the result of the enclosed
88
expression. Parentheses can be used to explicitly specify evaluation order
@@ -35,4 +35,13 @@ assert_eq!( a.f (), "The method f");
3535
assert_eq!((a.f)(), "The field f");
3636
```
3737

38+
## Group expression attributes
39+
40+
[Inner attributes] are allowed directly after the opening parenthesis of a
41+
group expression in the same expression contexts as [attributes on block
42+
expressions].
43+
44+
[Inner attributes]: attributes.html
3845
[_Expression_]: expressions.html
46+
[_InnerAttribute_]: attributes.html
47+
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions

src/expressions/match-expr.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ let message = match maybe_digit {
120120
Outer attributes are allowed on match arms. The only attributes that have
121121
meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].
122122
123+
[Inner attributes] are allowed directly after the opening brace of the match
124+
expression in the same expression contexts as [attributes on block
125+
expressions].
126+
123127
[_Expression_]: expressions.html
124128
[_BlockExpression_]: expressions/block-expr.html#block-expressions
125129
[place expression]: expressions.html#place-expressions-and-value-expressions
@@ -133,8 +137,10 @@ meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].
133137
[_Pattern_]: patterns.html
134138
[pattern]: patterns.html
135139
[Identifier Patterns]: patterns.html#identifier-patterns
140+
[Inner attributes]: attributes.html
136141
[Struct Patterns]: patterns.html#struct-patterns
137142
[Tuple Struct Patterns]: patterns.html#tuplestruct-patterns
138143
[Tuple Patterns]: patterns.html#tuple-patterns
139144
[Range Pattern]: patterns.html#range-patterns
145+
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions
140146
[binding mode]: patterns.html#binding-modes

src/expressions/struct-expr.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
> &nbsp;&nbsp; | _StructExprUnit_
88
>
99
> _StructExprStruct_ :\
10-
> &nbsp;&nbsp; [_PathInExpression_] `{` (_StructExprFields_ | _StructBase_)<sup>?</sup> `}`
10+
> &nbsp;&nbsp; [_PathInExpression_] `{` [_InnerAttribute_]<sup>\*</sup> (_StructExprFields_ | _StructBase_)<sup>?</sup> `}`
1111
>
1212
> _StructExprFields_ :\
1313
> &nbsp;&nbsp; _StructExprField_ (`,` _StructExprField_)<sup>\*</sup> (`,` _StructBase_ | `,`<sup>?</sup>)
@@ -16,10 +16,12 @@
1616
> &nbsp;&nbsp; &nbsp;&nbsp; [IDENTIFIER]\
1717
> &nbsp;&nbsp; | ([IDENTIFIER] | [TUPLE_INDEX]) `:` [_Expression_]
1818
>
19-
> _StructBase_ : `..` [_Expression_]
19+
> _StructBase_ :\
20+
> &nbsp;&nbsp; `..` [_Expression_]
2021
>
2122
> _StructExprTuple_ :\
2223
> &nbsp;&nbsp; [_PathInExpression_] `(`\
24+
> &nbsp;&nbsp; &nbsp;&nbsp; [_InnerAttribute_]<sup>\*</sup>\
2325
> &nbsp;&nbsp; &nbsp;&nbsp; ( [_Expression_] (`,` [_Expression_])<sup>\*</sup> `,`<sup>?</sup> )<sup>?</sup>\
2426
> &nbsp;&nbsp; `)`
2527
>
@@ -126,11 +128,19 @@ let a = Gamma; // Gamma unit value.
126128
let b = Gamma{}; // Exact same value as `a`.
127129
```
128130

131+
## Struct expression attributes
132+
133+
[Inner attributes] are allowed directly after the opening brace or parenthesis
134+
of a struct expression in the same expression contexts as [attributes on block
135+
expressions].
129136

130137
[IDENTIFIER]: identifiers.html
138+
[Inner attributes]: attributes.html
131139
[TUPLE_INDEX]: tokens.html#integer-literals
132140
[_Expression_]: expressions.html
141+
[_InnerAttribute_]: attributes.html
133142
[_PathInExpression_]: paths.html#paths-in-expressions
143+
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions
134144
[call expression]: expressions/call-expr.html
135145
[if let]: expressions/if-expr.html#if-let-expressions
136146
[if]: expressions/if-expr.html#if-expressions

0 commit comments

Comments
 (0)