]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
1 | # Expressions |
2 | ||
3 | An expression may have two roles: it always produces a *value*, and it may have | |
4 | *effects* (otherwise known as "side effects"). An expression *evaluates to* a | |
5 | value, and has effects during *evaluation*. Many expressions contain | |
6 | sub-expressions (operands). The meaning of each kind of expression dictates | |
7 | several things: | |
8 | ||
9 | * Whether or not to evaluate the sub-expressions when evaluating the expression | |
10 | * The order in which to evaluate the sub-expressions | |
7cac9316 XL |
11 | * How to combine the sub-expressions' values to obtain the value of the |
12 | expression | |
8bb4bdeb XL |
13 | |
14 | In this way, the structure of expressions dictates the structure of execution. | |
15 | Blocks are just another kind of expression, so blocks, statements, expressions, | |
16 | and blocks again can recursively nest inside each other to an arbitrary depth. | |
17 | ||
abe05a73 XL |
18 | ## Expression precedence |
19 | ||
20 | The precedence of Rust operators and expressions is ordered as follows, going | |
21 | from strong to weak. Binary Operators at the same precedence level are | |
22 | evaluated in the order given by their associativity. | |
23 | ||
24 | | Operator/Expression | Associativity | | |
25 | |-----------------------------|---------------------| | |
26 | | Paths | | | |
27 | | Method calls | | | |
28 | | Field expressions | left to right | | |
29 | | Function calls, array indexing | | | |
30 | | `?` | | | |
31 | | Unary `-` `*` `!` `&` `&mut` | | | |
32 | | `as` `:` | left to right | | |
33 | | `*` `/` `%` | left to right | | |
34 | | `+` `-` | left to right | | |
35 | | `<<` `>>` | left to right | | |
36 | | `&` | left to right | | |
37 | | `^` | left to right | | |
38 | | <code>|</code> | left to right | | |
39 | | `==` `!=` `<` `>` `<=` `>=` | Require parentheses | | |
40 | | `&&` | left to right | | |
41 | | <code>||</code> | left to right | | |
42 | | `..` `...` | Require parentheses | | |
43 | | `<-` | right to left | | |
44 | | `=` `+=` `-=` `*=` `/=` `%=` <br> `&=` <code>|=</code> `^=` `<<=` `>>=` | right to left | | |
45 | | `return` `break` closures | | | |
46 | ||
7cac9316 | 47 | ## Lvalues and rvalues |
8bb4bdeb XL |
48 | |
49 | Expressions are divided into two main categories: _lvalues_ and _rvalues_. | |
50 | Likewise within each expression, sub-expressions may occur in _lvalue context_ | |
51 | or _rvalue context_. The evaluation of an expression depends both on its own | |
52 | category and the context it occurs within. | |
53 | ||
54 | An lvalue is an expression that represents a memory location. These expressions | |
abe05a73 XL |
55 | are [paths](expressions/path-expr.html) which refer to local variables, static |
56 | variables, function parameters, [dereferences] (`*expr`), [array indexing] | |
57 | expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized | |
58 | lvalue expressions. All other expressions are rvalues. | |
8bb4bdeb | 59 | |
ea8adc8c XL |
60 | The left operand of an [assign]ment or [compound assignment] expression is an |
61 | lvalue context, as is the single operand of a unary [borrow], and the operand | |
62 | of any [implicit borrow](#implicit-borrows). The discriminant or subject of a | |
abe05a73 XL |
63 | [match] expression and right side of a `let` is also an lvalue context. All |
64 | other expression contexts are rvalue contexts. | |
8bb4bdeb | 65 | |
7cac9316 | 66 | ### Moved and copied types |
8bb4bdeb | 67 | |
abe05a73 XL |
68 | When an lvalue is evaluated in an _rvalue context_ or is bound by value in a |
69 | pattern, it denotes the value held _in_ that memory location. If value is of a | |
70 | type that implements `Copy`, then the value will be copied. In the remaining | |
71 | situations if the type of the value is [`Sized`](the-sized-trait.html) it may | |
72 | be possible to move the value. Only the following lvalues may be moved out of: | |
7cac9316 XL |
73 | |
74 | * [Variables](variables.html) which are not currently borrowed. | |
75 | * [Temporary values](#temporary-lifetimes). | |
ea8adc8c | 76 | * [Field]s of an lvalue which can be moved out of and |
7cac9316 | 77 | doesn't implement [`Drop`](the-drop-trait.html). |
ea8adc8c XL |
78 | * The result of [dereferencing] an expression with type `Box<T>` and that can |
79 | also be moved out of. | |
7cac9316 XL |
80 | |
81 | Moving out of an lvalue deinitializes that location (if it comes from a local | |
82 | variable), so that it can't be read from again. In all other cases, trying to | |
83 | use an lvalue in an rvalue context is an error. | |
84 | ||
85 | ### Mutability | |
86 | ||
ea8adc8c XL |
87 | For an lvalue to be [assign]ed to, mutably [borrow]ed, |
88 | [implicitly mutably borrowed](#implicit-borrows) | |
7cac9316 XL |
89 | or bound to a pattern containing `ref mut` it must be _mutable_, we call these |
90 | contexts _mutable_ lvalue contexts, other lvalue contexts are called | |
91 | _immutable_. | |
92 | ||
93 | The following expressions can create mutable lvalues: | |
94 | ||
95 | * Mutable [variables](variables.html), which are not currently borrowed. | |
ea8adc8c | 96 | * [Mutable `static` items](items/static-items.html#mutable-statics). |
7cac9316 | 97 | * [Temporary values](#temporary-lifetimes). |
ea8adc8c XL |
98 | * [Field]s, this evaluates the subexpression in a mutable lvalue context. |
99 | * [Dereferences] of a `*mut T` pointer. | |
7cac9316 XL |
100 | * Dereference of a variable, or field of a variable, with type `&mut T`. Note: |
101 | this is an exception to the requirement for the next rule. | |
102 | * Dereferences of a type that implements `DerefMut`, this then requires that | |
103 | the value being dereferenced is evaluated is a mutable lvalue context. | |
ea8adc8c | 104 | * [Array indexing] of a type that implements `DerefMut`, this |
041b39d2 | 105 | then evaluates the value being indexed (but not the index) in mutable lvalue |
7cac9316 XL |
106 | context. |
107 | ||
108 | ### Temporary lifetimes | |
109 | ||
110 | When using an rvalue in most lvalue contexts, a temporary unnamed lvalue is | |
3b2f2976 XL |
111 | created and used instead, if not promoted to `'static`. Promotion of an |
112 | rvalue expression to a `'static` slot occurs when the expression could be | |
113 | written in a constant, borrowed, and dereferencing that borrow where the | |
114 | expression was the originally written, without changing the runtime behavior. | |
115 | That is, the promoted expression can be evaluated at compile-time and the | |
116 | resulting value does not contain interior mutability or destructors (these | |
117 | properties are determined based on the value where possible, e.g. `&None` | |
118 | always has the type `&'static Option<_>`, as it contains nothing disallowed). | |
abe05a73 | 119 | Otherwise, the lifetime of temporary values is typically |
3b2f2976 | 120 | |
abe05a73 | 121 | - the innermost enclosing statement; the tail expression of a block is |
3b2f2976 | 122 | considered part of the statement that encloses the block, or |
abe05a73 | 123 | - the condition expression or the loop conditional expression if the |
3b2f2976 XL |
124 | temporary is created in the condition expression of an `if` or an `if`/`else` |
125 | or in the loop conditional expression of a `while` expression. | |
8bb4bdeb XL |
126 | |
127 | When a temporary rvalue is being created that is assigned into a `let` | |
7cac9316 XL |
128 | declaration, however, the temporary is created with the lifetime of the |
129 | enclosing block instead, as using the enclosing statement (the `let` | |
130 | declaration) would be a guaranteed error (since a pointer to the temporary | |
131 | would be stored into a variable, but the temporary would be freed before the | |
132 | variable could be used). The compiler uses simple syntactic rules to decide | |
133 | which values are being assigned into a `let` binding, and therefore deserve a | |
134 | longer temporary lifetime. | |
8bb4bdeb XL |
135 | |
136 | Here are some examples: | |
137 | ||
138 | - `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it | |
139 | is being borrowed, a temporary is created which will be freed after | |
140 | the innermost enclosing statement (the `let` declaration, in this case). | |
141 | - `let x = temp().foo()`. This is the same as the previous example, | |
142 | except that the value of `temp()` is being borrowed via autoref on a | |
143 | method-call. Here we are assuming that `foo()` is an `&self` method | |
144 | defined in some trait, say `Foo`. In other words, the expression | |
145 | `temp().foo()` is equivalent to `Foo::foo(&temp())`. | |
3b2f2976 XL |
146 | - `let x = if foo(&temp()) {bar()} else {baz()};`. The expression `temp()` is |
147 | an rvalue. As the temporary is created in the condition expression | |
148 | of an `if`/`else`, it will be freed at the end of the condition expression | |
149 | (in this example before the call to `bar` or `baz` is made). | |
abe05a73 | 150 | - `let x = if temp().must_run_bar {bar()} else {baz()};`. |
3b2f2976 XL |
151 | Here we assume the type of `temp()` is a struct with a boolean field |
152 | `must_run_bar`. As the previous example, the temporary corresponding to | |
153 | `temp()` will be freed at the end of the condition expression. | |
154 | - `while foo(&temp()) {bar();}`. The temporary containing the return value from | |
155 | the call to `temp()` is created in the loop conditional expression. Hence it | |
156 | will be freed at the end of the loop conditional expression (in this example | |
157 | before the call to `bar` if the loop body is executed). | |
8bb4bdeb XL |
158 | - `let x = &temp()`. Here, the same temporary is being assigned into |
159 | `x`, rather than being passed as a parameter, and hence the | |
160 | temporary's lifetime is considered to be the enclosing block. | |
161 | - `let x = SomeStruct { foo: &temp() }`. As in the previous case, the | |
162 | temporary is assigned into a struct which is then assigned into a | |
163 | binding, and hence it is given the lifetime of the enclosing block. | |
164 | - `let x = [ &temp() ]`. As in the previous case, the | |
165 | temporary is assigned into an array which is then assigned into a | |
166 | binding, and hence it is given the lifetime of the enclosing block. | |
167 | - `let ref x = temp()`. In this case, the temporary is created using a ref binding, | |
168 | but the result is the same: the lifetime is extended to the enclosing block. | |
169 | ||
7cac9316 | 170 | ### Implicit Borrows |
8bb4bdeb | 171 | |
7cac9316 | 172 | Certain expressions will treat an expression as an lvalue by implicitly |
ea8adc8c XL |
173 | borrowing it. For example, it is possible to compare two unsized [slices] for |
174 | equality directly, because the `==` operator implicitly borrows it's operands: | |
7cac9316 XL |
175 | |
176 | ```rust | |
177 | # let c = [1, 2, 3]; | |
178 | # let d = vec![1, 2, 3]; | |
179 | let a: &[i32]; | |
180 | let b: &[i32]; | |
181 | # a = &c; | |
182 | # b = &d; | |
183 | // ... | |
184 | *a == *b; | |
185 | // Equivalent form: | |
186 | ::std::cmp::PartialEq::eq(&*a, &*b); | |
187 | ``` | |
188 | ||
189 | Implicit borrows may be taken in the following expressions: | |
190 | ||
ea8adc8c XL |
191 | * Left operand in [method-call] expressions. |
192 | * Left operand in [field] expressions. | |
193 | * Left operand in [call expressions]. | |
194 | * Left operand in [array indexing] expressions. | |
195 | * Operand of the [dereference] operator (`*`). | |
196 | * Operands of [comparison]. | |
197 | * Left operands of the [compound assignment]. | |
7cac9316 XL |
198 | |
199 | ## Constant expressions | |
200 | ||
201 | Certain types of expressions can be evaluated at compile time. These are called | |
202 | _constant expressions_. Certain places, such as in | |
ea8adc8c | 203 | [constants](items/constant-items.html) and [statics](items/static-items.html), |
7cac9316 XL |
204 | require a constant expression, and are always evaluated at compile time. In |
205 | other places, such as in [`let` statements](statements.html#let-statements), | |
206 | constant expressions may be evaluated at compile time. If errors, such as out | |
ea8adc8c | 207 | of bounds [array indexing] or [overflow] occurs, |
7cac9316 XL |
208 | then it is a compiler error if the value must be evaluated at compile time, |
209 | otherwise it is just a warning, but the code will most likely panic when run. | |
210 | ||
211 | The following expressions are constant expressions, so long as any operands are | |
212 | also constant expressions: | |
213 | ||
ea8adc8c XL |
214 | * [Literals]. |
215 | * [Paths] to [functions](items/functions.html) and constants. | |
7cac9316 | 216 | Recursively defining constants is not allowed. |
ea8adc8c XL |
217 | * [Tuple expressions]. |
218 | * [Array expressions]. | |
219 | * [Struct] expressions, where the type does not implement [`Drop`](the-drop-trait.html). | |
220 | * [Enum variant] expressions, where the enumeration type does not implement `Drop`. | |
abe05a73 | 221 | * [Block expressions] (and `unsafe` blocks) which only contain items and |
ea8adc8c XL |
222 | possibly a (constant) tail expression. |
223 | * [Field] expressions. | |
224 | * Index expressions, [array indexing] or [slice] with a `usize`. | |
225 | * [Range expressions]. | |
226 | * [Closure expressions] which don't capture variables from the environment. | |
227 | * Built in [negation], [arithmetic, logical], [comparison] or [lazy boolean] | |
228 | operators used on integer and floating point types, `bool` and `char`. | |
abe05a73 XL |
229 | * Shared [borrow], except if applied to a type with [interior |
230 | mutability](interior-mutability.html). | |
231 | * The [dereference operator]. | |
ea8adc8c XL |
232 | * [Grouped] expressions. |
233 | * [Cast] expressions, except pointer to address and | |
7cac9316 XL |
234 | function pointer to address casts. |
235 | ||
7cac9316 XL |
236 | ## Overloading Traits |
237 | ||
238 | Many of the following operators and expressions can also be overloaded for | |
239 | other types using traits in `std::ops` or `std::cmp`, these traits here also | |
240 | exist in `core::ops` and `core::cmp` with the same names. | |
8bb4bdeb | 241 | |
ea8adc8c XL |
242 | [block expressions]: expressions/block-expr.html |
243 | [call expressions]: expressions/call-expr.html | |
244 | [closure expressions]: expressions/closure-expr.html | |
245 | [enum variant]: expressions/enum-variant-expr.html | |
246 | [field]: expressions/field-expr.html | |
247 | [literals]: expressions/literal-expr.html | |
248 | [match]: expressions/match-expr.html | |
249 | [method-call]: expressions/method-call-expr.html | |
250 | [paths]: expressions/path-expr.html | |
251 | [range expressions]: expressions/range-expr.html | |
252 | [struct]: expressions/struct-expr.html | |
253 | [tuple expressions]: expressions/tuple-expr.html | |
254 | ||
255 | [array expressions]: expressions/array-expr.html | |
256 | [array indexing]: expressions/array-expr.html#array-and-slice-indexing-expressions | |
257 | ||
258 | [arithmetic, logical]: expressions/operator-expr.html#arithmetic-and-logical-binary-operators | |
259 | [assign]: expressions/operator-expr.html#assignment-expressions | |
260 | [borrow]: expressions/operator-expr.html#borrow-operators | |
261 | [cast]: expressions/operator-expr.html#type-cast-expressions | |
262 | [comparison]: expressions/operator-expr.html#comparison-operators | |
263 | [compound assignment]: expressions/operator-expr.html#compound-assignment-expressions | |
264 | [dereferences]: expressions/operator-expr.html#the-dereference-operator | |
265 | [dereferencing]: expressions/operator-expr.html#the-dereference-operator | |
266 | [dereference operator]: expressions/operator-expr.html#the-dereference-operator | |
267 | [grouped]: expressions/operator-expr.html#grouped-expressions | |
268 | [lazy boolean]: expressions/operator-expr.html#lazy-boolean-operators | |
269 | [negation]: expressions/operator-expr.html#negation-operators | |
270 | [overflow]: expressions/operator-expr.html#overflow | |
271 | ||
272 | [slice]: types.html#array-and-slice-types |