]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/expressions.md
New upstream version 1.23.0+dfsg1
[rustc.git] / src / doc / reference / src / expressions.md
CommitLineData
8bb4bdeb
XL
1# Expressions
2
3An 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
5value, and has effects during *evaluation*. Many expressions contain
6sub-expressions (operands). The meaning of each kind of expression dictates
7several 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
14In this way, the structure of expressions dictates the structure of execution.
15Blocks are just another kind of expression, so blocks, statements, expressions,
16and blocks again can recursively nest inside each other to an arbitrary depth.
17
abe05a73
XL
18## Expression precedence
19
20The precedence of Rust operators and expressions is ordered as follows, going
21from strong to weak. Binary Operators at the same precedence level are
22evaluated 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>&#124;</code> | left to right |
39| `==` `!=` `<` `>` `<=` `>=` | Require parentheses |
40| `&&` | left to right |
41| <code>&#124;&#124;</code> | left to right |
42| `..` `...` | Require parentheses |
43| `<-` | right to left |
44| `=` `+=` `-=` `*=` `/=` `%=` <br> `&=` <code>&#124;=</code> `^=` `<<=` `>>=` | right to left |
45| `return` `break` closures | |
46
7cac9316 47## Lvalues and rvalues
8bb4bdeb
XL
48
49Expressions are divided into two main categories: _lvalues_ and _rvalues_.
50Likewise within each expression, sub-expressions may occur in _lvalue context_
51or _rvalue context_. The evaluation of an expression depends both on its own
52category and the context it occurs within.
53
54An lvalue is an expression that represents a memory location. These expressions
abe05a73
XL
55are [paths](expressions/path-expr.html) which refer to local variables, static
56variables, function parameters, [dereferences]&nbsp;(`*expr`), [array indexing]
57expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized
58lvalue expressions. All other expressions are rvalues.
8bb4bdeb 59
ea8adc8c
XL
60The left operand of an [assign]ment or [compound assignment] expression is an
61lvalue context, as is the single operand of a unary [borrow], and the operand
62of 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
64other expression contexts are rvalue contexts.
8bb4bdeb 65
7cac9316 66### Moved and copied types
8bb4bdeb 67
abe05a73
XL
68When an lvalue is evaluated in an _rvalue context_ or is bound by value in a
69pattern, it denotes the value held _in_ that memory location. If value is of a
70type that implements `Copy`, then the value will be copied. In the remaining
71situations if the type of the value is [`Sized`](the-sized-trait.html) it may
72be 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
81Moving out of an lvalue deinitializes that location (if it comes from a local
82variable), so that it can't be read from again. In all other cases, trying to
83use an lvalue in an rvalue context is an error.
84
85### Mutability
86
ea8adc8c
XL
87For an lvalue to be [assign]ed to, mutably [borrow]ed,
88[implicitly mutably borrowed](#implicit-borrows)
7cac9316
XL
89or bound to a pattern containing `ref mut` it must be _mutable_, we call these
90contexts _mutable_ lvalue contexts, other lvalue contexts are called
91_immutable_.
92
93The 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
110When using an rvalue in most lvalue contexts, a temporary unnamed lvalue is
3b2f2976
XL
111created and used instead, if not promoted to `'static`. Promotion of an
112rvalue expression to a `'static` slot occurs when the expression could be
113written in a constant, borrowed, and dereferencing that borrow where the
114expression was the originally written, without changing the runtime behavior.
115That is, the promoted expression can be evaluated at compile-time and the
116resulting value does not contain interior mutability or destructors (these
117properties are determined based on the value where possible, e.g. `&None`
118always has the type `&'static Option<_>`, as it contains nothing disallowed).
abe05a73 119Otherwise, 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
127When a temporary rvalue is being created that is assigned into a `let`
7cac9316
XL
128declaration, however, the temporary is created with the lifetime of the
129enclosing block instead, as using the enclosing statement (the `let`
130declaration) would be a guaranteed error (since a pointer to the temporary
131would be stored into a variable, but the temporary would be freed before the
132variable could be used). The compiler uses simple syntactic rules to decide
133which values are being assigned into a `let` binding, and therefore deserve a
134longer temporary lifetime.
8bb4bdeb
XL
135
136Here 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 172Certain expressions will treat an expression as an lvalue by implicitly
ea8adc8c
XL
173borrowing it. For example, it is possible to compare two unsized [slices] for
174equality 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];
179let a: &[i32];
180let b: &[i32];
181# a = &c;
182# b = &d;
183// ...
184*a == *b;
185// Equivalent form:
186::std::cmp::PartialEq::eq(&*a, &*b);
187```
188
189Implicit 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
201Certain 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
204require a constant expression, and are always evaluated at compile time. In
205other places, such as in [`let` statements](statements.html#let-statements),
206constant expressions may be evaluated at compile time. If errors, such as out
ea8adc8c 207of bounds [array indexing] or [overflow] occurs,
7cac9316
XL
208then it is a compiler error if the value must be evaluated at compile time,
209otherwise it is just a warning, but the code will most likely panic when run.
210
211The following expressions are constant expressions, so long as any operands are
212also 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]&nbsp;(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
238Many of the following operators and expressions can also be overloaded for
239other types using traits in `std::ops` or `std::cmp`, these traits here also
240exist 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