Skip to content

Commit

Permalink
Merge pull request rust-lang#126 from matthewjasper/expressions-fixes
Browse files Browse the repository at this point in the history
Small fixes to the expressions section
  • Loading branch information
Havvy authored Oct 4, 2017
2 parents 36adc6a + aec44d6 commit 16c2cc2
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 59 deletions.
72 changes: 48 additions & 24 deletions src/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,35 @@ 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.

## 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
evaluated in the order given by their associativity.

| Operator/Expression | Associativity |
|-----------------------------|---------------------|
| Paths | |
| Method calls | |
| Field expressions | left to right |
| Function calls, array indexing | |
| `?` | |
| Unary `-` `*` `!` `&` `&mut` | |
| `as` `:` | left to right |
| `*` `/` `%` | left to right |
| `+` `-` | left to right |
| `<<` `>>` | left to right |
| `&` | left to right |
| `^` | left to right |
| <code>&#124;</code> | left to right |
| `==` `!=` `<` `>` `<=` `>=` | Require parentheses |
| `&&` | left to right |
| <code>&#124;&#124;</code> | left to right |
| `..` `...` | Require parentheses |
| `<-` | right to left |
| `=` `+=` `-=` `*=` `/=` `%=` <br> `&=` <code>&#124;=</code> `^=` `<<=` `>>=` | right to left |
| `return` `break` closures | |

## Lvalues and rvalues

Expressions are divided into two main categories: _lvalues_ and _rvalues_.
Expand All @@ -23,25 +52,24 @@ or _rvalue context_. The evaluation of an expression depends both on its own
category and the context it occurs within.

An lvalue is an expression that represents a memory location. These expressions
are paths which refer to local variables, function and method arguments, or
static variables, [dereferences]&nbsp;(`*expr`), [array indexing] expressions
(`expr[expr]`), [field] references (`expr.f`) and parenthesized lvalue
expressions. All other expressions are rvalues.
are [paths](#path-expressions) which refer to local variables, static
variables, function parameters, [dereferences]&nbsp;(`*expr`), [array indexing]
expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized
lvalue expressions. All other expressions are rvalues.

The left operand of an [assign]ment or [compound assignment] expression is an
lvalue context, as is the single operand of a unary [borrow], and the operand
of any [implicit borrow](#implicit-borrows). The discriminant or subject of a
[match] expression and right side of a `let` binding may be an lvalue context,
if ref bindings are made, but is otherwise an rvalue context. All other
expression contexts are rvalue contexts.
[match] expression and right side of a `let` is also an lvalue context. All
other expression contexts are rvalue contexts.

### Moved and copied types

When an lvalue is evaluated in an _rvalue context_, it denotes the value held
_in_ that memory location. If value is of a type that implements `Copy`, then
the value will be copied. In the remaining situations if the type of the value
is [`Sized`](the-sized-trait.html) it may be possible to move the value. Only
the following lvalues may be moved out of:
When an lvalue is evaluated in an _rvalue context_ or is bound by value in a
pattern, it denotes the value held _in_ that memory location. If value is of a
type that implements `Copy`, then the value will be copied. In the remaining
situations if the type of the value is [`Sized`](the-sized-trait.html) it may
be possible to move the value. Only the following lvalues may be moved out of:

* [Variables](variables.html) which are not currently borrowed.
* [Temporary values](#temporary-lifetimes).
Expand Down Expand Up @@ -88,11 +116,11 @@ That is, the promoted expression can be evaluated at compile-time and the
resulting value does not contain interior mutability or destructors (these
properties are determined based on the value where possible, e.g. `&None`
always has the type `&'static Option<_>`, as it contains nothing disallowed).
Otherwise, the lifetime of temporary values is typically
Otherwise, the lifetime of temporary values is typically

- the innermost enclosing statement; the tail expression of a block is
- the innermost enclosing statement; the tail expression of a block is
considered part of the statement that encloses the block, or
- the condition expression or the loop conditional expression if the
- the condition expression or the loop conditional expression if the
temporary is created in the condition expression of an `if` or an `if`/`else`
or in the loop conditional expression of a `while` expression.

Expand All @@ -119,7 +147,7 @@ Here are some examples:
an rvalue. As the temporary is created in the condition expression
of an `if`/`else`, it will be freed at the end of the condition expression
(in this example before the call to `bar` or `baz` is made).
- `let x = if temp().must_run_bar {bar()} else {baz()};`.
- `let x = if temp().must_run_bar {bar()} else {baz()};`.
Here we assume the type of `temp()` is a struct with a boolean field
`must_run_bar`. As the previous example, the temporary corresponding to
`temp()` will be freed at the end of the condition expression.
Expand Down Expand Up @@ -186,29 +214,25 @@ also constant expressions:
* [Literals].
* [Paths] to [functions](items/functions.html) and constants.
Recursively defining constants is not allowed.
* Paths to statics, so long as only their address, not their value, is used.
This includes using their value indirectly through a complicated expression.
\*
* [Tuple expressions].
* [Array expressions].
* [Struct] expressions, where the type does not implement [`Drop`](the-drop-trait.html).
* [Enum variant] expressions, where the enumeration type does not implement `Drop`.
* [Block expressions]&nbsp;(and `unsafe` blocks) which contain only items and
* [Block expressions]&nbsp;(and `unsafe` blocks) which only contain items and
possibly a (constant) tail expression.
* [Field] expressions.
* Index expressions, [array indexing] or [slice] with a `usize`.
* [Range expressions].
* [Closure expressions] which don't capture variables from the environment.
* Built in [negation], [arithmetic, logical], [comparison] or [lazy boolean]
operators used on integer and floating point types, `bool` and `char`.
* Shared [borrow].
* The [dereference operator], but not to circumvent the rule on statics.
* Shared [borrow], except if applied to a type with [interior
mutability](interior-mutability.html).
* The [dereference operator].
* [Grouped] expressions.
* [Cast] expressions, except pointer to address and
function pointer to address casts.

\* Only in static items.

## Overloading Traits

Many of the following operators and expressions can also be overloaded for
Expand Down
15 changes: 8 additions & 7 deletions src/expressions/field-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ 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, a reference to a struct are treated as separate
entities when borrowing. If the struct does not implement
[`Drop`](the-drop-trait.html) this also applies to moving out of each of its fields
where possible. This also does not apply if automatic dereferencing is done
though user defined types.
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`](the-drop-trait.html) 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.

```rust
# struct A { f1: String, f2: String, f3: String }
# let mut x = A {
struct A { f1: String, f2: String, f3: String }
let mut x: A;
# x = A {
# f1: "f1".to_string(),
# f2: "f2".to_string(),
# f3: "f3".to_string()
Expand Down
3 changes: 2 additions & 1 deletion src/expressions/method-call-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ let log_pi = pi.unwrap_or(1.0).log(2.72);
```

When resolving method calls on an expression of type `A`, Rust will use the
following order:
following order, only looking at methods that are
[visible](#visibility-and-privacy.html) and traits that are in scope:

1. Inherent methods, with receiver of type `A`, `&A`, `&mut A`.
1. Trait methods with receiver of type `A`.
Expand Down
26 changes: 0 additions & 26 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,29 +331,3 @@ let mut x = 10;
x += 4;
assert_eq!(x, 14);
```

## Operator precedence

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


| Operator | Associativity |
|-----------------------------|---------------------|
| `?` | |
| Unary `-` `*` `!` `&` `&mut` | |
| `as` `:` | left to right |
| `*` `/` `%` | left to right |
| `+` `-` | left to right |
| `<<` `>>` | left to right |
| `&` | left to right |
| `^` | left to right |
| <code>&#124;</code> | left to right |
| `==` `!=` `<` `>` `<=` `>=` | Require parentheses |
| `&&` | left to right |
| <code>&#124;&#124;</code> | left to right |
| `..` `...` | Require parentheses |
| `<-` | right to left |
| `=` `+=` `-=` `*=` `/=` `%=` <br> `&=` <code>&#124;=</code> `^=` `<<=` `>>=` | right to left |

5 changes: 4 additions & 1 deletion src/items/static-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ statics:
* Statics may not contain any destructors.
* The types of static values must ascribe to `Sync` to allow thread-safe
access.
* Statics may not refer to other statics by value, only by reference.
* Statics allow using paths to statics in the
[constant-expression](#expresions.html#constant-expressions) used to
initialize them, but statics may not refer to other statics by value, only by
reference.
* Constants cannot refer to statics.

Constants should in general be preferred over statics, unless large amounts of
Expand Down

0 comments on commit 16c2cc2

Please sign in to comment.