From 4ad306ccde9c407a6e0ba9726a383ac0a7cb0b68 Mon Sep 17 00:00:00 2001 From: Havvy Date: Fri, 1 Dec 2017 19:43:17 -0800 Subject: [PATCH 1/2] lvalue and rvalue to place and value expressions --- src/expressions.md | 144 ++++++++++++++++------------ src/expressions/array-expr.md | 21 ++-- src/expressions/block-expr.md | 15 +-- src/expressions/field-expr.md | 19 ++-- src/expressions/match-expr.md | 28 +++--- src/expressions/method-call-expr.md | 4 +- src/expressions/operator-expr.md | 72 +++++++------- src/expressions/path-expr.md | 13 ++- src/expressions/struct-expr.md | 16 ++-- src/glossary.md | 4 +- 10 files changed, 190 insertions(+), 146 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index c433caca7..e5166cffb 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -44,76 +44,84 @@ evaluated in the order given by their associativity. | `=` `+=` `-=` `*=` `/=` `%=`
`&=` |= `^=` `<<=` `>>=` | right to left | | `return` `break` closures | | -## Lvalues and rvalues +## Place Expressions and Value Expressions -Expressions are divided into two main categories: _lvalues_ and _rvalues_. -Likewise within each expression, sub-expressions may occur in _lvalue context_ -or _rvalue 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, sub-expressions 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. -An lvalue is an expression that represents a memory location. These expressions -are [paths](expressions/path-expr.html) which refer to local variables, static -variables, function parameters, [dereferences] (`*expr`), [array indexing] -expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized -lvalue expressions. All other expressions are rvalues. +A *place expression* is an expression that represents a memory location. These +expressions are [paths] which refer to local variables, [static variables], +[dereferences] (`*expr`), [array indexing] expressions (`expr[expr]`), +[field] references (`expr.f`) and parenthesized place expressions. All other +expressions are value expressions. -The left operand of an [assign]ment or [compound assignment] expression is an -lvalue context, as is the single operand of a unary [borrow], and the operand -of any [implicit borrow](#implicit-borrows). The discriminant or subject of a -[match] expression and right side of a `let` is also an lvalue context. All -other expression contexts are rvalue contexts. +A *value expression* is an expression that represents an actual value. + +The left operand of an [assignment][assign] or [compound assignment] expression +is a place expression context, as is the single operand of a unary [borrow], and +the operand of any [implicit borrow]. The discriminant or subject of a +[match expression][match] and right side of a [let statement] is also a place +expression context. All other expression contexts are value expression contexts. + +> Note: Historically, place expressions were called *lvalues* and value +> expressions were called *rvalues*. ### Moved and copied types -When an lvalue is evaluated in an _rvalue context_ or is bound by value in a -pattern, it denotes the value held _in_ that memory location. If value is of a -type that implements `Copy`, then the value will be copied. In the remaining -situations if the type of the value is [`Sized`](the-sized-trait.html) it may -be possible to move the value. Only the following lvalues 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`](the-sized-trait.html), then it +may be possible to move the value. Only the following place expressions may be +moved out of: -* [Variables](variables.html) which are not currently borrowed. +* [Variables] which are not currently borrowed. * [Temporary values](#temporary-lifetimes). -* [Field]s of an lvalue which can be moved out of and +* [Fields][field] of a place expression which can be moved out of and doesn't implement [`Drop`](the-drop-trait.html). -* The result of [dereferencing] an expression with type `Box` and that can +* The result of [dereferencing] an expression with type [`Box`] and that can also be moved out of. -Moving out of an lvalue deinitializes that location (if it comes from a local -variable), so that it can't be read from again. In all other cases, trying to -use an lvalue in an rvalue 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 an lvalue to be [assign]ed to, mutably [borrow]ed, -[implicitly mutably borrowed](#implicit-borrows) -or bound to a pattern containing `ref mut` it must be _mutable_, we call these -contexts _mutable_ lvalue contexts, other lvalue contexts are called -_immutable_. +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 create mutable lvalues: +The following expressions can be mutable place expression contexts: -* Mutable [variables](variables.html), which are not currently borrowed. -* [Mutable `static` items](items/static-items.html#mutable-statics). -* [Temporary values](#temporary-lifetimes). -* [Field]s, this evaluates the subexpression in a mutable lvalue context. +* Mutable [variables], which are not currently borrowed. +* [Mutable `static` items]. +* [Temporary values]. +* [Fields][field], this evaluates the subexpression in a mutable place + expression context. * [Dereferences] 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 for the next rule. + 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 lvalue context. + the value being dereferenced is evaluated is a mutable place expression context. * [Array indexing] of a type that implements `DerefMut`, this - then evaluates the value being indexed (but not the index) in mutable lvalue - context. + then evaluates the value being indexed, but not the index, in mutable place + expression context. ### Temporary lifetimes -When using an rvalue in most lvalue contexts, a temporary unnamed lvalue is -created and used instead, if not promoted to `'static`. Promotion of an -rvalue expression to a `'static` slot occurs when the expression could be +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 `'static`. Promotion +of a value expression to a `'static` slot occurs when the expression could be written in a constant, borrowed, and dereferencing that borrow where the expression was the originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the -resulting value does not contain interior mutability or destructors (these +resulting value does not contain [interior mutability] or [destructors] (these properties are determined based on the value where possible, e.g. `&None` always has the type `&'static Option<_>`, as it contains nothing disallowed). Otherwise, the lifetime of temporary values is typically @@ -121,13 +129,13 @@ Otherwise, the lifetime of temporary values is typically - the innermost enclosing statement; the tail expression of a block is considered part of the statement that encloses the block, or - the condition expression or the loop conditional expression if the - temporary is created in the condition expression of an `if` or an `if`/`else` - or in the loop conditional expression of a `while` expression. + temporary is created in the condition expression of an `if` or in the loop + conditional expression of a `while` expression. -When a temporary rvalue is being created that is assigned into a `let` -declaration, however, the temporary is created with the lifetime of the -enclosing block instead, as using the enclosing statement (the `let` -declaration) would be a guaranteed error (since a pointer to the temporary +When a temporary value expression is being created that is assigned into a +[`let` declaration][let], however, the temporary is created with the lifetime of +the enclosing block instead, as using the enclosing [`let` declaration][let] +would be a guaranteed error (since a pointer to the temporary would be stored into a variable, but the temporary would be freed before the variable could be used). The compiler uses simple syntactic rules to decide which values are being assigned into a `let` binding, and therefore deserve a @@ -135,26 +143,26 @@ longer temporary lifetime. Here are some examples: -- `let x = foo(&temp())`. The expression `temp()` is an rvalue. As it +- `let x = foo(&temp())`. The expression `temp()` is a value expression. As it is being borrowed, a temporary is created which will be freed after - the innermost enclosing statement (the `let` declaration, in this case). + the innermost enclosing statement; in this case, the `let` declaration. - `let x = temp().foo()`. This is the same as the previous example, except that the value of `temp()` is being borrowed via autoref on a method-call. Here we are assuming that `foo()` is an `&self` method defined in some trait, say `Foo`. In other words, the expression `temp().foo()` is equivalent to `Foo::foo(&temp())`. - `let x = if foo(&temp()) {bar()} else {baz()};`. The expression `temp()` is - an rvalue. As the temporary is created in the condition expression - of an `if`/`else`, it will be freed at the end of the condition expression - (in this example before the call to `bar` or `baz` is made). + a value expression. As the temporary is created in the condition expression + of an `if`, it will be freed at the end of the condition expression; + in this example before the call to `bar` or `baz` is made. - `let x = if temp().must_run_bar {bar()} else {baz()};`. Here we assume the type of `temp()` is a struct with a boolean field `must_run_bar`. As the previous example, the temporary corresponding to `temp()` will be freed at the end of the condition expression. - `while foo(&temp()) {bar();}`. The temporary containing the return value from the call to `temp()` is created in the loop conditional expression. Hence it - will be freed at the end of the loop conditional expression (in this example - before the call to `bar` if the loop body is executed). + will be freed at the end of the loop conditional expression; in this example + before the call to `bar` if the loop body is executed. - `let x = &temp()`. Here, the same temporary is being assigned into `x`, rather than being passed as a parameter, and hence the temporary's lifetime is considered to be the enclosing block. @@ -164,12 +172,13 @@ Here are some examples: - `let x = [ &temp() ]`. As in the previous case, the temporary is assigned into an array which is then assigned into a binding, and hence it is given the lifetime of the enclosing block. -- `let ref x = temp()`. In this case, the temporary is created using a ref binding, - but the result is the same: the lifetime is extended to the enclosing block. +- `let ref x = temp()`. In this case, the temporary is created using a ref + binding, but the result is the same: the lifetime is extended to the enclosing + block. ### Implicit Borrows -Certain expressions will treat an expression as an lvalue by implicitly +Certain expressions will treat an expression as a place expression by implicitly borrowing it. For example, it is possible to compare two unsized [slices] for equality directly, because the `==` operator implicitly borrows it's operands: @@ -192,7 +201,7 @@ Implicit borrows may be taken in the following expressions: * Left operand in [field] expressions. * Left operand in [call expressions]. * Left operand in [array indexing] expressions. -* Operand of the [dereference] operator (`*`). +* Operand of the [dereference operator] \(`*`). * Operands of [comparison]. * Left operands of the [compound assignment]. @@ -236,7 +245,7 @@ to be ran. ## 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 here also +other types using traits in `std::ops` or `std::cmp`. These traits also exist in `core::ops` and `core::cmp` with the same names. [block expressions]: expressions/block-expr.html @@ -270,5 +279,14 @@ exist in `core::ops` and `core::cmp` with the same names. [overflow]: expressions/operator-expr.html#overflow [destructors]: destructors.html -[interior-mutability]: interior-mutability.html +[interior mutability]: interior-mutability.html +[`Box`]: ../std/boxed/struct.Box.html +[implicit borrow]: #implicit-borrows +[implicitly mutably borrowed]: #implicit-borrows +[let]: statements.html#let-statements +[let statement]: statements.html#let-statements +[Mutable `static` items]: items/static-items.html#mutable-statics [slice]: types.html#array-and-slice-types +[static variables]: items/static-items.html +[Temporary values]: #temporary-lifetimes +[Variables]: variables.html diff --git a/src/expressions/array-expr.md b/src/expressions/array-expr.md index 8a1f8c113..a78ca8d84 100644 --- a/src/expressions/array-expr.md +++ b/src/expressions/array-expr.md @@ -38,18 +38,17 @@ greater than 1 then this requires that the type of `a` is [Array and slice](types.html#array-and-slice-types)-typed expressions can be indexed by writing a square-bracket-enclosed expression (the index) after them. -When the array is mutable, the resulting -[lvalue](expressions.html#lvalues-and-rvalues) can be assigned to. +When the array is mutable, the resulting [place] can be assigned to. For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::opsIndexMut::index_mut(&mut a, b)` -in a mutable lvalue context. Just as with methods, Rust will also insert -dereference operations on `a` repeatedly to find an implementation. +in a mutable place expression context. Just as with methods, Rust will also +insert dereference operations on `a` repeatedly to find an implementation. Indices are zero-based, and are of type `usize` for arrays and slices. Array -access is a [constant expression](expressions.html#constant-expressions), so bounds can be -checked at compile-time for constant arrays with a constant index value. -Otherwise a check will be performed at run-time that will put the thread in a -_panicked state_ if it fails. +access is a [constant expression], so +bounds can be checked at compile-time for constant arrays with a constant index +value. Otherwise a check will be performed at run-time that will put the thread +in a _panicked state_ if it fails. ```rust,should_panic ([1, 2, 3, 4])[2]; // Evaluates to 3 @@ -69,6 +68,8 @@ arr[10]; // panics The array index expression can be implemented for types other than arrays and slices by implementing the [Index] and [IndexMut] traits. -[Index]: https://doc.rust-lang.org/std/ops/trait.Index.html -[IndexMut]: https://doc.rust-lang.org/std/ops/trait.IndexMut.html [_Expression_]: expressions.html +[place]: expressions.html#place-expressions-and-value-expressions +[Index]: ../std/ops/trait.Index.html +[IndexMut]: ../std/ops/trait.IndexMut.html +[constant expression]: expressions.html#constant-expressions \ No newline at end of file diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index 4ac5cbcdf..4f3ba6ab1 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -9,13 +9,13 @@ >    `}` A _block expression_ is similar to a module in terms of the declarations that -are possible, but can also contain [statements](statements.html) and end with -an expression. Each block conceptually introduces a new namespace scope. Use +are possible, but can also contain [statements] and end with +an [expression]. Each block conceptually introduces a new namespace scope. Use items can bring new names into scopes and declared items are in scope for only the block itself. A block will execute each statement sequentially, and then execute the -expression (if given). If the block doesn't end in an expression, its value is +expression, if given. If the block doesn't end in an expression, its value is `()`: ```rust @@ -30,9 +30,9 @@ let x: i32 = { println!("Hello."); 5 }; assert_eq!(5, x); ``` -Blocks are always [rvalues](expressions.html#lvalues-and-rvalues) and evaluate the last -expression in rvalue context. This can be used to force moving a value -if really needed. +Blocks are always [value expressions] and evaluate the last expression in +value expression context. This can be used to force moving a value if really +needed. ## `unsafe` blocks @@ -60,3 +60,6 @@ let a = unsafe { f() }; [_InnerAttribute_]: attributes.html [_Statement_]: statements.html [_Expression_]: expressions.html +[expression]: expressions.html +[statements]: statements.html +[value expressions]: expressions.html#place-expressions-and-value-expressions \ No newline at end of file diff --git a/src/expressions/field-expr.md b/src/expressions/field-expr.md index 5828e2043..8cc873dd3 100644 --- a/src/expressions/field-expr.md +++ b/src/expressions/field-expr.md @@ -5,11 +5,10 @@ >    [_Expression_] `.` [IDENTIFIER] A _field expression_ consists of an expression followed by a single dot and an -[identifier](identifiers.html), when not immediately followed by a -parenthesized expression-list (the latter is always a [method call -expression](expressions/method-call-expr.html)). A field expression denotes a field of a -[struct](types.html#struct-types) or [union](items/unions.html). To call a -function stored in a struct parentheses are needed around the field expression +[identifier], when not immediately followed by a parenthesized expression-list +(the latter is always a [method call expression]). A field expression denotes a +field of a [struct] or [union]. To call a function stored in a struct, +parentheses are needed around the field expression. ```rust,ignore mystruct.myfield; @@ -19,9 +18,8 @@ mystruct.method(); // Method expression (mystruct.function_field)() // Call expression containing a field expression ``` -A field access is an [lvalue](expressions.html#lvalues-and-rvalues) referring -to the location of that field. When the subexpression is -[mutable](expressions.html#mutability), the field expression is also mutable. +A field access is a [place expression] referring to the location of that field. +When the subexpression is [mutable], the field expression is also mutable. Also, if the type of the expression to the left of the dot is a pointer, it is automatically dereferenced as many times as necessary to make the field access @@ -49,3 +47,8 @@ let d: String = x.f3; // Move out of x.f3 [_Expression_]: expressions.html [IDENTIFIER]: identifiers.html +[method call expression]: expressions/method-call-expr.html +[struct]: items/structs.html +[union]: items/unions.html +[place expression]: expressions.html#place-expressions-and-value-expressions +[mutable]: expressions.html#mutability \ No newline at end of file diff --git a/src/expressions/match-expr.md b/src/expressions/match-expr.md index 1a4de06a6..91ec9a554 100644 --- a/src/expressions/match-expr.md +++ b/src/expressions/match-expr.md @@ -9,19 +9,19 @@ the patterns. The type of the patterns must equal the type of the head expression. A `match` behaves differently depending on whether or not the head expression -is an [lvalue or an rvalue](expressions.html#lvalues-and-rvalues). -If the head expression is an rvalue, it is first evaluated into a temporary -location, and the resulting value is sequentially compared to the patterns in -the arms until a match is found. The first arm with a matching pattern is -chosen as the branch target of the `match`, any variables bound by the pattern -are assigned to local variables in the arm's block, and control enters the -block. - -When the head expression is an lvalue, the match does not allocate a temporary -location (however, a by-value binding may copy or move from the lvalue). When -possible, it is preferable to match on lvalues, as the lifetime of these -matches inherits the lifetime of the lvalue, rather than being restricted to -the inside of the match. +is a [place expression or value expression][place expression]. +If the head expression is a [value expression], it is first evaluated into a +temporary location, and the resulting value is sequentially compared to the +patterns in the arms until a match is found. The first arm with a matching +pattern is chosen as the branch target of the `match`, any variables bound by +the pattern are assigned to local variables in the arm's block, and control +enters the block. + +When the head expression is a [place expression], the match does not allocate a +temporary location; however, a by-value binding may copy or move from the place. +When possible, it is preferable to match on place expressions, as the lifetime +of these matches inherits the lifetime of the place expression rather than being +restricted to the inside of the match. An example of a `match` expression: @@ -126,3 +126,5 @@ let message = match maybe_digit { }; ``` +[place expression]: expressions.html#place-expressions-and-value-expressions +[value expression]: expressions.html#place-expressions-and-value-expressions \ No newline at end of file diff --git a/src/expressions/method-call-expr.md b/src/expressions/method-call-expr.md index 87a15f9f6..b87e8f99e 100644 --- a/src/expressions/method-call-expr.md +++ b/src/expressions/method-call-expr.md @@ -1,7 +1,7 @@ # Method-call expressions A _method call_ consists of an expression followed by a single dot, an -[identifier](identifiers.html), and a parenthesized expression-list. Method +[identifier], and a parenthesized expression-list. Method calls are resolved to methods on specific traits, either statically dispatching to a method if the exact `self`-type of the left-hand-side is known, or dynamically dispatching if the left-hand-side expression is an indirect [trait @@ -50,3 +50,5 @@ generic methods or traits are considered the same), then it is a compiler error. These cases require a [more specific syntax.](expressions/call-expr.html#disambiguating-function-calls) for method and function invocation. + +[IDENTIFIER]: identifiers.html \ No newline at end of file diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 9bb3f8c39..2baa241ec 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -25,6 +25,8 @@ An expression enclosed in parentheses evaluates to the result of the enclosed expression. Parentheses can be used to explicitly specify evaluation order within an expression. +This operator cannot be overloaded. + An example of a parenthesized expression: ```rust @@ -37,15 +39,17 @@ assert_eq!(y, 20); ## Borrow operators The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix -operators. When applied to an lvalue produce a reference (pointer) to the -location that the value refers to. The lvalue is also placed into a borrowed -state for the duration of the reference. For a shared borrow (`&`), this -implies that the lvalue may not be mutated, but it may be read or shared again. -For a mutable borrow (`&mut`), the lvalue may not be accessed in any way until -the borrow expires. `&mut` evaluates its operand in a mutable lvalue context. -If the `&` or `&mut` operators are applied to an rvalue, a temporary value is -created; the lifetime of this temporary value is defined by [syntactic -rules](expressions.html#temporary-lifetimes). These operators cannot be overloaded. +operators. When applied to a [place expression], this expressions produces a +reference (pointer) to the location that the value refers to. The place is also +placed into a borrowed state for the duration of the reference. For a shared +borrow (`&`), this implies that the place may not be mutated, but it may be read +or shared again. For a mutable borrow (`&mut`), the place may not be accessed in +any way until the borrow expires. `&mut` evaluates its operand in a mutable +place expression context. If the `&` or `&mut` operators are applied to a [value +expression], then a temporary value is created; the lifetime of this temporary +value is defined by [syntactic rules]. + +These operators cannot be overloaded. ```rust { @@ -65,13 +69,13 @@ let mut array = [-2, 3, 9]; The `*` (dereference) operator is also a unary prefix operator. When applied to a [pointer](types.html#pointer-types) it denotes the pointed-to location. If the expression is of type `&mut T` and `*mut T`, and is either a local -variable, a (nested) field of a local variance or is a mutable lvalue, then the -resulting [lvalue](expressions.html#lvalues-and-rvalues) can be -assigned to. Dereferencing a raw pointer requires `unsafe`. +variable, a (nested) field of a local variance or is a mutable [place +expression], then the resulting place can be assigned to. Dereferencing a raw +pointer requires `unsafe`. On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an -[immutable lvalue context](expressions.html#mutability) and -`*std::ops::Deref::deref_mut(&mut x)` in a mutable lvalue context. +[immutable place expression context](expressions.html#mutability) and +`*std::ops::Deref::deref_mut(&mut x)` in a mutable place expression context. ```rust let x = &7; @@ -81,7 +85,7 @@ let y = &mut 9; assert_eq!(*y, 11); ``` -## The `?` operator. +## The `?` operator The `?` ("question mark") operator can be applied to values of the `Result` type to propagate errors. If applied to `Err(e)` it will return @@ -108,7 +112,7 @@ These are the last two unary operators. This table summarizes the behavior of them on primitive types and which traits are used to overload these operators for other types. Remember that signed integers are always represented using two's complement. The operands of all of these operators are evaluated in -rvalue context so are moved or copied. +[value expression context][value expression] so are moved or copied. | Symbol | Integer | `bool` | Floating Point | Overloading Trait | |--------|-------------|-------------|----------------|--------------------| @@ -132,8 +136,8 @@ Binary operators expressions are all written with infix notation. This table summarizes the behavior of arithmetic and logical binary operators on primitive types and which traits are used to overload these operators for other types. Remember that signed integers are always represented using two's -complement. The operands of all of these operators are evaluated in rvalue -context so are moved or copied. +complement. The operands of all of these operators are evaluated in [value +expression context][value expression] so are moved or copied. | Symbol | Integer | `bool` | Floating Point | Overloading Trait | |--------|-------------------------|-------------|----------------|--------------------| @@ -180,7 +184,7 @@ define actual comparisons by functions that use these traits as bounds. Many functions and macros in the standard library can then use that assumption (although not to ensure safety). Unlike the arithmetic and logical operators above, these operators implicitly take shared borrows of their operands, -evaluating them in lvalue context: +evaluating them in [place expression context][place expression]: ```rust,ignore a == b; @@ -295,21 +299,17 @@ same trait object. * `u8` to `char` cast * Casts to the `char` with the corresponding code point. -[float-int]: https://github.com/rust-lang/rust/issues/10184 -[float-float]: https://github.com/rust-lang/rust/issues/15536 - ## Assignment expressions -An _assignment expression_ consists of an -[lvalue](expressions.html#lvalues-and-rvalues) expression followed by an equals -sign (`=`) and an [rvalue](expressions.html#lvalues-and-rvalues) expression. +An _assignment expression_ consists of a [place expression] followed by an +equals sign (`=`) and a [value expression]. Evaluating an assignment expression [drops](destructors.html) the left-hand operand, unless it's an unitialized local variable or field of a local variable, and [either copies or moves](expressions.html#moved-and-copied-types) its -right-hand operand to its left-hand operand. The left-hand operand must be an -lvalue: using an rvalue results in a compiler error, rather than promoting it -to a temporary. +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 +than promoting it to a temporary. ```rust # let mut x = 0; @@ -320,15 +320,23 @@ x = y; ## Compound assignment expressions The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be -composed with the `=` operator. The expression `lval OP= val` is equivalent to -`lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`. -Any such expression always has the [`unit`](types.html#tuple-types) type. +composed with the `=` operator. The expression `place_exp OP= value` is +equivalent to `place_expr = place_expr OP val`. For example, `x = x + 1` may be +written as `x += 1`. Any such expression always has the [`unit` type]. These operators can all be overloaded using the trait with the same name as for the normal operation followed by 'Assign', for example, `std::ops::AddAssign` -is used to overload `+=`. As with `=`, `lval` must be an lvalue. +is used to overload `+=`. As with `=`, `place_expr` must be a [place +expression]. ```rust let mut x = 10; x += 4; assert_eq!(x, 14); ``` + +[place expression]: expressions.html#place-expressions-and-value-expressions +[value expression]: expressions.html#place-expressions-and-value-expressions +[syntactic rules]: expressions.html#temporary-lifetimes +[float-int]: https://github.com/rust-lang/rust/issues/10184 +[float-float]: https://github.com/rust-lang/rust/issues/15536 +[`unit` type]: types.html#tuple-types \ No newline at end of file diff --git a/src/expressions/path-expr.md b/src/expressions/path-expr.md index 66bd3e7f8..83b929744 100644 --- a/src/expressions/path-expr.md +++ b/src/expressions/path-expr.md @@ -1,10 +1,9 @@ # Path expressions -A [path](paths.html) used as an expression context denotes either a local +A [path] used as an expression context denotes either a local variable or an item. Path expressions that resolve to local or static variables -are [lvalues](expressions.html#lvalues-and-rvalues), other paths -are rvalues. Using a `static mut` variable requires an [`unsafe` -block](expressions/block-expr.html#unsafe-blocks). +are [place expressions], other paths are [value expressions]. Using a +[`static mut`] variable requires an [`unsafe` block]. ```rust # mod globals { @@ -19,3 +18,9 @@ let some_constructor = Some::; let push_integer = Vec::::push; let slice_reverse = <[i32]>::reverse; ``` + +[place expressions]: expressions.html#place-expressions-and-value-expressions +[value expressions]: expressions.html#place-expressions-and-value-expressions +[path]: paths.html +[`static mut`]: items/static-items.html#mutable-statics +[`unsafe` block]: expressions/block-expr.html#unsafe-blocks \ No newline at end of file diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md index b656dc97c..f8e9fa77c 100644 --- a/src/expressions/struct-expr.md +++ b/src/expressions/struct-expr.md @@ -1,10 +1,10 @@ # Struct expressions There are several forms of struct expressions. A _struct expression_ consists -of the [path](paths.html) of a [struct item](items/structs.html), followed by a +of the [path] of a [struct item](items/structs.html), followed by a brace-enclosed list of zero or more comma-separated name-value pairs, providing the field values of a new instance of the struct. A field name can be any -[identifier](identifiers.html), and is separated from its value expression by a +[identifier], and is separated from its value expression by a colon. In the case of a tuple struct the field names are numbers corresponding to the position of the field. The numbers must be written in decimal, containing no underscores and with no leading zeros or integer suffix. A value @@ -15,11 +15,6 @@ Struct expressions can't be used directly in the head of a [loop] or an [if], [if let] or [match] expression. But struct expressions can still be in used inside parentheses, for example. -[loop]: expressions/loop-expr.html -[if]: expressions/if-expr.html#if-expressions -[if let]: expressions/if-expr.html#if-let-expressions -[match]: expressions/match-expr.html - A _tuple struct expression_ consists of the path of a struct item, followed by a parenthesized list of one or more comma-separated expressions (in other words, the path of a struct item followed by a tuple expression). The struct @@ -78,3 +73,10 @@ Example: Point3d { x: x, y: y_value, z: z }; Point3d { x, y: y_value, z }; ``` + +[IDENTIFIER]: identifiers.html +[path]: paths.html +[loop]: expressions/loop-expr.html +[if]: expressions/if-expr.html#if-expressions +[if let]: expressions/if-expr.html#if-let-expressions +[match]: expressions/match-expr.html \ No newline at end of file diff --git a/src/glossary.md b/src/glossary.md index 16f3bc2ef..d39010592 100644 --- a/src/glossary.md +++ b/src/glossary.md @@ -56,8 +56,8 @@ For example, `2 + (3 * 4)` is an expression that returns the value 14. ### Initialized A variable is initialized if it has been assigned a value and hasn't since been -moved from. All other lvalues are assumed to be initialized. Only unsafe Rust -can create such an lvalue without initializing it. +moved from. All other memory locations are assumed to be initialized. Only +unsafe Rust can create such a memory without initializing it. ### Nominal Types From bfc6eec435adcf6812bb4855bbc46c121d0a12f4 Mon Sep 17 00:00:00 2001 From: Havvy Date: Tue, 5 Dec 2017 13:08:30 -0800 Subject: [PATCH 2/2] Go with 'memory location' over 'place' --- src/expressions/array-expr.md | 4 ++-- src/expressions/match-expr.md | 3 ++- src/expressions/operator-expr.md | 21 ++++++++++----------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/expressions/array-expr.md b/src/expressions/array-expr.md index a78ca8d84..132e45333 100644 --- a/src/expressions/array-expr.md +++ b/src/expressions/array-expr.md @@ -38,7 +38,7 @@ greater than 1 then this requires that the type of `a` is [Array and slice](types.html#array-and-slice-types)-typed expressions can be indexed by writing a square-bracket-enclosed expression (the index) after them. -When the array is mutable, the resulting [place] can be assigned to. +When the array is mutable, the resulting [memory location] can be assigned to. For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::opsIndexMut::index_mut(&mut a, b)` in a mutable place expression context. Just as with methods, Rust will also @@ -69,7 +69,7 @@ The array index expression can be implemented for types other than arrays and sl by implementing the [Index] and [IndexMut] traits. [_Expression_]: expressions.html -[place]: expressions.html#place-expressions-and-value-expressions +[memory location]: expressions.html#place-expressions-and-value-expressions [Index]: ../std/ops/trait.Index.html [IndexMut]: ../std/ops/trait.IndexMut.html [constant expression]: expressions.html#constant-expressions \ No newline at end of file diff --git a/src/expressions/match-expr.md b/src/expressions/match-expr.md index 91ec9a554..23e2d9f08 100644 --- a/src/expressions/match-expr.md +++ b/src/expressions/match-expr.md @@ -18,7 +18,8 @@ the pattern are assigned to local variables in the arm's block, and control enters the block. When the head expression is a [place expression], the match does not allocate a -temporary location; however, a by-value binding may copy or move from the place. +temporary location; however, a by-value binding may copy or move from the +memory location. When possible, it is preferable to match on place expressions, as the lifetime of these matches inherits the lifetime of the place expression rather than being restricted to the inside of the match. diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 2baa241ec..e7195ea27 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -40,14 +40,13 @@ assert_eq!(y, 20); The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix operators. When applied to a [place expression], this expressions produces a -reference (pointer) to the location that the value refers to. The place is also -placed into a borrowed state for the duration of the reference. For a shared -borrow (`&`), this implies that the place may not be mutated, but it may be read -or shared again. For a mutable borrow (`&mut`), the place may not be accessed in -any way until the borrow expires. `&mut` evaluates its operand in a mutable -place expression context. If the `&` or `&mut` operators are applied to a [value -expression], then a temporary value is created; the lifetime of this temporary -value is defined by [syntactic rules]. +reference (pointer) to the location that the value refers to. The memory +location is also placed into a borrowed state for the duration of the reference. +For a shared borrow (`&`), this implies that the place may not be mutated, but +it may be read or shared again. For a mutable borrow (`&mut`), the place may not +be accessed in any way until the borrow expires. `&mut` evaluates its operand in +a mutable place expression context. If the `&` or `&mut` operators are applied +to a [value expression], then a [temporary value] is created. These operators cannot be overloaded. @@ -70,8 +69,8 @@ The `*` (dereference) operator is also a unary prefix operator. When applied to a [pointer](types.html#pointer-types) it denotes the pointed-to location. If the expression is of type `&mut T` and `*mut T`, and is either a local variable, a (nested) field of a local variance or is a mutable [place -expression], then the resulting place can be assigned to. Dereferencing a raw -pointer requires `unsafe`. +expression], then the resulting memory location can be assigned to. +Dereferencing a raw pointer requires `unsafe`. On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an [immutable place expression context](expressions.html#mutability) and @@ -336,7 +335,7 @@ assert_eq!(x, 14); [place expression]: expressions.html#place-expressions-and-value-expressions [value expression]: expressions.html#place-expressions-and-value-expressions -[syntactic rules]: expressions.html#temporary-lifetimes +[temporary value]: expressions.html#temporary-lifetimes [float-int]: https://github.com/rust-lang/rust/issues/10184 [float-float]: https://github.com/rust-lang/rust/issues/15536 [`unit` type]: types.html#tuple-types \ No newline at end of file