From eb5290329316e96c48c032075f7dbfa56990702b Mon Sep 17 00:00:00 2001 From: "Havvy (Ryan Scheel)" Date: Sat, 13 Feb 2021 22:10:46 -0800 Subject: [PATCH] One sentence is one line src/expressions/* --- src/expressions/array-expr.md | 50 +++----- src/expressions/await-expr.md | 37 ++---- src/expressions/block-expr.md | 104 ++++++--------- src/expressions/call-expr.md | 44 +++---- src/expressions/closure-expr.md | 55 +++----- src/expressions/field-expr.md | 22 ++-- src/expressions/grouped-expr.md | 12 +- src/expressions/if-expr.md | 38 +++--- src/expressions/literal-expr.md | 5 +- src/expressions/loop-expr.md | 100 ++++++--------- src/expressions/match-expr.md | 82 +++++------- src/expressions/method-call-expr.md | 72 ++++------- src/expressions/operator-expr.md | 191 +++++++++++----------------- src/expressions/path-expr.md | 7 +- src/expressions/range-expr.md | 4 +- src/expressions/return-expr.md | 6 +- src/expressions/struct-expr.md | 56 ++++---- src/expressions/tuple-expr.md | 37 ++---- 18 files changed, 342 insertions(+), 580 deletions(-) diff --git a/src/expressions/array-expr.md b/src/expressions/array-expr.md index 0fd5427a9..2659b229e 100644 --- a/src/expressions/array-expr.md +++ b/src/expressions/array-expr.md @@ -10,28 +10,22 @@ >       [_Expression_] ( `,` [_Expression_] )\* `,`?\ >    | [_Expression_] `;` [_Expression_] -An _[array] expression_ can be written by enclosing zero or more -comma-separated expressions of uniform type in square brackets. This produces -an array containing each of these values in the order they are written. +An _[array] expression_ can be written by enclosing zero or more comma-separated expressions of uniform type in square brackets. +This produces an array containing each of these values in the order they are written. -Alternatively there can be exactly two expressions inside the brackets, -separated by a semicolon. The expression after the `;` must have type `usize` -and be a [constant expression], such as a [literal] or a [constant item]. `[a; -b]` creates an array containing `b` copies of the value of `a`. If the -expression after the semicolon has a value greater than 1 then this requires -that the type of `a` is [`Copy`], or `a` must be a path to a constant item. +Alternatively there can be exactly two expressions inside the brackets, separated by a semicolon. +The expression after the `;` must have type `usize` and be a [constant expression], such as a [literal] or a [constant item]. +`[a; b]` creates an array containing `b` copies of the value of `a`. +If the expression after the semicolon has a value greater than 1 then this requires that the type of `a` is [`Copy`], or `a` must be a path to a constant item. When the repeat expression `a` is a constant item, it is evaluated `b` times. -If `b` is 0, the constant item is not evaluated at all. For expressions that -are not a constant item, it is evaluated exactly once, and then the result is -copied `b` times. +If `b` is 0, the constant item is not evaluated at all. +For expressions that are not a constant item, it is evaluated exactly once, and then the result is copied `b` times.
-Warning: In the case where `b` is 0, and `a` is a non-constant item, there is -currently a bug in `rustc` where the value `a` is evaluated but not dropped, -thus causing a leak. See [issue -#74836](https://github.com/rust-lang/rust/issues/74836). +Warning: In the case where `b` is 0, and `a` is a non-constant item, there is currently a bug in `rustc` where the value `a` is evaluated but not dropped, thus causing a leak. +See [issue #74836](https://github.com/rust-lang/rust/issues/74836).
@@ -47,9 +41,7 @@ const EMPTY: Vec = Vec::new(); ### Array expression attributes -[Inner attributes] are allowed directly after the opening bracket of an array -expression in the same expression contexts as [attributes on block -expressions]. +[Inner attributes] are allowed directly after the opening bracket of an array expression in the same expression contexts as [attributes on block expressions]. ## Array and slice indexing expressions @@ -57,20 +49,15 @@ expressions]. > _IndexExpression_ :\ >    [_Expression_] `[` [_Expression_] `]` -[Array] and [slice]-typed expressions can be indexed by writing a -square-bracket-enclosed expression of type `usize` (the index) after them. +[Array] and [slice]-typed expressions can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them. 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::ops::IndexMut::index_mut(&mut a, b)` in a mutable place expression -context. Just as with methods, Rust will also insert dereference operations on -`a` repeatedly to find an implementation. +For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::ops::IndexMut::index_mut(&mut a, b)` 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 for arrays and slices. Array access is a [constant -expression], so bounds can be checked at compile-time 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. +Indices are zero-based for arrays and slices. +Array access is a [constant expression], so bounds can be checked at compile-time 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 // lint is deny by default. @@ -90,8 +77,7 @@ let arr = ["a", "b"]; arr[10]; // warning: index out of bounds ``` -The array index expression can be implemented for types other than arrays and slices -by implementing the [Index] and [IndexMut] traits. +The array index expression can be implemented for types other than arrays and slices by implementing the [Index] and [IndexMut] traits. [`Copy`]: ../special-types-and-traits.md#copy [IndexMut]: ../../std/ops/trait.IndexMut.html diff --git a/src/expressions/await-expr.md b/src/expressions/await-expr.md index 85985c6f4..509a70e83 100644 --- a/src/expressions/await-expr.md +++ b/src/expressions/await-expr.md @@ -4,24 +4,17 @@ > _AwaitExpression_ :\ >    [_Expression_] `.` `await` -Await expressions are legal only within an [async context], like an -[`async fn`] or an [`async` block]. They operate on a [future]. Their effect -is to suspend the current computation until the given future is ready -to produce a value. +Await expressions are legal only within an [async context], like an [`async fn`] or an [`async` block]. +They operate on a [future]. +Their effect is to suspend the current computation until the given future is ready to produce a value. More specifically, an `.await` expression has the following effect. 1. Evaluate `` to a [future] `tmp`; 2. Pin `tmp` using [`Pin::new_unchecked`]; -3. This pinned future is then polled by calling the [`Future::poll`] method and - passing it the current [task context](#task-context); -3. If the call to `poll` returns [`Poll::Pending`], then the future - returns `Poll::Pending`, suspending its state so that, when the - surrounding async context is re-polled, execution returns to step - 2; -4. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the - value contained in the [`Poll::Ready`] variant is used as the result - of the `await` expression itself. +3. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context); +3. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 2; +4. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself. [`async fn`]: ../items/functions.md#async-functions [`async` block]: block-expr.md#async-blocks @@ -33,23 +26,19 @@ More specifically, an `.await` expression has the following effect. [`Poll::Pending`]: ../../std/task/enum.Poll.html#variant.Pending [`Poll::Ready`]: ../../std/task/enum.Poll.html#variant.Ready -> **Edition differences**: Await expressions are only available beginning with -> Rust 2018. +> **Edition differences**: Await expressions are only available beginning with Rust 2018. ## Task context -The task context refers to the [`Context`] which was supplied to the -current [async context] when the async context itself was -polled. Because `await` expressions are only legal in an async -context, there must be some task context available. +The task context refers to the [`Context`] which was supplied to the current [async context] when the async context itself was polled. +Because `await` expressions are only legal in an async context, there must be some task context available. [`Context`]: ../../std/task/struct.Context.html [async context]: ../expressions/block-expr.md#async-context ## Approximate desugaring -Effectively, an `.await` expression is roughly -equivalent to the following (this desugaring is not normative): +Effectively, an `.await` expression is roughly equivalent to the following (this desugaring is not normative): ```rust,ignore @@ -64,7 +53,5 @@ match /* */ { } ``` -where the `yield` pseudo-code returns `Poll::Pending` and, when -re-invoked, resumes execution from that point. The variable -`current_context` refers to the context taken from the async -environment. +where the `yield` pseudo-code returns `Poll::Pending` and, when re-invoked, resumes execution from that point. +The variable `current_context` refers to the context taken from the async environment. diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index 291634f3c..da2cc9905 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -12,28 +12,20 @@ >    | [_Statement_]\+ [_ExpressionWithoutBlock_]\ >    | [_ExpressionWithoutBlock_] -A *block expression*, or *block*, is a control flow expression and anonymous -namespace scope for items and variable declarations. As a control flow -expression, a block sequentially executes its component non-item declaration -statements and then its final optional expression. As an anonymous namespace -scope, item declarations are only in scope inside the block itself and variables -declared by `let` statements are in scope from the next statement until the end -of the block. - -Blocks are written as `{`, then any [inner attributes], then [statements], -then an optional expression, and finally a `}`. Statements are usually required -to be followed by a semicolon, with two exceptions. Item declaration statements do -not need to be followed by a semicolon. Expression statements usually require -a following semicolon except if its outer expression is a flow control -expression. Furthermore, extra semicolons between statements are allowed, but -these semicolons do not affect semantics. - -When evaluating a block expression, each statement, except for item declaration -statements, is executed sequentially. Then the final expression is executed, -if given. - -The type of a block is the type of the final expression, or `()` if the final -expression is omitted. +A *block expression*, or *block*, is a control flow expression and anonymous namespace scope for items and variable declarations. +As a control flow expression, a block sequentially executes its component non-item declaration statements and then its final optional expression. +As an anonymous namespace scope, item declarations are only in scope inside the block itself and variables declared by `let` statements are in scope from the next statement until the end of the block. + +Blocks are written as `{`, then any [inner attributes], then [statements], then an optional expression, and finally a `}`. +Statements are usually required to be followed by a semicolon, with two exceptions. +Item declaration statements do not need to be followed by a semicolon. +Expression statements usually require a following semicolon except if its outer expression is a flow control expression. +Furthermore, extra semicolons between statements are allowed, but these semicolons do not affect semantics. + +When evaluating a block expression, each statement, except for item declaration statements, is executed sequentially. +Then the final expression is executed, if given. + +The type of a block is the type of the final expression, or `()` if the final expression is omitted. ```rust # fn fn_call() {} @@ -49,14 +41,11 @@ let five: i32 = { assert_eq!(5, five); ``` -> Note: As a control flow expression, if a block expression is the outer -> expression of an expression statement, the expected type is `()` unless it -> is followed immediately by a semicolon. +> Note: As a control flow expression, if a block expression is the outer expression of an expression statement, the expected type is `()` unless it is followed immediately by a semicolon. -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. For example, the following example fails on the call to `consume_self` -because the struct was moved out of `s` in the block expression. +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. +For example, the following example fails on the call to `consume_self` because the struct was moved out of `s` in the block expression. ```rust,compile_fail struct Struct; @@ -83,20 +72,15 @@ fn move_by_block_expression() { > _AsyncBlockExpression_ :\ >    `async` `move`? _BlockExpression_ -An *async block* is a variant of a block expression which evaluates to -a *future*. The final expression of the block, if present, determines -the result value of the future. +An *async block* is a variant of a block expression which evaluates to a *future*. +The final expression of the block, if present, determines the result value of the future. Executing an async block is similar to executing a closure expression: its immediate effect is to produce and return an anonymous type. -Whereas closures return a type that implements one or more of the -[`std::ops::Fn`] traits, however, the type returned for an async block -implements the [`std::future::Future`] trait. The actual data format for -this type is unspecified. +Whereas closures return a type that implements one or more of the [`std::ops::Fn`] traits, however, the type returned for an async block implements the [`std::future::Future`] trait. +The actual data format for this type is unspecified. -> **Note:** The future type that rustc generates is roughly equivalent -> to an enum with one variant per `await` point, where each variant -> stores the data needed to resume from its corresponding point. +> **Note:** The future type that rustc generates is roughly equivalent to an enum with one variant per `await` point, where each variant stores the data needed to resume from its corresponding point. > **Edition differences**: Async blocks are only available beginning with Rust 2018. @@ -105,11 +89,9 @@ this type is unspecified. ### Capture modes -Async blocks capture variables from their environment using the same -[capture modes] as closures. Like closures, when written `async { -.. }` the capture mode for each variable will be inferred from the -content of the block. `async move { .. }` blocks however will move all -referenced variables into the resulting future. +Async blocks capture variables from their environment using the same [capture modes] as closures. +Like closures, when written `async { .. }` the capture mode for each variable will be inferred from the content of the block. +`async move { .. }` blocks however will move all referenced variables into the resulting future. [capture modes]: ../types/closure.md#capture-modes [shared references]: ../types/pointer.md#shared-references- @@ -117,25 +99,20 @@ referenced variables into the resulting future. ### Async context -Because async blocks construct a future, they define an **async -context** which can in turn contain [`await` expressions]. Async -contexts are established by async blocks as well as the bodies of -async functions, whose semantics are defined in terms of async blocks. +Because async blocks construct a future, they define an **async context** which can in turn contain [`await` expressions]. +Async contexts are established by async blocks as well as the bodies of async functions, whose semantics are defined in terms of async blocks. [`await` expressions]: await-expr.md ### Control-flow operators -Async blocks act like a function boundary, much like -closures. Therefore, the `?` operator and `return` expressions both -affect the output of the future, not the enclosing function or other -context. That is, `return ` from within a closure will return -the result of `` as the output of the future. Similarly, if -`?` propagates an error, that error is propagated as the result -of the future. +Async blocks act like a function boundary, much like closures. +Therefore, the `?` operator and `return` expressions both affect the output of the future, not the enclosing function or other context. +That is, `return ` from within a closure will return the result of `` as the output of the future. +Similarly, if `?` propagates an error, that error is propagated as the result of the future. -Finally, the `break` and `continue` keywords cannot be used to branch -out from an async block. Therefore the following is illegal: +Finally, the `break` and `continue` keywords cannot be used to branch out from an async block. +Therefore the following is illegal: ```rust,edition2018,compile_fail loop { @@ -153,8 +130,8 @@ loop { _See [`unsafe` block](../unsafe-blocks.md) for more information on when to use `unsafe`_ -A block of code can be prefixed with the `unsafe` keyword to permit [unsafe -operations]. Examples: +A block of code can be prefixed with the `unsafe` keyword to permit [unsafe operations]. +Examples: ```rust unsafe { @@ -170,8 +147,7 @@ let a = unsafe { an_unsafe_fn() }; ## Attributes on block expressions -[Inner attributes] are allowed directly after the opening brace of a block -expression in the following situations: +[Inner attributes] are allowed directly after the opening brace of a block expression in the following situations: * [Function] and [method] bodies. * Loop bodies ([`loop`], [`while`], [`while let`], and [`for`]). @@ -181,11 +157,9 @@ expression in the following situations: * A block expression as the tail expression of another block expression. -The attributes that have meaning on a block expression are [`cfg`] and [the -lint check attributes]. +The attributes that have meaning on a block expression are [`cfg`] and [the lint check attributes]. -For example, this function returns `true` on unix platforms and `false` on other -platforms. +For example, this function returns `true` on unix platforms and `false` on other platforms. ```rust fn is_unix_platform() -> bool { diff --git a/src/expressions/call-expr.md b/src/expressions/call-expr.md index 399408d86..0992f5e9f 100644 --- a/src/expressions/call-expr.md +++ b/src/expressions/call-expr.md @@ -7,15 +7,13 @@ > _CallParams_ :\ >    [_Expression_] ( `,` [_Expression_] )\* `,`? -A _call expression_ consists of an expression followed by a parenthesized -expression-list. It invokes a function, providing zero or more input variables. -If the function eventually returns, then the expression completes. For -[non-function types](../types/function-item.md), the expression f(...) uses -the method on one of the [`std::ops::Fn`], [`std::ops::FnMut`] or -[`std::ops::FnOnce`] traits, which differ in whether they take the type by -reference, mutable reference, or take ownership respectively. An automatic -borrow will be taken if needed. Rust will also automatically dereference `f` as -required. Some examples of call expressions: +A _call expression_ consists of an expression followed by a parenthesized expression-list. +It invokes a function, providing zero or more input variables. +If the function eventually returns, then the expression completes. +For [non-function types](../types/function-item.md), the expression f(...) uses the method on one of the [`std::ops::Fn`], [`std::ops::FnMut`] or [`std::ops::FnOnce`] traits, which differ in whether they take the type by reference, mutable reference, or take ownership respectively. +An automatic borrow will be taken if needed. +Rust will also automatically dereference `f` as required. +Some examples of call expressions: ```rust # fn add(x: i32, y: i32) -> i32 { 0 } @@ -25,28 +23,22 @@ let name: &'static str = (|| "Rust")(); ## Disambiguating Function Calls -Rust treats all function calls as sugar for a more explicit, [fully-qualified -syntax]. Upon compilation, Rust will desugar all function calls into the explicit -form. Rust may sometimes require you to qualify function calls with trait, -depending on the ambiguity of a call in light of in-scope items. +Rust treats all function calls as sugar for a more explicit, [fully-qualified syntax]. +Upon compilation, Rust will desugar all function calls into the explicit form. +Rust may sometimes require you to qualify function calls with trait, depending on the ambiguity of a call in light of in-scope items. -> **Note**: In the past, the Rust community used the terms "Unambiguous -> Function Call Syntax", "Universal Function Call Syntax", or "UFCS", in -> documentation, issues, RFCs, and other community writings. However, the term -> lacks descriptive power and potentially confuses the issue at hand. We mention -> it here for searchability's sake. +> **Note**: In the past, the Rust community used the terms "Unambiguous Function Call Syntax", "Universal Function Call Syntax", or "UFCS", in documentation, issues, RFCs, and other community writings. +> However, the term lacks descriptive power and potentially confuses the issue at hand. +> We mention it here for searchability's sake. -Several situations often occur which result in ambiguities about the receiver or -referent of method or associated function calls. These situations may include: +Several situations often occur which result in ambiguities about the receiver or referent of method or associated function calls. +These situations may include: * Multiple in-scope traits define methods with the same name for the same types -* Auto-`deref` is undesirable; for example, distinguishing between methods on a - smart pointer itself and the pointer's referent -* Methods which take no arguments, like [`default()`], and return properties of a - type, like [`size_of()`] +* Auto-`deref` is undesirable; for example, distinguishing between methods on a smart pointer itself and the pointer's referent +* Methods which take no arguments, like [`default()`], and return properties of a type, like [`size_of()`] -To resolve the ambiguity, the programmer may refer to their desired method or -function using more specific paths, types, or traits. +To resolve the ambiguity, the programmer may refer to their desired method or function using more specific paths, types, or traits. For example, diff --git a/src/expressions/closure-expr.md b/src/expressions/closure-expr.md index 217a6a19c..366984611 100644 --- a/src/expressions/closure-expr.md +++ b/src/expressions/closure-expr.md @@ -12,45 +12,29 @@ > _ClosureParam_ :\ >    [_OuterAttribute_]\* [_Pattern_] ( `:` [_Type_] )? -A _closure expression_, also know as a lambda expression or a lambda, defines a -closure and denotes it as a value, in a single expression. A closure expression -is a pipe-symbol-delimited (`|`) list of irrefutable [patterns] followed by an -expression. Type annotations may optionally be added for the type of the -parameters or for the return type. If there is a return type, the expression -used for the body of the closure must be a normal [block]. A closure expression -also may begin with the `move` keyword before the initial `|`. +A _closure expression_, also know as a lambda expression or a lambda, defines a closure and denotes it as a value, in a single expression. +A closure expression is a pipe-symbol-delimited (`|`) list of irrefutable [patterns] followed by an expression. +Type annotations may optionally be added for the type of the parameters or for the return type. +If there is a return type, the expression used for the body of the closure must be a normal [block]. +A closure expression also may begin with the `move` keyword before the initial `|`. -A closure expression denotes a function that maps a list of parameters onto -the expression that follows the parameters. Just like a [`let` binding], the -parameters are irrefutable [patterns], whose type annotation is optional and -will be inferred from context if not given. Each closure expression has a -unique, anonymous type. +A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters. +Just like a [`let` binding], the parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given. +Each closure expression has a unique, anonymous type. -Closure expressions are most useful when passing functions as arguments to other -functions, as an abbreviation for defining and capturing a separate function. +Closure expressions are most useful when passing functions as arguments to other functions, as an abbreviation for defining and capturing a separate function. -Significantly, closure expressions _capture their environment_, which regular -[function definitions] do not. Without the `move` keyword, the closure expression -[infers how it captures each variable from its environment](../types/closure.md#capture-modes), -preferring to capture by shared reference, effectively borrowing -all outer variables mentioned inside the closure's body. If needed the compiler -will infer that instead mutable references should be taken, or that the values -should be moved or copied (depending on their type) from the environment. A -closure can be forced to capture its environment by copying or moving values by -prefixing it with the `move` keyword. This is often used to ensure that the -closure's type is `'static`. +Significantly, closure expressions _capture their environment_, which regular [function definitions] do not. +Without the `move` keyword, the closure expression [infers how it captures each variable from its environment](../types/closure.md#capture-modes), preferring to capture by shared reference, effectively borrowing all outer variables mentioned inside the closure's body. +If needed the compiler will infer that instead mutable references should be taken, or that the values should be moved or copied (depending on their type) from the environment. +A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword. +This is often used to ensure that the closure's type is `'static`. -The compiler will determine which of the [closure -traits](../types/closure.md#call-traits-and-coercions) the closure's type will implement by how it -acts on its captured variables. The closure will also implement -[`Send`](../special-types-and-traits.md#send) and/or -[`Sync`](../special-types-and-traits.md#sync) if all of its captured types do. -These traits allow functions to accept closures using generics, even though the -exact types can't be named. +The compiler will determine which of the [closure traits](../types/closure.md#call-traits-and-coercions) the closure's type will implement by how it acts on its captured variables. +The closure will also implement [`Send`](../special-types-and-traits.md#send) and/or [`Sync`](../special-types-and-traits.md#sync) if all of its captured types do. +These traits allow functions to accept closures using generics, even though the exact types can't be named. -In this example, we define a function `ten_times` that takes a higher-order -function argument, and we then call it with a closure expression as an argument, -followed by a closure expression that moves values from its environment. +In this example, we define a function `ten_times` that takes a higher-order function argument, and we then call it with a closure expression as an argument, followed by a closure expression that moves values from its environment. ```rust fn ten_times(f: F) where F: Fn(i32) { @@ -69,8 +53,7 @@ ten_times(move |j| println!("{}, {}", word, j)); ## Attributes on closure parameters -Attributes on closure parameters follow the same rules and restrictions as -[regular function parameters]. +Attributes on closure parameters follow the same rules and restrictions as [regular function parameters]. [block]: block-expr.md [function definitions]: ../items/functions.md diff --git a/src/expressions/field-expr.md b/src/expressions/field-expr.md index 20fb98219..59451d2b6 100644 --- a/src/expressions/field-expr.md +++ b/src/expressions/field-expr.md @@ -4,11 +4,9 @@ > _FieldExpression_ :\ >    [_Expression_] `.` [IDENTIFIER] -A _field expression_ consists of an expression followed by a single dot and an -[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. +A _field expression_ consists of an expression followed by a single dot and an [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 @@ -22,16 +20,12 @@ mystruct.method(); // Method expression 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 -possible. In cases of ambiguity, we prefer fewer autoderefs to more. +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 possible. +In cases of ambiguity, we prefer fewer autoderefs to more. -Finally, the fields of a struct or a reference to a struct are treated as -separate entities when borrowing. If the struct does not implement -[`Drop`](../special-types-and-traits.md#drop) and is stored in a local variable, -this also applies to moving out of each of its fields. This also does not apply -if automatic dereferencing is done though user defined types other than -[`Box`](../special-types-and-traits.html#boxt). +Finally, the fields of a struct or a reference to a struct are treated as separate entities when borrowing. +If the struct does not implement [`Drop`](../special-types-and-traits.md#drop) and is stored in a local variable, this also applies to moving out of each of its fields. +This also does not apply if automatic dereferencing is done though user defined types other than [`Box`](../special-types-and-traits.html#boxt). ```rust struct A { f1: String, f2: String, f3: String } diff --git a/src/expressions/grouped-expr.md b/src/expressions/grouped-expr.md index 8e57cdbb7..096b36c82 100644 --- a/src/expressions/grouped-expr.md +++ b/src/expressions/grouped-expr.md @@ -4,9 +4,8 @@ > _GroupedExpression_ :\ >    `(` [_InnerAttribute_]\* [_Expression_] `)` -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. +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. An example of a parenthesized expression: @@ -17,8 +16,7 @@ assert_eq!(x, 14); assert_eq!(y, 20); ``` -An example of a necessary use of parentheses is when calling a function pointer -that is a member of a struct: +An example of a necessary use of parentheses is when calling a function pointer that is a member of a struct: ```rust # struct A { @@ -37,9 +35,7 @@ assert_eq!((a.f)(), "The field f"); ## Group expression attributes -[Inner attributes] are allowed directly after the opening parenthesis of a -group expression in the same expression contexts as [attributes on block -expressions]. +[Inner attributes] are allowed directly after the opening parenthesis of a group expression in the same expression contexts as [attributes on block expressions]. [Inner attributes]: ../attributes.md [_Expression_]: ../expressions.md diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index 5b63acf81..c552635cc 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -10,17 +10,14 @@ > | _IfExpression_ > | _IfLetExpression_ ) )\? -An `if` expression is a conditional branch in program control. The syntax of an -`if` expression is a condition operand, followed by a consequent block, any -number of `else if` conditions and blocks, and an optional trailing `else` -block. The condition operands must have the [boolean type]. If a condition -operand evaluates to `true`, the consequent block is executed and any -subsequent `else if` or `else` block is skipped. If a condition operand -evaluates to `false`, the consequent block is skipped and any subsequent `else -if` condition is evaluated. If all `if` and `else if` conditions evaluate to -`false` then any `else` block is executed. An if expression evaluates to the -same value as the executed block, or `()` if no block is evaluated. An `if` -expression must have the same type in all situations. +An `if` expression is a conditional branch in program control. +The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. +The condition operands must have the [boolean type]. +If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped. +If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated. +If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed. +An if expression evaluates to the same value as the executed block, or `()` if no block is evaluated. +An `if` expression must have the same type in all situations. ```rust # let x = 3; @@ -51,12 +48,10 @@ assert_eq!(y, "Bigger"); > | _IfExpression_ > | _IfLetExpression_ ) )\? -An `if let` expression is semantically similar to an `if` expression but in -place of a condition operand it expects the keyword `let` followed by a -pattern, an `=` and a [scrutinee] operand. If the value of the scrutinee -matches the pattern, the corresponding block will execute. Otherwise, flow -proceeds to the following `else` block if it exists. Like `if` expressions, -`if let` expressions have a value determined by the block that is evaluated. +An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand. +If the value of the scrutinee matches the pattern, the corresponding block will execute. +Otherwise, flow proceeds to the following `else` block if it exists. +Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated. ```rust let dish = ("Ham", "Eggs"); @@ -116,8 +111,7 @@ match EXPR { } ``` -Multiple patterns may be specified with the `|` operator. This has the same semantics -as with `|` in `match` expressions: +Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions: ```rust enum E { @@ -132,10 +126,8 @@ if let E::X(n) | E::Y(n) = v { ``` The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. -Use of a lazy boolean operator is ambiguous with a planned feature change -of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]). -When lazy boolean operator expression is desired, this can be achieved -by using parenthesis as below: +Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]). +When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below: ```rust,ignore diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index c64c6d6c2..0e2d7c0a4 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -12,9 +12,8 @@ >    | [FLOAT_LITERAL]\ >    | [BOOLEAN_LITERAL] -A _literal expression_ consists of one of the [literal](../tokens.md#literals) -forms described earlier. It directly describes a number, character, string, -or boolean value. +A _literal expression_ consists of one of the [literal](../tokens.md#literals) forms described earlier. +It directly describes a number, character, string, or boolean value. ```rust "hello"; // string type diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 7d475cd02..bb2a061bd 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -20,11 +20,9 @@ Rust supports four loop expressions: * A [`loop` expression](#infinite-loops) denotes an infinite loop. * A [`while` expression](#predicate-loops) loops until a predicate is false. * A [`while let` expression](#predicate-pattern-loops) tests a pattern. -* A [`for` expression](#iterator-loops) extracts values from an iterator, - looping until the iterator is empty. +* A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty. -All four types of loop support [`break` expressions](#break-expressions), -[`continue` expressions](#continue-expressions), and [labels](#loop-labels). +All four types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels). Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). ## Infinite loops @@ -36,10 +34,8 @@ Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). A `loop` expression repeats execution of its body continuously: `loop { println!("I live."); }`. -A `loop` expression without an associated `break` expression is diverging and -has type [`!`](../types/never.md). A `loop` expression containing -associated [`break` expression(s)](#break-expressions) may terminate, and must -have type compatible with the value of the `break` expression(s). +A `loop` expression without an associated `break` expression is diverging and has type [`!`](../types/never.md). +A `loop` expression containing associated [`break` expression(s)](#break-expressions) may terminate, and must have type compatible with the value of the `break` expression(s). ## Predicate loops @@ -47,10 +43,9 @@ have type compatible with the value of the `break` expression(s). > _PredicateLoopExpression_ :\ >    `while` [_Expression_]_except struct expression_ [_BlockExpression_] -A `while` loop begins by evaluating the [boolean] loop conditional operand. If -the loop conditional operand evaluates to `true`, the loop body block -executes, then control returns to the loop conditional operand. If the loop -conditional expression evaluates to `false`, the `while` expression completes. +A `while` loop begins by evaluating the [boolean] loop conditional operand. +If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand. +If the loop conditional expression evaluates to `false`, the `while` expression completes. An example: @@ -70,12 +65,9 @@ while i < 10 { >    `while` `let` [_MatchArmPatterns_] `=` [_Expression_]_except struct or lazy boolean operator expression_ > [_BlockExpression_] -A `while let` loop is semantically similar to a `while` loop but in place of a -condition expression it expects the keyword `let` followed by a pattern, an -`=`, a [scrutinee] expression and a block expression. If the value of the -scrutinee matches the pattern, the loop body block executes then control -returns to the pattern matching statement. Otherwise, the while expression -completes. +A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression. +If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement. +Otherwise, the while expression completes. ```rust let mut x = vec![1, 2, 3]; @@ -90,8 +82,7 @@ while let _ = 5 { } ``` -A `while let` loop is equivalent to a `loop` expression containing a [`match` -expression] as follows. +A `while let` loop is equivalent to a `loop` expression containing a [`match` expression] as follows. ```rust,ignore @@ -112,8 +103,8 @@ is equivalent to } ``` -Multiple patterns may be specified with the `|` operator. This has the same semantics -as with `|` in `match` expressions: +Multiple patterns may be specified with the `|` operator. +This has the same semantics as with `|` in `match` expressions: ```rust let mut vals = vec![2, 3, 1, 2, 2]; @@ -132,11 +123,9 @@ As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolea >    `for` [_Pattern_] `in` [_Expression_]_except struct expression_ > [_BlockExpression_] -A `for` expression is a syntactic construct for looping over elements provided -by an implementation of `std::iter::IntoIterator`. If the iterator yields a -value, that value is matched against the irrefutable pattern, the body of the -loop is executed, and then control returns to the head of the `for` loop. If the -iterator is empty, the `for` expression completes. +A `for` expression is a syntactic construct for looping over elements provided by an implementation of `std::iter::IntoIterator`. +If the iterator yields a value, that value is matched against the irrefutable pattern, the body of the loop is executed, and then control returns to the head of the `for` loop. +If the iterator is empty, the `for` expression completes. An example of a `for` loop over the contents of an array: @@ -187,15 +176,11 @@ is equivalent to } ``` -`IntoIterator`, `Iterator`, and `Option` are always the standard library items -here, not whatever those names resolve to in the current scope. The variable -names `next`, `iter`, and `val` are for exposition only, they do not actually -have names the user can type. +`IntoIterator`, `Iterator`, and `Option` are always the standard library items here, not whatever those names resolve to in the current scope. +The variable names `next`, `iter`, and `val` are for exposition only, they do not actually have names the user can type. -> **Note**: that the outer `match` is used to ensure that any -> [temporary values] in `iter_expr` don't get dropped before the loop is -> finished. `next` is declared before being assigned because it results in -> types being inferred correctly more often. +> **Note**: that the outer `match` is used to ensure that any [temporary values] in `iter_expr` don't get dropped before the loop is finished. +> `next` is declared before being assigned because it results in types being inferred correctly more often. ## Loop labels @@ -203,13 +188,9 @@ have names the user can type. > _LoopLabel_ :\ >    [LIFETIME_OR_LABEL] `:` -A loop expression may optionally have a _label_. The label is written as -a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`, -`'bar: while false {}`, `'humbug: for _ in 0..0 {}`. -If a label is present, then labeled `break` and `continue` expressions nested -within this loop may exit out of this loop or return control to its head. -See [break expressions](#break-expressions) and [continue -expressions](#continue-expressions). +A loop expression may optionally have a _label_. The label is written as a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`, `'bar: while false {}`, `'humbug: for _ in 0..0 {}`. +If a label is present, then labeled `break` and `continue` expressions nested within this loop may exit out of this loop or return control to its head. +See [break expressions](#break-expressions) and [continue expressions](#continue-expressions). ## `break` expressions @@ -217,8 +198,7 @@ expressions](#continue-expressions). > _BreakExpression_ :\ >    `break` [LIFETIME_OR_LABEL]? [_Expression_]? -When `break` is encountered, execution of the associated loop body is -immediately terminated, for example: +When `break` is encountered, execution of the associated loop body is immediately terminated, for example: ```rust let mut last = 0; @@ -231,9 +211,9 @@ for x in 1..100 { assert_eq!(last, 12); ``` -A `break` expression is normally associated with the innermost `loop`, `for` or -`while` loop enclosing the `break` expression, but a [label](#loop-labels) can -be used to specify which enclosing loop is affected. Example: +A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression, +but a [label](#loop-labels) can be used to specify which enclosing loop is affected. +Example: ```rust 'outer: loop { @@ -243,9 +223,7 @@ be used to specify which enclosing loop is affected. Example: } ``` -A `break` expression is only permitted in the body of a loop, and has one of -the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) -`break EXPR` or `break 'label EXPR`. +A `break` expression is only permitted in the body of a loop, and has one of the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) `break EXPR` or `break 'label EXPR`. ## `continue` expressions @@ -253,21 +231,17 @@ the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) > _ContinueExpression_ :\ >    `continue` [LIFETIME_OR_LABEL]? -When `continue` is encountered, the current iteration of the associated loop -body is immediately terminated, returning control to the loop *head*. In -the case of a `while` loop, the head is the conditional expression controlling -the loop. In the case of a `for` loop, the head is the call-expression -controlling the loop. +When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop *head*. +In the case of a `while` loop, the head is the conditional expression controlling the loop. +In the case of a `for` loop, the head is the call-expression controlling the loop. -Like `break`, `continue` is normally associated with the innermost enclosing -loop, but `continue 'label` may be used to specify the loop affected. +Like `break`, `continue` is normally associated with the innermost enclosing loop, but `continue 'label` may be used to specify the loop affected. A `continue` expression is only permitted in the body of a loop. ## `break` and loop values -When associated with a `loop`, a break expression may be used to return a value -from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where -`EXPR` is an expression whose result is returned from the `loop`. For example: +When associated with a `loop`, a break expression may be used to return a value from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where `EXPR` is an expression whose result is returned from the `loop`. +For example: ```rust let (mut a, mut b) = (1, 1); @@ -283,10 +257,8 @@ let result = loop { assert_eq!(result, 13); ``` -In the case a `loop` has an associated `break`, it is not considered diverging, -and the `loop` must have a type compatible with each `break` expression. -`break` without an expression is considered identical to `break` with -expression `()`. +In the case a `loop` has an associated `break`, it is not considered diverging, and the `loop` must have a type compatible with each `break` expression. +`break` without an expression is considered identical to `break` with expression `()`. [LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels [_BlockExpression_]: block-expr.md diff --git a/src/expressions/match-expr.md b/src/expressions/match-expr.md index 6d9f3f2af..c6181f7fb 100644 --- a/src/expressions/match-expr.md +++ b/src/expressions/match-expr.md @@ -23,26 +23,18 @@ > _MatchArmGuard_ :\ >    `if` [_Expression_] -A *`match` expression* branches on a pattern. The exact form of matching that -occurs depends on the [pattern]. A `match` -expression has a *[scrutinee] expression*, which is the value to compare to the -patterns. The scrutinee expression and the patterns must have the same type. - -A `match` behaves differently depending on whether or not the scrutinee -expression is a [place expression or value expression][place expression]. -If the scrutinee 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 scrutinee expression is a [place expression], the match does not -allocate a 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. +A *`match` expression* branches on a pattern. +The exact form of matching that occurs depends on the [pattern]. +A `match` expression has a *[scrutinee] expression*, which is the value to compare to the patterns. +The scrutinee expression and the patterns must have the same type. + +A `match` behaves differently depending on whether or not the scrutinee expression is a [place expression or value expression][place expression]. +If the scrutinee 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 scrutinee expression is a [place expression], the match does not allocate a 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. An example of a `match` expression: @@ -59,11 +51,11 @@ match x { } ``` -Variables bound within the pattern are scoped to the match guard and the arm's -expression. The [binding mode] (move, copy, or reference) depends on the pattern. +Variables bound within the pattern are scoped to the match guard and the arm's expression. +The [binding mode] (move, copy, or reference) depends on the pattern. -Multiple match patterns may be joined with the `|` operator. Each pattern will be -tested in left-to-right sequence until a successful match is found. +Multiple match patterns may be joined with the `|` operator. +Each pattern will be tested in left-to-right sequence until a successful match is found. ```rust let x = 9; @@ -84,23 +76,20 @@ match S(1, 2) { } ``` -> Note: The `2..=9` is a [Range Pattern], not a [Range Expression]. Thus, only -> those types of ranges supported by range patterns can be used in match arms. +> Note: The `2..=9` is a [Range Pattern], not a [Range Expression]. +> Thus, only those types of ranges supported by range patterns can be used in match arms. -Every binding in each `|` separated pattern must appear in all of the patterns -in the arm. Every binding of the same name must have the same type, and have -the same binding mode. +Every binding in each `|` separated pattern must appear in all of the patterns in the arm. +Every binding of the same name must have the same type, and have the same binding mode. ## Match guards -Match arms can accept _match guards_ to further refine the -criteria for matching a case. Pattern guards appear after the pattern and -consist of a `bool`-typed expression following the `if` keyword. +Match arms can accept _match guards_ to further refine the criteria for matching a case. +Pattern guards appear after the pattern and consist of a `bool`-typed expression following the `if` keyword. When the pattern matches successfully, the pattern guard expression is executed. If the expression evaluates to true, the pattern is successfully matched against. -Otherwise, the next pattern, including other matches with the `|` operator in -the same arm, is tested. +Otherwise, the next pattern, including other matches with the `|` operator in the same arm, is tested. ```rust # let maybe_digit = Some(0); @@ -113,8 +102,8 @@ let message = match maybe_digit { }; ``` -> Note: Multiple matches using the `|` operator can cause the pattern guard and -> the side effects it has to execute multiple times. For example: +> Note: Multiple matches using the `|` operator can cause the pattern guard and the side effects it has to execute multiple times. +> For example: > > ```rust > # use std::cell::Cell; @@ -127,23 +116,18 @@ let message = match maybe_digit { > ``` A pattern guard may refer to the variables bound within the pattern they follow. -Before evaluating the guard, a shared reference is taken to the part of the -scrutinee the variable matches on. While evaluating the guard, -this shared reference is then used when accessing the variable. -Only when the guard evaluates to true is the value moved, or copied, -from the scrutinee into the variable. This allows shared borrows to be used -inside guards without moving out of the scrutinee in case guard fails to match. -Moreover, by holding a shared reference while evaluating the guard, -mutation inside guards is also prevented. +Before evaluating the guard, a shared reference is taken to the part of the scrutinee the variable matches on. +While evaluating the guard, this shared reference is then used when accessing the variable. +Only when the guard evaluates to true is the value moved, or copied, from the scrutinee into the variable. +This allows shared borrows to be used inside guards without moving out of the scrutinee in case guard fails to match. +Moreover, by holding a shared reference while evaluating the guard, mutation inside guards is also prevented. ## Attributes on match arms -Outer attributes are allowed on match arms. The only attributes that have -meaning on match arms are [`cfg`], [`cold`], and the [lint check attributes]. +Outer attributes are allowed on match arms. +The only attributes that have meaning on match arms are [`cfg`], [`cold`], and the [lint check attributes]. -[Inner attributes] are allowed directly after the opening brace of the match -expression in the same expression contexts as [attributes on block -expressions]. +[Inner attributes] are allowed directly after the opening brace of the match expression in the same expression contexts as [attributes on block expressions]. [_Expression_]: ../expressions.md [place expression]: ../expressions.md#place-expressions-and-value-expressions diff --git a/src/expressions/method-call-expr.md b/src/expressions/method-call-expr.md index b6b139a52..5e7caa5e4 100644 --- a/src/expressions/method-call-expr.md +++ b/src/expressions/method-call-expr.md @@ -4,12 +4,8 @@ > _MethodCallExpression_ :\ >    [_Expression_] `.` [_PathExprSegment_] `(`[_CallParams_]? `)` -A _method call_ consists of an expression (the *receiver*) followed by a single -dot, an expression path segment, and a parenthesized expression-list. Method calls are -resolved to associated [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 object](../types/trait-object.md). +A _method call_ consists of an expression (the *receiver*) followed by a single dot, an expression path segment, and a parenthesized expression-list. +Method calls are resolved to associated [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 object](../types/trait-object.md). ```rust let pi: Result = "3.14".parse(); @@ -17,34 +13,25 @@ let log_pi = pi.unwrap_or(1.0).log(2.72); # assert!(1.14 < log_pi && log_pi < 1.15) ``` -When looking up a method call, the receiver may be automatically dereferenced or -borrowed in order to call a method. This requires a more complex lookup process -than for other functions, since there may be a number of possible methods to -call. The following procedure is used: +When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method. +This requires a more complex lookup process than for other functions, since there may be a number of possible methods to call. +The following procedure is used: -The first step is to build a list of candidate receiver types. Obtain -these by repeatedly [dereferencing][dereference] the receiver expression's type, -adding each type encountered to the list, then finally attempting an [unsized -coercion] at the end, and adding the result type if that is successful. Then, -for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`. +The first step is to build a list of candidate receiver types. +Obtain these by repeatedly [dereferencing][dereference] the receiver expression's type, adding each type encountered to the list, then finally attempting an [unsized coercion] at the end, and adding the result type if that is successful. +Then, for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`. -For instance, if the receiver has type `Box<[i32;2]>`, then the candidate types -will be `Box<[i32;2]>`, `&Box<[i32;2]>`, `&mut Box<[i32;2]>`, `[i32; 2]` (by -dereferencing), `&[i32; 2]`, `&mut [i32; 2]`, `[i32]` (by unsized coercion), -`&[i32]`, and finally `&mut [i32]`. +For instance, if the receiver has type `Box<[i32;2]>`, then the candidate types will be `Box<[i32;2]>`, `&Box<[i32;2]>`, `&mut Box<[i32;2]>`, `[i32; 2]` (by dereferencing), `&[i32; 2]`, `&mut [i32; 2]`, `[i32]` (by unsized coercion), `&[i32]`, and finally `&mut [i32]`. -Then, for each candidate type `T`, search for a [visible] method with -a receiver of that type in the following places: +Then, for each candidate type `T`, search for a [visible] method with a receiver of that type in the following places: 1. `T`'s inherent methods (methods implemented directly on `T`). -1. Any of the methods provided by a [visible] trait implemented by `T`. If `T` - is a type parameter, methods provided by trait bounds on `T` are looked up - first. Then all remaining methods in scope are looked up. - -> Note: the lookup is done for each type in order, which can occasionally lead -> to surprising results. The below code will print "In trait impl!", because -> `&self` methods are looked up first, the trait method is found before the -> struct's `&mut self` method is found. +1. Any of the methods provided by a [visible] trait implemented by `T`. + If `T` is a type parameter, methods provided by trait bounds on `T` are looked up first. + Then all remaining methods in scope are looked up. + +> Note: the lookup is done for each type in order, which can occasionally lead to surprising results. +> The below code will print "In trait impl!", because `&self` methods are looked up first, the trait method is found before the struct's `&mut self` method is found. > > ```rust > struct Foo {} @@ -71,29 +58,20 @@ a receiver of that type in the following places: > } > ``` -If this results in multiple possible candidates, then it is an error, and the -receiver must be [converted][disambiguate call] to an appropriate receiver type -to make the method call. +If this results in multiple possible candidates, then it is an error, and the receiver must be [converted][disambiguate call] to an appropriate receiver type to make the method call. -This process does not take into account the mutability or lifetime of the -receiver, or whether a method is `unsafe`. Once a method is looked up, if it -can't be called for one (or more) of those reasons, the result is a compiler -error. +This process does not take into account the mutability or lifetime of the receiver, or whether a method is `unsafe`. +Once a method is looked up, if it can't be called for one (or more) of those reasons, the result is a compiler error. -If a step is reached where there is more than one possible method, such as where -generic methods or traits are considered the same, then it is a compiler -error. These cases require a [disambiguating function call syntax] for method -and function invocation. +If a step is reached where there is more than one possible method, such as where generic methods or traits are considered the same, then it is a compiler error. +These cases require a [disambiguating function call syntax] for method and function invocation.
-***Warning:*** For [trait objects], if there is an inherent method of the same -name as a trait method, it will give a compiler error when trying to call the -method in a method call expression. Instead, you can call the method using -[disambiguating function call syntax], in which case it calls the trait -method, not the inherent method. There is no way to call the inherent method. -Just don't define inherent methods on trait objects with the same name a trait -method and you'll be fine. +***Warning:*** For [trait objects], if there is an inherent method of the same name as a trait method, it will give a compiler error when trying to call the method in a method call expression. +Instead, you can call the method using [disambiguating function call syntax], in which case it calls the trait method, not the inherent method. +There is no way to call the inherent method. +Just don't define inherent methods on trait objects with the same name a trait method and you'll be fine.
diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index ebd9c8b0c..73284bb78 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -13,24 +13,19 @@ >    | [_AssignmentExpression_]\ >    | [_CompoundAssignmentExpression_] -Operators are defined for built in types by the Rust language. Many of the -following operators can also be overloaded using traits in `std::ops` or -`std::cmp`. +Operators are defined for built in types by the Rust language. +Many of the following operators can also be overloaded using traits in `std::ops` or `std::cmp`. ## Overflow Integer operators will panic when they overflow when compiled in debug mode. -The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used -to control this more directly. The following things are considered to be -overflow: - -* When `+`, `*` or `-` create a value greater than the maximum value, or less - than the minimum value that can be stored. This includes unary `-` on the - smallest value of any signed integer type. -* Using `/` or `%`, where the left-hand argument is the smallest integer of a - signed integer type and the right-hand argument is `-1`. -* Using `<<` or `>>` where the right-hand argument is greater than or equal to - the number of bits in the type of the left-hand argument, or is negative. +The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used to control this more directly. +The following things are considered to be overflow: + +* When `+`, `*` or `-` create a value greater than the maximum value, or less than the minimum value that can be stored. + This includes unary `-` on the smallest value of any signed integer type. +* Using `/` or `%`, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is `-1`. +* Using `<<` or `>>` where the right-hand argument is greater than or equal to the number of bits in the type of the left-hand argument, or is negative. ## Borrow operators @@ -39,15 +34,13 @@ overflow: >       (`&`|`&&`) [_Expression_]\ >    | (`&`|`&&`) `mut` [_Expression_] -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 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. +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 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. @@ -64,8 +57,7 @@ let mut array = [-2, 3, 9]; } ``` -Even though `&&` is a single token ([the lazy 'and' operator](#lazy-boolean-operators)), -when used in the context of borrow expressions it works as two borrows: +Even though `&&` is a single token ([the lazy 'and' operator](#lazy-boolean-operators)), when used in the context of borrow expressions it works as two borrows: ```rust // same meanings: @@ -84,16 +76,12 @@ let a = & & & & mut 10; > _DereferenceExpression_ :\ >    `*` [_Expression_] -The `*` (dereference) operator is also a unary prefix operator. When applied to -a [pointer](../types/pointer.md) it denotes the pointed-to location. If -the expression is of type `&mut T` or `*mut T`, and is either a local -variable, a (nested) field of a local variable or is a mutable [place -expression], then the resulting memory location can be assigned to. +The `*` (dereference) operator is also a unary prefix operator. +When applied to a [pointer](../types/pointer.md) it denotes the pointed-to location. +If the expression is of type `&mut T` or `*mut T`, and is either a local variable, a (nested) field of a local variable or is a mutable [place 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.md#mutability) and -`*std::ops::DerefMut::deref_mut(&mut x)` in a mutable place expression context. +On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an [immutable place expression context](../expressions.md#mutability) and `*std::ops::DerefMut::deref_mut(&mut x)` in a mutable place expression context. ```rust let x = &7; @@ -109,14 +97,12 @@ assert_eq!(*y, 11); > _ErrorPropagationExpression_ :\ >    [_Expression_] `?` -The question mark operator (`?`) unwraps valid values or returns erroneous -values, propagating them to the calling function. It is a unary postfix -operator that can only be applied to the types `Result` and `Option`. +The question mark operator (`?`) unwraps valid values or returns erroneous values, propagating them to the calling function. +It is a unary postfix operator that can only be applied to the types `Result` and `Option`. -When applied to values of the `Result` type, it propagates errors. If -the value is `Err(e)`, then it will return `Err(From::from(e))` from the -enclosing function or closure. If applied to `Ok(x)`, then it will unwrap the -value to evaluate to `x`. +When applied to values of the `Result` type, it propagates errors. +If the value is `Err(e)`, then it will return `Err(From::from(e))` from the enclosing function or closure. +If applied to `Ok(x)`, then it will unwrap the value to evaluate to `x`. ```rust # use std::num::ParseIntError; @@ -131,9 +117,9 @@ println!("{:?}", res); # assert!(res.is_err()) ``` -When applied to values of the `Option` type, it propagates `None`s. If the -value is `None`, then it will return `None`. If applied to `Some(x)`, then it -will unwrap the value to evaluate to `x`. +When applied to values of the `Option` type, it propagates `None`s. +If the value is `None`, then it will return `None`. +If applied to `Some(x)`, then it will unwrap the value to evaluate to `x`. ```rust fn try_option_some() -> Option { @@ -158,11 +144,10 @@ assert_eq!(try_option_none(), None); >       `-` [_Expression_]\ >    | `!` [_Expression_] -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 -[value expression context][value expression] so are moved or copied. +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 [value expression context][value expression] so are moved or copied. | Symbol | Integer | `bool` | Floating Point | Overloading Trait | |--------|-------------|-------------- |----------------|--------------------| @@ -195,12 +180,10 @@ assert_eq!(true, !false); >    | [_Expression_] `<<` [_Expression_]\ >    | [_Expression_] `>>` [_Expression_] -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 [value -expression context][value expression] so are moved or copied. +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 [value expression context][value expression] so are moved or copied. | Symbol | Integer | `bool` | Floating Point | Overloading Trait | Overloading Compound Assignment Trait | |--------|-------------------------|---------------|----------------|--------------------| ------------------------------------- | @@ -246,18 +229,12 @@ assert_eq!(-10 >> 2, -3); >    | [_Expression_] `>=` [_Expression_]\ >    | [_Expression_] `<=` [_Expression_] -Comparison operators are also defined both for primitive types and many types -in the standard library. Parentheses are required when chaining comparison -operators. For example, the expression `a == b == c` is invalid and may be -written as `(a == b) == c`. +Comparison operators are also defined both for primitive types and many types in the standard library. +Parentheses are required when chaining comparison operators. For example, the expression `a == b == c` is invalid and may be written as `(a == b) == c`. -Unlike arithmetic and logical operators, the traits for overloading these -operators are used more generally to show how a type may be compared and will -likely be assumed to 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 [place expression context][place expression]: +Unlike arithmetic and logical operators, the traits for overloading these operators are used more generally to show how a type may be compared and will likely be assumed to 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 [place expression context][place expression]: ```rust # let a = 1; @@ -296,13 +273,10 @@ assert!("World" >= "Hello"); >       [_Expression_] `||` [_Expression_]\ >    | [_Expression_] `&&` [_Expression_] -The operators `||` and `&&` may be applied to operands of boolean type. The -`||` operator denotes logical 'or', and the `&&` operator denotes logical -'and'. They differ from `|` and `&` in that the right-hand operand is only -evaluated when the left-hand operand does not already determine the result of -the expression. That is, `||` only evaluates its right-hand operand when the -left-hand operand evaluates to `false`, and `&&` only when it evaluates to -`true`. +The operators `||` and `&&` may be applied to operands of boolean type. +The `||` operator denotes logical 'or', and the `&&` operator denotes logical 'and'. +They differ from `|` and `&` in that the right-hand operand is only evaluated when the left-hand operand does not already determine the result of the expression. +That is, `||` only evaluates its right-hand operand when the left-hand operand evaluates to `false`, and `&&` only when it evaluates to `true`. ```rust let x = false || true; // true @@ -317,8 +291,7 @@ let y = false && panic!(); // false, doesn't evaluate `panic!()` A type cast expression is denoted with the binary operator `as`. -Executing an `as` expression casts the value on the left-hand side to the type -on the right-hand side. +Executing an `as` expression casts the value on the left-hand side to the type on the right-hand side. An example of an `as` expression: @@ -332,9 +305,8 @@ fn average(values: &[f64]) -> f64 { } ``` -`as` can be used to explicitly perform [coercions](../type-coercions.md), as -well as the following additional casts. Here `*T` means either `*const T` or -`*mut T`. +`as` can be used to explicitly perform [coercions](../type-coercions.md), as well as the following additional casts. +Here `*T` means either `*const T` or `*mut T`. | Type of `e` | `U` | Cast performed by `e as U` | |-----------------------|-----------------------|----------------------------------| @@ -353,8 +325,7 @@ well as the following additional casts. Here `*T` means either `*const T` or | [Function pointer] | Integer | Function pointer to address cast | | Closure \*\* | Function pointer | Closure to function pointer cast | -\* or `T` and `V` are compatible unsized types, e.g., both slices, both the -same trait object. +\* or `T` and `V` are compatible unsized types, e.g., both slices, both the same trait object. \*\* only for closures that do not capture (close over) any local variables @@ -410,25 +381,18 @@ halfway between two floating point numbers. 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*. +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. +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. +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. +> **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. +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]. @@ -455,8 +419,7 @@ x = y; >    | [_Expression_] `<<=` [_Expression_]\ >    | [_Expression_] `>>=` [_Expression_] -*Compound assignment expressions* combine arithmetic and logical binary -operators with assignment expressions. +*Compound assignment expressions* combine arithmetic and logical binary operators with assignment expressions. For example: @@ -466,28 +429,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 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. +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. +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 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. -> **Note**: This is different than other expressions in that the right operand -> is evaluated before the left one. +> **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. +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. For example, the following expression statements in `example` are equivalent: @@ -511,12 +466,10 @@ fn example() {
-Warning: The evaluation order of operands swaps depending on the types of the -operands: with primitive types the right-hand side will get evaluated first, -while with non-primitive types the left-hand side will get evaluated first. -Try not to write code that depends on the evaluation order of operands in -compound assignment expressions. See [this test] for an example of using this -dependency. +Warning: The evaluation order of operands swaps depending on the types of the operands: +with primitive types the right-hand side will get evaluated first, while with non-primitive types the left-hand side will get evaluated first. +Try not to write code that depends on the evaluation order of operands in compound assignment expressions. +See [this test] for an example of using this dependency.
diff --git a/src/expressions/path-expr.md b/src/expressions/path-expr.md index 84278da96..0909c5ddb 100644 --- a/src/expressions/path-expr.md +++ b/src/expressions/path-expr.md @@ -5,10 +5,9 @@ >       [_PathInExpression_]\ >    | [_QualifiedPathInExpression_] -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 [place expressions], other paths are [value expressions]. Using a -[`static mut`] variable requires an [`unsafe` block]. +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 [place expressions], other paths are [value expressions]. +Using a [`static mut`] variable requires an [`unsafe` block]. ```rust # mod globals { diff --git a/src/expressions/range-expr.md b/src/expressions/range-expr.md index f46c45dce..37409a4cf 100644 --- a/src/expressions/range-expr.md +++ b/src/expressions/range-expr.md @@ -27,9 +27,7 @@ > _RangeToInclusiveExpr_ :\ >    `..=` [_Expression_] -The `..` and `..=` operators will construct an object of one of the -`std::ops::Range` (or `core::ops::Range`) variants, according to the following -table: +The `..` and `..=` operators will construct an object of one of the `std::ops::Range` (or `core::ops::Range`) variants, according to the following table: | Production | Syntax | Type | Range | |------------------------|---------------|------------------------------|-----------------------| diff --git a/src/expressions/return-expr.md b/src/expressions/return-expr.md index 1146b6e4f..b1b3787d8 100644 --- a/src/expressions/return-expr.md +++ b/src/expressions/return-expr.md @@ -4,10 +4,8 @@ > _ReturnExpression_ :\ >    `return` [_Expression_]? -Return expressions are denoted with the keyword `return`. Evaluating a `return` -expression moves its argument into the designated output location for the -current function call, destroys the current function activation frame, and -transfers control to the caller frame. +Return expressions are denoted with the keyword `return`. +Evaluating a `return` expression moves its argument into the designated output location for the current function call, destroys the current function activation frame, and transfers control to the caller frame. An example of a `return` expression: diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md index a56d0c7de..40708d98d 100644 --- a/src/expressions/struct-expr.md +++ b/src/expressions/struct-expr.md @@ -27,9 +27,9 @@ > > _StructExprUnit_ : [_PathInExpression_] -A _struct expression_ creates a struct or union value. It consists of a path to a [struct] -or [union] item followed by the values for the fields of the item. There are three forms -of struct expressions: struct, tuple, and unit. +A _struct expression_ creates a struct or union value. +It consists of a path to a [struct] or [union] item followed by the values for the fields of the item. +There are three forms of struct expressions: struct, tuple, and unit. The following are examples of struct expressions: @@ -49,23 +49,18 @@ some_fn::(Cookie); ## Field struct expression -A struct expression with fields enclosed in curly braces allows you to specify the value -for each individual field in any order. The field name is separated from its value with a -colon. +A struct expression with fields enclosed in curly braces allows you to specify the value for each individual field in any order. +The field name is separated from its value with a colon. -A value of a [union] type can also be created using this syntax, except that it must -specify exactly one field. +A value of a [union] type can also be created using this syntax, except that it must specify exactly one field. ## Functional update syntax -A struct expression can terminate with the syntax `..` followed by an -expression to denote a functional update. The expression following `..` (the -base) must have the same struct type as the new struct type being formed. +A struct expression can terminate with the syntax `..` followed by an expression to denote a functional update. +The expression following `..` (the base) must have the same struct type as the new struct type being formed. -The entire expression uses the given values for the fields that were specified -and moves or copies the remaining fields from the base expression. As with all -struct expressions, all of the fields of the struct must be [visible], even -those not explicitly named. +The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression. +As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named. ```rust # struct Point3d { x: i32, y: i32, z: i32 } @@ -75,14 +70,11 @@ Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed drop(y_ref); ``` -Struct expressions with curly braces can't be used directly in a [loop] or [if] -expression's head, or in the [scrutinee] of an [if let] or [match] expression. -However, struct expressions can be in used in these situations if they are -within another expression, for example inside [parentheses]. +Struct expressions with curly braces can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression. +However, struct expressions can be in used in these situations if they are within another expression, for example inside [parentheses]. -The field names can be decimal integer values to specify indices for constructing tuple -structs. This can be used with base structs to fill out the remaining indices not -specified: +The field names can be decimal integer values to specify indices for constructing tuple structs. +This can be used with base structs to fill out the remaining indices not specified: ```rust struct Color(u8, u8, u8); @@ -93,9 +85,8 @@ let c3 = Color{1: 0, ..c2}; // Fill out all other fields using a base struct. ### Struct field init shorthand -When initializing a data structure (struct, enum, union) with named (but not -numbered) fields, it is allowed to write `fieldname` as a shorthand for -`fieldname: fieldname`. This allows a compact syntax with less duplication. +When initializing a data structure (struct, enum, union) with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. +This allows a compact syntax with less duplication. For example: ```rust @@ -109,9 +100,8 @@ Point3d { x, y: y_value, z }; ## Tuple struct expression -A struct expression with fields enclosed in parentheses constructs a tuple struct. Though -it is listed here as a specific expression for completeness, it is equivalent to a [call -expression] to the tuple struct's constructor. For example: +A struct expression with fields enclosed in parentheses constructs a tuple struct. +Though it is listed here as a specific expression for completeness, it is equivalent to a [call expression] to the tuple struct's constructor. For example: ```rust struct Position(i32, i32, i32); @@ -122,9 +112,9 @@ let pos = c(8, 6, 7); // Creates a `Position` value. ## Unit struct expression -A unit struct expression is just the path to a unit struct item. This refers to the unit -struct's implicit constant of its value. The unit struct value can also be constructed -with a fieldless struct expression. For example: +A unit struct expression is just the path to a unit struct item. +This refers to the unit struct's implicit constant of its value. +The unit struct value can also be constructed with a fieldless struct expression. For example: ```rust struct Gamma; @@ -134,9 +124,7 @@ let b = Gamma{}; // Exact same value as `a`. ## Struct expression attributes -[Inner attributes] are allowed directly after the opening brace or parenthesis -of a struct expression in the same expression contexts as [attributes on block -expressions]. +[Inner attributes] are allowed directly after the opening brace or parenthesis of a struct expression in the same expression contexts as [attributes on block expressions]. [IDENTIFIER]: ../identifiers.md [Inner attributes]: ../attributes.md diff --git a/src/expressions/tuple-expr.md b/src/expressions/tuple-expr.md index cd1deb330..ef0576113 100644 --- a/src/expressions/tuple-expr.md +++ b/src/expressions/tuple-expr.md @@ -9,19 +9,14 @@ > _TupleElements_ :\ >    ( [_Expression_] `,` )+ [_Expression_]? -Tuple expressions evaluate into [tuple values][tuple type] with the operands -initializing the elements of the tuple. +Tuple expressions evaluate into [tuple values][tuple type] with the operands initializing the elements of the tuple. -Tuple expressions are written by listing the [operands] in a parenthesized, -comma-separated list. 1-ary tuple expressions require a comma after their -operand to be disambiguated with a [parenthetical expression]. +Tuple expressions are written by listing the [operands] in a parenthesized, comma-separated list. 1-ary tuple expressions require a comma after their operand to be disambiguated with a [parenthetical expression]. -The number of operands is the arity of the constructed tuple. Tuple expressions -without operands produce the unit tuple. For other tuple expressions, the first -written operand initializes the 0th element and subsequent operands initializes -the next highest element. For example, in the tuple expression -`('a', 'b', 'c')`, `'a'` initializes the value of the 0th element, `'b'` the -1st, and `'c'` the 2nd. +The number of operands is the arity of the constructed tuple. +Tuple expressions without operands produce the unit tuple. +For other tuple expressions, the first written operand initializes the 0th element and subsequent operands initializes the next highest element. +For example, in the tuple expression `('a', 'b', 'c')`, `'a'` initializes the value of the 0th element, `'b'` the 1st, and `'c'` the 2nd. Examples of tuple expressions: @@ -34,9 +29,7 @@ Examples of tuple expressions: ### Tuple expression attributes -[Inner attributes] are allowed directly after the opening parenthesis of a -tuple expression in the same expression contexts as [attributes on block -expressions]. +[Inner attributes] are allowed directly after the opening parenthesis of a tuple expression in the same expression contexts as [attributes on block expressions]. ## Tuple indexing expressions @@ -44,14 +37,12 @@ expressions]. > _TupleIndexingExpression_ :\ >    [_Expression_] `.` [TUPLE_INDEX] -Tuple indexing expressions evaluate like [field access expressions], but access -elements of [tuples][tuple type] or [tuple structs]. +Tuple indexing expressions evaluate like [field access expressions], but access elements of [tuples][tuple type] or [tuple structs]. -Tuple index expressions are written as an operand, `.`, and a tuple index. The -index must be written as a [decimal literal] with no leading zeros, underscores, -or suffix. The operand must have the type of a tuple or tuple struct. If the -tuple index is not an element of the tuple or tuple struct, it is a compiler -error. +Tuple index expressions are written as an operand, `.`, and a tuple index. +The index must be written as a [decimal literal] with no leading zeros, underscores, or suffix. +The operand must have the type of a tuple or tuple struct. +If the tuple index is not an element of the tuple or tuple struct, it is a compiler error. Examples of tuple indexing expressions: @@ -65,9 +56,7 @@ assert_eq!(point.0, 1.0); assert_eq!(point.1, 0.0); ``` -> **Note**: Unlike field access expressions, tuple index expressions can be the -> function operand of a [call expression] as it cannot be confused with a -> method call since method names cannot be numbers. +> **Note**: Unlike field access expressions, tuple index expressions can be the function operand of a [call expression] as it cannot be confused with a method call since method names cannot be numbers. [_Expression_]: ../expressions.md [_InnerAttribute_]: ../attributes.md