| r[statement] | |
| # Statements | |
| r[statement.syntax] | |
| ```grammar,statements | |
| Statement -> | |
| `;` | |
| | Item | |
| | LetStatement | |
| | ExpressionStatement | |
| | OuterAttribute* MacroInvocationSemi | |
| ``` | |
| r[statement.intro] | |
| A *statement* is a component of a [block], which is in turn a component of an outer [expression] or [function]. | |
| r[statement.kind] | |
| Rust has two kinds of statement: [declaration statements](#declaration-statements) and [expression statements](#expression-statements). | |
| r[statement.decl] | |
| ## Declaration statements | |
| A *declaration statement* is one that introduces one or more *names* into the enclosing statement block. The declared names may denote new variables or new [items][item]. | |
| The two kinds of declaration statements are item declarations and `let` statements. | |
| r[statement.item] | |
| ### Item declarations | |
| r[statement.item.intro] | |
| An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module]. | |
| r[statement.item.scope] | |
| Declaring an item within a statement block restricts its [scope] to the block containing the statement. The item is not given a [canonical path] nor are any sub-items it may declare. | |
| r[statement.item.associated-scope] | |
| The exception to this is that associated items defined by [implementations] are still accessible in outer scopes as long as the item and, if applicable, trait are accessible. It is otherwise identical in meaning to declaring the item inside a module. | |
| r[statement.item.outer-generics] | |
| There is no implicit capture of the containing function's generic parameters, parameters, and local variables. For example, `inner` may not access `outer_var`. | |
| ```rust | |
| fn outer() { | |
| let outer_var = true; | |
| fn inner() { /* outer_var is not in scope here */ } | |
| inner(); | |
| } | |
| ``` | |
| r[statement.let] | |
| ### `let` statements | |
| r[statement.let.syntax] | |
| ```grammar,statements | |
| LetStatement -> | |
| OuterAttribute* `let` PatternNoTopAlt ( `:` Type )? | |
| ( | |
| `=` Expression | |
| | `=` Expression _except [LazyBooleanExpression] or end with a `}`_ | |
| `else` BlockExpressionNoInnerAttributes | |
| )? `;` | |
| ``` | |
| r[statement.let.intro] | |
| A *`let` statement* introduces a new set of [variables], given by a [pattern]. The pattern is followed optionally by a type annotation and then either ends, or is followed by an initializer expression plus an optional `else` block. | |
| r[statement.let.inference] | |
| When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference. | |
| r[statement.let.scope] | |
| Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope, except when they are shadowed by another variable declaration. | |
| r[statement.let.constraint] | |
| If an `else` block is not present, the pattern must be irrefutable. If an `else` block is present, the pattern may be refutable. | |
| r[statement.let.behavior] | |
| If the pattern does not match (this requires it to be refutable), the `else` block is executed. The `else` block must always diverge (evaluate to the [never type]). | |
| ```rust | |
| let (mut v, w) = (vec![1, 2, 3], 42); // The bindings may be mut or const | |
| let Some(t) = v.pop() else { // Refutable patterns require an else block | |
| panic!(); // The else block must diverge | |
| }; | |
| let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler | |
| // will lint as the else block is redundant. | |
| panic!(); | |
| }; | |
| ``` | |
| r[statement.expr] | |
| ## Expression statements | |
| r[statement.expr.syntax] | |
| ```grammar,statements | |
| ExpressionStatement -> | |
| ExpressionWithoutBlock `;` | |
| | ExpressionWithBlock `;`? | |
| ``` | |
| r[statement.expr.intro] | |
| An *expression statement* is one that evaluates an [expression] and ignores its result. As a rule, an expression statement's purpose is to trigger the effects of evaluating its expression. | |
| r[statement.expr.restriction-semicolon] | |
| An expression that consists of only a [block expression][block] or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon. This can cause an ambiguity between it being parsed as a standalone statement and as a part of another expression; in this case, it is parsed as a statement. | |
| r[statement.expr.constraint-block] | |
| The type of [ExpressionWithBlock] expressions when used as statements must be the unit type. | |
| ```rust | |
| # let mut v = vec![1, 2, 3]; | |
| v.pop(); // Ignore the element returned from pop | |
| if v.is_empty() { | |
| v.push(5); | |
| } else { | |
| v.remove(0); | |
| } // Semicolon can be omitted. | |
| [1]; // Separate expression statement, not an indexing expression. | |
| ``` | |
| When the trailing semicolon is omitted, the result must be type `()`. | |
| ```rust | |
| // bad: the block's type is i32, not () | |
| // Error: expected `()` because of default return type | |
| // if true { | |
| // 1 | |
| // } | |
| // good: the block's type is i32 | |
| if true { | |
| 1 | |
| } else { | |
| 2 | |
| }; | |
| ``` | |
| r[statement.attribute] | |
| ## Attributes on statements | |
| Statements accept [outer attributes]. The attributes that have meaning on a statement are [`cfg`], and [the lint check attributes]. | |
| [block]: expressions/block-expr.md | |
| [expression]: expressions.md | |
| [function]: items/functions.md | |
| [item]: items.md | |
| [module]: items/modules.md | |
| [never type]: types/never.md | |
| [canonical path]: paths.md#canonical-paths | |
| [implementations]: items/implementations.md | |
| [variables]: variables.md | |
| [outer attributes]: attributes.md | |
| [`cfg`]: conditional-compilation.md | |
| [the lint check attributes]: attributes/diagnostics.md#lint-check-attributes | |
| [pattern]: patterns.md | |
| [scope]: names/scopes.md |