From 9aa79194bb278523cea68546b611264e30051d1f Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Thu, 1 Apr 2021 17:10:16 -0700 Subject: [PATCH 1/7] One line one sentence main expressions chapter --- src/expressions.md | 129 +++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 81 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index aaa25af03..26792208c 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -41,28 +41,24 @@ >       | [_MatchExpression_]\ >    ) -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, called the *operands* of the expression. The meaning of each -kind of expression dictates several things: +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, called the *operands* of the expression. +The meaning of each kind of expression dictates several things: * 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, -and blocks again can recursively nest inside each other to an arbitrary depth. +Blocks are just another kind of expression, so blocks, statements, expressions, and blocks again can recursively nest inside each other to an arbitrary depth. -> **Note**: We give names to the operands of expressions so that we may discuss -> them, but these names are not stable and may be changed. +> **Note**: We give names to the operands of expressions so that we may discuss them, but these names are not stable and may be changed. ## Expression precedence -The precedence of Rust operators and expressions is ordered as follows, going -from strong to weak. Binary Operators at the same precedence level are grouped -in the order given by their associativity. +The precedence of Rust operators and expressions is ordered as follows, going from strong to weak. +Binary Operators at the same precedence level are grouped in the order given by their associativity. | Operator/Expression | Associativity | |-----------------------------|---------------------| @@ -88,9 +84,8 @@ in the order given by their associativity. ## 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. +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 @@ -112,15 +107,12 @@ evaluate them conditionally as described on their respective pages. * 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. +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. +> **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: +For example, the two `next` method calls will always be called in the same order: ```rust # // Using vec instead of array to avoid references @@ -133,96 +125,75 @@ assert_eq!( ); ``` -> **Note**: Since this is applied recursively, these 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 -Expressions are divided into two main categories: place expressions and -value expressions. Likewise within each expression, operands may occur -in either place context or value context. The evaluation of an expression -depends both on its own category and the context it occurs within. +Expressions are divided into two main categories: place expressions and value expressions. +Likewise within each expression, operands may occur in either place context or value context. +The evaluation of an expression depends both on its own category and the context it occurs within. -A *place expression* is an expression that represents a memory location. These -expressions are [paths] which refer to local variables, [static variables], -[dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), -[field] references (`expr.f`) and parenthesized place expressions. All other -expressions are value expressions. +A *place expression* is an expression that represents a memory location. +These expressions are [paths] which refer to local variables, [static variables], [dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized place expressions. +All other expressions are value expressions. A *value expression* is an expression that represents an actual value. The following contexts are *place expression* contexts: -* The left operand of an [assignment][assign] or [compound assignment] - expression. +* The left operand of an [assignment][assign] or [compound assignment] expression. * The operand of a unary [borrow] or [dereference][deref] operator. * The operand of a field expression. * The indexed operand of an array indexing expression. * The operand of any [implicit borrow]. * The initializer of a [let statement]. -* The [scrutinee] of an [`if let`], [`match`][match], or [`while let`] - expression. +* The [scrutinee] of an [`if let`], [`match`][match], or [`while let`] expression. * The base of a [functional update] struct expression. -> Note: Historically, place expressions were called *lvalues* and value -> expressions were called *rvalues*. +> Note: Historically, place expressions were called *lvalues* and value expressions were called *rvalues*. ### Moved and copied types -When a place expression is evaluated in a value expression context, or is bound -by value in a pattern, it denotes the value held _in_ that memory location. If -the type of that value implements [`Copy`], then the value will be copied. In -the remaining situations if that type is [`Sized`], then it may be possible to -move the value. Only the following place expressions may be moved out of: +When a place expression is evaluated in a value expression context, or is bound by value in a pattern, it denotes the value held _in_ that memory location. +If the type of that value implements [`Copy`], then the value will be copied. +In the remaining situations if that type is [`Sized`], then it may be possible to move the value. +Only the following place expressions may be moved out of: * [Variables] which are not currently borrowed. * [Temporary values](#temporaries). -* [Fields][field] of a place expression which can be moved out of and - doesn't implement [`Drop`]. -* The result of [dereferencing][deref] an expression with type [`Box`] and - that can also be moved out of. +* [Fields][field] of a place expression which can be moved out of and doesn't implement [`Drop`]. +* The result of [dereferencing][deref] an expression with type [`Box`] and that can also be moved out of. -Moving out of a place expression that evaluates to a local variable, the -location is deinitialized and cannot be read from again until it is -reinitialized. In all other cases, trying to use a place expression in a value -expression context is an error. +Moving out of a place expression that evaluates to a local variable, the location is deinitialized and cannot be read from again until it is reinitialized. +In all other cases, trying to use a place expression in a value expression context is an error. ### Mutability -For a place expression to be [assigned][assign] to, mutably [borrowed][borrow], -[implicitly mutably borrowed], or bound to a pattern containing `ref mut` it -must be _mutable_. We call these *mutable place expressions*. In contrast, -other place expressions are called *immutable place expressions*. +For a place expression to be [assigned][assign] to, mutably [borrowed][borrow], [implicitly mutably borrowed], or bound to a pattern containing `ref mut` it must be _mutable_. +We call these *mutable place expressions*. +In contrast, other place expressions are called *immutable place expressions*. The following expressions can be mutable place expression contexts: * Mutable [variables], which are not currently borrowed. * [Mutable `static` items]. * [Temporary values]. -* [Fields][field], this evaluates the subexpression in a mutable place - expression context. +* [Fields][field], this evaluates the subexpression in a mutable place expression context. * [Dereferences][deref] of a `*mut T` pointer. -* Dereference of a variable, or field of a variable, with type `&mut T`. Note: - This is an exception to the requirement of the next rule. -* Dereferences of a type that implements `DerefMut`, this then requires that - the value being dereferenced is evaluated is a mutable place expression context. -* [Array indexing] of a type that implements `IndexMut`, this - then evaluates the value being indexed, but not the index, in mutable place - expression context. +* Dereference of a variable, or field of a variable, with type `&mut T`. + Note: This is an exception to the requirement of the next rule. +* Dereferences of a type that implements `DerefMut`, this then requires that the value being dereferenced is evaluated is a mutable place expression context. +* [Array indexing] of a type that implements `IndexMut`, this then evaluates the value being indexed, but not the index, in mutable place expression context. ### Temporaries -When using a value expression in most place expression contexts, a temporary -unnamed memory location is created initialized to that value and the expression -evaluates to that location instead, except if [promoted] to a `static`. The -[drop scope] of the temporary is usually the end of the enclosing statement. +When using a value expression in most place expression contexts, a temporary unnamed memory location is created initialized to that value and the expression evaluates to that location instead, except if [promoted] to a `static`. +The [drop scope] of the temporary is usually the end of the enclosing statement. ### Implicit Borrows -Certain expressions will treat an expression as a place expression by implicitly -borrowing it. For example, it is possible to compare two unsized [slices][slice] for -equality directly, because the `==` operator implicitly borrows it's operands: +Certain expressions will treat an expression as a place expression by implicitly borrowing it. +For example, it is possible to compare two unsized [slices][slice] for equality directly, because the `==` operator implicitly borrows it's operands: ```rust # let c = [1, 2, 3]; @@ -249,14 +220,12 @@ Implicit borrows may be taken in the following expressions: ## Overloading Traits -Many of the following operators and expressions can also be overloaded for -other types using traits in `std::ops` or `std::cmp`. These traits also -exist in `core::ops` and `core::cmp` with the same names. +Many of the following operators and expressions can also be overloaded for other types using traits in `std::ops` or `std::cmp`. +These traits also exist in `core::ops` and `core::cmp` with the same names. ## Expression Attributes -[Outer attributes][_OuterAttribute_] before an expression are allowed only in -a few specific cases: +[Outer attributes][_OuterAttribute_] before an expression are allowed only in a few specific cases: * Before an expression used as a [statement]. * Elements of [array expressions], [tuple expressions], [call expressions], @@ -271,9 +240,7 @@ a few specific cases: They are never allowed before: * [Range][_RangeExpression_] expressions. -* Binary operator expressions ([_ArithmeticOrLogicalExpression_], - [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_], - [_AssignmentExpression_], [_CompoundAssignmentExpression_]). +* Binary operator expressions ([_ArithmeticOrLogicalExpression_], [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_], [_AssignmentExpression_], [_CompoundAssignmentExpression_]). [block expressions]: expressions/block-expr.md From 0c6d2df525582bde104c412908d47224a0efe505 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Mon, 5 Apr 2021 17:54:58 -0700 Subject: [PATCH 2/7] Change operand name for compound assign lhs --- src/expressions/operator-expr.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 75f59636d..28be0b6e3 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -435,20 +435,20 @@ x += 1; assert!(x == 6); ``` -The syntax of compound assignment is a [mutable] [place expression], the *assigned operand*, then one of the operators followed by an `=` as a single token (no whitespace), and then a [value expression], the *modifying operand*. +The syntax of compound assignment is a [mutable] [place expression], the *assigned place operand*, then one of the operators followed by an `=` as a single token (no whitespace), and then a [value expression], the *modifying 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. Evaluation of compound assignment expressions depends on the types of the operators. -If both types are primitives, then the modifying operand will be evaluated first followed by the assigned operand. -It will then set the value of the assigned operand's place to the value of performing the operation of the operator with the values of the assigned operand and modifying operand. +If both types are primitives, then the modifying operand will be evaluated first followed by the assigned place operand. +It will then set the value of the assigned place operand's place to the value of performing the operation of the operator with the values of the assigned place operand and modifying operand. > **Note**: This is different than other expressions in that the right operand is evaluated before the left one. Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assigment trait of the operator (see the table earlier in this chapter). -A mutable borrow of the assigned operand is automatically taken. +A mutable borrow of the assigned place operand is automatically taken. For example, the following expression statements in `example` are equivalent: From 4e42e53569563e2b52207320023c13653b4cf054 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Mon, 5 Apr 2021 17:56:59 -0700 Subject: [PATCH 3/7] Expand upon expression precedence --- src/expressions.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/expressions.md b/src/expressions.md index 26792208c..9a27d204c 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -57,8 +57,14 @@ Blocks are just another kind of expression, so blocks, statements, expressions, ## Expression precedence -The precedence of Rust operators and expressions is ordered as follows, going from strong to weak. +The grammar for expressions as presented in this book is wrong. +It purposefully ignores that certain operands cannot be certain expressions due to precedence. +For example, `a * b + c` is actually parsed as an addition operator expression with the multiplication operator expression as its left operand. +The grammar, taking precedence into account, is too unweildy to read and understand. + +The precedence of operators and expressions is ordered as follows, going from strongest to weakest. Binary Operators at the same precedence level are grouped in the order given by their associativity. +Expressions in this table cannot have operands that are expressions lower in the table. | Operator/Expression | Associativity | |-----------------------------|---------------------| @@ -82,6 +88,8 @@ Binary Operators at the same precedence level are grouped in the order given by | `=` `+=` `-=` `*=` `/=` `%=`
`&=` |= `^=` `<<=` `>>=` | right to left | | `return` `break` closures | | +> **Note**: Wrapping an expression with a [parenthetical expression] increases its precedence. + ## Evaluation order of operands The following list of expressions all evaluate their operands the same way, as described after the list. @@ -250,6 +258,7 @@ They are never allowed before: [`if let`]: expressions/if-expr.md#if-let-expressions [match]: expressions/match-expr.md [method-call]: expressions/method-call-expr.md +[parenthetical expression]: expressions/grouped-expr.md [paths]: expressions/path-expr.md [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md From 74bf944e471ae1eaa94e105196ea6a0b6d980c7a Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Mon, 5 Apr 2021 18:11:37 -0700 Subject: [PATCH 4/7] Expression categories --- src/expressions.md | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 9a27d204c..f1ba2d1ba 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -135,28 +135,41 @@ assert_eq!( > **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 +## Expression categories -Expressions are divided into two main categories: place expressions and value expressions. -Likewise within each expression, operands may occur in either place context or value context. -The evaluation of an expression depends both on its own category and the context it occurs within. + + -A *place expression* is an expression that represents a memory location. -These expressions are [paths] which refer to local variables, [static variables], [dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized place expressions. -All other expressions are value expressions. +Expressions and expression contexts are divided into two *expression categories*: *place* and *value*. +For expressions, what they evaluate into determines their categories. +Expressions that evaluate to a value are *value expressions* while those that evaluate to a place are *place expressions*. +For expression contexts, whether they operate on a place or value determines their context. -A *value expression* is an expression that represents an actual value. +Evaluating an expression in the opposite expression context has effects after evaluation of the expression to produce the expected place or value of the context. +When evaluating a value expression in place expression context, a temporary place is initialized to that value. +When evaluating a place expression in value expression context, the value at that place is read, moving or copying it. -The following contexts are *place expression* contexts: +The following lists all place expressions. +Expressions not listed here are value expressions. -* The left operand of an [assignment][assign] or [compound assignment] expression. +* [Paths] which refer to local variables or [static variables]. +* [The dereference operator][deref] +* [Field access expressions][field] +* [Tuple indexing expressions] +* [Array indexing expressions] +* [Parenthetical expressions] when its enclosed operand is a place expression + +The following list all place expression contexts. +All other contexts are value expression contexts. + +* The initializer of a [let statement]. +* The assigned place operand of an [assignment][assign] or [compound assignment] expression. * The operand of a unary [borrow] or [dereference][deref] operator. -* The operand of a field expression. +* The container operand of a field expression. * The indexed operand of an array indexing expression. * The operand of any [implicit borrow]. -* The initializer of a [let statement]. -* The [scrutinee] of an [`if let`], [`match`][match], or [`while let`] expression. -* The base of a [functional update] struct expression. +* The [scrutinee] operand of an [`if let`], [`match`][match], or [`while let`] expression. +* The base operand of a [functional update] struct expression. > Note: Historically, place expressions were called *lvalues* and value expressions were called *rvalues*. From 1980677914ee7ad063a822c371d00af7b4bd2b51 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Mon, 5 Apr 2021 18:36:46 -0700 Subject: [PATCH 5/7] Expressions intro --- src/expressions.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index f1ba2d1ba..17b7d74b8 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -41,14 +41,17 @@ >       | [_MatchExpression_]\ >    ) -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, called the *operands* of the expression. +Expressions are the fundamental unit of computation. +When evaluated, they may have *effects* and evaluates to either a value or place. + +Where expressions are allowed are *expression contexts*. +Expressions commonly 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 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 +* How to combine the operands' values to obtain the value or place 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, and blocks again can recursively nest inside each other to an arbitrary depth. From 5832c52adce8dddf58b0025390a4998c2b58f377 Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Mon, 5 Apr 2021 19:04:43 -0700 Subject: [PATCH 6/7] Links --- src/expressions.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 17b7d74b8..2c0a20115 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -91,7 +91,7 @@ Expressions in this table cannot have operands that are expressions lower in the | `=` `+=` `-=` `*=` `/=` `%=`
`&=` |= `^=` `<<=` `>>=` | right to left | | `return` `break` closures | | -> **Note**: Wrapping an expression with a [parenthetical expression] increases its precedence. +> **Note**: Wrapping an expression with a [parenthetical expression][paren] increases its precedence. ## Evaluation order of operands @@ -160,7 +160,7 @@ Expressions not listed here are value expressions. * [Field access expressions][field] * [Tuple indexing expressions] * [Array indexing expressions] -* [Parenthetical expressions] when its enclosed operand is a place expression +* [Parenthetical expressions][paren] when its enclosed operand is a place expression The following list all place expression contexts. All other contexts are value expression contexts. @@ -207,7 +207,7 @@ The following expressions can be mutable place expression contexts: * Dereference of a variable, or field of a variable, with type `&mut T`. Note: This is an exception to the requirement of the next rule. * Dereferences of a type that implements `DerefMut`, this then requires that the value being dereferenced is evaluated is a mutable place expression context. -* [Array indexing] of a type that implements `IndexMut`, this then evaluates the value being indexed, but not the index, in mutable place expression context. +* [Array indexing expressions] of a type that implements `IndexMut`, this then evaluates the value being indexed, but not the index, in mutable place expression context. ### Temporaries @@ -237,7 +237,7 @@ Implicit borrows may be taken in the following expressions: * Left operand in [method-call] expressions. * Left operand in [field] expressions. * Left operand in [call expressions]. -* Left operand in [array indexing] expressions. +* Left operand in [array indexing expressions]. * Operand of the [dereference operator][deref] (`*`). * Operands of [comparison]. * Left operands of the [compound assignment]. @@ -274,14 +274,15 @@ They are never allowed before: [`if let`]: expressions/if-expr.md#if-let-expressions [match]: expressions/match-expr.md [method-call]: expressions/method-call-expr.md -[parenthetical expression]: expressions/grouped-expr.md +[paren]: expressions/grouped-expr.md [paths]: expressions/path-expr.md [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md +[tuple indexing expressions]: expressions/tuple-expr.md#tuple-indexing-expressions [`while let`]: expressions/loop-expr.md#predicate-pattern-loops -[array expressions]: expressions/array-expr.md -[array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions +[array expressions]: expressions/array-expr.md +[array indexing expressions]: expressions/array-expr.md#array-and-slice-indexing-expressions [assign]: expressions/operator-expr.md#assignment-expressions [borrow]: expressions/operator-expr.md#borrow-operators From 3304bd8d3345a0f052f88e3dab33081f16b96e88 Mon Sep 17 00:00:00 2001 From: Ryan Scheel Date: Wed, 7 Apr 2021 02:00:08 -0700 Subject: [PATCH 7/7] Typo and "easily" Co-authored-by: Jacob Lifshay --- src/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expressions.md b/src/expressions.md index 2c0a20115..ced7abd3a 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -63,7 +63,7 @@ Blocks are just another kind of expression, so blocks, statements, expressions, The grammar for expressions as presented in this book is wrong. It purposefully ignores that certain operands cannot be certain expressions due to precedence. For example, `a * b + c` is actually parsed as an addition operator expression with the multiplication operator expression as its left operand. -The grammar, taking precedence into account, is too unweildy to read and understand. +The grammar, taking precedence into account, is too unwieldy to easily read and understand. The precedence of operators and expressions is ordered as follows, going from strongest to weakest. Binary Operators at the same precedence level are grouped in the order given by their associativity.