]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/expressions.md
New upstream version 1.44.1+dfsg1
[rustc.git] / src / doc / reference / src / expressions.md
CommitLineData
8bb4bdeb
XL
1# Expressions
2
8faf50e0
XL
3> **<sup>Syntax</sup>**\
4> _Expression_ :\
13cf67c4
XL
5> &nbsp;&nbsp; &nbsp;&nbsp; _ExpressionWithoutBlock_\
6> &nbsp;&nbsp; | _ExpressionWithBlock_
7>
8> _ExpressionWithoutBlock_ :\
9> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\
10> &nbsp;&nbsp; (\
11> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_LiteralExpression_]\
12> &nbsp;&nbsp; &nbsp;&nbsp; | [_PathExpression_]\
13> &nbsp;&nbsp; &nbsp;&nbsp; | [_OperatorExpression_]\
14> &nbsp;&nbsp; &nbsp;&nbsp; | [_GroupedExpression_]\
15> &nbsp;&nbsp; &nbsp;&nbsp; | [_ArrayExpression_]\
e1599b0c 16> &nbsp;&nbsp; &nbsp;&nbsp; | [_AwaitExpression_]\
13cf67c4
XL
17> &nbsp;&nbsp; &nbsp;&nbsp; | [_IndexExpression_]\
18> &nbsp;&nbsp; &nbsp;&nbsp; | [_TupleExpression_]\
19> &nbsp;&nbsp; &nbsp;&nbsp; | [_TupleIndexingExpression_]\
20> &nbsp;&nbsp; &nbsp;&nbsp; | [_StructExpression_]\
21> &nbsp;&nbsp; &nbsp;&nbsp; | [_EnumerationVariantExpression_]\
22> &nbsp;&nbsp; &nbsp;&nbsp; | [_CallExpression_]\
23> &nbsp;&nbsp; &nbsp;&nbsp; | [_MethodCallExpression_]\
24> &nbsp;&nbsp; &nbsp;&nbsp; | [_FieldExpression_]\
25> &nbsp;&nbsp; &nbsp;&nbsp; | [_ClosureExpression_]\
26> &nbsp;&nbsp; &nbsp;&nbsp; | [_ContinueExpression_]\
27> &nbsp;&nbsp; &nbsp;&nbsp; | [_BreakExpression_]\
28> &nbsp;&nbsp; &nbsp;&nbsp; | [_RangeExpression_]\
29> &nbsp;&nbsp; &nbsp;&nbsp; | [_ReturnExpression_]\
30> &nbsp;&nbsp; &nbsp;&nbsp; | [_MacroInvocation_]\
31> &nbsp;&nbsp; )
32>
33> _ExpressionWithBlock_ :\
34> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\
35> &nbsp;&nbsp; (\
36> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]\
e1599b0c 37> &nbsp;&nbsp; &nbsp;&nbsp; | [_AsyncBlockExpression_]\
13cf67c4
XL
38> &nbsp;&nbsp; &nbsp;&nbsp; | [_UnsafeBlockExpression_]\
39> &nbsp;&nbsp; &nbsp;&nbsp; | [_LoopExpression_]\
40> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfExpression_]\
41> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfLetExpression_]\
42> &nbsp;&nbsp; &nbsp;&nbsp; | [_MatchExpression_]\
43> &nbsp;&nbsp; )
0531ce1d 44
8bb4bdeb
XL
45An expression may have two roles: it always produces a *value*, and it may have
46*effects* (otherwise known as "side effects"). An expression *evaluates to* a
47value, and has effects during *evaluation*. Many expressions contain
48sub-expressions (operands). The meaning of each kind of expression dictates
49several things:
50
51* Whether or not to evaluate the sub-expressions when evaluating the expression
52* The order in which to evaluate the sub-expressions
7cac9316
XL
53* How to combine the sub-expressions' values to obtain the value of the
54 expression
8bb4bdeb
XL
55
56In this way, the structure of expressions dictates the structure of execution.
57Blocks are just another kind of expression, so blocks, statements, expressions,
58and blocks again can recursively nest inside each other to an arbitrary depth.
59
abe05a73
XL
60## Expression precedence
61
62The precedence of Rust operators and expressions is ordered as follows, going
83c7162d
XL
63from strong to weak. Binary Operators at the same precedence level are grouped
64in the order given by their associativity.
abe05a73
XL
65
66| Operator/Expression | Associativity |
67|-----------------------------|---------------------|
68| Paths | |
69| Method calls | |
70| Field expressions | left to right |
71| Function calls, array indexing | |
72| `?` | |
73| Unary `-` `*` `!` `&` `&mut` | |
83c7162d 74| `as` | left to right |
abe05a73
XL
75| `*` `/` `%` | left to right |
76| `+` `-` | left to right |
77| `<<` `>>` | left to right |
78| `&` | left to right |
79| `^` | left to right |
80| <code>&#124;</code> | left to right |
81| `==` `!=` `<` `>` `<=` `>=` | Require parentheses |
82| `&&` | left to right |
83| <code>&#124;&#124;</code> | left to right |
0531ce1d 84| `..` `..=` | Require parentheses |
abe05a73
XL
85| `=` `+=` `-=` `*=` `/=` `%=` <br> `&=` <code>&#124;=</code> `^=` `<<=` `>>=` | right to left |
86| `return` `break` closures | |
87
ff7c6d11 88## Place Expressions and Value Expressions
8bb4bdeb 89
ff7c6d11
XL
90Expressions are divided into two main categories: place expressions and
91value expressions. Likewise within each expression, sub-expressions may occur
92in either place context or value context. The evaluation of an expression
93depends both on its own category and the context it occurs within.
8bb4bdeb 94
ff7c6d11
XL
95A *place expression* is an expression that represents a memory location. These
96expressions are [paths] which refer to local variables, [static variables],
532ac7d7 97[dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`),
ff7c6d11
XL
98[field] references (`expr.f`) and parenthesized place expressions. All other
99expressions are value expressions.
8bb4bdeb 100
ff7c6d11
XL
101A *value expression* is an expression that represents an actual value.
102
532ac7d7
XL
103The following contexts are *place expression* contexts:
104
105* The left operand of an [assignment][assign] or [compound assignment]
106 expression.
107* The operand of a unary [borrow] or [dereference][deref] operator.
108* The operand of a field expression.
109* The indexed operand of an array indexing expression.
110* The operand of any [implicit borrow].
111* The initializer of a [let statement].
112* The [scrutinee] of an [`if let`], [`match`][match], or [`while let`]
113 expression.
114* The base of a [functional update] struct expression.
ff7c6d11
XL
115
116> Note: Historically, place expressions were called *lvalues* and value
117> expressions were called *rvalues*.
8bb4bdeb 118
7cac9316 119### Moved and copied types
8bb4bdeb 120
ff7c6d11
XL
121When a place expression is evaluated in a value expression context, or is bound
122by value in a pattern, it denotes the value held _in_ that memory location. If
123the type of that value implements [`Copy`], then the value will be copied. In
124the remaining situations if that type is [`Sized`], then it may be possible to
125move the value. Only the following place expressions may be moved out of:
7cac9316 126
ff7c6d11 127* [Variables] which are not currently borrowed.
7cac9316 128* [Temporary values](#temporary-lifetimes).
ff7c6d11
XL
129* [Fields][field] of a place expression which can be moved out of and
130 doesn't implement [`Drop`].
532ac7d7
XL
131* The result of [dereferencing][deref] an expression with type [`Box<T>`] and
132 that can also be moved out of.
7cac9316 133
ff7c6d11
XL
134Moving out of a place expression that evaluates to a local variable, the
135location is deinitialized and cannot be read from again until it is
136reinitialized. In all other cases, trying to use a place expression in a value
137expression context is an error.
7cac9316
XL
138
139### Mutability
140
ff7c6d11
XL
141For a place expression to be [assigned][assign] to, mutably [borrowed][borrow],
142[implicitly mutably borrowed], or bound to a pattern containing `ref mut` it
143must be _mutable_. We call these *mutable place expressions*. In contrast,
144other place expressions are called *immutable place expressions*.
7cac9316 145
ff7c6d11 146The following expressions can be mutable place expression contexts:
7cac9316 147
ff7c6d11
XL
148* Mutable [variables], which are not currently borrowed.
149* [Mutable `static` items].
150* [Temporary values].
151* [Fields][field], this evaluates the subexpression in a mutable place
152 expression context.
532ac7d7 153* [Dereferences][deref] of a `*mut T` pointer.
7cac9316 154* Dereference of a variable, or field of a variable, with type `&mut T`. Note:
ff7c6d11 155 This is an exception to the requirement of the next rule.
7cac9316 156* Dereferences of a type that implements `DerefMut`, this then requires that
ff7c6d11 157 the value being dereferenced is evaluated is a mutable place expression context.
ea8adc8c 158* [Array indexing] of a type that implements `DerefMut`, this
ff7c6d11
XL
159 then evaluates the value being indexed, but not the index, in mutable place
160 expression context.
7cac9316
XL
161
162### Temporary lifetimes
163
ff7c6d11
XL
164When using a value expression in most place expression contexts, a temporary
165unnamed memory location is created initialized to that value and the expression
166evaluates to that location instead, except if promoted to `'static`. Promotion
167of a value expression to a `'static` slot occurs when the expression could be
3b2f2976 168written in a constant, borrowed, and dereferencing that borrow where the
0bf4aa26
XL
169expression was originally written, without changing the runtime behavior. That
170is, the promoted expression can be evaluated at compile-time and the resulting
171value does not contain [interior mutability] or [destructors] (these properties
172are determined based on the value where possible, e.g. `&None` always has the
173type `&'static Option<_>`, as it contains nothing disallowed). Otherwise, the
174lifetime of temporary values is typically
3b2f2976 175
abe05a73 176- the innermost enclosing statement; the tail expression of a block is
3b2f2976 177 considered part of the statement that encloses the block, or
abe05a73 178- the condition expression or the loop conditional expression if the
ff7c6d11
XL
179 temporary is created in the condition expression of an `if` or in the loop
180 conditional expression of a `while` expression.
8bb4bdeb 181
ff7c6d11
XL
182When a temporary value expression is being created that is assigned into a
183[`let` declaration][let], however, the temporary is created with the lifetime of
184the enclosing block instead, as using the enclosing [`let` declaration][let]
185would be a guaranteed error (since a pointer to the temporary
7cac9316
XL
186would be stored into a variable, but the temporary would be freed before the
187variable could be used). The compiler uses simple syntactic rules to decide
188which values are being assigned into a `let` binding, and therefore deserve a
189longer temporary lifetime.
8bb4bdeb
XL
190
191Here are some examples:
192
ff7c6d11 193- `let x = foo(&temp())`. The expression `temp()` is a value expression. As it
8bb4bdeb 194 is being borrowed, a temporary is created which will be freed after
ff7c6d11 195 the innermost enclosing statement; in this case, the `let` declaration.
8bb4bdeb
XL
196- `let x = temp().foo()`. This is the same as the previous example,
197 except that the value of `temp()` is being borrowed via autoref on a
198 method-call. Here we are assuming that `foo()` is an `&self` method
199 defined in some trait, say `Foo`. In other words, the expression
200 `temp().foo()` is equivalent to `Foo::foo(&temp())`.
3b2f2976 201- `let x = if foo(&temp()) {bar()} else {baz()};`. The expression `temp()` is
ff7c6d11
XL
202 a value expression. As the temporary is created in the condition expression
203 of an `if`, it will be freed at the end of the condition expression;
204 in this example before the call to `bar` or `baz` is made.
abe05a73 205- `let x = if temp().must_run_bar {bar()} else {baz()};`.
3b2f2976
XL
206 Here we assume the type of `temp()` is a struct with a boolean field
207 `must_run_bar`. As the previous example, the temporary corresponding to
208 `temp()` will be freed at the end of the condition expression.
209- `while foo(&temp()) {bar();}`. The temporary containing the return value from
210 the call to `temp()` is created in the loop conditional expression. Hence it
ff7c6d11
XL
211 will be freed at the end of the loop conditional expression; in this example
212 before the call to `bar` if the loop body is executed.
8bb4bdeb
XL
213- `let x = &temp()`. Here, the same temporary is being assigned into
214 `x`, rather than being passed as a parameter, and hence the
215 temporary's lifetime is considered to be the enclosing block.
216- `let x = SomeStruct { foo: &temp() }`. As in the previous case, the
217 temporary is assigned into a struct which is then assigned into a
218 binding, and hence it is given the lifetime of the enclosing block.
219- `let x = [ &temp() ]`. As in the previous case, the
220 temporary is assigned into an array which is then assigned into a
221 binding, and hence it is given the lifetime of the enclosing block.
ff7c6d11
XL
222- `let ref x = temp()`. In this case, the temporary is created using a ref
223 binding, but the result is the same: the lifetime is extended to the enclosing
224 block.
8bb4bdeb 225
7cac9316 226### Implicit Borrows
8bb4bdeb 227
ff7c6d11 228Certain expressions will treat an expression as a place expression by implicitly
b7449926 229borrowing it. For example, it is possible to compare two unsized [slices][slice] for
ea8adc8c 230equality directly, because the `==` operator implicitly borrows it's operands:
7cac9316
XL
231
232```rust
233# let c = [1, 2, 3];
234# let d = vec![1, 2, 3];
235let a: &[i32];
236let b: &[i32];
237# a = &c;
238# b = &d;
239// ...
240*a == *b;
241// Equivalent form:
242::std::cmp::PartialEq::eq(&*a, &*b);
243```
244
245Implicit borrows may be taken in the following expressions:
246
ea8adc8c
XL
247* Left operand in [method-call] expressions.
248* Left operand in [field] expressions.
249* Left operand in [call expressions].
250* Left operand in [array indexing] expressions.
532ac7d7 251* Operand of the [dereference operator][deref] (`*`).
ea8adc8c
XL
252* Operands of [comparison].
253* Left operands of the [compound assignment].
7cac9316 254
7cac9316
XL
255## Overloading Traits
256
257Many of the following operators and expressions can also be overloaded for
ff7c6d11 258other types using traits in `std::ops` or `std::cmp`. These traits also
7cac9316 259exist in `core::ops` and `core::cmp` with the same names.
8bb4bdeb 260
13cf67c4
XL
261## Expression Attributes
262
263[Outer attributes][_OuterAttribute_] before an expression are allowed only in
264a few specific cases:
265
266* Before an expression used as a [statement].
267* Elements of [array expressions], [tuple expressions], [call expressions],
e1599b0c 268 and tuple-style [struct] and [enum variant] expressions.
13cf67c4
XL
269 <!--
270 These were likely stabilized inadvertently.
271 See https://github.com/rust-lang/rust/issues/32796 and
272 https://github.com/rust-lang/rust/issues/15701
273 -->
274* The tail expression of [block expressions].
275<!-- Keep list in sync with block-expr.md -->
276
277They are never allowed before:
13cf67c4
XL
278* [Range][_RangeExpression_] expressions.
279* Binary operator expressions ([_ArithmeticOrLogicalExpression_],
280 [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_],
281 [_AssignmentExpression_], [_CompoundAssignmentExpression_]).
282
283
416331ca
XL
284[block expressions]: expressions/block-expr.md
285[call expressions]: expressions/call-expr.md
286[enum variant]: expressions/enum-variant-expr.md
287[field]: expressions/field-expr.md
288[functional update]: expressions/struct-expr.md#functional-update-syntax
289[`if let`]: expressions/if-expr.md#if-let-expressions
290[match]: expressions/match-expr.md
291[method-call]: expressions/method-call-expr.md
292[paths]: expressions/path-expr.md
293[struct]: expressions/struct-expr.md
294[tuple expressions]: expressions/tuple-expr.md
295[`while let`]: expressions/loop-expr.md#predicate-pattern-loops
296
297[array expressions]: expressions/array-expr.md
298[array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions
299
300[assign]: expressions/operator-expr.md#assignment-expressions
301[borrow]: expressions/operator-expr.md#borrow-operators
302[comparison]: expressions/operator-expr.md#comparison-operators
303[compound assignment]: expressions/operator-expr.md#compound-assignment-expressions
304[deref]: expressions/operator-expr.md#the-dereference-operator
305
306[destructors]: destructors.md
307[interior mutability]: interior-mutability.md
308[`Box<T>`]: ../std/boxed/struct.Box.md
309[`Copy`]: special-types-and-traits.md#copy
310[`Drop`]: special-types-and-traits.md#drop
311[`Sized`]: special-types-and-traits.md#sized
ff7c6d11
XL
312[implicit borrow]: #implicit-borrows
313[implicitly mutably borrowed]: #implicit-borrows
416331ca
XL
314[let]: statements.md#let-statements
315[let statement]: statements.md#let-statements
316[Mutable `static` items]: items/static-items.md#mutable-statics
317[scrutinee]: glossary.md#scrutinee
318[slice]: types/slice.md
319[statement]: statements.md
320[static variables]: items/static-items.md
ff7c6d11 321[Temporary values]: #temporary-lifetimes
416331ca
XL
322[Variables]: variables.md
323
324
325[_ArithmeticOrLogicalExpression_]: expressions/operator-expr.md#arithmetic-and-logical-binary-operators
326[_ArrayExpression_]: expressions/array-expr.md
e1599b0c
XL
327[_AsyncBlockExpression_]: expressions/block-expr.md#async-blocks
328[_AwaitExpression_]: expressions/await-expr.md
416331ca
XL
329[_AssignmentExpression_]: expressions/operator-expr.md#assignment-expressions
330[_BlockExpression_]: expressions/block-expr.md
331[_BreakExpression_]: expressions/loop-expr.md#break-expressions
332[_CallExpression_]: expressions/call-expr.md
333[_ClosureExpression_]: expressions/closure-expr.md
334[_ComparisonExpression_]: expressions/operator-expr.md#comparison-operators
335[_CompoundAssignmentExpression_]: expressions/operator-expr.md#compound-assignment-expressions
336[_ContinueExpression_]: expressions/loop-expr.md#continue-expressions
337[_EnumerationVariantExpression_]: expressions/enum-variant-expr.md
338[_FieldExpression_]: expressions/field-expr.md
339[_GroupedExpression_]: expressions/grouped-expr.md
340[_IfExpression_]: expressions/if-expr.md#if-expressions
341[_IfLetExpression_]: expressions/if-expr.md#if-let-expressions
342[_IndexExpression_]: expressions/array-expr.md#array-and-slice-indexing-expressions
343[_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators
344[_LiteralExpression_]: expressions/literal-expr.md
345[_LoopExpression_]: expressions/loop-expr.md
346[_MacroInvocation_]: macros.md#macro-invocation
347[_MatchExpression_]: expressions/match-expr.md
348[_MethodCallExpression_]: expressions/method-call-expr.md
349[_OperatorExpression_]: expressions/operator-expr.md
350[_OuterAttribute_]: attributes.md
351[_PathExpression_]: expressions/path-expr.md
352[_RangeExpression_]: expressions/range-expr.md
353[_ReturnExpression_]: expressions/return-expr.md
354[_StructExpression_]: expressions/struct-expr.md
355[_TupleExpression_]: expressions/tuple-expr.md
356[_TupleIndexingExpression_]: expressions/tuple-expr.md#tuple-indexing-expressions
357[_TypeCastExpression_]: expressions/operator-expr.md#type-cast-expressions
358[_UnsafeBlockExpression_]: expressions/block-expr.md#unsafe-blocks