# Statements

> Syntax
> Statement :
> `;`
> | Item
> | LetStatement
> | ExpressionStatement
> | MacroInvocationSemi

A statement is a component of a block, which is in turn a component of an outer expression or function.

Rust has two kinds of statement: declaration statements and expression statements.

## 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.

The two kinds of declaration statements are item declarations and `let` statements.

### Item declarations

An item declaration statement has a syntactic form identical to an item declaration within a module. 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. 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.

There is no implicit capture of the containing function's generic parameters, parameters, and local variables. For example, `inner` may not access `outer_var`.

    # #![allow(unused_variables)]
    #fn main() {
    fn outer() {
      let outer_var = true;

      fn inner() { /* outer_var is not in scope here */ }

      inner();
    }
    #}

### `let` statements

> Syntax
> LetStatement :
> OuterAttribute\* `let` Pattern ( `:` Type )? (`=` Expression )? `;`

A `let` statement introduces a new set of variables, given by a pattern. The pattern is followed optionally by a type annotation and then optionally by an initializer expression. 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. Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope.

## Expression statements

> Syntax
> ExpressionStatement :
> ExpressionWithoutBlock `;`
> | ExpressionWithBlock

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.

An expression that consists of only a block expression 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. The type of ExpressionWithBlock expressions when used as statements must be the unit type.

    # #![allow(unused_variables)]
    #fn main() {
    # 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 `()`.

    # #![allow(unused_variables)]
    #fn main() {
    // 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
    };
    #}

## Attributes on Statements

Statements accept outer attributes. The attributes that have meaning on a statement are `cfg`, and the lint check attributes.