Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document execution order #888

Merged
merged 7 commits into from
Jan 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 57 additions & 6 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,12 @@
An expression may have two roles: it always produces a *value*, and it may have
*effects* (otherwise known as "side effects"). An expression *evaluates to* a
value, and has effects during *evaluation*. Many expressions contain
sub-expressions (operands). The meaning of each kind of expression dictates
joshtriplett marked this conversation as resolved.
Show resolved Hide resolved
several things:
sub-expressions, called the *operands* of the expression. The meaning of each
kind of expression dictates several things:

* Whether or not to evaluate the sub-expressions when evaluating the expression
* The order in which to evaluate the sub-expressions
* How to combine the sub-expressions' values to obtain the value of the
expression
* Whether or not to evaluate the operands when evaluating the expression
* The order in which to evaluate the operands
* How to combine the operands' values to obtain the value of the expression

In this way, the structure of expressions dictates the structure of execution.
Blocks are just another kind of expression, so blocks, statements, expressions,
Expand Down Expand Up @@ -85,6 +84,58 @@ in the order given by their associativity.
| `=` `+=` `-=` `*=` `/=` `%=` <br> `&=` <code>&#124;=</code> `^=` `<<=` `>>=` | right to left |
| `return` `break` closures | |

## Evaluation order of operands

The following list of expressions all evaluate their operands the same way, as
described after the list. Other expressions either don't take operands or
evaluate them conditionally as described on their respective pages.

* Dereference expression
* Error propagation expression
* Negation expression
* Arithmetic and logical binary operators
* Comparison operators
* Type cast expression
* Grouped expression
* Array expression
* Await expression
* Index expression
* Tuple expression
* Tuple index expression
* Struct expression
* Enumeration variant expression
* Call expression
* Method call expression
* Field expression
* Break expression
* Range expression
* Return expression

The operands of these expressions are evaluated prior to applying the effects of
the expression. Expressions taking multiple operands are evaluated left to right
as written in the source code.

> **Note**: Which subexpressions are the operands of an expression is
> determined by expression precedence as per the previous section.

For example, the two `next` method calls will always be called in the same
order:

```rust
# // Using vec instead of array to avoid references
# // since there is no stable owned array iterator
# // at the time this example was written.
let mut one_two = vec![1, 2].into_iter();
assert_eq!(
(1, 2),
(one_two.next().unwrap(), one_two.next().unwrap())
);
```

> **Note**: Since this is applied recursively, these expressions are also
> evaluated from innermost to outermost, ignoring siblings until there are no
> inner subexpressions.

## Place Expressions and Value Expressions

Expressions are divided into two main categories: place expressions and
Expand Down
41 changes: 29 additions & 12 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,20 +409,35 @@ halfway between two floating point numbers.
> _AssignmentExpression_ :\
> &nbsp;&nbsp; [_Expression_] `=` [_Expression_]

An _assignment expression_ consists of a [place expression] followed by an
equals sign (`=`) and a [value expression]. Such an expression always has
the [`unit` type].

Evaluating an assignment expression [drops](../destructors.md) the left-hand
operand, unless it's an uninitialized local variable or field of a local variable,
and [either copies or moves](../expressions.md#moved-and-copied-types) its
right-hand operand to its left-hand operand. The left-hand operand must be a
place expression: using a value expression results in a compiler error, rather
An *assignment expression* moves a value into a specified place.

An assignment expression consists of a [mutable] [place expression], the
*assigned place operand*, followed by an equals sign (`=`) and a [value
expression], the *assigned value operand*.

Unlike other place operands, the assigned place operand must be a place
expression. Attempting to use a value expression is a compiler error rather
than promoting it to a temporary.

Evaluating assignment expressions begins by evaluating its operands. The
assigned value operand is evaluated first, followed by the assigned place
operand.

> **Note**: This is different than other expressions in that the right operand
> is evaluated before the left one.

It then has the effect of first [dropping] the value at the assigned place,
unless the place is an uninitialized local variable or an uninitialized field of
a local variable. Next it either [copies or moves] the assigned value to the
assigned place.

An assignment expression always produces [the unit value][unit].

Example:

```rust
# let mut x = 0;
# let y = 0;
let mut x = 0;
let y = 0;
x = y;
```

Expand Down Expand Up @@ -506,13 +521,15 @@ dependency.

</div>

[copies or moves]: ../expressions.md#moved-and-copied-types
[dropping]: ../destructors.md
[mutable]: ../expressions.md#mutability
[place expression]: ../expressions.md#place-expressions-and-value-expressions
[unit]: ../types/tuple.md
[value expression]: ../expressions.md#place-expressions-and-value-expressions
[temporary value]: ../expressions.md#temporaries
[this test]: https://github.com/rust-lang/rust/blob/master/src/test/ui/expr/compound-assignment/eval-order.rs
[float-float]: https://github.com/rust-lang/rust/issues/15536
[`unit` type]: ../types/tuple.md
[Function pointer]: ../types/function-pointer.md
[Function item]: ../types/function-item.md

Expand Down