diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:13:23 +0000 |
commit | 20431706a863f92cb37dc512fef6e48d192aaf2c (patch) | |
tree | 2867f13f5fd5437ba628c67d7f87309ccadcd286 /src/doc/reference | |
parent | Releasing progress-linux version 1.65.0+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.tar.xz rustc-20431706a863f92cb37dc512fef6e48d192aaf2c.zip |
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/doc/reference')
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 @@ > | [_MethodCallExpression_]\ > | [_FieldExpression_]\ > | [_ClosureExpression_]\ +> | [_AsyncBlockExpression_]\ > | [_ContinueExpression_]\ > | [_BreakExpression_]\ > | [_RangeExpression_]\ @@ -34,7 +35,6 @@ > [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\ > (\ > [_BlockExpression_]\ -> | [_AsyncBlockExpression_]\ > | [_UnsafeBlockExpression_]\ > | [_LoopExpression_]\ > | [_IfExpression_]\ @@ -42,28 +42,24 @@ > | [_MatchExpression_]\ > ) -An expression may have two roles: it always produces a *value*, and it may have -*effects* (otherwise known as "side effects"). An expression *evaluates to* a -value, and has effects during *evaluation*. Many expressions contain -sub-expressions, called the *operands* of the expression. The meaning of each -kind of expression dictates several things: +An expression may have two roles: it always produces a *value*, and it may have *effects* (otherwise known as "side effects"). +An expression *evaluates to* a value, and has effects during *evaluation*. +Many expressions contain sub-expressions, called the *operands* of the expression. +The meaning of each kind of expression dictates several things: * Whether or not to evaluate the operands when evaluating the expression * The order in which to evaluate the operands * How to combine the operands' values to obtain the value of the expression In this way, the structure of expressions dictates the structure of execution. -Blocks are just another kind of expression, so blocks, statements, expressions, -and blocks again can recursively nest inside each other to an arbitrary depth. +Blocks are just another kind of expression, so blocks, statements, expressions, and blocks again can recursively nest inside each other to an arbitrary depth. -> **Note**: We give names to the operands of expressions so that we may discuss -> them, but these names are not stable and may be changed. +> **Note**: We give names to the operands of expressions so that we may discuss them, but these names are not stable and may be changed. ## Expression precedence -The precedence of Rust operators and expressions is ordered as follows, going -from strong to weak. Binary Operators at the same precedence level are grouped -in the order given by their associativity. +The precedence of Rust operators and expressions is ordered as follows, going from strong to weak. +Binary Operators at the same precedence level are grouped in the order given by their associativity. | Operator/Expression | Associativity | |-----------------------------|---------------------| @@ -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_ :\ > [_OuterAttribute_]<sup>\*</sup> [_PatternNoTopAlt_] ( `:` [_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 @@ > | [_PredicateLoopExpression_]\ > | [_PredicatePatternLoopExpression_]\ > | [_IteratorLoopExpression_]\ +> | [_LabelBlockExpression_]\ > ) [_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_ :\ +> [_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_ :\ > `type` [IDENTIFIER] [_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 @@ > | [_PathPattern_]\ > | [_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_ :\ > `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_ :\ > `_` -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_ :\ > `..` -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 { > _RangePatternBound_ `..=` _RangePatternBound_ > > _HalfOpenRangePattern_ :\ -> | _RangePatternBound_ `..` +> _RangePatternBound_ `..` +> | `..=` _RangePatternBound_ > > _ObsoleteRangePattern_ :\ > _RangePatternBound_ `...` _RangePatternBound_ @@ -425,29 +401,50 @@ match tuple { > | `-`<sup>?</sup> [FLOAT_LITERAL]\ > | [_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 ≤ 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 ≤ 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_ :\ > (`&`|`&&`) `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_ :\ > [_Pattern_] ( `,` [_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_ :\ > `(` [_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 { > [_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 @@ > | [_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_ :\ > [_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. > [_ExpressionWithoutBlock_][expression] `;`\ > | [_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 |