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 line one sentence for expressions and statements main chapters #1277

Merged
merged 3 commits into from
Oct 5, 2022
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
137 changes: 52 additions & 85 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,24 @@
>       | [_MatchExpression_]\
>    )

An expression may have two roles: it always produces a *value*, and it may have
*effects* (otherwise known as "side effects"). An expression *evaluates to* a
value, and has effects during *evaluation*. Many expressions contain
sub-expressions, called the *operands* of the expression. The meaning of each
kind of expression dictates several things:
An expression may have two roles: it always produces a *value*, and it may have *effects* (otherwise known as "side effects").
An expression *evaluates to* a value, and has effects during *evaluation*.
Many expressions contain sub-expressions, called the *operands* of the expression.
The meaning of each kind of expression dictates several things:

* Whether or not to evaluate the operands when evaluating the expression
* The order in which to evaluate the operands
* How to combine the operands' values to obtain the value of the expression

In this way, the structure of expressions dictates the structure of execution.
Blocks are just another kind of expression, so blocks, statements, expressions,
and blocks again can recursively nest inside each other to an arbitrary depth.
Blocks are just another kind of expression, so blocks, statements, expressions, and blocks again can recursively nest inside each other to an arbitrary depth.

> **Note**: We give names to the operands of expressions so that we may discuss
> them, but these names are not stable and may be changed.
> **Note**: We give names to the operands of expressions so that we may discuss them, but these names are not stable and may be changed.

## Expression precedence

The precedence of Rust operators and expressions is ordered as follows, going
from strong to weak. Binary Operators at the same precedence level are grouped
in the order given by their associativity.
The precedence of Rust operators and expressions is ordered as follows, going from strong to weak.
Binary Operators at the same precedence level are grouped in the order given by their associativity.

| Operator/Expression | Associativity |
|-----------------------------|---------------------|
Expand All @@ -89,9 +85,8 @@ in the order given by their associativity.

## Evaluation order of operands

The following list of expressions all evaluate their operands the same way, as
described after the list. Other expressions either don't take operands or
evaluate them conditionally as described on their respective pages.
The following list of expressions all evaluate their operands the same way, as described after the list.
Other expressions either don't take operands or evaluate them conditionally as described on their respective pages.

* Dereference expression
* Error propagation expression
Expand All @@ -113,15 +108,13 @@ evaluate them conditionally as described on their respective pages.
* Range expression
* Return expression

The operands of these expressions are evaluated prior to applying the effects of
the expression. Expressions taking multiple operands are evaluated left to right
as written in the source code.
The operands of these expressions are evaluated prior to applying the effects of the expression.
Expressions taking multiple operands are evaluated left to right as written in the source code.

> **Note**: Which subexpressions are the operands of an expression is
> determined by expression precedence as per the previous section.

For example, the two `next` method calls will always be called in the same
order:
For example, the two `next` method calls will always be called in the same order:

```rust
# // Using vec instead of array to avoid references
Expand All @@ -134,23 +127,18 @@ assert_eq!(
);
```

> **Note**: Since this is applied recursively, these expressions are also
> evaluated from innermost to outermost, ignoring siblings until there are no
> inner subexpressions.
> **Note**: Since this is applied recursively, these expressions are also evaluated from innermost to outermost, ignoring siblings until there are no inner subexpressions.

## Place Expressions and Value Expressions

Expressions are divided into two main categories: place expressions and value
expressions; there is also a third, minor category of expressions called
assignee expressions. Within each expression, operands may likewise occur in
either place context or value context. The evaluation of an expression depends
both on its own category and the context it occurs within.
Expressions are divided into two main categories: place expressions and value expressions;
there is also a third, minor category of expressions called assignee expressions.
Within each expression, operands may likewise occur in either place context or value context.
The evaluation of an expression depends both on its own category and the context it occurs within.

A *place expression* is an expression that represents a memory location. These
expressions are [paths] which refer to local variables, [static variables],
[dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`),
[field] references (`expr.f`) and parenthesized place expressions. All other
expressions are value expressions.
A *place expression* is an expression that represents a memory location.
These expressions are [paths] which refer to local variables, [static variables], [dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized place expressions.
All other expressions are value expressions.

A *value expression* is an expression that represents an actual value.

Expand All @@ -166,11 +154,10 @@ The following contexts are *place expression* contexts:
expression.
* The base of a [functional update] struct expression.

> Note: Historically, place expressions were called *lvalues* and value
> expressions were called *rvalues*.
> Note: Historically, place expressions were called *lvalues* and value expressions were called *rvalues*.

An *assignee expression* is an expression that appears in the left operand of an
[assignment][assign] expression. Explicitly, the assignee expressions are:
An *assignee expression* is an expression that appears in the left operand of an [assignment][assign] expression.
Explicitly, the assignee expressions are:

- Place expressions.
- [Underscores][_UnderscoreExpression_].
Expand All @@ -185,59 +172,49 @@ Arbitrary parenthesisation is permitted inside assignee expressions.

### Moved and copied types

When a place expression is evaluated in a value expression context, or is bound
by value in a pattern, it denotes the value held _in_ that memory location. If
the type of that value implements [`Copy`], then the value will be copied. In
the remaining situations, if that type is [`Sized`], then it may be possible to
move the value. Only the following place expressions may be moved out of:
When a place expression is evaluated in a value expression context, or is bound by value in a pattern, it denotes the value held _in_ that memory location.
If the type of that value implements [`Copy`], then the value will be copied.
In the remaining situations, if that type is [`Sized`], then it may be possible to move the value.
Only the following place expressions may be moved out of:

* [Variables] which are not currently borrowed.
* [Temporary values](#temporaries).
* [Fields][field] of a place expression which can be moved out of and
don't implement [`Drop`].
* The result of [dereferencing][deref] an expression with type [`Box<T>`] and
that can also be moved out of.
* [Fields][field] of a place expression which can be moved out of and don't implement [`Drop`].
* The result of [dereferencing][deref] an expression with type [`Box<T>`] and that can also be moved out of.

After moving out of a place expression that evaluates to a local variable, the
location is deinitialized and cannot be read from again until it is
reinitialized. In all other cases, trying to use a place expression in a value
expression context is an error.
After moving out of a place expression that evaluates to a local variable, the location is deinitialized and cannot be read from again until it is reinitialized.
In all other cases, trying to use a place expression in a value expression context is an error.

### Mutability

For a place expression to be [assigned][assign] to, mutably [borrowed][borrow],
[implicitly mutably borrowed], or bound to a pattern containing `ref mut`, it
must be _mutable_. We call these *mutable place expressions*. In contrast,
other place expressions are called *immutable place expressions*.
For a place expression to be [assigned][assign] to, mutably [borrowed][borrow], [implicitly mutably borrowed], or bound to a pattern containing `ref mut`, it must be _mutable_.
We call these *mutable place expressions*.
In contrast, other place expressions are called *immutable place expressions*.

The following expressions can be mutable place expression contexts:

* Mutable [variables] which are not currently borrowed.
* [Mutable `static` items].
* [Temporary values].
* [Fields][field]: this evaluates the subexpression in a mutable place
expression context.
* [Fields][field]: this evaluates the subexpression in a mutable place expression context.
* [Dereferences][deref] of a `*mut T` pointer.
* Dereference of a variable, or field of a variable, with type `&mut T`. Note:
This is an exception to the requirement of the next rule.
* Dereferences of a type that implements `DerefMut`: this then requires that
the value being dereferenced is evaluated in a mutable place expression context.
* [Array indexing] of a type that implements `IndexMut`: this
then evaluates the value being indexed, but not the index, in mutable place
expression context.
* Dereference of a variable, or field of a variable, with type `&mut T`.
Note: This is an exception to the requirement of the next rule.
* Dereferences of a type that implements `DerefMut`:
this then requires that the value being dereferenced is evaluated in a mutable place expression context.
* [Array indexing] of a type that implements `IndexMut`:
this then evaluates the value being indexed, but not the index, in mutable place expression context.

### Temporaries

When using a value expression in most place expression contexts, a temporary
unnamed memory location is created and initialized to that value. The expression
evaluates to that location instead, except if [promoted] to a `static`. The
[drop scope] of the temporary is usually the end of the enclosing statement.
When using a value expression in most place expression contexts, a temporary unnamed memory location is created and initialized to that value.
The expression evaluates to that location instead, except if [promoted] to a `static`.
The [drop scope] of the temporary is usually the end of the enclosing statement.

### Implicit Borrows

Certain expressions will treat an expression as a place expression by implicitly
borrowing it. For example, it is possible to compare two unsized [slices][slice] for
equality directly, because the `==` operator implicitly borrows its operands:
Certain expressions will treat an expression as a place expression by implicitly borrowing it.
For example, it is possible to compare two unsized [slices][slice] for equality directly, because the `==` operator implicitly borrows its operands:

```rust
# let c = [1, 2, 3];
Expand All @@ -264,31 +241,21 @@ Implicit borrows may be taken in the following expressions:

## Overloading Traits

Many of the following operators and expressions can also be overloaded for
other types using traits in `std::ops` or `std::cmp`. These traits also
exist in `core::ops` and `core::cmp` with the same names.
Many of the following operators and expressions can also be overloaded for other types using traits in `std::ops` or `std::cmp`.
These traits also exist in `core::ops` and `core::cmp` with the same names.

## Expression Attributes

[Outer attributes][_OuterAttribute_] before an expression are allowed only in
a few specific cases:
[Outer attributes][_OuterAttribute_] before an expression are allowed only in a few specific cases:

* Before an expression used as a [statement].
* Elements of [array expressions], [tuple expressions], [call expressions],
and tuple-style [struct] expressions.
<!--
These were likely stabilized inadvertently.
See https://github.com/rust-lang/rust/issues/32796 and
https://github.com/rust-lang/rust/issues/15701
-->
* Elements of [array expressions], [tuple expressions], [call expressions], and tuple-style [struct] expressions.
* The tail expression of [block expressions].
<!-- Keep list in sync with block-expr.md -->

They are never allowed before:
* [Range][_RangeExpression_] expressions.
* Binary operator expressions ([_ArithmeticOrLogicalExpression_],
[_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_],
[_AssignmentExpression_], [_CompoundAssignmentExpression_]).
* Binary operator expressions ([_ArithmeticOrLogicalExpression_], [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_], [_AssignmentExpression_], [_CompoundAssignmentExpression_]).


[block expressions]: expressions/block-expr.md
Expand Down
12 changes: 4 additions & 8 deletions src/statements-and-expressions.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
# Statements and expressions

Rust is _primarily_ an expression language. This means that most forms of
value-producing or effect-causing evaluation are directed by the uniform syntax
category of _expressions_. Each kind of expression can typically _nest_ within
each other kind of expression, and rules for evaluation of expressions involve
specifying both the value produced by the expression and the order in which its
sub-expressions are themselves evaluated.
Rust is _primarily_ an expression language.
This means that most forms of value-producing or effect-causing evaluation are directed by the uniform syntax category of _expressions_.
Each kind of expression can typically _nest_ within each other kind of expression, and rules for evaluation of expressions involve specifying both the value produced by the expression and the order in which its sub-expressions are themselves evaluated.

In contrast, statements serve _mostly_ to contain and explicitly
sequence expression evaluation.
In contrast, statements serve _mostly_ to contain and explicitly sequence expression evaluation.
Loading