summaryrefslogtreecommitdiffstats
path: root/src/doc/reference
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:12:43 +0000
commitcf94bdc0742c13e2a0cac864c478b8626b266e1b (patch)
tree044670aa50cc5e2b4229aa0b6b3df6676730c0a6 /src/doc/reference
parentAdding debian version 1.65.0+dfsg1-2. (diff)
downloadrustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.tar.xz
rustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.zip
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc/reference')
-rw-r--r--src/doc/reference/book.toml2
-rw-r--r--src/doc/reference/src/SUMMARY.md3
-rw-r--r--src/doc/reference/src/attributes.md3
-rw-r--r--src/doc/reference/src/attributes/codegen.md2
-rw-r--r--src/doc/reference/src/attributes/derive.md4
-rw-r--r--src/doc/reference/src/attributes/diagnostics.md2
-rw-r--r--src/doc/reference/src/conditional-compilation.md19
-rw-r--r--src/doc/reference/src/destructors.md2
-rw-r--r--src/doc/reference/src/expressions.md139
-rw-r--r--src/doc/reference/src/expressions/block-expr.md9
-rw-r--r--src/doc/reference/src/expressions/closure-expr.md2
-rw-r--r--src/doc/reference/src/expressions/grouped-expr.md4
-rw-r--r--src/doc/reference/src/expressions/loop-expr.md34
-rw-r--r--src/doc/reference/src/identifiers.md6
-rw-r--r--src/doc/reference/src/inline-assembly.md7
-rw-r--r--src/doc/reference/src/items/associated-items.md145
-rw-r--r--src/doc/reference/src/items/external-blocks.md58
-rw-r--r--src/doc/reference/src/items/functions.md4
-rw-r--r--src/doc/reference/src/items/traits.md1
-rw-r--r--src/doc/reference/src/items/type-aliases.md18
-rw-r--r--src/doc/reference/src/patterns.md324
-rw-r--r--src/doc/reference/src/statements-and-expressions.md12
-rw-r--r--src/doc/reference/src/statements.md86
-rw-r--r--src/doc/reference/src/tokens.md2
-rw-r--r--src/doc/reference/src/type-layout.md30
-rw-r--r--src/doc/reference/src/types/function-pointer.md2
-rw-r--r--src/doc/reference/src/types/pointer.md6
-rw-r--r--src/doc/reference/src/unsafe-blocks.md22
-rw-r--r--src/doc/reference/src/unsafe-functions.md5
-rw-r--r--src/doc/reference/src/unsafe-keyword.md58
30 files changed, 634 insertions, 377 deletions
diff --git a/src/doc/reference/book.toml b/src/doc/reference/book.toml
index 19b9afc79..9fb3730c8 100644
--- a/src/doc/reference/book.toml
+++ b/src/doc/reference/book.toml
@@ -10,6 +10,8 @@ edit-url-template = "https://github.com/rust-lang/reference/edit/master/{path}"
[output.html.redirect]
"/expressions/enum-variant-expr.html" = "struct-expr.html"
+"/unsafe-blocks.html" = "unsafe-keyword.html"
+"/unsafe-functions.html" = "unsafe-keyword.html"
[rust]
edition = "2021"
diff --git a/src/doc/reference/src/SUMMARY.md b/src/doc/reference/src/SUMMARY.md
index 82d70d043..4d9cc1d76 100644
--- a/src/doc/reference/src/SUMMARY.md
+++ b/src/doc/reference/src/SUMMARY.md
@@ -118,8 +118,7 @@
- [Inline assembly](inline-assembly.md)
- [Unsafety](unsafety.md)
- - [Unsafe functions](unsafe-functions.md)
- - [Unsafe blocks](unsafe-blocks.md)
+ - [The `unsafe` keyword](unsafe-keyword.md)
- [Behavior considered undefined](behavior-considered-undefined.md)
- [Behavior not considered unsafe](behavior-not-considered-unsafe.md)
diff --git a/src/doc/reference/src/attributes.md b/src/doc/reference/src/attributes.md
index 857cd7d72..b7c1ef609 100644
--- a/src/doc/reference/src/attributes.md
+++ b/src/doc/reference/src/attributes.md
@@ -228,6 +228,8 @@ The following is an index of all built-in attributes.
- [`link`] — Specifies a native library to link with an `extern` block.
- [`link_name`] — Specifies the name of the symbol for functions or statics
in an `extern` block.
+ - [`link_ordinal`] — Specifies the ordinal of the symbol for functions or
+ statics in an `extern` block.
- [`no_link`] — Prevents linking an extern crate.
- [`repr`] — Controls type layout.
- [`crate_type`] — Specifies the type of crate (library, executable, etc.).
@@ -297,6 +299,7 @@ The following is an index of all built-in attributes.
[`ignore`]: attributes/testing.md#the-ignore-attribute
[`inline`]: attributes/codegen.md#the-inline-attribute
[`link_name`]: items/external-blocks.md#the-link_name-attribute
+[`link_ordinal`]: items/external-blocks.md#the-link_ordinal-attribute
[`link_section`]: abi.md#the-link_section-attribute
[`link`]: items/external-blocks.md#the-link-attribute
[`macro_export`]: macros-by-example.md#path-based-scope
diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md
index 4ebabaccf..3a36a10ca 100644
--- a/src/doc/reference/src/attributes/codegen.md
+++ b/src/doc/reference/src/attributes/codegen.md
@@ -347,7 +347,7 @@ trait object whose methods are attributed.
[target architecture]: ../conditional-compilation.md#target_arch
[trait]: ../items/traits.md
[undefined behavior]: ../behavior-considered-undefined.md
-[unsafe function]: ../unsafe-functions.md
+[unsafe function]: ../unsafe-keyword.md
[rust-abi]: ../items/external-blocks.md#abi
[`core::intrinsics::caller_location`]: ../../core/intrinsics/fn.caller_location.html
[`core::panic::Location::caller`]: ../../core/panic/struct.Location.html#method.caller
diff --git a/src/doc/reference/src/attributes/derive.md b/src/doc/reference/src/attributes/derive.md
index b8909ac71..bb5631f7a 100644
--- a/src/doc/reference/src/attributes/derive.md
+++ b/src/doc/reference/src/attributes/derive.md
@@ -24,10 +24,6 @@ impl<T: PartialEq> PartialEq for Foo<T> {
fn eq(&self, other: &Foo<T>) -> bool {
self.a == other.a && self.b == other.b
}
-
- fn ne(&self, other: &Foo<T>) -> bool {
- self.a != other.a || self.b != other.b
- }
}
```
diff --git a/src/doc/reference/src/attributes/diagnostics.md b/src/doc/reference/src/attributes/diagnostics.md
index 1dd9363d8..45f9cc440 100644
--- a/src/doc/reference/src/attributes/diagnostics.md
+++ b/src/doc/reference/src/attributes/diagnostics.md
@@ -184,7 +184,7 @@ Tuple struct fields are ignored.
Here is an example:
```rust
-#[deprecated(since = "5.2", note = "foo was rarely used. Users should instead use bar")]
+#[deprecated(since = "5.2.0", note = "foo was rarely used. Users should instead use bar")]
pub fn foo() {}
pub fn bar() {}
diff --git a/src/doc/reference/src/conditional-compilation.md b/src/doc/reference/src/conditional-compilation.md
index 6966cec4f..97840e4f6 100644
--- a/src/doc/reference/src/conditional-compilation.md
+++ b/src/doc/reference/src/conditional-compilation.md
@@ -191,6 +191,25 @@ Example values:
* `"pc"`
* `"unknown"`
+### `target_has_atomic`
+
+Key-value option set for each bit width that the target supports
+atomic loads, stores, and compare-and-swap operations.
+
+When this cfg is present, all of the stable [`core::sync::atomic`] APIs are available for
+the relevant atomic width.
+
+[`core::sync::atomic`]: ../core/sync/atomic/index.html
+
+Possible values:
+
+* `"8"`
+* `"16"`
+* `"32"`
+* `"64"`
+* `"128"`
+* `"ptr"`
+
### `test`
Enabled when compiling the test harness. Done with `rustc` by using the
diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md
index 6d616b3e7..242d9b2db 100644
--- a/src/doc/reference/src/destructors.md
+++ b/src/doc/reference/src/destructors.md
@@ -158,7 +158,7 @@ smallest scope that contains the expression and is one of the following:
* The entire function body.
* A statement.
-* The body of a [`if`], [`while`] or [`loop`] expression.
+* The body of an [`if`], [`while`] or [`loop`] expression.
* The `else` block of an `if` expression.
* The condition expression of an `if` or `while` expression, or a `match`
guard.
diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md
index 32ee658ff..b2411cd8e 100644
--- a/src/doc/reference/src/expressions.md
+++ b/src/doc/reference/src/expressions.md
@@ -22,6 +22,7 @@
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MethodCallExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_FieldExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ClosureExpression_]\
+> &nbsp;&nbsp; &nbsp;&nbsp; | [_AsyncBlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ContinueExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_BreakExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_RangeExpression_]\
@@ -34,7 +35,6 @@
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\
> &nbsp;&nbsp; (\
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]\
-> &nbsp;&nbsp; &nbsp;&nbsp; | [_AsyncBlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_UnsafeBlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_LoopExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfExpression_]\
@@ -42,28 +42,24 @@
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MatchExpression_]\
> &nbsp;&nbsp; )
-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 |
|-----------------------------|---------------------|
@@ -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
@@ -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
@@ -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.
@@ -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_].
@@ -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];
@@ -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
diff --git a/src/doc/reference/src/expressions/block-expr.md b/src/doc/reference/src/expressions/block-expr.md
index a68b27e56..bd9c0a623 100644
--- a/src/doc/reference/src/expressions/block-expr.md
+++ b/src/doc/reference/src/expressions/block-expr.md
@@ -103,7 +103,7 @@ Async contexts are established by async blocks as well as the bodies of async fu
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.
+That is, `return <expr>` from within an async block 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.
@@ -112,7 +112,7 @@ Therefore the following is illegal:
```rust,compile_fail
loop {
async move {
- break; // This would break out of the loop.
+ break; // error[E0267]: `break` inside of an `async` block
}
}
```
@@ -140,6 +140,10 @@ unsafe {
let a = unsafe { an_unsafe_fn() };
```
+## Labelled block expressions
+
+Labelled block expressions are documented in the [Loops and other breakable expressions] section.
+
## Attributes on block expressions
[Inner attributes] are allowed directly after the opening brace of a block expression in the following situations:
@@ -189,3 +193,4 @@ fn is_unix_platform() -> bool {
[tuple expressions]: tuple-expr.md
[unsafe operations]: ../unsafety.md
[value expressions]: ../expressions.md#place-expressions-and-value-expressions
+[Loops and other breakable expressions]: loop-expr.md#labelled-block-expressions
diff --git a/src/doc/reference/src/expressions/closure-expr.md b/src/doc/reference/src/expressions/closure-expr.md
index bdc177bb5..103f74795 100644
--- a/src/doc/reference/src/expressions/closure-expr.md
+++ b/src/doc/reference/src/expressions/closure-expr.md
@@ -12,7 +12,7 @@
> _ClosureParam_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> [_PatternNoTopAlt_]&nbsp;( `:` [_Type_] )<sup>?</sup>
-A *closure expression*, also know as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type.
+A *closure expression*, also known as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type.
The syntax for a closure expression is an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], called the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, called the *return type*, and then an expression, called the *closure body operand*.
The optional type after each pattern is a type annotation for the pattern.
If there is a return type, the closure body must be a [block].
diff --git a/src/doc/reference/src/expressions/grouped-expr.md b/src/doc/reference/src/expressions/grouped-expr.md
index 0ff7e2c90..1ae2209c5 100644
--- a/src/doc/reference/src/expressions/grouped-expr.md
+++ b/src/doc/reference/src/expressions/grouped-expr.md
@@ -16,8 +16,8 @@ Parentheses can be used to explicitly modify the precedence order of subexpressi
An example of a parenthesized expression:
```rust
-let x: i32 = 2 + 3 * 4;
-let y: i32 = (2 + 3) * 4;
+let x: i32 = 2 + 3 * 4; // not parenthesized
+let y: i32 = (2 + 3) * 4; // parenthesized
assert_eq!(x, 14);
assert_eq!(y, 20);
```
diff --git a/src/doc/reference/src/expressions/loop-expr.md b/src/doc/reference/src/expressions/loop-expr.md
index 308f3e346..204207ee0 100644
--- a/src/doc/reference/src/expressions/loop-expr.md
+++ b/src/doc/reference/src/expressions/loop-expr.md
@@ -1,4 +1,4 @@
-# Loops
+# Loops and other breakable expressions
> **<sup>Syntax</sup>**\
> _LoopExpression_ :\
@@ -7,6 +7,7 @@
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicateLoopExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicatePatternLoopExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IteratorLoopExpression_]\
+> &nbsp;&nbsp; &nbsp;&nbsp; | [_LabelBlockExpression_]\
> &nbsp;&nbsp; )
[_LoopLabel_]: #loop-labels
@@ -14,16 +15,19 @@
[_PredicateLoopExpression_]: #predicate-loops
[_PredicatePatternLoopExpression_]: #predicate-pattern-loops
[_IteratorLoopExpression_]: #iterator-loops
+[_LabelBlockExpression_]: #labelled-block-expressions
-Rust supports four loop expressions:
+Rust supports five 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 [labelled block expression](#labelled-block-expressions) runs a loop exactly once, but allows exiting the loop early with `break`.
-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).
+All five types of loop support [`break` expressions](#break-expressions), and [labels](#loop-labels).
+All except labelled block expressions support [`continue` expressions](#continue-expressions).
+Only `loop` and labelled block expressions support [evaluation to non-trivial values](#break-and-loop-values).
## Infinite loops
@@ -193,6 +197,18 @@ A loop expression may optionally have a _label_. The label is written as a lifet
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).
+Labels follow the hygiene and shadowing rules of local variables. For example, this code will print "outer loop":
+
+```rust
+'a: loop {
+ 'a: loop {
+ break 'a;
+ }
+ print!("outer loop");
+ break 'a;
+}
+```
+
## `break` expressions
> **<sup>Syntax</sup>**\
@@ -226,6 +242,16 @@ 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`.
+## Labelled block expressions
+
+> **<sup>Syntax</sup>**\
+> _LabelBlockExpression_ :\
+> &nbsp;&nbsp; [_BlockExpression_]
+
+Labelled block expressions are exactly like block expressions, except that they allow using `break` expressions within the block.
+Unlike other loops, `break` expressions within a label expression *must* have a label (i.e. the label is not optional).
+Unlike other loops, labelled block expressions *must* begin with a label.
+
## `continue` expressions
> **<sup>Syntax</sup>**\
diff --git a/src/doc/reference/src/identifiers.md b/src/doc/reference/src/identifiers.md
index a4e972cd3..c760f6826 100644
--- a/src/doc/reference/src/identifiers.md
+++ b/src/doc/reference/src/identifiers.md
@@ -13,7 +13,7 @@
> NON_KEYWORD_IDENTIFIER | RAW_IDENTIFIER
<!-- When updating the version, update the UAX links, too. -->
-Identifiers follow the specification in [Unicode Standard Annex #31][UAX31] for Unicode version 13.0, with the additions described below. Some examples of identifiers:
+Identifiers follow the specification in [Unicode Standard Annex #31][UAX31] for Unicode version 15.0, with the additions described below. Some examples of identifiers:
* `foo`
* `_identifier`
@@ -68,5 +68,5 @@ keyword except the ones listed above for `RAW_IDENTIFIER`.
[proc-macro]: procedural-macros.md
[reserved]: keywords.md#reserved-keywords
[strict]: keywords.md#strict-keywords
-[UAX15]: https://www.unicode.org/reports/tr15/tr15-50.html
-[UAX31]: https://www.unicode.org/reports/tr31/tr31-33.html
+[UAX15]: https://www.unicode.org/reports/tr15/tr15-53.html
+[UAX31]: https://www.unicode.org/reports/tr31/tr31-37.html
diff --git a/src/doc/reference/src/inline-assembly.md b/src/doc/reference/src/inline-assembly.md
index 6233475a3..996b157da 100644
--- a/src/doc/reference/src/inline-assembly.md
+++ b/src/doc/reference/src/inline-assembly.md
@@ -123,12 +123,17 @@ Several types of operands are supported:
* `inlateout(<reg>) <expr>` / `inlateout(<reg>) <in expr> => <out expr>`
- Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`).
- You should only write to the register after all inputs are read, otherwise you may clobber an input.
+* `sym <path>`
+ - `<path>` must refer to a `fn` or `static`.
+ - A mangled symbol name referring to the item is substituted into the asm template string.
+ - The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).
+ - `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data.
Operand expressions are evaluated from left to right, just like function call arguments.
After the `asm!` has executed, outputs are written to in left to right order.
This is significant if two outputs point to the same place: that place will contain the value of the rightmost output.
-Since `global_asm!` exists outside a function, it cannot use input/output operands.
+Since `global_asm!` exists outside a function, it can only use `sym` operands.
## Register operands
diff --git a/src/doc/reference/src/items/associated-items.md b/src/doc/reference/src/items/associated-items.md
index f5dc31aae..2401127b5 100644
--- a/src/doc/reference/src/items/associated-items.md
+++ b/src/doc/reference/src/items/associated-items.md
@@ -205,22 +205,49 @@ types cannot be defined in [inherent implementations] nor can they be given a
default implementation in traits.
An *associated type declaration* declares a signature for associated type
-definitions. It is written as `type`, then an [identifier], and
-finally an optional list of trait bounds.
+definitions. It is written in one of the following forms, where `Assoc` is the
+name of the associated type, `Params` is a comma-separated list of type,
+lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds
+that the associated type must meet, and `WhereBounds` is a comma-separated list
+of bounds that the parameters must meet:
+
+<!-- ignore: illustrative example forms -->
+```rust,ignore
+type Assoc;
+type Assoc: Bounds;
+type Assoc<Params>;
+type Assoc<Params>: Bounds;
+type Assoc<Params> where WhereBounds;
+type Assoc<Params>: Bounds where WhereBounds;
+```
The identifier is the name of the declared type alias. The optional trait bounds
must be fulfilled by the implementations of the type alias.
There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound.
-An *associated type definition* defines a type alias on another type. It is
-written as `type`, then an [identifier], then an `=`, and finally a [type].
+An *associated type definition* defines a type alias for the implementation
+of a trait on a type. They are written similarly to an *associated type declaration*,
+but cannot contain `Bounds`, but instead must contain a `Type`:
+
+<!-- ignore: illustrative example forms -->
+```rust,ignore
+type Assoc = Type;
+type Assoc<Params> = Type; // the type `Type` here may reference `Params`
+type Assoc<Params> = Type where WhereBounds;
+type Assoc<Params> where WhereBounds = Type; // deprecated, prefer the form above
+```
If a type `Item` has an associated type `Assoc` from a trait `Trait`, then
`<Item as Trait>::Assoc` is a type that is an alias of the type specified in the
associated type definition. Furthermore, if `Item` is a type parameter, then
`Item::Assoc` can be used in type parameters.
-Associated types must not include [generic parameters] or [where clauses].
+Associated types may include [generic parameters] and [where clauses]; these are
+often referred to as *generic associated types*, or *GATs*. If the type `Thing`
+has an associated type `Item` from a trait `Trait` with the generics `<'a>` , the
+type can be named like `<Thing as Trait>::Item<'x>`, where `'x` is some lifetime
+in scope. In this case, `'x` will be used wherever `'a` appears in the associated
+type definitions on impls.
```rust
trait AssociatedType {
@@ -249,6 +276,37 @@ fn main() {
}
```
+An example of associated types with generics and where clauses:
+
+```rust
+struct ArrayLender<'a, T>(&'a mut [T; 16]);
+
+trait Lend {
+ // Generic associated type declaration
+ type Lender<'a> where Self: 'a;
+ fn lend<'a>(&'a mut self) -> Self::Lender<'a>;
+}
+
+impl<T> Lend for [T; 16] {
+ // Generic associated type definition
+ type Lender<'a> = ArrayLender<'a, T> where Self: 'a;
+
+ fn lend<'a>(&'a mut self) -> Self::Lender<'a> {
+ ArrayLender(self)
+ }
+}
+
+fn borrow<'a, T: Lend>(array: &'a mut T) -> <T as Lend>::Lender<'a> {
+ array.lend()
+}
+
+
+fn main() {
+ let mut array = [0usize; 16];
+ let lender = borrow(&mut array);
+}
+```
+
### Associated Types Container Example
Consider the following example of a `Container` trait. Notice that the type is
@@ -279,6 +337,83 @@ impl<T> Container for Vec<T> {
}
```
+### Relationship between `Bounds` and `WhereBounds`
+
+In this example:
+
+```rust
+# use std::fmt::Debug;
+trait Example {
+ type Output<T>: Ord where T: Debug;
+}
+```
+
+Given a reference to the associated type like `<X as Example>::Output<Y>`, the associated type itself must be `Ord`, and the type `Y` must be `Debug`.
+
+### Required where clauses on generic associated types
+
+Generic associated type declarations on traits currently may require a list of
+where clauses, dependent on functions in the trait and how the GAT is used. These
+rules may be loosened in the future; updates can be found [on the generic
+associated types initiative repository](https://rust-lang.github.io/generic-associated-types-initiative/explainer/required_bounds.html).
+
+In a few words, these where clauses are required in order to maximize the allowed
+definitions of the associated type in impls. To do this, any clauses that *can be
+proven to hold* on functions (using the parameters of the function or trait)
+where a GAT appears as an input or output must also be written on the GAT itself.
+
+```rust
+trait LendingIterator {
+ type Item<'x> where Self: 'x;
+ fn next<'a>(&'a mut self) -> Self::Item<'a>;
+}
+```
+
+In the above, on the `next` function, we can prove that `Self: 'a`, because of
+the implied bounds from `&'a mut self`; therefore, we must write the equivalent
+bound on the GAT itself: `where Self: 'x`.
+
+When there are multiple functions in a trait that use the GAT, then the
+*intersection* of the bounds from the different functions are used, rather than
+the union.
+
+```rust
+trait Check<T> {
+ type Checker<'x>;
+ fn create_checker<'a>(item: &'a T) -> Self::Checker<'a>;
+ fn do_check(checker: Self::Checker<'_>);
+}
+```
+
+In this example, no bounds are required on the `type Checker<'a>;`. While we
+know that `T: 'a` on `create_checker`, we do not know that on `do_check`. However,
+if `do_check` was commented out, then the `where T: 'x` bound would be required
+on `Checker`.
+
+The bounds on associated types also propagate required where clauses.
+
+```rust
+trait Iterable {
+ type Item<'a> where Self: 'a;
+ type Iterator<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
+ fn iter<'a>(&'a self) -> Self::Iterator<'a>;
+}
+```
+
+Here, `where Self: 'a` is required on `Item` because of `iter`. However, `Item`
+is used in the bounds of `Iterator`, the `where Self: 'a` clause is also required
+there.
+
+Finally, any explicit uses of `'static` on GATs in the trait do not count towards
+the required bounds.
+
+```rust
+trait StaticReturn {
+ type Y<'a>;
+ fn foo(&self) -> Self::Y<'static>;
+}
+```
+
## Associated Constants
*Associated constants* are [constants] associated with a type.
diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md
index e768a1502..c91e1d10c 100644
--- a/src/doc/reference/src/items/external-blocks.md
+++ b/src/doc/reference/src/items/external-blocks.md
@@ -122,6 +122,9 @@ specifies the kind of library with the following possible values:
- `static` — Indicates a static library.
- `framework` — Indicates a macOS framework. This is only valid for macOS
targets.
+- `raw-dylib` — Indicates a dynamic library where the compiler will generate
+ an import library to link against (see [`dylib` versus `raw-dylib`] below
+ for details). This is only valid for Windows targets.
The `name` key must be included if `kind` is specified.
@@ -198,9 +201,26 @@ The default for this modifier is `-whole-archive`.
More implementation details about this modifier can be found in
[`whole-archive` documentation for rustc].
+#### `dylib` versus `raw-dylib`
+
+On Windows, linking against a dynamic library requires that an import library
+is provided to the linker: this is a special static library that declares all
+of the symbols exported by the dynamic library in such a way that the linker
+knows that they have to be dynamically loaded at runtime.
+
+Specifying `kind = "dylib"` instructs the Rust compiler to link an import
+library based on the `name` key. The linker will then use its normal library
+resolution logic to find that import library. Alternatively, specifying
+`kind = "raw-dylib"` instructs the compiler to generate an import library
+during compilation and provide that to the linker instead.
+
+`raw-dylib` is only supported on Windows and not supported on 32-bit x86
+(`target_arch="x86"`). Using it when targeting other platforms or
+x86 on Windows will result in a compiler error.
+
### The `link_name` attribute
-The `link_name` attribute may be specified on declarations inside an `extern`
+The *`link_name` attribute* may be specified on declarations inside an `extern`
block to indicate the symbol to import for the given function or static. It
uses the [_MetaNameValueStr_] syntax to specify the name of the symbol.
@@ -211,6 +231,41 @@ extern {
}
```
+Using this attribute with the `link_ordinal` attribute will result in a
+compiler error.
+
+### The `link_ordinal` attribute
+
+The *`link_ordinal` attribute* can be applied on declarations inside an `extern`
+block to indicate the numeric ordinal to use when generating the import library
+to link against. An ordinal is a unique number per symbol exported by a dynamic
+library on Windows and can be used when the library is being loaded to find
+that symbol rather than having to look it up by name.
+
+<div class="warning">
+
+Warning: `link_ordinal` should only be used in cases where the ordinal of the
+symbol is known to be stable: if the ordinal of a symbol is not explicitly set
+when its containing binary is built then one will be automatically assigned to
+it, and that assigned ordinal may change between builds of the binary.
+
+</div>
+
+<!-- ignore: Only works on x86 Windows -->
+```rust,ignore
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "stdcall" {
+ #[link_ordinal(15)]
+ fn imported_function_stdcall(i: i32);
+}
+```
+
+This attribute is only used with the `raw-dylib` linking kind.
+Using any other kind will result in a compiler error.
+
+Using this attribute with the `link_name` attribute will result in a
+compiler error.
+
### Attributes on function parameters
Attributes on extern function parameters follow the same rules and
@@ -233,3 +288,4 @@ restrictions as [regular function parameters].
[regular function parameters]: functions.md#attributes-on-function-parameters
[`bundle` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-bundle
[`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive
+[`dylib` versus `raw-dylib`]: #dylib-versus-raw-dylib
diff --git a/src/doc/reference/src/items/functions.md b/src/doc/reference/src/items/functions.md
index 325588a53..5b4ac7af6 100644
--- a/src/doc/reference/src/items/functions.md
+++ b/src/doc/reference/src/items/functions.md
@@ -59,8 +59,8 @@ fn answer_to_life_the_universe_and_everything() -> i32 {
## Function parameters
-As with `let` bindings, function parameters are irrefutable [patterns], so any
-pattern that is valid in a let binding is also valid as a parameter:
+Function parameters are irrefutable [patterns], so any pattern that is valid in
+an else-less `let` binding is also valid as a parameter:
```rust
fn first((value, _): (i32, i32)) -> i32 { value }
diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md
index 26870a0fc..3c5d31d5c 100644
--- a/src/doc/reference/src/items/traits.md
+++ b/src/doc/reference/src/items/traits.md
@@ -70,6 +70,7 @@ Object safe traits can be the base trait of a [trait object]. A trait is
* All [supertraits] must also be object safe.
* `Sized` must not be a [supertrait][supertraits]. In other words, it must not require `Self: Sized`.
* It must not have any associated constants.
+* It must not have any associated types with generics.
* All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable:
* Dispatchable functions require:
* Not have any type parameters (although lifetime parameters are allowed),
diff --git a/src/doc/reference/src/items/type-aliases.md b/src/doc/reference/src/items/type-aliases.md
index ff0cc75f7..d2e14b903 100644
--- a/src/doc/reference/src/items/type-aliases.md
+++ b/src/doc/reference/src/items/type-aliases.md
@@ -4,7 +4,7 @@
> _TypeAlias_ :\
> &nbsp;&nbsp; `type` [IDENTIFIER]&nbsp;[_GenericParams_]<sup>?</sup>
> ( `:` [_TypeParamBounds_] )<sup>?</sup>
-> [_WhereClause_]<sup>?</sup> ( `=` [_Type_] )<sup>?</sup> `;`
+> [_WhereClause_]<sup>?</sup> ( `=` [_Type_] [_WhereClause_]<sup>?</sup>)<sup>?</sup> `;`
A _type alias_ defines a new name for an existing [type]. Type aliases are
declared with the keyword `type`. Every value has a single, specific type, but
@@ -31,11 +31,18 @@ let _ = UseAlias(5); // OK
let _ = TypeAlias(5); // Doesn't work
```
-A type alias without the [_Type_] specification may only appear as an
-[associated type] in a [trait].
+A type alias, when not used as an associated type, must include a [_Type_] and
+may not include [_TypeParamBounds_].
-A type alias with [_TypeParamBounds_] may only specified when used as
-an [associated type] in a [trait].
+A type alias, when used as an [associated type] in a [trait], must not include a
+[_Type_] specification but may include [_TypeParamBounds_].
+
+A type alias, when used as an [associated type] in a [trait impl], must include
+a [_Type_] specification and may not include [_TypeParamBounds_].
+
+Where clauses before the equals sign on a type alias in a [trait impl] (like
+`type TypeAlias<T> where T: Foo = Bar<T>`) are deprecated. Where clauses after
+the equals sign (like `type TypeAlias<T> = Bar<T> where T: Foo`) are preferred.
[IDENTIFIER]: ../identifiers.md
[_GenericParams_]: generics.md
@@ -45,3 +52,4 @@ an [associated type] in a [trait].
[associated type]: associated-items.md#associated-types
[trait]: traits.md
[type]: ../types.md
+[trait impl]: implementations.md#trait-implementations
diff --git a/src/doc/reference/src/patterns.md b/src/doc/reference/src/patterns.md
index 5c81ecd87..14bbac155 100644
--- a/src/doc/reference/src/patterns.md
+++ b/src/doc/reference/src/patterns.md
@@ -22,18 +22,16 @@
> &nbsp;&nbsp; | [_PathPattern_]\
> &nbsp;&nbsp; | [_MacroInvocation_]
-Patterns are used to match values against structures and to,
-optionally, bind variables to values inside these structures. They are also
-used in variable declarations and parameters for functions and closures.
+Patterns are used to match values against structures and to, optionally, bind variables to values inside these structures.
+They are also used in variable declarations and parameters for functions and closures.
The pattern in the following example does four things:
* Tests if `person` has the `car` field filled with something.
-* Tests if the person's `age` field is between 13 and 19, and binds its value to
- the `person_age` variable.
+* Tests if the person's `age` field is between 13 and 19, and binds its value to the `person_age` variable.
* Binds a reference to the `name` field to the variable `person_name`.
-* Ignores the rest of the fields of `person`. The remaining fields can have any value and
- are not bound to any variables.
+* Ignores the rest of the fields of `person`.
+ The remaining fields can have any value and are not bound to any variables.
```rust
# struct Car;
@@ -65,8 +63,7 @@ if let
Patterns are used in:
* [`let` declarations](statements.md#let-statements)
-* [Function](items/functions.md) and [closure](expressions/closure-expr.md)
- parameters
+* [Function](items/functions.md) and [closure](expressions/closure-expr.md) parameters
* [`match` expressions](expressions/match-expr.md)
* [`if let` expressions](expressions/if-expr.md)
* [`while let` expressions](expressions/loop-expr.md#predicate-pattern-loops)
@@ -75,13 +72,10 @@ Patterns are used in:
## Destructuring
Patterns can be used to *destructure* [structs], [enums], and [tuples].
-Destructuring breaks up a value into its component pieces. The syntax used is
-almost the same as when creating such values. In a pattern whose [scrutinee]
-expression has a `struct`, `enum` or `tuple` type, a placeholder (`_`) stands
-in for a *single* data field, whereas a wildcard `..` stands in for *all* the
-remaining fields of a particular variant. When destructuring a data structure
-with named (but not numbered) fields, it is allowed to write `fieldname` as a
-shorthand for `fieldname: fieldname`.
+Destructuring breaks up a value into its component pieces.
+The syntax used is almost the same as when creating such values.
+In a pattern whose [scrutinee] expression has a `struct`, `enum` or `tuple` type, a placeholder (`_`) stands in for a *single* data field, whereas a wildcard `..` stands in for *all* the remaining fields of a particular variant.
+When destructuring a data structure with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`.
```rust
# enum Message {
@@ -104,9 +98,9 @@ match message {
## Refutability
-A pattern is said to be *refutable* when it has the possibility of not being matched
-by the value it is being matched against. *Irrefutable* patterns, on the other hand,
-always match the value they are being matched against. Examples:
+A pattern is said to be *refutable* when it has the possibility of not being matched by the value it is being matched against.
+*Irrefutable* patterns, on the other hand, always match the value they are being matched against.
+Examples:
```rust
let (x, y) = (1, 2); // "(x, y)" is an irrefutable pattern
@@ -141,16 +135,12 @@ if let (a, 3) = (1, 2) { // "(a, 3)" is refutable, and will not match
[INTEGER_LITERAL]: tokens.md#integer-literals
[FLOAT_LITERAL]: tokens.md#floating-point-literals
-_Literal patterns_ match exactly the same value as what is created by the
-literal. Since negative numbers are not [literals], literal patterns also
-accept an optional minus sign before the literal, which acts like the negation
-operator.
+_Literal patterns_ match exactly the same value as what is created by the literal.
+Since negative numbers are not [literals], literal patterns also accept an optional minus sign before the literal, which acts like the negation operator.
<div class="warning">
-Floating-point literals are currently accepted, but due to the complexity of comparing
-them, they are going to be forbidden on literal patterns in a future version of Rust (see
-[issue #41620](https://github.com/rust-lang/rust/issues/41620)).
+Floating-point literals are currently accepted, but due to the complexity of comparing them, they are going to be forbidden on literal patterns in a future version of Rust (see [issue #41620](https://github.com/rust-lang/rust/issues/41620)).
</div>
@@ -175,14 +165,13 @@ for i in -2..5 {
> _IdentifierPattern_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; `ref`<sup>?</sup> `mut`<sup>?</sup> [IDENTIFIER] (`@` [_PatternNoTopAlt_] ) <sup>?</sup>
-Identifier patterns bind the value they match to a variable. The identifier
-must be unique within the pattern. The variable will shadow any variables of
-the same name in scope. The scope of the new binding depends on the context of
-where the pattern is used (such as a `let` binding or a `match` arm).
+Identifier patterns bind the value they match to a variable.
+The identifier must be unique within the pattern.
+The variable will shadow any variables of the same name in scope.
+The scope of the new binding depends on the context of where the pattern is used (such as a `let` binding or a `match` arm).
-Patterns that consist of only an identifier, possibly with a `mut`, match any value and
-bind it to that identifier. This is the most commonly used pattern in variable
-declarations and parameters for functions and closures.
+Patterns that consist of only an identifier, possibly with a `mut`, match any value and bind it to that identifier.
+This is the most commonly used pattern in variable declarations and parameters for functions and closures.
```rust
let mut variable = 10;
@@ -191,9 +180,8 @@ fn sum(x: i32, y: i32) -> i32 {
# }
```
-To bind the matched value of a pattern to a variable, use the syntax `variable @
-subpattern`. For example, the following binds the value 2 to `e` (not the
-entire range: the range here is a range subpattern).
+To bind the matched value of a pattern to a variable, use the syntax `variable @ subpattern`.
+For example, the following binds the value 2 to `e` (not the entire range: the range here is a range subpattern).
```rust
let x = 2;
@@ -204,10 +192,8 @@ match x {
}
```
-By default, identifier patterns bind a variable to a copy of or move from the
-matched value depending on whether the matched value implements [`Copy`].
-This can be changed to bind to a reference by using the `ref` keyword,
-or to a mutable reference using `ref mut`. For example:
+By default, identifier patterns bind a variable to a copy of or move from the matched value depending on whether the matched value implements [`Copy`].
+This can be changed to bind to a reference by using the `ref` keyword, or to a mutable reference using `ref mut`. For example:
```rust
# let a = Some(10);
@@ -222,10 +208,10 @@ match a {
}
```
-In the first match expression, the value is copied (or moved). In the second match,
-a reference to the same memory location is bound to the variable value. This syntax is
-needed because in destructuring subpatterns the `&` operator can't be applied to
-the value's fields. For example, the following is not valid:
+In the first match expression, the value is copied (or moved).
+In the second match, a reference to the same memory location is bound to the variable value.
+This syntax is needed because in destructuring subpatterns the `&` operator can't be applied to the value's fields.
+For example, the following is not valid:
```rust,compile_fail
# struct Person {
@@ -247,21 +233,18 @@ To make it valid, write the following:
if let Person {name: ref person_name, age: 18..=150 } = value { }
```
-Thus, `ref` is not something that is being matched against. Its objective is
-exclusively to make the matched binding a reference, instead of potentially
-copying or moving what was matched.
+Thus, `ref` is not something that is being matched against.
+Its objective is exclusively to make the matched binding a reference, instead of potentially copying or moving what was matched.
-[Path patterns](#path-patterns) take precedence over identifier patterns. It is an error
-if `ref` or `ref mut` is specified and the identifier shadows a constant.
+[Path patterns](#path-patterns) take precedence over identifier patterns.
+It is an error if `ref` or `ref mut` is specified and the identifier shadows a constant.
-Identifier patterns are irrefutable if the `@` subpattern is irrefutable or
-the subpattern is not specified.
+Identifier patterns are irrefutable if the `@` subpattern is irrefutable or the subpattern is not specified.
### Binding modes
-To service better ergonomics, patterns operate in different *binding modes* in
-order to make it easier to bind references to values. When a reference value is matched by
-a non-reference pattern, it will be automatically treated as a `ref` or `ref mut` binding.
+To service better ergonomics, patterns operate in different *binding modes* in order to make it easier to bind references to values.
+When a reference value is matched by a non-reference pattern, it will be automatically treated as a `ref` or `ref mut` binding.
Example:
```rust
@@ -271,26 +254,22 @@ if let Some(y) = x {
}
```
-*Non-reference patterns* include all patterns except bindings, [wildcard
-patterns](#wildcard-pattern) (`_`), [`const` patterns](#path-patterns) of reference types,
-and [reference patterns](#reference-patterns).
-
-If a binding pattern does not explicitly have `ref`, `ref mut`, or `mut`, then it uses the
-*default binding mode* to determine how the variable is bound. The default binding
-mode starts in "move" mode which uses move semantics. When matching a pattern, the
-compiler starts from the outside of the pattern and works inwards. Each time a reference
-is matched using a non-reference pattern, it will automatically dereference the value and
-update the default binding mode. References will set the default binding mode to `ref`.
-Mutable references will set the mode to `ref mut` unless the mode is already `ref` in
-which case it remains `ref`. If the automatically dereferenced value is still a reference,
-it is dereferenced and this process repeats.
-
-Move bindings and reference bindings can be mixed together in the same pattern, doing so will
-result in partial move of the object bound to and the object cannot be used afterwards.
+*Non-reference patterns* include all patterns except bindings, [wildcard patterns](#wildcard-pattern) (`_`), [`const` patterns](#path-patterns) of reference types, and [reference patterns](#reference-patterns).
+
+If a binding pattern does not explicitly have `ref`, `ref mut`, or `mut`, then it uses the *default binding mode* to determine how the variable is bound.
+The default binding mode starts in "move" mode which uses move semantics.
+When matching a pattern, the compiler starts from the outside of the pattern and works inwards.
+Each time a reference is matched using a non-reference pattern, it will automatically dereference the value and update the default binding mode.
+References will set the default binding mode to `ref`.
+Mutable references will set the mode to `ref mut` unless the mode is already `ref` in which case it remains `ref`.
+If the automatically dereferenced value is still a reference, it is dereferenced and this process repeats.
+
+Move bindings and reference bindings can be mixed together in the same pattern.
+Doing so will result in partial move of the object bound to and the object cannot be used afterwards.
This applies only if the type cannot be copied.
-In the example below, `name` is moved out of `person`, trying to use `person` as a whole or
-`person.name` would result in an error because of *partial move*.
+In the example below, `name` is moved out of `person`.
+Trying to use `person` as a whole or `person.name` would result in an error because of *partial move*.
Example:
@@ -310,10 +289,10 @@ let Person { name, ref age } = person;
> _WildcardPattern_ :\
> &nbsp;&nbsp; `_`
-The _wildcard pattern_ (an underscore symbol) matches any value. It is used to ignore values when they don't
-matter. Inside other patterns it matches a single data field (as opposed to the `..`
-which matches the remaining fields). Unlike identifier patterns, it does not copy, move
-or borrow the value it matches.
+The _wildcard pattern_ (an underscore symbol) matches any value.
+It is used to ignore values when they don't matter.
+Inside other patterns it matches a single data field (as opposed to the `..` which matches the remaining fields).
+Unlike identifier patterns, it does not copy, move or borrow the value it matches.
Examples:
@@ -351,13 +330,9 @@ The wildcard pattern is always irrefutable.
> _RestPattern_ :\
> &nbsp;&nbsp; `..`
-The _rest pattern_ (the `..` token) acts as a variable-length pattern which
-matches zero or more elements that haven't been matched already before and
-after. It may only be used in [tuple](#tuple-patterns), [tuple
-struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and
-may only appear once as one of the elements in those patterns. It is also
-allowed in an [identifier pattern](#identifier-patterns) for [slice
-patterns](#slice-patterns) only.
+The _rest pattern_ (the `..` token) acts as a variable-length pattern which matches zero or more elements that haven't been matched already before and after.
+It may only be used in [tuple](#tuple-patterns), [tuple struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and may only appear once as one of the elements in those patterns.
+It is also allowed in an [identifier pattern](#identifier-patterns) for [slice patterns](#slice-patterns) only.
The rest pattern is always irrefutable.
@@ -413,7 +388,8 @@ match tuple {
> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..=` _RangePatternBound_
>
> _HalfOpenRangePattern_ :\
-> &nbsp;&nbsp; | _RangePatternBound_ `..`
+> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..`
+> &nbsp;&nbsp; | `..=` _RangePatternBound_
>
> _ObsoleteRangePattern_ :\
> &nbsp;&nbsp; _RangePatternBound_ `...` _RangePatternBound_
@@ -425,29 +401,50 @@ match tuple {
> &nbsp;&nbsp; | `-`<sup>?</sup> [FLOAT_LITERAL]\
> &nbsp;&nbsp; | [_PathExpression_]
-Range patterns match values within the range defined by their bounds. A range pattern may be
-closed or half-open. A range pattern is closed if it has both a lower and an upper bound, and
-it matches all the values between and including both of its bounds. A range pattern that is
-half-open is written with a lower bound but not an upper bound, and matches any value equal to
-or greater than the specified lower bound.
+*Range patterns* match scalar values within the range defined by their bounds.
+A bound on the left of its sigils is a *lower bound*.
+A bound on the right is an *upper bound*.
+A range pattern may be closed or half-open.
+
+A range pattern is *closed* if it has both a lower and an upper bound.
+The only closed ranged pattern is the inclusive range pattern.
+
+*Inclusive range patterns* match all the values between and including both of its bounds.
+It is written as its lower bounds, followed by `..=`, followed by its upper bounds.
+The type of it is the type unification of its upper and lower bounds.
+
+For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`.
+
+The lower bound cannot be greater than the upper bound.
+That is, in `a..=b`, a &le; b must be the case.
+For example, it is an error to have a range pattern `10..=0`.
-For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. For an integer the
-pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but
-not 0, and not negative numbers for signed integers. The bounds can be literals or paths that point
-to constant values.
+Range patterns are *half-open* if they have only an upper or lower bound.
+They have the same type as their upper or lower bound.
-A half-open range pattern in the style `a..` cannot be used to match within the context of a slice.
+A half open range with only a lower bound is written as its lower bound followed by `..`.
+These range patterns will match on any value greater than or equal to the lower bound.
+For example, `1..` will match 1, 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers.
+The bounds can be literals or paths that point to constant values.
-A pattern `a..=b` must always have a &le; b. It is an error to have a range pattern
-`10..=0`, for example.
+A half open range with only an upper bound is written as `..=` followed by its upper bound.
+These range patterns will match on any value less than or equal to the upper bound.
+For example, `..=10` will match 10, 1, 0, and for signed interger types, all negative values.
-Range patterns only work on scalar types. The accepted types are:
+Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
-* Integer types (u8, i8, u16, i16, usize, isize, etc.).
-* Character types (char).
-* Floating point types (f32 and f64). This is being deprecated and will not be available
- in a future version of Rust (see
- [issue #41620](https://github.com/rust-lang/rust/issues/41620)).
+The bounds is written as one of:
+
+* A character, byte, integer, or float literal.
+* A `-` followed by an integer or float literal.
+* A [path]
+
+If the bounds is written as a path, after macro resolution, the path must resolve to a constant item of the type `char`, an integer type, or a float type.
+
+The type and value of the bounds is dependent upon how it is written out.
+If the bounds is a [path], the pattern has the type and value of the [constant] the path resolves to.
+If it is a literal, it has the type and value of the corresponding [literal expression].
+If is a literal preceded by a `-`, it has the same type as the corresponding [literal expression] and the value of [negating] the value of the corresponding literal expression.
Examples:
@@ -524,23 +521,26 @@ println!("{}", match 0xfacade {
});
```
-Range patterns for (non-`usize` and -`isize`) integer and `char` types are irrefutable
-when they span the entire set of possible values of a type. For example, `0u8..=255u8`
-is irrefutable. The range of values for an integer type is the closed range from its
-minimum to maximum value. The range of values for a `char` type are precisely those
-ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and
-`'\u{E000}'..='\u{10FFFF}'`.
+Range patterns for fix-width integer and `char` types are irrefutable when they span the entire set of possible values of a type.
+For example, `0u8..=255u8` is irrefutable.
+The range of values for an integer type is the closed range from its minimum to maximum value.
+The range of values for a `char` type are precisely those ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and `'\u{E000}'..='\u{10FFFF}'`.
+
+Floating point range patterns are deprecated and may be removed in a future Rust release.
+See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more information.
> **Edition Differences**: Before the 2021 edition, closed range patterns may also be written using `...` as an alternative to `..=`, with the same meaning.
+> **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns.
+> That is, neither `x .. y` nor `.. x` are valid range patterns.
+
## Reference patterns
> **<sup>Syntax</sup>**\
> _ReferencePattern_ :\
> &nbsp;&nbsp; (`&`|`&&`) `mut`<sup>?</sup> [_PatternWithoutRange_]
-Reference patterns dereference the pointers that are being matched
-and, thus, borrow them.
+Reference patterns dereference the pointers that are being matched and, thus, borrow them.
For example, these two matches on `x: &i32` are equivalent:
@@ -553,11 +553,9 @@ let b = match int_reference { &0 => "zero", _ => "some" };
assert_eq!(a, b);
```
-The grammar production for reference patterns has to match the token `&&` to match a
-reference to a reference because it is a token by itself, not two `&` tokens.
+The grammar production for reference patterns has to match the token `&&` to match a reference to a reference because it is a token by itself, not two `&` tokens.
-Adding the `mut` keyword dereferences a mutable reference. The mutability must match the
-mutability of the reference.
+Adding the `mut` keyword dereferences a mutable reference. The mutability must match the mutability of the reference.
Reference patterns are always irrefutable.
@@ -594,8 +592,7 @@ Reference patterns are always irrefutable.
Struct patterns match struct values that match all criteria defined by its subpatterns.
They are also used to [destructure](#destructuring) a struct.
-On a struct pattern, the fields are referenced by name, index (in the case of tuple
-structs) or ignored by use of `..`:
+On a struct pattern, the fields are referenced by name, index (in the case of tuple structs) or ignored by use of `..`:
```rust
# struct Point {
@@ -644,8 +641,7 @@ match struct_value {
}
```
-The `ref` and/or `mut` _IDENTIFIER_ syntax matches any value and binds it to
-a variable with the same name as the given field.
+The `ref` and/or `mut` _IDENTIFIER_ syntax matches any value and binds it to a variable with the same name as the given field.
```rust
# struct Struct {
@@ -669,9 +665,8 @@ A struct pattern is refutable when one of its subpatterns is refutable.
> _TupleStructItems_ :\
> &nbsp;&nbsp; [_Pattern_]&nbsp;( `,` [_Pattern_] )<sup>\*</sup> `,`<sup>?</sup>
-Tuple struct patterns match tuple struct and enum values that match all criteria defined
-by its subpatterns. They are also used to [destructure](#destructuring) a tuple struct or
-enum value.
+Tuple struct patterns match tuple struct and enum values that match all criteria defined by its subpatterns.
+They are also used to [destructure](#destructuring) a tuple struct or enum value.
A tuple struct pattern is refutable when one of its subpatterns is refutable.
@@ -689,8 +684,7 @@ A tuple struct pattern is refutable when one of its subpatterns is refutable.
Tuple patterns match tuple values that match all criteria defined by its subpatterns.
They are also used to [destructure](#destructuring) a tuple.
-The form `(..)` with a single [_RestPattern_] is a special form that does not
-require a comma, and matches a tuple of any size.
+The form `(..)` with a single [_RestPattern_] is a special form that does not require a comma, and matches a tuple of any size.
The tuple pattern is refutable when one of its subpatterns is refutable.
@@ -710,10 +704,8 @@ assert_eq!(b, "ten");
> _GroupedPattern_ :\
> &nbsp;&nbsp; `(` [_Pattern_] `)`
-Enclosing a pattern in parentheses can be used to explicitly control the
-precedence of compound patterns. For example, a reference pattern next to a
-range pattern such as `&0..=5` is ambiguous and is not allowed, but can be
-expressed with parentheses.
+Enclosing a pattern in parentheses can be used to explicitly control the precedence of compound patterns.
+For example, a reference pattern next to a range pattern such as `&0..=5` is ambiguous and is not allowed, but can be expressed with parentheses.
```rust
let int_reference = &3;
@@ -733,6 +725,7 @@ match int_reference {
> &nbsp;&nbsp; [_Pattern_] \(`,` [_Pattern_])<sup>\*</sup> `,`<sup>?</sup>
Slice patterns can match both arrays of fixed size and slices of dynamic size.
+
```rust
// Fixed size
let arr = [1, 2, 3];
@@ -751,14 +744,10 @@ match v[..] {
};
```
-Slice patterns are irrefutable when matching an array as long as each element
-is irrefutable. When matching a slice, it is irrefutable only in the form with
-a single `..` [rest pattern](#rest-patterns) or [identifier
-pattern](#identifier-patterns) with the `..` rest pattern as a subpattern.
+Slice patterns are irrefutable when matching an array as long as each element is irrefutable.
+When matching a slice, it is irrefutable only in the form with a single `..` [rest pattern](#rest-patterns) or [identifier pattern](#identifier-patterns) with the `..` rest pattern as a subpattern.
-Within a slice, a half-open range pattern like `a..` must be enclosed in parentheses,
-as in `(a..)`, to clarify it is intended to match a single value.
-A future version of Rust may give the non-parenthesized version an alternate meaning.
+Within a slice, a half-open range pattern like `a..` must be enclosed in parentheses, as in `(a..)`, to clarify it is intended to match a single value.
## Path patterns
@@ -778,33 +767,27 @@ Unqualified path patterns can refer to:
Qualified path patterns can only refer to associated constants.
-Constants cannot be a union type. Struct and enum constants must have
-`#[derive(PartialEq, Eq)]` (not merely implemented).
+Constants cannot be a union type.
+Struct and enum constants must have `#[derive(PartialEq, Eq)]` (not merely implemented).
-Path patterns are irrefutable when they refer to structs or an enum variant when the enum
-has only one variant or a constant whose type is irrefutable. They are refutable when they
-refer to refutable constants or enum variants for enums with multiple variants.
+Path patterns are irrefutable when they refer to structs or an enum variant when the enum has only one variant or a constant whose type is irrefutable.
+They are refutable when they refer to refutable constants or enum variants for enums with multiple variants.
## Or-patterns
-_Or-patterns_ are patterns that match on one of two or more sub-patterns (e.g.
-`A | B | C`). They can nest arbitrarily. Syntactically, or-patterns are allowed
-in any of the places where other patterns are allowed (represented by the
-_Pattern_ production), with the exceptions of `let`-bindings and function and
-closure arguments (represented by the _PatternNoTopAlt_ production).
+_Or-patterns_ are patterns that match on one of two or more sub-patterns (for example `A | B | C`).
+They can nest arbitrarily.
+Syntactically, or-patterns are allowed in any of the places where other patterns are allowed (represented by the _Pattern_ production), with the exceptions of `let`-bindings and function and closure arguments (represented by the _PatternNoTopAlt_ production).
### Static semantics
-1. Given a pattern `p | q` at some depth for some arbitrary patterns `p` and `q`,
- the pattern is considered ill-formed if:
+1. Given a pattern `p | q` at some depth for some arbitrary patterns `p` and `q`, the pattern is considered ill-formed if:
+ the type inferred for `p` does not unify with the type inferred for `q`, or
+ the same set of bindings are not introduced in `p` and `q`, or
- + the type of any two bindings with the same name in `p` and `q` do not unify
- with respect to types or binding modes.
+ + the type of any two bindings with the same name in `p` and `q` do not unify with respect to types or binding modes.
- Unification of types is in all instances aforementioned exact and
- implicit [type coercions] do not apply.
+ Unification of types is in all instances aforementioned exact and implicit [type coercions] do not apply.
2. When type checking an expression `match e_s { a_1 => e_1, ... a_n => e_n }`,
for each match arm `a_i` which contains a pattern of form `p_i | q_i`,
@@ -812,35 +795,27 @@ closure arguments (represented by the _PatternNoTopAlt_ production).
at the depth `d` where it exists the fragment of `e_s` at depth `d`,
the type of the expression fragment does not unify with `p_i | q_i`.
-3. With respect to exhaustiveness checking, a pattern `p | q` is
- considered to cover `p` as well as `q`. For some constructor `c(x, ..)`
- the distributive law applies such that `c(p | q, ..rest)` covers the same
- set of value as `c(p, ..rest) | c(q, ..rest)` does. This can be applied
- recursively until there are no more nested patterns of form `p | q` other
- than those that exist at the top level.
+3. With respect to exhaustiveness checking, a pattern `p | q` is considered to cover `p` as well as `q`.
+ For some constructor `c(x, ..)` the distributive law applies such that `c(p | q, ..rest)` covers the same set of value as `c(p, ..rest) | c(q, ..rest)` does.
+ This can be applied recursively until there are no more nested patterns of form `p | q` other than those that exist at the top level.
- Note that by *"constructor"* we do not refer to tuple struct patterns,
- but rather we refer to a pattern for any product type.
- This includes enum variants, tuple structs, structs with named fields,
- arrays, tuples, and slices.
+ Note that by *"constructor"* we do not refer to tuple struct patterns, but rather we refer to a pattern for any product type.
+ This includes enum variants, tuple structs, structs with named fields, arrays, tuples, and slices.
### Dynamic semantics
-1. The dynamic semantics of pattern matching a scrutinee expression `e_s`
- against a pattern `c(p | q, ..rest)` at depth `d` where `c` is some constructor,
- `p` and `q` are arbitrary patterns, and `rest` is optionally any remaining
- potential factors in `c`, is defined as being the same as that of
- `c(p, ..rest) | c(q, ..rest)`.
+1. The dynamic semantics of pattern matching a scrutinee expression `e_s` against a pattern `c(p | q, ..rest)` at depth `d` where `c` is some constructor,
+ `p` and `q` are arbitrary patterns,
+ and `rest` is optionally any remaining potential factors in `c`,
+ is defined as being the same as that of `c(p, ..rest) | c(q, ..rest)`.
### Precedence with other undelimited patterns
-As shown elsewhere in this chapter, there are several types of patterns that
-are syntactically undelimited, including identifier patterns, reference
-patterns, and or-patterns. Or-patterns always have the lowest-precedence. This
-allows us to reserve syntactic space for a possible future type ascription
-feature and also to reduce ambiguity. For example, `x @ A(..) | B(..)` will
-result in an error that `x` is not bound in all patterns, `&A(x) | B(x)` will
-result in a type mismatch between `x` in the different subpatterns.
+As shown elsewhere in this chapter, there are several types of patterns that are syntactically undelimited, including identifier patterns, reference patterns, and or-patterns.
+Or-patterns always have the lowest-precedence.
+This allows us to reserve syntactic space for a possible future type ascription feature and also to reduce ambiguity.
+For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound in all patterns.
+`&A(x) | B(x)` will result in a type mismatch between `x` in the different subpatterns.
[_GroupedPattern_]: #grouped-patterns
[_IdentifierPattern_]: #identifier-patterns
@@ -865,8 +840,13 @@ result in a type mismatch between `x` in the different subpatterns.
[`Copy`]: special-types-and-traits.md#copy
[IDENTIFIER]: identifiers.md
+[constant]: items/constant-items.md
[enums]: items/enumerations.md
[literals]: expressions/literal-expr.md
+[literal expression]: expressions/literal-expr.md
+[negating]: expressions/operator-expr.md#negation-operators
+[path]: expressions/path-expr.md
+[range expressions]: expressions/range-expr.md
[structs]: items/structs.md
[tuples]: types/tuple.md
[scrutinee]: glossary.md#scrutinee
diff --git a/src/doc/reference/src/statements-and-expressions.md b/src/doc/reference/src/statements-and-expressions.md
index b093972a9..fede41196 100644
--- a/src/doc/reference/src/statements-and-expressions.md
+++ b/src/doc/reference/src/statements-and-expressions.md
@@ -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.
diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md
index 8d9c21d7d..c2ae585a0 100644
--- a/src/doc/reference/src/statements.md
+++ b/src/doc/reference/src/statements.md
@@ -9,35 +9,27 @@
> &nbsp;&nbsp; | [_MacroInvocationSemi_]
-A *statement* is a component of a [block], which is in turn a component of an
-outer [expression] or [function].
+A *statement* is a component of a [block], which is in turn a component of an outer [expression] or [function].
-Rust has two kinds of statement: [declaration
-statements](#declaration-statements) and [expression
-statements](#expression-statements).
+Rust has two kinds of statement: [declaration statements](#declaration-statements) and [expression statements](#expression-statements).
## Declaration statements
-A *declaration statement* is one that introduces one or more *names* into the
-enclosing statement block. The declared names may denote new variables or new
-[items][item].
+A *declaration statement* is one that introduces one or more *names* into the enclosing statement block.
+The declared names may denote new variables or new [items][item].
-The two kinds of declaration statements are item declarations and `let`
-statements.
+The two kinds of declaration statements are item declarations and `let` statements.
### Item declarations
-An *item declaration statement* has a syntactic form identical to an
-[item declaration][item] within a [module]. Declaring an item within a statement
-block restricts its scope to the block containing the statement. The item is not
-given a [canonical path] nor are any sub-items it may declare. The exception to
-this is that associated items defined by [implementations] are still accessible
-in outer scopes as long as the item and, if applicable, trait are accessible.
+An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module].
+Declaring an item within a statement block restricts its scope to the block containing the statement.
+The item is not given a [canonical path] nor are any sub-items it may declare.
+The exception to this is that associated items defined by [implementations] are still accessible in outer scopes as long as the item and, if applicable, trait are accessible.
It is otherwise identical in meaning to declaring the item inside a module.
-There is no implicit capture of the containing function's generic parameters,
-parameters, and local variables. For example, `inner` may not access
-`outer_var`.
+There is no implicit capture of the containing function's generic parameters, parameters, and local variables.
+For example, `inner` may not access `outer_var`.
```rust
fn outer() {
@@ -54,16 +46,32 @@ fn outer() {
> **<sup>Syntax</sup>**\
> _LetStatement_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> `let` [_PatternNoTopAlt_]
-> ( `:` [_Type_] )<sup>?</sup> (`=` [_Expression_] )<sup>?</sup> `;`
+> ( `:` [_Type_] )<sup>?</sup> (`=` [_Expression_] [†](#let-else-restriction)
+> ( `else` [_BlockExpression_]) <sup>?</sup> ) <sup>?</sup> `;`
+>
+> <span id="let-else-restriction">† When an `else` block is specified, the
+> _Expression_ must not be a [_LazyBooleanExpression_], or end with a `}`.</span>
+
+A *`let` statement* introduces a new set of [variables], given by a [pattern].
+The pattern is followed optionally by a type annotation and then either ends, or is followed by an initializer expression plus an optional `else` block.
+When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference.
+Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope, except when they are shadowed by another variable declaration.
+
+If an `else` block is not present, the pattern must be irrefutable.
+If an `else` block is present, the pattern may be refutable.
+If the pattern does not match (this requires it to be refutable), the `else` block is executed.
+The `else` block must always diverge (evaluate to the [never type]).
-A *`let` statement* introduces a new set of [variables], given by an
-irrefutable [pattern]. The pattern is followed optionally by a type
-annotation and then optionally by an initializer expression. When no
-type annotation is given, the compiler will infer the type, or signal
-an error if insufficient type information is available for definite
-inference. Any variables introduced by a variable declaration are visible
-from the point of declaration until the end of the enclosing block scope,
-except when they are shadowed by another variable declaration.
+```rust
+let (mut v, w) = (vec![1, 2, 3], 42); // The bindings may be mut or const
+let Some(t) = v.pop() else { // Refutable patterns require an else block
+ panic!(); // The else block must diverge
+};
+let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler
+ // will lint as the else block is redundant.
+ panic!();
+};
+```
## Expression statements
@@ -72,16 +80,13 @@ except when they are shadowed by another variable declaration.
> &nbsp;&nbsp; &nbsp;&nbsp; [_ExpressionWithoutBlock_][expression] `;`\
> &nbsp;&nbsp; | [_ExpressionWithBlock_][expression] `;`<sup>?</sup>
-An *expression statement* is one that evaluates an [expression] and ignores its
-result. As a rule, an expression statement's purpose is to trigger the effects
-of evaluating its expression.
+An *expression statement* is one that evaluates an [expression] and ignores its result.
+As a rule, an expression statement's purpose is to trigger the effects of evaluating its expression.
-An expression that consists of only a [block expression][block] or control flow
-expression, if used in a context where a statement is permitted, can omit the
-trailing semicolon. This can cause an ambiguity between it being parsed as a
-standalone statement and as a part of another expression; in this case, it is
-parsed as a statement. The type of [_ExpressionWithBlock_][expression]
-expressions when used as statements must be the unit type.
+An expression that consists of only a [block expression][block] or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon.
+This can cause an ambiguity between it being parsed as a standalone statement and as a part of another expression;
+in this case, it is parsed as a statement.
+The type of [_ExpressionWithBlock_][expression] expressions when used as statements must be the unit type.
```rust
# let mut v = vec![1, 2, 3];
@@ -113,14 +118,15 @@ if true {
## Attributes on Statements
-Statements accept [outer attributes]. The attributes that have meaning on a
-statement are [`cfg`], and [the lint check attributes].
+Statements accept [outer attributes].
+The attributes that have meaning on a statement are [`cfg`], and [the lint check attributes].
[block]: expressions/block-expr.md
[expression]: expressions.md
[function]: items/functions.md
[item]: items.md
[module]: items/modules.md
+[never type]: types/never.md
[canonical path]: paths.md#canonical-paths
[implementations]: items/implementations.md
[variables]: variables.md
@@ -128,9 +134,11 @@ statement are [`cfg`], and [the lint check attributes].
[`cfg`]: conditional-compilation.md
[the lint check attributes]: attributes/diagnostics.md#lint-check-attributes
[pattern]: patterns.md
+[_BlockExpression_]: expressions/block-expr.md
[_ExpressionStatement_]: #expression-statements
[_Expression_]: expressions.md
[_Item_]: items.md
+[_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators
[_LetStatement_]: #let-statements
[_MacroInvocationSemi_]: macros.md#macro-invocation
[_OuterAttribute_]: attributes.md
diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md
index 197c20147..8f9bcb1f7 100644
--- a/src/doc/reference/src/tokens.md
+++ b/src/doc/reference/src/tokens.md
@@ -667,7 +667,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite
> **Edition Differences**: Starting with the 2021 edition, reserved prefixes are reported as an error by the lexer (in particular, they cannot be passed to macros).
>
-> Before the 2021 edition, a reserved prefixes are accepted by the lexer and interpreted as multiple tokens (for example, one token for the identifier or keyword, followed by a `#` token).
+> Before the 2021 edition, reserved prefixes are accepted by the lexer and interpreted as multiple tokens (for example, one token for the identifier or keyword, followed by a `#` token).
>
> Examples accepted in all editions:
> ```rust
diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md
index ce9296662..80a36abb8 100644
--- a/src/doc/reference/src/type-layout.md
+++ b/src/doc/reference/src/type-layout.md
@@ -20,8 +20,10 @@ The alignment of a value can be checked with the [`align_of_val`] function.
The *size* of a value is the offset in bytes between successive elements in an
array with that item type including alignment padding. The size of a value is
-always a multiple of its alignment. The size of a value can be checked with the
-[`size_of_val`] function.
+always a multiple of its alignment. Note that some types are zero-sized; 0 is
+considered a multiple of any alignment (for example, on some platforms, the type
+`[u16; 0]` has size 0 and alignment 2). The size of a value can be checked with
+the [`size_of_val`] function.
Types where all values have the same size and alignment, and both are known at
compile time, implement the [`Sized`] trait and can be checked with the
@@ -86,9 +88,9 @@ String slices are a UTF-8 representation of characters that have the same layout
## Tuple Layout
-Tuples do not have any guarantees about their layout.
+Tuples are laid out according to the [default representation][Default].
-The exception to this is the unit tuple (`()`) which is guaranteed as a
+The exception to this is the unit tuple (`()`), which is guaranteed as a
zero-sized type to have a size of 0 and an alignment of 1.
## Trait Object Layout
@@ -162,7 +164,25 @@ representation will not change the layout of `Inner`.
Nominal types without a `repr` attribute have the default representation.
Informally, this representation is also called the `rust` representation.
-There are no guarantees of data layout made by this representation.
+The only data layout guarantees made by this representation are those required
+for soundness. They are:
+
+ 1. The fields are properly aligned.
+ 2. The fields do not overlap.
+ 3. The alignment of the type is at least the maximum alignment of its fields.
+
+Formally, the first guarantee means that the offset of any field is divisible by
+that field's alignment. The second guarantee means that the fields can be
+ordered such that the offset plus the size of any field is less than or equal to
+the offset of the next field in the ordering. The ordering does not have to be
+the same as the order in which the fields are specified in the declaration of
+the type.
+
+Be aware that the second guarantee does not imply that the fields have distinct
+addresses: zero-sized types may have the same address as other fields in the
+same struct.
+
+There are no other guarantees of data layout made by this representation.
### The `C` Representation
diff --git a/src/doc/reference/src/types/function-pointer.md b/src/doc/reference/src/types/function-pointer.md
index a51f76135..82103beaa 100644
--- a/src/doc/reference/src/types/function-pointer.md
+++ b/src/doc/reference/src/types/function-pointer.md
@@ -62,5 +62,5 @@ restrictions as [regular function parameters].
[closures]: closure.md
[extern function]: ../items/functions.md#extern-function-qualifier
[function items]: function-item.md
-[unsafe function]: ../unsafe-functions.md
+[unsafe function]: ../unsafe-keyword.md
[regular function parameters]: ../items/functions.md#attributes-on-function-parameters
diff --git a/src/doc/reference/src/types/pointer.md b/src/doc/reference/src/types/pointer.md
index 9c8d80f39..4a74370a5 100644
--- a/src/doc/reference/src/types/pointer.md
+++ b/src/doc/reference/src/types/pointer.md
@@ -11,8 +11,8 @@ They can be moved or copied, stored into data structs, and returned from functio
### Shared references (`&`)
-These point to memory _owned by some other value_.
-When a shared reference to a value is created it prevents direct mutation of the value.
+Shared references point to memory which is owned by some other value.
+When a shared reference to a value is created, it prevents direct mutation of the value.
[Interior mutability] provides an exception for this in certain circumstances.
As the name suggests, any number of shared references to a value may exist.
A shared reference type is written `&type`, or `&'a type` when you need to specify an explicit lifetime.
@@ -22,7 +22,7 @@ Releasing a reference has no effect on the value it points to, but referencing o
### Mutable references (`&mut`)
-These also point to memory owned by some other value.
+Mutable references point to memory which is owned by some other value.
A mutable reference type is written `&mut type` or `&'a mut type`.
A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`.
diff --git a/src/doc/reference/src/unsafe-blocks.md b/src/doc/reference/src/unsafe-blocks.md
deleted file mode 100644
index 754278445..000000000
--- a/src/doc/reference/src/unsafe-blocks.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Unsafe blocks
-
-A block of code can be prefixed with the `unsafe` keyword, to permit calling
-`unsafe` functions or dereferencing raw pointers within a safe function.
-
-When a programmer has sufficient conviction that a sequence of potentially
-unsafe operations is actually safe, they can encapsulate that sequence (taken
-as a whole) within an `unsafe` block. The compiler will consider uses of such
-code safe, in the surrounding context.
-
-Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
-or implement features not directly present in the language. For example, Rust
-provides the language features necessary to implement memory-safe concurrency
-in the language but the implementation of threads and message passing is in the
-standard library.
-
-Rust's type system is a conservative approximation of the dynamic safety
-requirements, so in some cases there is a performance cost to using safe code.
-For example, a doubly-linked list is not a tree structure and can only be
-represented with reference-counted pointers in safe code. By using `unsafe`
-blocks to represent the reverse links as raw pointers, it can be implemented
-with only boxes.
diff --git a/src/doc/reference/src/unsafe-functions.md b/src/doc/reference/src/unsafe-functions.md
deleted file mode 100644
index 7a5064c08..000000000
--- a/src/doc/reference/src/unsafe-functions.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Unsafe functions
-
-Unsafe functions are functions that are not safe in all contexts and/or for all
-possible inputs. Such a function must be prefixed with the keyword `unsafe` and
-can only be called from an `unsafe` block or another `unsafe` function.
diff --git a/src/doc/reference/src/unsafe-keyword.md b/src/doc/reference/src/unsafe-keyword.md
new file mode 100644
index 000000000..5fa5deea6
--- /dev/null
+++ b/src/doc/reference/src/unsafe-keyword.md
@@ -0,0 +1,58 @@
+# The `unsafe` keyword
+
+The `unsafe` keyword can occur in several different contexts:
+unsafe functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe trait`), and unsafe trait implementations (`unsafe impl`).
+It plays several different roles, depending on where it is used and whether the `unsafe_op_in_unsafe_fn` lint is enabled:
+- it is used to mark code that *defines* extra safety conditions (`unsafe fn`, `unsafe trait`)
+- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without [`unsafe_op_in_unsafe_fn`])
+
+The following discusses each of these cases.
+See the [keyword documentation][keyword] for some illustrative examples.
+
+## Unsafe functions (`unsafe fn`)
+
+Unsafe functions are functions that are not safe in all contexts and/or for all possible inputs.
+We say they have *extra safety conditions*, which are requirements that must be upheld by all callers and that the compiler does not check.
+For example, [`get_unchecked`] has the extra safety condition that the index must be in-bounds.
+The unsafe function should come with documentation explaining what those extra safety conditions are.
+
+Such a function must be prefixed with the keyword `unsafe` and can only be called from inside an `unsafe` block, or inside `unsafe fn` without the [`unsafe_op_in_unsafe_fn`] lint.
+
+## Unsafe blocks (`unsafe {}`)
+
+A block of code can be prefixed with the `unsafe` keyword, to permit calling `unsafe` functions or dereferencing raw pointers.
+By default, the body of an unsafe function is also considered to be an unsafe block;
+this can be changed by enabling the [`unsafe_op_in_unsafe_fn`] lint.
+
+By putting operations into an unsafe block, the programmer states that they have taken care of satisfying the extra safety conditions of all operations inside that block.
+
+Unsafe blocks are the logical dual to unsafe functions:
+where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations have been discharged.
+There are many ways to discharge proof obligations;
+for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn` and use its own proof obligations to discharge the proof obligations of its callees.
+
+Unsafe blocks are used to wrap foreign libraries, make direct use of hardware or implement features not directly present in the language.
+For example, Rust provides the language features necessary to implement memory-safe concurrency in the language but the implementation of threads and message passing in the standard library uses unsafe blocks.
+
+Rust's type system is a conservative approximation of the dynamic safety requirements, so in some cases there is a performance cost to using safe code.
+For example, a doubly-linked list is not a tree structure and can only be represented with reference-counted pointers in safe code.
+By using `unsafe` blocks to represent the reverse links as raw pointers, it can be implemented without reference counting.
+(See ["Learn Rust With Entirely Too Many Linked Lists"](https://rust-unofficial.github.io/too-many-lists/) for a more in-depth exploration of this particular example.)
+
+## Unsafe traits (`unsafe trait`)
+
+An unsafe trait is a trait that comes with extra safety conditions that must be upheld by *implementations* of the trait.
+The unsafe trait should come with documentation explaining what those extra safety conditions are.
+
+Such a trait must be prefixed with the keyword `unsafe` and can only be implemented by `unsafe impl` blocks.
+
+## Unsafe trait implementations (`unsafe impl`)
+
+When implementing an unsafe trait, the implementation needs to be prefixed with the `unsafe` keyword.
+By writing `unsafe impl`, the programmer states that they have taken care of satisfying the extra safety conditions required by the trait.
+
+Unsafe trait implementations are the logical dual to unsafe traits: where unsafe traits define a proof obligation that implementations must uphold, unsafe implementations state that all relevant proof obligations have been discharged.
+
+[keyword]: ../std/keyword.unsafe.html
+[`get_unchecked`]: ../std/primitive.slice.html#method.get_unchecked
+[`unsafe_op_in_unsafe_fn`]: ../rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn