]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
1 | # Expressions |
2 | ||
8faf50e0 XL |
3 | > **<sup>Syntax</sup>**\ |
4 | > _Expression_ :\ | |
13cf67c4 XL |
5 | > _ExpressionWithoutBlock_\ |
6 | > | _ExpressionWithBlock_ | |
7 | > | |
8 | > _ExpressionWithoutBlock_ :\ | |
9 | > [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\ | |
10 | > (\ | |
11 | > [_LiteralExpression_]\ | |
12 | > | [_PathExpression_]\ | |
13 | > | [_OperatorExpression_]\ | |
14 | > | [_GroupedExpression_]\ | |
15 | > | [_ArrayExpression_]\ | |
e1599b0c | 16 | > | [_AwaitExpression_]\ |
13cf67c4 XL |
17 | > | [_IndexExpression_]\ |
18 | > | [_TupleExpression_]\ | |
19 | > | [_TupleIndexingExpression_]\ | |
20 | > | [_StructExpression_]\ | |
13cf67c4 XL |
21 | > | [_CallExpression_]\ |
22 | > | [_MethodCallExpression_]\ | |
23 | > | [_FieldExpression_]\ | |
24 | > | [_ClosureExpression_]\ | |
25 | > | [_ContinueExpression_]\ | |
26 | > | [_BreakExpression_]\ | |
27 | > | [_RangeExpression_]\ | |
28 | > | [_ReturnExpression_]\ | |
29 | > | [_MacroInvocation_]\ | |
30 | > ) | |
31 | > | |
32 | > _ExpressionWithBlock_ :\ | |
33 | > [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\ | |
34 | > (\ | |
35 | > [_BlockExpression_]\ | |
e1599b0c | 36 | > | [_AsyncBlockExpression_]\ |
13cf67c4 XL |
37 | > | [_UnsafeBlockExpression_]\ |
38 | > | [_LoopExpression_]\ | |
39 | > | [_IfExpression_]\ | |
40 | > | [_IfLetExpression_]\ | |
41 | > | [_MatchExpression_]\ | |
42 | > ) | |
0531ce1d | 43 | |
8bb4bdeb XL |
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 | |
5869c6ff XL |
47 | sub-expressions, called the *operands* of the expression. The meaning of each |
48 | kind of expression dictates several things: | |
8bb4bdeb | 49 | |
5869c6ff XL |
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 | |
8bb4bdeb XL |
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 | ||
cdc7bbd5 XL |
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 | ||
abe05a73 XL |
61 | ## Expression precedence |
62 | ||
63 | The precedence of Rust operators and expressions is ordered as follows, going | |
83c7162d XL |
64 | from strong to weak. Binary Operators at the same precedence level are grouped |
65 | in the order given by their associativity. | |
abe05a73 XL |
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` | | | |
83c7162d | 75 | | `as` | left to right | |
abe05a73 XL |
76 | | `*` `/` `%` | left to right | |
77 | | `+` `-` | left to right | | |
78 | | `<<` `>>` | left to right | | |
79 | | `&` | left to right | | |
80 | | `^` | left to right | | |
81 | | <code>|</code> | left to right | | |
82 | | `==` `!=` `<` `>` `<=` `>=` | Require parentheses | | |
83 | | `&&` | left to right | | |
84 | | <code>||</code> | left to right | | |
0531ce1d | 85 | | `..` `..=` | Require parentheses | |
abe05a73 XL |
86 | | `=` `+=` `-=` `*=` `/=` `%=` <br> `&=` <code>|=</code> `^=` `<<=` `>>=` | right to left | |
87 | | `return` `break` closures | | | |
88 | ||
5869c6ff XL |
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 | |
5869c6ff XL |
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 | ||
ff7c6d11 | 140 | ## Place Expressions and Value Expressions |
8bb4bdeb | 141 | |
ff7c6d11 | 142 | Expressions are divided into two main categories: place expressions and |
cdc7bbd5 | 143 | value expressions. Likewise within each expression, operands may occur |
ff7c6d11 XL |
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. | |
8bb4bdeb | 146 | |
ff7c6d11 XL |
147 | A *place expression* is an expression that represents a memory location. These |
148 | expressions are [paths] which refer to local variables, [static variables], | |
532ac7d7 | 149 | [dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), |
ff7c6d11 XL |
150 | [field] references (`expr.f`) and parenthesized place expressions. All other |
151 | expressions are value expressions. | |
8bb4bdeb | 152 | |
ff7c6d11 XL |
153 | A *value expression* is an expression that represents an actual value. |
154 | ||
532ac7d7 XL |
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. | |
ff7c6d11 XL |
167 | |
168 | > Note: Historically, place expressions were called *lvalues* and value | |
169 | > expressions were called *rvalues*. | |
8bb4bdeb | 170 | |
7cac9316 | 171 | ### Moved and copied types |
8bb4bdeb | 172 | |
ff7c6d11 XL |
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: | |
7cac9316 | 178 | |
ff7c6d11 | 179 | * [Variables] which are not currently borrowed. |
f9f354fc | 180 | * [Temporary values](#temporaries). |
ff7c6d11 XL |
181 | * [Fields][field] of a place expression which can be moved out of and |
182 | doesn't implement [`Drop`]. | |
532ac7d7 XL |
183 | * The result of [dereferencing][deref] an expression with type [`Box<T>`] and |
184 | that can also be moved out of. | |
7cac9316 | 185 | |
ff7c6d11 XL |
186 | 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. | |
7cac9316 XL |
190 | |
191 | ### Mutability | |
192 | ||
ff7c6d11 XL |
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*. | |
7cac9316 | 197 | |
ff7c6d11 | 198 | The following expressions can be mutable place expression contexts: |
7cac9316 | 199 | |
ff7c6d11 XL |
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. | |
532ac7d7 | 205 | * [Dereferences][deref] of a `*mut T` pointer. |
7cac9316 | 206 | * Dereference of a variable, or field of a variable, with type `&mut T`. Note: |
ff7c6d11 | 207 | This is an exception to the requirement of the next rule. |
7cac9316 | 208 | * Dereferences of a type that implements `DerefMut`, this then requires that |
ff7c6d11 | 209 | the value being dereferenced is evaluated is a mutable place expression context. |
f035d41b | 210 | * [Array indexing] of a type that implements `IndexMut`, this |
ff7c6d11 XL |
211 | then evaluates the value being indexed, but not the index, in mutable place |
212 | expression context. | |
7cac9316 | 213 | |
f9f354fc | 214 | ### Temporaries |
7cac9316 | 215 | |
ff7c6d11 XL |
216 | When using a value expression in most place expression contexts, a temporary |
217 | unnamed memory location is created initialized to that value and the expression | |
f9f354fc XL |
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. | |
8bb4bdeb | 220 | |
7cac9316 | 221 | ### Implicit Borrows |
8bb4bdeb | 222 | |
ff7c6d11 | 223 | Certain expressions will treat an expression as a place expression by implicitly |
b7449926 | 224 | borrowing it. For example, it is possible to compare two unsized [slices][slice] for |
ea8adc8c | 225 | equality directly, because the `==` operator implicitly borrows it's operands: |
7cac9316 XL |
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 | ||
ea8adc8c XL |
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. | |
532ac7d7 | 246 | * Operand of the [dereference operator][deref] (`*`). |
ea8adc8c XL |
247 | * Operands of [comparison]. |
248 | * Left operands of the [compound assignment]. | |
7cac9316 | 249 | |
7cac9316 XL |
250 | ## Overloading Traits |
251 | ||
252 | Many of the following operators and expressions can also be overloaded for | |
ff7c6d11 | 253 | other types using traits in `std::ops` or `std::cmp`. These traits also |
7cac9316 | 254 | exist in `core::ops` and `core::cmp` with the same names. |
8bb4bdeb | 255 | |
13cf67c4 XL |
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], | |
6a06907d | 263 | and tuple-style [struct] expressions. |
13cf67c4 XL |
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: | |
13cf67c4 XL |
273 | * [Range][_RangeExpression_] expressions. |
274 | * Binary operator expressions ([_ArithmeticOrLogicalExpression_], | |
275 | [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_], | |
276 | [_AssignmentExpression_], [_CompoundAssignmentExpression_]). | |
277 | ||
278 | ||
416331ca XL |
279 | [block expressions]: expressions/block-expr.md |
280 | [call expressions]: expressions/call-expr.md | |
416331ca XL |
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 | |
f9f354fc XL |
301 | [drop scope]: destructors.md#drop-scopes |
302 | ||
303 | [`Box<T>`]: ../std/boxed/struct.Box.html | |
416331ca XL |
304 | [`Copy`]: special-types-and-traits.md#copy |
305 | [`Drop`]: special-types-and-traits.md#drop | |
306 | [`Sized`]: special-types-and-traits.md#sized | |
ff7c6d11 XL |
307 | [implicit borrow]: #implicit-borrows |
308 | [implicitly mutably borrowed]: #implicit-borrows | |
f9f354fc | 309 | [interior mutability]: interior-mutability.md |
416331ca XL |
310 | [let statement]: statements.md#let-statements |
311 | [Mutable `static` items]: items/static-items.md#mutable-statics | |
312 | [scrutinee]: glossary.md#scrutinee | |
f9f354fc | 313 | [promoted]: destructors.md#constant-promotion |
416331ca XL |
314 | [slice]: types/slice.md |
315 | [statement]: statements.md | |
316 | [static variables]: items/static-items.md | |
f9f354fc | 317 | [Temporary values]: #temporaries |
416331ca XL |
318 | [Variables]: variables.md |
319 | ||
416331ca XL |
320 | [_ArithmeticOrLogicalExpression_]: expressions/operator-expr.md#arithmetic-and-logical-binary-operators |
321 | [_ArrayExpression_]: expressions/array-expr.md | |
e1599b0c XL |
322 | [_AsyncBlockExpression_]: expressions/block-expr.md#async-blocks |
323 | [_AwaitExpression_]: expressions/await-expr.md | |
416331ca XL |
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 | |
416331ca XL |
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 |