From ff28b3544849950921fadc998ecbbde4cab697c0 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Tue, 6 Oct 2020 12:28:59 -0700 Subject: [PATCH 1/7] Document evaluation order --- src/expressions.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/expressions.md b/src/expressions.md index 9cc684b99..3bc1adc73 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -85,6 +85,30 @@ in the order given by their associativity. | `=` `+=` `-=` `*=` `/=` `%=`
`&=` |= `^=` `<<=` `>>=` | right to left | | `return` `break` closures | | +## Evaluation order + +Most expressions include subexpressions. Unless otherwise stated on the +expression's page, evaluation of these inner expressions is left to right as +written in the source code. + +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, 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 From 9379f415df9ef1b7cc4fdcf63337b3c077bf0923 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Sun, 25 Oct 2020 22:07:20 -0700 Subject: [PATCH 2/7] More precise terminology on evaluation order I've italicized "operand" showing that it is a definition. I didn't actually remember that being added to the reference, so I basically tried to redefine it in the previous commit. I don't like the term, but since it's already there, I'll just use it. I also put in a note saying that operator precedence determines the operands of an expression. That section could probably be written in a style that better expresses that perspective, but I'm trying to keep this change minimal. I also stated that the evaluation of operands is done prior to applying the effect. This goes in line with the beginning of the chapter with what the meaning of an expression. Note also that this only describes the default. Expressions that deviate from the default already should describe their evaluation order. --- src/expressions.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 3bc1adc73..5dc185c79 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -45,8 +45,8 @@ 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 -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 @@ -85,11 +85,14 @@ in the order given by their associativity. | `=` `+=` `-=` `*=` `/=` `%=`
`&=` |= `^=` `<<=` `>>=` | right to left | | `return` `break` closures | | -## Evaluation order +## Evaluation order of operands -Most expressions include subexpressions. Unless otherwise stated on the -expression's page, evaluation of these inner expressions is left to right as -written in the source code. +Unless otherwise stated on the expression's page, evaluation of the operands of +an expression is done before applying the effect of the expression. The operands +are executed 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: From 02315d3b6351553e2d04073ef8843ba8b4ac5a78 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Sun, 25 Oct 2020 22:24:02 -0700 Subject: [PATCH 3/7] Change sub-expression to operand in a few places --- src/expressions.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 5dc185c79..26b3c2663 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -48,10 +48,9 @@ value, and has effects during *evaluation*. Many expressions contain 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, From 8458c781b01b80c51a5b5d4576eaadb4ac7b1412 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Wed, 11 Nov 2020 21:25:39 -0800 Subject: [PATCH 4/7] Explicitly list which exprs for shared eval order PR --- src/expressions.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 26b3c2663..c86586f15 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -86,9 +86,29 @@ in the order given by their associativity. ## Evaluation order of operands -Unless otherwise stated on the expression's page, evaluation of the operands of -an expression is done before applying the effect of the expression. The operands -are executed left to right as written in the source code. +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. + +* Operator expressions (except the Lazy boolean operators) +* 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. From 9360ab990a253174bedff15a3191d5657b04ec31 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Thu, 19 Nov 2020 23:40:28 -0800 Subject: [PATCH 5/7] Assignment expressions are *NOT* LTR evaluated. This commit does not try to define their evaluation order, they just removed them from the list of shared LTR evaluated expressions. --- src/expressions.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index c86586f15..c2702a342 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -90,7 +90,12 @@ 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. -* Operator expressions (except the Lazy boolean operators) +* Dereference expression +* Error propagation expression +* Negation expression +* Arithmetic and logical binary operators +* Comparison operators +* Type cast expression * Grouped expression * Array expression * Await expression @@ -127,9 +132,9 @@ assert_eq!( ); ``` -> **Note**: Since this is applied recursively, expressions are also evaluated -> from innermost to outermost, ignoring siblings until there are no inner -> subexpressions. +> **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 From 301182e14ed1af56cefa07606b979fb488880603 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Fri, 20 Nov 2020 02:26:20 -0800 Subject: [PATCH 6/7] Referencify Assignment Operator I'm being wish-washy with expression/operand in the syntax section. I'm not quite sure if we should call them `place operands` everywhere. --- src/expressions/operator-expr.md | 41 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 6b0fdc13e..44b5d851d 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -409,20 +409,35 @@ halfway between two floating point numbers. > _AssignmentExpression_ :\ >    [_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 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; ``` @@ -506,13 +521,15 @@ dependency. +[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 From 6a17a570b2951fb67254b57f0dcf4e371f7ebc92 Mon Sep 17 00:00:00 2001 From: Ryan Scheel Date: Wed, 13 Jan 2021 21:47:54 -0800 Subject: [PATCH 7/7] Execution order: Spell out uninitialized explicitly on field as well It could have been read that it was any field, not just uninitialized fields. Co-authored-by: Josh Triplett --- src/expressions/operator-expr.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 44b5d851d..302751fab 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -427,9 +427,9 @@ 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 field of a local -variable. Next it either [copies or moves] the assigned value to 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].