Syntax
Expression :
ExpressionWithoutBlock
| ExpressionWithBlockExpressionWithoutBlock :
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 (operands). The meaning of each kind of expression dictates several things:
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.
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 |
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:
if let
, match
, or while let
expression.Note: Historically, place expressions were called lvalues and value expressions were called rvalues.
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:
Drop
.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.
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:
static
items.*mut T
pointer.&mut T
. Note: This is an exception to the requirement of the next rule.DerefMut
, this then requires that the value being dereferenced is evaluated is a mutable place expression context.IndexMut
, this then evaluates the value being indexed, but not the index, in mutable place expression context.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.
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:
*
).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.
Outer attributes before an expression are allowed only in a few specific cases:
They are never allowed before:
© 2010 The Rust Project Developers
Licensed under the Apache License, Version 2.0 or the MIT license, at your option.
https://doc.rust-lang.org/reference/expressions.html