Skip to content

Grammar: Statements. #427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,16 @@ Attributes may be applied to many things in the language:

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

Some examples of attributes:

Expand Down Expand Up @@ -600,3 +603,4 @@ You can implement `derive` for your own traits through [procedural macros].
[`Termination`]: ../std/process/trait.Termination.html
[where clause]: items/where-clauses.html
[trait or lifetime bounds]: trait-bounds.html
[Expression Attributes]: expressions.html#expression-attributes
94 changes: 71 additions & 23 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,42 @@

> **<sup>Syntax</sup>**\
> _Expression_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; [_LiteralExpression_]\
> &nbsp;&nbsp; | [_PathExpression_]\
> &nbsp;&nbsp; | [_BlockExpression_]\
> &nbsp;&nbsp; | [_OperatorExpression_]\
> &nbsp;&nbsp; | [_GroupedExpression_]\
> &nbsp;&nbsp; | [_ArrayExpression_]\
> &nbsp;&nbsp; | [_IndexExpression_]\
> &nbsp;&nbsp; | [_TupleExpression_]\
> &nbsp;&nbsp; | [_TupleIndexingExpression_]\
> &nbsp;&nbsp; | [_StructExpression_]\
> &nbsp;&nbsp; | [_EnumerationVariantExpression_]\
> &nbsp;&nbsp; | [_CallExpression_]\
> &nbsp;&nbsp; | [_MethodCallExpression_]\
> &nbsp;&nbsp; | [_FieldExpression_]\
> &nbsp;&nbsp; | [_ClosureExpression_]\
> &nbsp;&nbsp; | [_LoopExpression_]\
> &nbsp;&nbsp; | [_ContinueExpression_]\
> &nbsp;&nbsp; | [_BreakExpression_]\
> &nbsp;&nbsp; | [_RangeExpression_]\
> &nbsp;&nbsp; | [_IfExpression_]\
> &nbsp;&nbsp; | [_IfLetExpression_]\
> &nbsp;&nbsp; | [_MatchExpression_]\
> &nbsp;&nbsp; | [_ReturnExpression_]
> &nbsp;&nbsp; &nbsp;&nbsp; _ExpressionWithoutBlock_\
> &nbsp;&nbsp; | _ExpressionWithBlock_
>
> _ExpressionWithoutBlock_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\
> &nbsp;&nbsp; (\
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_LiteralExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PathExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_OperatorExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_GroupedExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ArrayExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IndexExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_TupleExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_TupleIndexingExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_StructExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_EnumerationVariantExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_CallExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MethodCallExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_FieldExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ClosureExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ContinueExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_BreakExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_RangeExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ReturnExpression_]\
> &nbsp;&nbsp; )
>
> _ExpressionWithBlock_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\
> &nbsp;&nbsp; (\
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_UnsafeBlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_LoopExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfLetExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MatchExpression_]\
> &nbsp;&nbsp; )

An expression may have two roles: it always produces a *value*, and it may have
*effects* (otherwise known as "side effects"). An expression *evaluates to* a
Expand Down Expand Up @@ -235,6 +248,31 @@ Many of the following operators and expressions can also be overloaded for
other types using traits in `std::ops` or `std::cmp`. These traits also
exist in `core::ops` and `core::cmp` with the same names.

## Expression Attributes

[Outer attributes][_OuterAttribute_] before an expression are allowed only in
a few specific cases:

* Before an expression used as a [statement].
* Elements of [array expressions], [tuple expressions], [call expressions],
tuple-style [struct] and [enum variant] expressions.
<!--
These were likely stabilized inadvertently.
See https://github.com/rust-lang/rust/issues/32796 and
https://github.com/rust-lang/rust/issues/15701
-->
* The tail expression of [block expressions].
<!-- Keep list in sync with block-expr.md -->

They are never allowed before:

* [`if`][_IfExpression_] and [`if let`][_IfLetExpression_] expressions.
* [Range][_RangeExpression_] expressions.
* Binary operator expressions ([_ArithmeticOrLogicalExpression_],
[_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_],
[_AssignmentExpression_], [_CompoundAssignmentExpression_]).


[block expressions]: expressions/block-expr.html
[call expressions]: expressions/call-expr.html
[closure expressions]: expressions/closure-expr.html
Expand Down Expand Up @@ -278,30 +316,40 @@ exist in `core::ops` and `core::cmp` with the same names.
[Mutable `static` items]: items/static-items.html#mutable-statics
[const contexts]: const_eval.html
[slice]: types.html#array-and-slice-types
[statement]: statements.html
[static variables]: items/static-items.html
[Temporary values]: #temporary-lifetimes
[Variables]: variables.html


[_ArithmeticOrLogicalExpression_]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators
[_ArrayExpression_]: expressions/array-expr.html
[_AssignmentExpression_]: expressions/operator-expr.html#assignment-expressions
[_BlockExpression_]: expressions/block-expr.html
[_BreakExpression_]: expressions/loop-expr.html#break-expressions
[_CallExpression_]: expressions/call-expr.html
[_ClosureExpression_]: expressions/closure-expr.html
[_ComparisonExpression_]: expressions/operator-expr.html#comparison-operators
[_CompoundAssignmentExpression_]: expressions/operator-expr.html#compound-assignment-expressions
[_ContinueExpression_]: expressions/loop-expr.html#continue-expressions
[_EnumerationVariantExpression_]: expressions/enum-variant-expr.html
[_FieldExpression_]: expressions/field-expr.html
[_GroupedExpression_]: expressions/grouped-expr.html
[_IfExpression_]: expressions/if-expr.html#if-expressions
[_IfLetExpression_]: expressions/if-expr.html#if-let-expressions
[_IndexExpression_]: expressions/array-expr.html#array-and-slice-indexing-expressions
[_LazyBooleanExpression_]: expressions/operator-expr.html#lazy-boolean-operators
[_LiteralExpression_]: expressions/literal-expr.html
[_LoopExpression_]: expressions/loop-expr.html
[_MatchExpression_]: expressions/match-expr.html
[_MethodCallExpression_]: expressions/method-call-expr.html
[_OperatorExpression_]: expressions/operator-expr.html
[_OuterAttribute_]: attributes.html
[_PathExpression_]: expressions/path-expr.html
[_RangeExpression_]: expressions/range-expr.html
[_ReturnExpression_]: expressions/return-expr.html
[_StructExpression_]: expressions/struct-expr.html
[_TupleExpression_]: expressions/tuple-expr.html
[_TupleIndexingExpression_]: expressions/tuple-expr.html#tuple-indexing-expressions
[_TypeCastExpression_]: expressions/operator-expr.html#type-cast-expressions
[_UnsafeBlockExpression_]: expressions/block-expr.html#unsafe-blocks
23 changes: 17 additions & 6 deletions src/expressions/array-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

> **<sup>Syntax</sup>**\
> _ArrayExpression_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; `[` `]`\
> &nbsp;&nbsp; | `[` [_Expression_] ( `,` [_Expression_] )<sup>\*</sup> `,`<sup>?</sup> `]`\
> &nbsp;&nbsp; | `[` [_Expression_] `;` [_Expression_] `]`
> &nbsp;&nbsp; `[` [_InnerAttribute_]<sup>\*</sup> _ArrayElements_<sup>?</sup> `]`
>
> _ArrayElements_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] ( `,` [_Expression_] )<sup>\*</sup> `,`<sup>?</sup>\
> &nbsp;&nbsp; | [_Expression_] `;` [_Expression_]

An _[array](types.html#array-and-slice-types) expression_ can be written by
enclosing zero or more comma-separated expressions of uniform type in square
Expand All @@ -30,6 +32,12 @@ greater than 1 then this requires that the type of `a` is
[[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D array
```

### Array expression attributes

[Inner attributes] are allowed directly after the opening bracket of an array
expression in the same expression contexts as [attributes on block
expressions].

## Array and slice indexing expressions

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

[_Expression_]: expressions.html
[memory location]: expressions.html#place-expressions-and-value-expressions
[Index]: ../std/ops/trait.Index.html
[IndexMut]: ../std/ops/trait.IndexMut.html
[Index]: ../std/ops/trait.Index.html
[Inner attributes]: attributes.html
[_Expression_]: expressions.html
[_InnerAttribute_]: attributes.html
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions
[constant expression]: const_eval.html#constant-expressions
[memory location]: expressions.html#place-expressions-and-value-expressions
63 changes: 38 additions & 25 deletions src/expressions/block-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@
> _BlockExpression_ :\
> &nbsp;&nbsp; `{`\
> &nbsp;&nbsp; &nbsp;&nbsp; [_InnerAttribute_]<sup>\*</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; _Statements_<sup>\*</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_]<sup>?</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; _Statements_<sup>?</sup>\
> &nbsp;&nbsp; `}`
>
> _Statements_ :\
> &nbsp;&nbsp; ( `;`\
> &nbsp;&nbsp; | [_ItemDeclaration_]\
> &nbsp;&nbsp; | [_LetStatement_] ;\
> &nbsp;&nbsp; | [_NonControlFlowExpressionStatement_][expression statement] ;\
> &nbsp;&nbsp; | [_FlowControlExpressionStatement_][expression statement] ;<sup>?</sup>\
> &nbsp;&nbsp; )<sup>\*</sup>

A *block expression*, or *block*, is a control flow expression and anonymouse
> &nbsp;&nbsp; &nbsp;&nbsp; [_Statement_]<sup>\+</sup>\
> &nbsp;&nbsp; | [_Statement_]<sup>\+</sup> [_ExpressionWithoutBlock_]\
> &nbsp;&nbsp; | [_ExpressionWithoutBlock_]

A *block expression*, or *block*, is a control flow expression and anonymous
namespace scope for items and variable declarations. As a control flow
expression, a block sequentially executes its component non-item declaration
statements and then its final optional expression. As an anonymous namespace
Expand Down Expand Up @@ -60,7 +56,7 @@ assert_eq!(5, five);
> expression of an expression statement, the expected type is `()` unless it
> is followed immediately by a semicolon.

Blocks are always [value expressions] and evaluate the last expression in
Blocks are always [value expressions] and evaluate the last expression in
value expression context. This can be used to force moving a value if really
needed. For example, the following example fails on the call to `consume_self`
because the struct was moved out of `s` in the block expression.
Expand Down Expand Up @@ -109,11 +105,19 @@ let a = unsafe { an_unsafe_fn() };

## Attributes on block expressions

Block expressions allow [outer attributes] and [inner attributes] directly after
the opening brace when the block expression is the outer expression of an
[expression statement] or the final expression of another block expression. The
attributes that have meaning on a block expression are [`cfg`] and [the lint
check attributes].
[Inner attributes] are allowed directly after the opening brace of a block
expression in the following situations:

* [Function] and [method] bodies.
* Loop bodies ([`loop`], [`while`], [`while let`], and [`for`]).
* Block expressions used as a [statement].
* Block expressions as elements of [array expressions], [tuple expressions],
[call expressions], tuple-style [struct] and [enum variant] expressions.
* A block expression as the tail expression of another block expression.
<!-- Keep list in sync with expressions.md -->

The attributes that have meaning on a block expression are [`cfg`] and [the
lint check attributes].

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

[_ExpressionWithoutBlock_]: expressions.html
[_InnerAttribute_]: attributes.html
[_ItemDeclaration_]: items.html
[_LetStatement_]: statements.html#let-statements
[expression statement]: statements.html#expression-statements
[_Expression_]: expressions.html
[_Statement_]: statements.html
[`cfg`]: conditional-compilation.html
[`for`]: expressions/loop-expr.html#iterator-loops
[`loop`]: expressions/loop-expr.html#infinite-loops
[`while let`]: expressions/loop-expr.html#predicate-pattern-loops
[`while`]: expressions/loop-expr.html#predicate-loops
[array expressions]: expressions/array-expr.html
[call expressions]: expressions/call-expr.html
[enum variant]: expressions/enum-variant-expr.html
[expression attributes]: expressions.html#expression-attributes
[expression]: expressions.html
[statements]: statements.html
[value expressions]: expressions.html#place-expressions-and-value-expressions
[outer attributes]: attributes.html
[function]: items/functions.html
[inner attributes]: attributes.html
[expression statement]: statements.html#expression-statements
[`cfg`]: conditional-compilation.html
[method]: items/associated-items.html#methods
[statement]: statements.html
[statements]: statements.html
[struct]: expressions/struct-expr.html
[the lint check attributes]: attributes.html#lint-check-attributes
[tuple expressions]: expressions/tuple-expr.html
[unsafe operations]: unsafety.html
[value expressions]: expressions.html#place-expressions-and-value-expressions
11 changes: 10 additions & 1 deletion src/expressions/grouped-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> **<sup>Syntax</sup>**\
> _GroupedExpression_ :\
> &nbsp;&nbsp; `(` [_Expression_] `)`
> &nbsp;&nbsp; `(` [_InnerAttribute_]<sup>\*</sup> [_Expression_] `)`

An expression enclosed in parentheses evaluates to the result of the enclosed
expression. Parentheses can be used to explicitly specify evaluation order
Expand Down Expand Up @@ -35,4 +35,13 @@ assert_eq!( a.f (), "The method f");
assert_eq!((a.f)(), "The field f");
```

## Group expression attributes

[Inner attributes] are allowed directly after the opening parenthesis of a
group expression in the same expression contexts as [attributes on block
expressions].

[Inner attributes]: attributes.html
[_Expression_]: expressions.html
[_InnerAttribute_]: attributes.html
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions
6 changes: 6 additions & 0 deletions src/expressions/match-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ let message = match maybe_digit {
Outer attributes are allowed on match arms. The only attributes that have
meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].

[Inner attributes] are allowed directly after the opening brace of the match
expression in the same expression contexts as [attributes on block
expressions].

[_Expression_]: expressions.html
[_BlockExpression_]: expressions/block-expr.html#block-expressions
[place expression]: expressions.html#place-expressions-and-value-expressions
Expand All @@ -133,8 +137,10 @@ meaning on match arms are [`cfg`], `cold`, and the [lint check attributes].
[_Pattern_]: patterns.html
[pattern]: patterns.html
[Identifier Patterns]: patterns.html#identifier-patterns
[Inner attributes]: attributes.html
[Struct Patterns]: patterns.html#struct-patterns
[Tuple Struct Patterns]: patterns.html#tuplestruct-patterns
[Tuple Patterns]: patterns.html#tuple-patterns
[Range Pattern]: patterns.html#range-patterns
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions
[binding mode]: patterns.html#binding-modes
14 changes: 12 additions & 2 deletions src/expressions/struct-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
> &nbsp;&nbsp; | _StructExprUnit_
>
> _StructExprStruct_ :\
> &nbsp;&nbsp; [_PathInExpression_] `{` (_StructExprFields_ | _StructBase_)<sup>?</sup> `}`
> &nbsp;&nbsp; [_PathInExpression_] `{` [_InnerAttribute_]<sup>\*</sup> (_StructExprFields_ | _StructBase_)<sup>?</sup> `}`
>
> _StructExprFields_ :\
> &nbsp;&nbsp; _StructExprField_ (`,` _StructExprField_)<sup>\*</sup> (`,` _StructBase_ | `,`<sup>?</sup>)
Expand All @@ -16,10 +16,12 @@
> &nbsp;&nbsp; &nbsp;&nbsp; [IDENTIFIER]\
> &nbsp;&nbsp; | ([IDENTIFIER] | [TUPLE_INDEX]) `:` [_Expression_]
>
> _StructBase_ : `..` [_Expression_]
> _StructBase_ :\
> &nbsp;&nbsp; `..` [_Expression_]
>
> _StructExprTuple_ :\
> &nbsp;&nbsp; [_PathInExpression_] `(`\
> &nbsp;&nbsp; &nbsp;&nbsp; [_InnerAttribute_]<sup>\*</sup>\
> &nbsp;&nbsp; &nbsp;&nbsp; ( [_Expression_] (`,` [_Expression_])<sup>\*</sup> `,`<sup>?</sup> )<sup>?</sup>\
> &nbsp;&nbsp; `)`
>
Expand Down Expand Up @@ -126,11 +128,19 @@ let a = Gamma; // Gamma unit value.
let b = Gamma{}; // Exact same value as `a`.
```

## Struct expression attributes

[Inner attributes] are allowed directly after the opening brace or parenthesis
of a struct expression in the same expression contexts as [attributes on block
expressions].

[IDENTIFIER]: identifiers.html
[Inner attributes]: attributes.html
[TUPLE_INDEX]: tokens.html#integer-literals
[_Expression_]: expressions.html
[_InnerAttribute_]: attributes.html
[_PathInExpression_]: paths.html#paths-in-expressions
[attributes on block expressions]: expressions/block-expr.html#attributes-on-block-expressions
[call expression]: expressions/call-expr.html
[if let]: expressions/if-expr.html#if-let-expressions
[if]: expressions/if-expr.html#if-expressions
Expand Down
Loading