Block expressions - The Rust Reference

# Block expressions

> Syntax
> BlockExpression :
> `{`
> InnerAttribute*
> Statements*
> Expression?
> `}`

> Statements :
> ( `;`
> | ItemDeclaration
> | LetStatement ;
> | NonControlFlowExpressionStatement ;
> | FlowControlExpressionStatement ;?
> )*

A block expression, or block, is a control flow expression and anonymouse 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 scope, item declarations are only in scope inside the block itself and variables declared by `let` statements are in scope from the next statement until the end of the block.

Blocks are written as `{`, then any inner attributes, then statements, then an optional expression, and finally a `}`. Statements are usually required to be followed a semicolon, with two exceptions. Item declaration statements do not need to be followed by a semicolon. Expression statements usually require a following semicolon except if its outer expression is a flow control expression. Furthermore, extra semicolons between statements are allowed, but these semicolons do not affect semantics.

> Note: The semicolon following a statement is not a part of the statement itself. They are invalid when using the `stmt` macro matcher.

When evaluating a block expression, each statement, except for item declaration statements, is executed sequentially. Then the final expression is executed, if given.

The type of a block is the type of the final expression, or `()` if the final expression is omitted.

    # #![allow(unused_variables)]
    #fn main() {
    # fn fn_call() {}
    let _: () = {
        fn_call();
    };

    let five: i32 = {
        fn_call();
        5
    };

    assert_eq!(5, five);
    #}

> Note: As a control flow expression, if a block expression is the outer 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 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.

    # #![allow(unused_variables)]
    #fn main() {
    struct Struct;

    impl Struct {
        fn consume_self(self) {}
        fn borrow_self(&self) {}
    }

    fn move_by_block_expression() {
        let s = Struct;

        // Move the value out of `s` in the block expreesion.
        (&{ s }).borrow_self();

        // Fails to execute because `s` is moved out of.
        s.consume_self();
    }
    #}

## `unsafe` blocks

> Syntax
> UnsafeBlockExpression :
> `unsafe` BlockExpression

See `unsafe` block for more information on when to use `unsafe`

A block of code can be prefixed with the `unsafe` keyword to permit unsafe operations. Examples:

    # #![allow(unused_variables)]
    #fn main() {
    unsafe {
        let b = [13u8, 17u8];
        let a = &b[0] as *const u8;
        assert_eq!(*a, 13);
        assert_eq!(*a.offset(1), 17);
    }

    # unsafe fn an_unsafe_fn() -> i32 { 10 }
    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.

For example, this function returns `true` on unix platforms and `false` on other platforms.

    # #![allow(unused_variables)]
    #fn main() {
    fn is_unix_platform() -> bool {
        #[cfg(unix)] { true }
        #[cfg(not(unix))] { false }
    }
    #}