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