Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One sentence is one line src/expressions/* #962

Merged
merged 1 commit into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 18 additions & 32 deletions src/expressions/array-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,22 @@
> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] ( `,` [_Expression_] )<sup>\*</sup> `,`<sup>?</sup>\
> &nbsp;&nbsp; | [_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.

<div class="warning">

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).

</div>

Expand All @@ -47,30 +41,23 @@ const EMPTY: Vec<i32> = 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

> **<sup>Syntax</sup>**\
> _IndexExpression_ :\
> &nbsp;&nbsp; [_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.
Expand All @@ -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
Expand Down
37 changes: 12 additions & 25 deletions src/expressions/await-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,17 @@
> _AwaitExpression_ :\
> &nbsp;&nbsp; [_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 `<expr>.await` expression has the following effect.

1. Evaluate `<expr>` 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
Expand All @@ -33,23 +26,19 @@ More specifically, an `<expr>.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 `<expr>.await` expression is roughly
equivalent to the following (this desugaring is not normative):
Effectively, an `<expr>.await` expression is roughly equivalent to the following (this desugaring is not normative):

<!-- ignore: example expansion -->
```rust,ignore
Expand All @@ -64,7 +53,5 @@ match /* <expr> */ {
}
```

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.
104 changes: 39 additions & 65 deletions src/expressions/block-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,20 @@
> &nbsp;&nbsp; | [_Statement_]<sup>\+</sup> [_ExpressionWithoutBlock_]\
> &nbsp;&nbsp; | [_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() {}
Expand All @@ -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;
Expand All @@ -83,20 +72,15 @@ fn move_by_block_expression() {
> _AsyncBlockExpression_ :\
> &nbsp;&nbsp; `async` `move`<sup>?</sup> _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.

Expand All @@ -105,37 +89,30 @@ 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-
[mutable reference]: ../types/pointer.md#mutables-references-

### 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 <expr>` from within a closure will return
the result of `<expr>` as the output of the future. Similarly, if
`<expr>?` 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 <expr>` from within a closure will return the result of `<expr>` as the output of the future.
Similarly, if `<expr>?` 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 {
Expand All @@ -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 {
Expand All @@ -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`]).
Expand All @@ -181,11 +157,9 @@ expression in the following situations:
* A block expression as the tail expression of another block expression.
<!-- Keep list in sync with expressions.md -->

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 {
Expand Down
Loading