# Expressions

^{Syntax}

Expression:

ExpressionWithoutBlock

|ExpressionWithBlock

ExpressionWithoutBlock:

OuterAttribute^{*}†

(

LiteralExpression

|PathExpression

|OperatorExpression

|GroupedExpression

|ArrayExpression

|AwaitExpression

|IndexExpression

|TupleExpression

|TupleIndexingExpression

|StructExpression

|EnumerationVariantExpression

|CallExpression

|MethodCallExpression

|FieldExpression

|ClosureExpression

|ContinueExpression

|BreakExpression

|RangeExpression

|ReturnExpression

|MacroInvocation

)

ExpressionWithBlock:

OuterAttribute^{*}†

(

BlockExpression

|AsyncBlockExpression

|UnsafeBlockExpression

|LoopExpression

|IfExpression

|IfLetExpression

|MatchExpression

)

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
value, and has effects during *evaluation*. Many expressions contain
sub-expressions, called the *operands* of the expression. The meaning of each
kind of expression dictates several things:

- Whether or not to evaluate the operands when evaluating the expression
- The order in which to evaluate the operands
- How to combine the operands' values to obtain the value of the expression

In this way, the structure of expressions dictates the structure of execution. Blocks are just another kind of expression, so blocks, statements, expressions, and blocks again can recursively nest inside each other to an arbitrary depth.

## Expression precedence

The precedence of Rust operators and expressions is ordered as follows, going from strong to weak. Binary Operators at the same precedence level are grouped in the order given by their associativity.

Operator/Expression | Associativity |
---|---|

Paths | |

Method calls | |

Field expressions | left to right |

Function calls, array indexing | |

`?` | |

Unary `-` `*` `!` `&` `&mut` | |

`as` | left to right |

`*` `/` `%` | left to right |

`+` `-` | left to right |

`<<` `>>` | left to right |

`&` | left to right |

`^` | left to right |

`|` | left to right |

`==` `!=` `<` `>` `<=` `>=` | Require parentheses |

`&&` | left to right |

`||` | left to right |

`..` `..=` | Require parentheses |

`=` `+=` `-=` `*=` `/=` `%=` `&=` `|=` `^=` `<<=` `>>=` | right to left |

`return` `break` closures |

## Evaluation order of operands

The following list of expressions all evaluate their operands the same way, as described after the list. Other expressions either don't take operands or evaluate them conditionally as described on their respective pages.

- Dereference expression
- Error propagation expression
- Negation expression
- Arithmetic and logical binary operators
- Comparison operators
- Type cast expression
- Grouped expression
- Array expression
- Await expression
- Index expression
- Tuple expression
- Tuple index expression
- Struct expression
- Enumeration variant expression
- Call expression
- Method call expression
- Field expression
- Break expression
- Range expression
- Return expression

The operands of these expressions are evaluated prior to applying the effects of the expression. Expressions taking multiple operands are evaluated left to right as written in the source code.

Note: Which subexpressions are the operands of an expression is determined by expression precedence as per the previous section.

For example, the two `next`

method calls will always be called in the same
order:

`#![allow(unused)] fn main() { // Using vec instead of array to avoid references // since there is no stable owned array iterator // at the time this example was written. let mut one_two = vec![1, 2].into_iter(); assert_eq!( (1, 2), (one_two.next().unwrap(), one_two.next().unwrap()) ); }`

Note: Since this is applied recursively, these expressions are also evaluated from innermost to outermost, ignoring siblings until there are no inner subexpressions.

## Place Expressions and Value Expressions

Expressions are divided into two main categories: place expressions and value expressions. Likewise within each expression, sub-expressions may occur in either place context or value context. The evaluation of an expression depends both on its own category and the context it occurs within.

A *place expression* is an expression that represents a memory location. These
expressions are paths which refer to local variables, static variables,
dereferences (`*expr`

), array indexing expressions (`expr[expr]`

),
field references (`expr.f`

) and parenthesized place expressions. All other
expressions are value expressions.

A *value expression* is an expression that represents an actual value.

The following contexts are *place expression* contexts:

- The left operand of an assignment or compound assignment expression.
- The operand of a unary borrow or dereference operator.
- The operand of a field expression.
- The indexed operand of an array indexing expression.
- The operand of any implicit borrow.
- The initializer of a let statement.
- The scrutinee of an
`if let`

,`match`

, or`while let`

expression. - The base of a functional update struct expression.

Note: Historically, place expressions were called

lvaluesand value expressions were calledrvalues.

### Moved and copied types

When a place expression is evaluated in a value expression context, or is bound
by value in a pattern, it denotes the value held *in* that memory location. If
the type of that value implements `Copy`

, then the value will be copied. In
the remaining situations if that type is `Sized`

, then it may be possible to
move the value. Only the following place expressions may be moved out of:

- Variables which are not currently borrowed.
- Temporary values.
- Fields of a place expression which can be moved out of and
doesn't implement
`Drop`

. - The result of dereferencing an expression with type
`Box<T>`

and that can also be moved out of.

Moving out of a place expression that evaluates to a local variable, the location is deinitialized and cannot be read from again until it is reinitialized. In all other cases, trying to use a place expression in a value expression context is an error.

### Mutability

For a place expression to be assigned to, mutably borrowed,
implicitly mutably borrowed, or bound to a pattern containing `ref mut`

it
must be *mutable*. We call these *mutable place expressions*. In contrast,
other place expressions are called *immutable place expressions*.

The following expressions can be mutable place expression contexts:

- Mutable variables, which are not currently borrowed.
- Mutable
`static`

items. - Temporary values.
- Fields, this evaluates the subexpression in a mutable place expression context.
- Dereferences of a
`*mut T`

pointer. - Dereference of a variable, or field of a variable, with type
`&mut T`

. Note: This is an exception to the requirement of the next rule. - Dereferences of a type that implements
`DerefMut`

, this then requires that the value being dereferenced is evaluated is a mutable place expression context. - Array indexing of a type that implements
`IndexMut`

, this then evaluates the value being indexed, but not the index, in mutable place expression context.

### Temporaries

When using a value expression in most place expression contexts, a temporary
unnamed memory location is created initialized to that value and the expression
evaluates to that location instead, except if promoted to a `static`

. The
drop scope of the temporary is usually the end of the enclosing statement.

### Implicit Borrows

Certain expressions will treat an expression as a place expression by implicitly
borrowing it. For example, it is possible to compare two unsized slices for
equality directly, because the `==`

operator implicitly borrows it's operands:

`#![allow(unused)] fn main() { let c = [1, 2, 3]; let d = vec![1, 2, 3]; let a: &[i32]; let b: &[i32]; a = &c; b = &d; // ... *a == *b; // Equivalent form: ::std::cmp::PartialEq::eq(&*a, &*b); }`

Implicit borrows may be taken in the following expressions:

- Left operand in method-call expressions.
- Left operand in field expressions.
- Left operand in call expressions.
- Left operand in array indexing expressions.
- Operand of the dereference operator (
`*`

). - Operands of comparison.
- Left operands of the compound assignment.

## Overloading Traits

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 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, and tuple-style struct and enum variant expressions.
- The tail expression of block expressions.

They are never allowed before:

- Range expressions.
- Binary operator expressions (
*ArithmeticOrLogicalExpression*,*ComparisonExpression*,*LazyBooleanExpression*,*TypeCastExpression*,*AssignmentExpression*,*CompoundAssignmentExpression*).