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