You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Use "the syntax of" uniformly.
* Use asterisks for all defined terms.
* Define more terms, espcially in the syntax section.
** Reword things so that definitions are generally first.
** I did not necessarily go with the best wording; the idea is to
improve, not perfect. I still need to dedicate time to each
expressions individually.
* Remove usage of "the compiler" and "Rust".
** This also involved rewording.
** How to deal with closure types and closure expressions is gonna be
an interesting question to solve. I avoided solving it here.
* Remove non-normative information or put them in a `Note`.
* A few added section headers
* Move links to the bottom
Note that I've left quite a few nonsensical statements alone, such as
any that use "denote". They'll be treated separately.
About halfway through the list of expressions and this PR is getting
large. So I'm gonna cut this one here, stopping at grouped expressions
in the alphabetical list.
An _[array] expression_ can be written by enclosing zero or more comma-separated expressions of uniform type in square brackets.
13
+
*Array expressions* construct [arrays][array].
14
+
Array expressions come in two forms.
15
+
16
+
The first form lists out every value in the array.
17
+
The syntax for this form is a comma-separated list of operands of uniform type enclosed in square brackets.
14
18
This produces an array containing each of these values in the order they are written.
15
19
16
-
Alternatively there can be exactly two expressions inside the brackets, separated by a semicolon.
17
-
The expression after the `;` must have type `usize` and be a [constant expression], such as a [literal] or a [constant item].
20
+
The syntax for the second form is two operands separated by a semicolon (`;`) enclosed in square brackets.
21
+
The operand after the `;` must have type `usize` and be a [constant expression], such as a [literal] or a [constant item].
18
22
`[a; b]` creates an array containing `b` copies of the value of `a`.
19
-
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.
23
+
If the operand 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.
20
24
21
-
When the repeat expression `a` is a constant item, it is evaluated `b` times.
25
+
When the repeat expression,`a`, is a constant item, it is evaluated `b` times.
22
26
If `b` is 0, the constant item is not evaluated at all.
23
27
For expressions that are not a constant item, it is evaluated exactly once, and then the result is copied `b` times.
[Array] and [slice]-typed expressions can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them.
56
+
[Array] and [slice]-typed values can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them.
53
57
When the array is mutable, the resulting [memory location] can be assigned to.
54
58
55
59
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.
Copy file name to clipboardExpand all lines: src/expressions/await-expr.md
+14-16
Original file line number
Diff line number
Diff line change
@@ -4,9 +4,9 @@
4
4
> _AwaitExpression_ :\
5
5
> [_Expression_]`.``await`
6
6
7
+
*Await expressions* suspend the current computation until the given future is ready to produce a value.
8
+
The syntax for an await expression is an operand with a type that implements the Future trait, `.`, and then the `await` keyword.
7
9
Await expressions are legal only within an [async context], like an [`async fn`] or an [`async` block].
8
-
They operate on a [future].
9
-
Their effect is to suspend the current computation until the given future is ready to produce a value.
10
10
11
11
More specifically, an `<expr>.await` expression has the following effect.
12
12
@@ -16,29 +16,16 @@ More specifically, an `<expr>.await` expression has the following effect.
16
16
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;
17
17
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.
Copy file name to clipboardExpand all lines: src/expressions/block-expr.md
+35-34
Original file line number
Diff line number
Diff line change
@@ -16,10 +16,12 @@ A *block expression*, or *block*, is a control flow expression and anonymous nam
16
16
As a control flow expression, a block sequentially executes its component non-item declaration statements and then its final optional expression.
17
17
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.
18
18
19
-
Blocks are written as `{`, then any [inner attributes], then [statements], then an optional expression, and finally a `}`.
20
-
Statements are usually required to be followed by a semicolon, with two exceptions.
21
-
Item declaration statements do not need to be followed by a semicolon.
22
-
Expression statements usually require a following semicolon except if its outer expression is a flow control expression.
19
+
The syntax for a block is `{`, then any [inner attributes], then [statements], then an optional operand, and finally a `}`.
20
+
21
+
Statements are usually required to be followed by a semicolon, with two exceptions:
22
+
23
+
1. Item declaration statements do not need to be followed by a semicolon.
24
+
2. Expression statements usually require a following semicolon except if its outer expression is a flow control expression.
23
25
Furthermore, extra semicolons between statements are allowed, but these semicolons do not affect semantics.
24
26
25
27
When evaluating a block expression, each statement, except for item declaration statements, is executed sequentially.
@@ -43,36 +45,38 @@ assert_eq!(5, five);
43
45
44
46
> 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.
45
47
46
-
Blocks are always [value expressions] and evaluate the last expression in value expression context.
47
-
This can be used to force moving a value if really needed.
48
-
For example, the following example fails on the call to `consume_self` because the struct was moved out of `s` in the block expression.
48
+
Blocks are always [value expressions] and evaluate the last operand in value expression context.
49
49
50
-
```rust,compile_fail
51
-
struct Struct;
52
-
53
-
impl Struct {
54
-
fn consume_self(self) {}
55
-
fn borrow_self(&self) {}
56
-
}
57
50
58
-
fn move_by_block_expression() {
59
-
let s = Struct;
60
-
61
-
// Move the value out of `s` in the block expression.
62
-
(&{ s }).borrow_self();
63
-
64
-
// Fails to execute because `s` is moved out of.
65
-
s.consume_self();
66
-
}
67
-
```
51
+
> **Note**: This can be used to force moving a value if really needed.
52
+
> For example, the following example fails on the call to `consume_self` because the struct was moved out of `s` in the block expression.
53
+
>
54
+
> ```rust,compile_fail
55
+
> struct Struct;
56
+
>
57
+
> impl Struct {
58
+
> fn consume_self(self) {}
59
+
> fn borrow_self(&self) {}
60
+
> }
61
+
>
62
+
> fn move_by_block_expression() {
63
+
> let s = Struct;
64
+
>
65
+
> // Move the value out of `s` in the block expression.
66
+
> (&{ s }).borrow_self();
67
+
>
68
+
> // Fails to execute because `s` is moved out of.
A _call expression_ consists of an expression followed by a parenthesized expression-list.
11
-
It invokes a function, providing zero or more input variables.
10
+
A *call expression* calls a function.
11
+
The syntax of a call expression is an operand, the *function operand*, followed by a parenthesized comma-separated list of operands, the *argument operands*.
12
12
If the function eventually returns, then the expression completes.
13
13
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.
14
14
An automatic borrow will be taken if needed.
15
-
Rust will also automatically dereference `f` as required.
15
+
`f` will also be automatically dereferences as required.
Rust treats all function calls as sugar for a more explicit,[fully-qualified syntax].
27
+
All function calls are sugar for a more explicit [fully-qualified syntax].
27
28
Upon compilation, Rust will desugar all function calls into the explicit form.
28
29
Rust may sometimes require you to qualify function calls with trait, depending on the ambiguity of a call in light of in-scope items.
29
30
30
-
> **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.
31
-
> However, the term lacks descriptive power and potentially confuses the issue at hand.
32
-
> We mention it here for searchability's sake.
31
+
> **Note**: In the past, the terms "Unambiguous Function Call Syntax", "Universal Function Call Syntax", or "UFCS", have been used in documentation, issues, RFCs, and other community writings.
32
+
> However, these terms lack descriptive power and potentially confuse the issue at hand.
33
+
> We mention them here for searchability's sake.
33
34
34
35
Several situations often occur which result in ambiguities about the receiver or referent of method or associated function calls.
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.
16
-
A closure expression is a pipe-symbol-delimited (`|`) list of irrefutable [patterns] followed by an expression.
17
-
Type annotations may optionally be added for the type of the parameters or for the return type.
18
-
If there is a return type, the expression used for the body of the closure must be a normal [block].
19
-
A closure expression also may begin with the `move` keyword before the initial `|`.
15
+
A *closure expression*, also know as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type.
16
+
The syntax for a closure expression is an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, the *return type*, and then an operand, the *closure body*.
17
+
The optional type after each pattern is a type annotation for the pattern.
18
+
If there is a return type, the closure body must be a [block].
20
19
21
20
A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters.
22
-
Just like a [`let` binding], the parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given.
21
+
Just like a [`let` binding], the closure parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given.
23
22
Each closure expression has a unique, anonymous type.
24
23
25
-
Closure expressions are most useful when passing functions as arguments to other functions, as an abbreviation for defining and capturing a separate function.
26
-
27
24
Significantly, closure expressions _capture their environment_, which regular [function definitions] do not.
28
25
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.
29
26
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.
30
27
A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword.
31
-
This is often used to ensure that the closure's type is `'static`.
28
+
This is often used to ensure that the closure's lifetime is `'static`.
29
+
30
+
## Closure trait implementations
31
+
32
+
Which traits the closure type implement depends on how variables are captured and the types of the captured variables.
33
+
See the [call traits and coercions] chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`.
34
+
The closure type implements [`Send`] and [`Sync`] if the type of every captured variable also implements the trait.
32
35
33
-
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.
34
-
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.
35
-
These traits allow functions to accept closures using generics, even though the exact types can't be named.
36
+
## Example
36
37
37
38
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.
38
39
@@ -55,15 +56,18 @@ ten_times(move |j| println!("{}, {}", word, j));
55
56
56
57
Attributes on closure parameters follow the same rules and restrictions as [regular function parameters].
57
58
58
-
[block]: block-expr.md
59
-
[function definitions]: ../items/functions.md
60
-
[patterns]: ../patterns.md
61
-
[regular function parameters]: ../items/functions.md#attributes-on-function-parameters
62
-
63
59
[_Expression_]: ../expressions.md
64
60
[_BlockExpression_]: block-expr.md
65
61
[_TypeNoBounds_]: ../types.md#type-expressions
66
62
[_Pattern_]: ../patterns.md
67
63
[_Type_]: ../types.md#type-expressions
68
64
[`let` binding]: ../statements.md#let-statements
65
+
[`Send`]: ../special-types-and-traits.md#send
66
+
[`Sync`]: ../special-types-and-traits.md#sync
69
67
[_OuterAttribute_]: ../attributes.md
68
+
[block]: block-expr.md
69
+
[call traits and coercions]: ../types/closure.md#call-traits-and-coercions
70
+
[closure type]: ../types/closure.md
71
+
[function definitions]: ../items/functions.md
72
+
[patterns]: ../patterns.md
73
+
[regular function parameters]: ../items/functions.md#attributes-on-function-parameters
0 commit comments