From 49115e0d52bf24fb2ff39a4ca03e70870bdce4ec Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 25 Jan 2026 21:18:29 -0800 Subject: [PATCH] Unwrap items, expressions, patterns, and types This unwraps the text to follow our style guide. --- src/destructors.md | 113 ++++----------- src/dynamically-sized-types.md | 15 +- src/expressions.md | 49 ++----- src/expressions/array-expr.md | 15 +- src/expressions/await-expr.md | 10 +- src/expressions/block-expr.md | 33 ++--- src/expressions/call-expr.md | 9 +- src/expressions/closure-expr.md | 13 +- src/expressions/field-expr.md | 10 +- src/expressions/grouped-expr.md | 6 +- src/expressions/if-expr.md | 18 +-- src/expressions/literal-expr.md | 24 ++-- src/expressions/loop-expr.md | 38 ++--- src/expressions/match-expr.md | 25 ++-- src/expressions/method-call-expr.md | 22 +-- src/expressions/operator-expr.md | 88 ++++-------- src/expressions/struct-expr.md | 16 +-- src/expressions/tuple-expr.md | 9 +- src/expressions/underscore-expr.md | 3 +- src/interior-mutability.md | 24 +--- src/items.md | 8 +- src/items/associated-items.md | 132 +++++------------- src/items/constant-items.md | 28 ++-- src/items/enumerations.md | 57 +++----- src/items/extern-crates.md | 24 +--- src/items/external-blocks.md | 177 ++++++----------------- src/items/functions.md | 135 +++++------------- src/items/generics.md | 72 +++------- src/items/implementations.md | 80 +++-------- src/items/modules.md | 55 ++------ src/items/static-items.md | 50 ++----- src/items/structs.md | 12 +- src/items/traits.md | 43 ++---- src/items/type-aliases.md | 20 +-- src/items/unions.md | 60 ++------ src/items/use-declarations.md | 74 +++------- src/lifetime-elision.md | 54 +++---- src/patterns.md | 137 ++++++------------ src/statements-and-expressions.md | 4 +- src/statements.md | 31 ++--- src/subtyping.md | 37 ++--- src/trait-bounds.md | 62 +++------ src/type-coercions.md | 84 +++-------- src/type-layout.md | 209 +++++++--------------------- src/types.md | 29 +--- src/types/array.md | 6 +- src/types/boolean.md | 21 +-- src/types/closure.md | 67 +++------ src/types/enum.md | 16 +-- src/types/function-item.md | 23 +-- src/types/function-pointer.md | 6 +- src/types/impl-trait.md | 33 ++--- src/types/inferred.md | 3 +- src/types/never.md | 6 +- src/types/numeric.md | 18 +-- src/types/parameters.md | 6 +- src/types/pointer.md | 34 ++--- src/types/slice.md | 9 +- src/types/struct.md | 22 +-- src/types/textual.md | 22 +-- src/types/trait-object.md | 43 ++---- src/types/tuple.md | 20 +-- src/types/union.md | 17 +-- 63 files changed, 701 insertions(+), 1885 deletions(-) diff --git a/src/destructors.md b/src/destructors.md index 73b4d65948..572fdf7d76 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -2,11 +2,7 @@ r[destructors] # Destructors r[destructors.intro] -When an [initialized] [variable] or [temporary] goes out of -[scope](#drop-scopes), its *destructor* is run or it is *dropped*. [Assignment] -also runs the destructor of its left-hand operand, if it's initialized. If a -variable has been partially initialized, only its initialized fields are -dropped. +When an [initialized] [variable] or [temporary] goes out of [scope](#drop-scopes), its *destructor* is run or it is *dropped*. [Assignment] also runs the destructor of its left-hand operand, if it's initialized. If a variable has been partially initialized, only its initialized fields are dropped. r[destructors.operation] The destructor of a type `T` consists of: @@ -16,16 +12,13 @@ The destructor of a type `T` consists of: * The fields of a [struct] are dropped in declaration order. * The fields of the active [enum variant] are dropped in declaration order. * The fields of a [tuple] are dropped in order. - * The elements of an [array] or owned [slice] are dropped from the - first element to the last. - * The variables that a [closure] captures by move are dropped in an - unspecified order. + * The elements of an [array] or owned [slice] are dropped from the first element to the last. + * The variables that a [closure] captures by move are dropped in an unspecified order. * [Trait objects] run the destructor of the underlying type. * Other types don't result in any further drops. r[destructors.drop_in_place] -If a destructor must be run manually, such as when implementing your own smart -pointer, [`core::ptr::drop_in_place`] can be used. +If a destructor must be run manually, such as when implementing your own smart pointer, [`core::ptr::drop_in_place`] can be used. Some examples: @@ -63,18 +56,13 @@ r[destructors.scope] ## Drop scopes r[destructors.scope.intro] -Each variable or temporary is associated to a *drop scope*. When control flow -leaves a drop scope all variables associated to that scope are dropped in -reverse order of declaration (for variables) or creation (for temporaries). +Each variable or temporary is associated to a *drop scope*. When control flow leaves a drop scope all variables associated to that scope are dropped in reverse order of declaration (for variables) or creation (for temporaries). r[destructors.scope.desugaring] -Drop scopes can be determined by replacing [`for`], [`if`], and [`while`] -expressions with equivalent expressions using [`match`], [`loop`] and -`break`. +Drop scopes can be determined by replacing [`for`], [`if`], and [`while`] expressions with equivalent expressions using [`match`], [`loop`] and `break`. r[destructors.scope.operators] -Overloaded operators are not distinguished from built-in operators and [binding -modes] are not considered. +Overloaded operators are not distinguished from built-in operators and [binding modes] are not considered. r[destructors.scope.list] Given a function, or closure, there are drop scopes for: @@ -90,16 +78,13 @@ r[destructors.scope.expression] r[destructors.scope.block] * Each block, including the function body - * In the case of a [block expression], the scope for the block and the - expression are the same scope. + * In the case of a [block expression], the scope for the block and the expression are the same scope. r[destructors.scope.match-arm] * Each arm of a `match` expression r[destructors.scope.nesting] -Drop scopes are nested within one another as follows. When multiple scopes are -left at once, such as when returning from a function, variables are dropped -from the inside outwards. +Drop scopes are nested within one another as follows. When multiple scopes are left at once, such as when returning from a function, variables are dropped from the inside outwards. r[destructors.scope.nesting.function] * The entire function scope is the outer most scope. @@ -108,39 +93,30 @@ r[destructors.scope.nesting.function-body] * The function body block is contained within the scope of the entire function. r[destructors.scope.nesting.expr-statement] -* The parent of the expression in an expression statement is the scope of the - statement. +* The parent of the expression in an expression statement is the scope of the statement. r[destructors.scope.nesting.let-initializer] -* The parent of the initializer of a [`let` statement] is the `let` statement's - scope. +* The parent of the initializer of a [`let` statement] is the `let` statement's scope. r[destructors.scope.nesting.statement] -* The parent of a statement scope is the scope of the block that contains the - statement. +* The parent of a statement scope is the scope of the block that contains the statement. r[destructors.scope.nesting.match-guard] -* The parent of the expression for a `match` guard is the scope of the arm that - the guard is for. +* The parent of the expression for a `match` guard is the scope of the arm that the guard is for. r[destructors.scope.nesting.match-arm] -* The parent of the expression after the `=>` in a `match` expression is the - scope of the arm that it's in. +* The parent of the expression after the `=>` in a `match` expression is the scope of the arm that it's in. r[destructors.scope.nesting.match] -* The parent of the arm scope is the scope of the `match` expression that it - belongs to. +* The parent of the arm scope is the scope of the `match` expression that it belongs to. r[destructors.scope.nesting.other] -* The parent of all other scopes is the scope of the immediately enclosing - expression. +* The parent of all other scopes is the scope of the immediately enclosing expression. r[destructors.scope.params] ### Scopes of function parameters -All function parameters are in the scope of the entire function body, so are -dropped last when evaluating the function. Each actual function parameter is -dropped after any bindings introduced in that parameter's pattern. +All function parameters are in the scope of the entire function body, so are dropped last when evaluating the function. Each actual function parameter is dropped after any bindings introduced in that parameter's pattern. ```rust # struct PrintOnDrop(&'static str); @@ -166,10 +142,7 @@ r[destructors.scope.bindings] ### Scopes of local variables r[destructors.scope.bindings.intro] -Local variables declared in a `let` statement are associated to the scope of -the block that contains the `let` statement. Local variables declared in a -`match` expression are associated to the arm scope of the `match` arm that they -are declared in. +Local variables declared in a `let` statement are associated to the scope of the block that contains the `let` statement. Local variables declared in a `match` expression are associated to the arm scope of the `match` arm that they are declared in. ```rust # struct PrintOnDrop(&'static str); @@ -243,20 +216,16 @@ r[destructors.scope.temporary] ### Temporary scopes r[destructors.scope.temporary.intro] -The *temporary scope* of an expression is the scope that is used for the -temporary variable that holds the result of that expression when used in a -[place context], unless it is [promoted]. +The *temporary scope* of an expression is the scope that is used for the temporary variable that holds the result of that expression when used in a [place context], unless it is [promoted]. r[destructors.scope.temporary.enclosing] -Apart from lifetime extension, the temporary scope of an expression is the -smallest scope that contains the expression and is one of the following: +Apart from lifetime extension, the temporary scope of an expression is the smallest scope that contains the expression and is one of the following: * The entire function. * A statement. * The body of an [`if`], [`while`] or [`loop`] expression. * The `else` block of an `if` expression. -* The non-pattern matching condition expression of an `if` or `while` expression, - or a `match` guard. +* The non-pattern matching condition expression of an `if` or `while` expression, or a `match` guard. * The body expression for a match arm. * Each operand of a [lazy boolean expression]. * The pattern-matching condition(s) and consequent body of [`if`] ([destructors.scope.temporary.edition2024]). @@ -329,11 +298,7 @@ match PrintOnDrop("Matched value in final expression") { r[destructors.scope.operands] ### Operands -Temporaries are also created to hold the result of operands to an expression -while the other operands are evaluated. The temporaries are associated to the -scope of the expression with that operand. Since the temporaries are moved from -once the expression is evaluated, dropping them has no effect unless one of the -operands to an expression breaks out of the expression, returns, or [panics][panic]. +Temporaries are also created to hold the result of operands to an expression while the other operands are evaluated. The temporaries are associated to the scope of the expression with that operand. Since the temporaries are moved from once the expression is evaluated, dropping them has no effect unless one of the operands to an expression breaks out of the expression, returns, or [panics][panic]. ```rust # struct PrintOnDrop(&'static str); @@ -360,14 +325,7 @@ loop { r[destructors.scope.const-promotion] ### Constant promotion -Promotion of a value expression to a `'static` slot occurs when the expression -could be written in a constant and borrowed, and that borrow could be dereferenced -where -the expression was originally written, without changing the runtime behavior. -That is, the promoted expression can be evaluated at compile-time and the -resulting value does not contain [interior mutability] or [destructors] (these -properties are determined based on the value where possible, e.g. `&None` -always has the type `&'static Option<_>`, as it contains nothing disallowed). +Promotion of a value expression to a `'static` slot occurs when the expression could be written in a constant and borrowed, and that borrow could be dereferenced where the expression was originally written, without changing the runtime behavior. That is, the promoted expression can be evaluated at compile-time and the resulting value does not contain [interior mutability] or [destructors] (these properties are determined based on the value where possible, e.g. `&None` always has the type `&'static Option<_>`, as it contains nothing disallowed). r[destructors.scope.lifetime-extension] ### Temporary lifetime extension @@ -376,10 +334,7 @@ r[destructors.scope.lifetime-extension] > The exact rules for temporary lifetime extension are subject to change. This is describing the current behavior only. r[destructors.scope.lifetime-extension.let] -The temporary scopes for expressions in `let` statements are sometimes -*extended* to the scope of the block containing the `let` statement. This is -done when the usual temporary scope would be too small, based on certain -syntactic rules. For example: +The temporary scopes for expressions in `let` statements are sometimes *extended* to the scope of the block containing the `let` statement. This is done when the usual temporary scope would be too small, based on certain syntactic rules. For example: ```rust let x = &mut 0; @@ -389,8 +344,7 @@ println!("{}", x); ``` r[destructors.scope.lifetime-extension.static] -Lifetime extension also applies to `static` and `const` items, where it -makes temporaries live until the end of the program. For example: +Lifetime extension also applies to `static` and `const` items, where it makes temporaries live until the end of the program. For example: ```rust const C: &Vec = &Vec::new(); @@ -444,8 +398,7 @@ An *extending pattern* is either: So `ref x`, `V(ref x)` and `[ref x, y]` are all extending patterns, but `x`, `&ref x` and `&(ref x,)` are not. r[destructors.scope.lifetime-extension.patterns.let] -If the pattern in a `let` statement is an extending pattern then the temporary -scope of the initializer expression is extended. +If the pattern in a `let` statement is an extending pattern then the temporary scope of the initializer expression is extended. ```rust # fn temp() {} @@ -474,15 +427,12 @@ r[destructors.scope.lifetime-extension.exprs] #### Extending based on expressions r[destructors.scope.lifetime-extension.exprs.extending] -For a let statement with an initializer, an *extending expression* is an -expression which is one of the following: +For a let statement with an initializer, an *extending expression* is an expression which is one of the following: * The initializer expression. * The operand of an extending [borrow] expression. * The [super operands] of an extending [super macro call] expression. -* The operand(s) of an extending [array][array expression], [cast][cast - expression], [braced struct][struct expression], or [tuple][tuple expression] - expression. +* The operand(s) of an extending [array][array expression], [cast][cast expression], [braced struct][struct expression], or [tuple][tuple expression] expression. * The arguments to an extending [tuple struct] or [tuple enum variant] constructor expression. * The final expression of an extending [block expression] except for an [async block expression]. * The final expression of an extending [`if`] expression's consequent, `else if`, or `else` block. @@ -491,8 +441,7 @@ expression which is one of the following: > [!NOTE] > The desugaring of a [destructuring assignment] makes its assigned value operand (the RHS) an extending expression within a newly-introduced block. For details, see [expr.assign.destructure.tmp-ext]. -So the borrow expressions in `&mut 0`, `(&1, &mut 2)`, and `Some(&mut 3)` -are all extending expressions. The borrows in `&0 + &1` and `f(&mut 0)` are not. +So the borrow expressions in `&mut 0`, `(&1, &mut 2)`, and `Some(&mut 3)` are all extending expressions. The borrows in `&0 + &1` and `f(&mut 0)` are not. r[destructors.scope.lifetime-extension.exprs.borrows] The operand of an extending [borrow] expression has its [temporary scope] [extended]. @@ -628,9 +577,7 @@ r[destructors.forget] r[destructors.manually-suppressing] ### Manually suppressing destructors -[`core::mem::forget`] can be used to prevent the destructor of a variable from being run, -and [`core::mem::ManuallyDrop`] provides a wrapper to prevent a -variable or field from being dropped automatically. +[`core::mem::forget`] can be used to prevent the destructor of a variable from being run, and [`core::mem::ManuallyDrop`] provides a wrapper to prevent a variable or field from being dropped automatically. > [!NOTE] > Preventing a destructor from being run via [`core::mem::forget`] or other means is safe even if it has a type that isn't `'static`. Besides the places where destructors are guaranteed to run as defined by this document, types may *not* safely rely on a destructor being run for soundness. diff --git a/src/dynamically-sized-types.md b/src/dynamically-sized-types.md index 0496e16c73..c9f2506bb1 100644 --- a/src/dynamically-sized-types.md +++ b/src/dynamically-sized-types.md @@ -8,26 +8,19 @@ r[dynamic-sized.restriction] Such types can only be used in certain cases: r[dynamic-sized.pointer-types] -* [Pointer types] to DSTs are - sized but have twice the size of pointers to sized types +* [Pointer types] to DSTs are sized but have twice the size of pointers to sized types * Pointers to slices and `str` also store the number of elements. * Pointers to trait objects also store a pointer to a vtable. r[dynamic-sized.question-sized] -* DSTs can be provided as - type arguments to generic type parameters having the special `?Sized` bound. - They can also be used for associated type definitions when the corresponding associated type declaration has a `?Sized` bound. - By default, any type parameter or associated type has a `Sized` bound, unless it is relaxed using `?Sized`. +* DSTs can be provided as type arguments to generic type parameters having the special `?Sized` bound. They can also be used for associated type definitions when the corresponding associated type declaration has a `?Sized` bound. By default, any type parameter or associated type has a `Sized` bound, unless it is relaxed using `?Sized`. r[dynamic-sized.trait-impl] * Traits may be implemented for DSTs. - Unlike with generic type parameters, `Self: ?Sized` is the default in trait definitions. + types">DSTs. Unlike with generic type parameters, `Self: ?Sized` is the default in trait definitions. r[dynamic-sized.struct-field] -* Structs may contain a DST as the - last field; this makes the struct itself a - DST. +* Structs may contain a DST as the last field; this makes the struct itself a DST. > [!NOTE] > [Variables], function parameters, [const] items, and [static] items must be `Sized`. diff --git a/src/expressions.md b/src/expressions.md index 9abc51ae59..0cfad80340 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -62,8 +62,7 @@ The meaning of each kind of expression dictates several things: * How to combine the operands' values to obtain the value of the expression r[expr.structure] -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. +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. > [!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. @@ -71,8 +70,7 @@ Blocks are just another kind of expression, so blocks, statements, expressions, r[expr.precedence] ## 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 | |-----------------------------|---------------------| @@ -100,8 +98,7 @@ r[expr.operand-order] ## Evaluation order of operands r[expr.operand-order.default] -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 @@ -124,8 +121,7 @@ Other expressions either don't take operands or evaluate them conditionally as d * Return expression r[expr.operand-order.operands-before-primary] -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. @@ -150,10 +146,7 @@ r[expr.place-value] ## Place expressions and value expressions r[expr.place-value.intro] -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. r[expr.place-value.place-memory-location] A *place expression* is an expression that represents a memory location. @@ -176,24 +169,21 @@ The following contexts are *place expression* contexts: * The indexed operand of an array indexing expression. * The operand of any [implicit borrow]. * The initializer of a [let statement]. -* The [scrutinee] of an [`if let`], [`match`][match], or [`while let`] - expression. +* The [scrutinee] of an [`if let`], [`match`][match], or [`while let`] expression. * The base of a [functional update] struct expression. > [!NOTE] > Historically, place expressions were called *lvalues* and value expressions were called *rvalues*. r[expr.place-value.assignee] -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]. - [Tuples] of assignee expressions. - [Slices][expr.array.index] of assignee expressions. - [Tuple structs] of assignee expressions. -- [Structs] of assignee expressions (with optionally named - fields). +- [Structs] of assignee expressions (with optionally named fields). - [Unit structs] r[expr.place-value.parenthesis] @@ -229,9 +219,7 @@ r[expr.mut] ### Mutability r[expr.mut.intro] -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*. r[expr.mut.valid-places] The following expressions can be mutable place expression contexts: @@ -241,19 +229,14 @@ The following expressions can be mutable place expression contexts: * [Temporary values]. * [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. r[expr.temporary] ### 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. r[expr.super-macros] ### Super macros @@ -337,8 +320,7 @@ r[expr.implicit-borrow] ### Implicit borrows r[expr.implicit-borrow-intro] -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]; @@ -368,8 +350,7 @@ Implicit borrows may be taken in the following expressions: r[expr.overload] ## 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. r[expr.attr] ## Expression attributes diff --git a/src/expressions/array-expr.md b/src/expressions/array-expr.md index 351da7bf4d..766501277b 100644 --- a/src/expressions/array-expr.md +++ b/src/expressions/array-expr.md @@ -13,8 +13,7 @@ ArrayElements -> ``` r[expr.array.constructor] -*Array expressions* construct [arrays][array]. -Array expressions come in two forms. +*Array expressions* construct [arrays][array]. Array expressions come in two forms. r[expr.array.array] The first form lists out every value in the array. @@ -49,8 +48,7 @@ let _: [u8; C] = [0; (((_)))]; // Inferred const. > In an array expression, an [inferred const] is parsed as an [expression][Expression] but then semantically treated as a separate kind of [const generic argument]. r[expr.array.repeat-behavior] -An array expression of this form creates an array with the length of the value of the length operand with each element being a copy of the repeat operand. -That is, `[a; b]` creates an array containing `b` copies of the value of `a`. +An array expression of this form creates an array with the length of the value of the length operand with each element being a copy of the repeat operand. That is, `[a; b]` creates an array containing `b` copies of the value of `a`. r[expr.array.repeat-copy] If the length operand has a value greater than 1 then this requires the repeat operand to have a type that implements [`Copy`], to be a [const block expression], or to be a [path] to a constant item. @@ -83,19 +81,16 @@ IndexExpression -> Expression `[` Expression `]` ``` r[expr.array.index.array] -[Array] and [slice]-typed values can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them. -When the array is mutable, the resulting [memory location] can be assigned to. +[Array] and [slice]-typed values can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them. When the array is mutable, the resulting [memory location] can be assigned to. r[expr.array.index.trait] -For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::ops::IndexMut::index_mut(&mut a, b)` in a mutable place expression context. -Just as with methods, Rust will also insert dereference operations on `a` repeatedly to find an implementation. +For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::ops::IndexMut::index_mut(&mut a, b)` in a mutable place expression context. Just as with methods, Rust will also insert dereference operations on `a` repeatedly to find an implementation. r[expr.array.index.zero-index] Indices are zero-based for arrays and slices. r[expr.array.index.const] -Array access is a [constant expression], so bounds can be checked at compile-time with a constant index value. -Otherwise a check will be performed at run-time that will put the thread in a [_panicked state_][panic] if it fails. +Array access is a [constant expression], so bounds can be checked at compile-time with a constant index value. Otherwise a check will be performed at run-time that will put the thread in a [_panicked state_][panic] if it fails. ```rust,should_panic // lint is deny by default. diff --git a/src/expressions/await-expr.md b/src/expressions/await-expr.md index e35a753946..ee6d90f031 100644 --- a/src/expressions/await-expr.md +++ b/src/expressions/await-expr.md @@ -7,9 +7,7 @@ AwaitExpression -> Expression `.` `await` ``` r[expr.await.intro] -An `await` expression is a syntactic construct for suspending a computation -provided by an implementation of `std::future::IntoFuture` until the given -future is ready to produce a value. +An `await` expression is a syntactic construct for suspending a computation provided by an implementation of `std::future::IntoFuture` until the given future is ready to produce a value. r[expr.await.construct] The syntax for an await expression is an expression with a type that implements the [`IntoFuture`] trait, called the *future operand*, then the token `.`, and then the `await` keyword. @@ -34,8 +32,7 @@ r[expr.await.edition2018] r[expr.await.task] ## Task context -The task context refers to the [`Context`] which was supplied to the current [async context] when the async context itself was polled. -Because `await` expressions are only legal in an async context, there must be some task context available. +The task context refers to the [`Context`] which was supplied to the current [async context] when the async context itself was polled. Because `await` expressions are only legal in an async context, there must be some task context available. r[expr.await.desugar] ## Approximate desugaring @@ -55,8 +52,7 @@ match operand.into_future() { } ``` -where the `yield` pseudo-code returns `Poll::Pending` and, when re-invoked, resumes execution from that point. -The variable `current_context` refers to the context taken from the async environment. +where the `yield` pseudo-code returns `Poll::Pending` and, when re-invoked, resumes execution from that point. The variable `current_context` refers to the context taken from the async environment. [`async fn`]: ../items/functions.md#async-functions [`async` closure]: closure-expr.md#async-closures diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index a05a487c94..e8f602af0c 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -22,8 +22,7 @@ r[expr.block.sequential-evaluation] As a control flow expression, a block sequentially executes its component non-item declaration statements and then its final optional expression. r[expr.block.namespace] -As an anonymous namespace scope, item declarations are only in scope inside the block itself and variables declared by `let` statements are in scope from the next statement until the end of the block. -See the [scopes] chapter for more details. +As an anonymous namespace scope, item declarations are only in scope inside the block itself and variables declared by `let` statements are in scope from the next statement until the end of the block. See the [scopes] chapter for more details. r[expr.block.inner-attributes] The syntax for a block is `{`, then any [inner attributes], then any number of [statements], then an optional expression, called the final operand, and finally a `}`. @@ -103,8 +102,7 @@ r[expr.block.async.future-result] The final expression of the block, if present, determines the result value of the future. r[expr.block.async.anonymous-type] -Executing an async block is similar to executing a closure expression: -its immediate effect is to produce and return an anonymous type. +Executing an async block is similar to executing a closure expression: its immediate effect is to produce and return an anonymous type. r[expr.block.async.future] Whereas closures return a type that implements one or more of the [`std::ops::Fn`] traits, however, the type returned for an async block implements the [`std::future::Future`] trait. @@ -122,15 +120,12 @@ r[expr.block.async.edition2018] r[expr.block.async.capture] ### Capture modes -Async blocks capture variables from their environment using the same [capture modes] as closures. -Like closures, when written `async { .. }` the capture mode for each variable will be inferred from the content of the block. -`async move { .. }` blocks however will move all referenced variables into the resulting future. +Async blocks capture variables from their environment using the same [capture modes] as closures. Like closures, when written `async { .. }` the capture mode for each variable will be inferred from the content of the block. `async move { .. }` blocks however will move all referenced variables into the resulting future. r[expr.block.async.context] ### Async context -Because async blocks construct a future, they define an **async context** which can in turn contain [`await` expressions]. -Async contexts are established by async blocks as well as the bodies of async functions, whose semantics are defined in terms of async blocks. +Because async blocks construct a future, they define an **async context** which can in turn contain [`await` expressions]. Async contexts are established by async blocks as well as the bodies of async functions, whose semantics are defined in terms of async blocks. r[expr.block.async.function] ### Control-flow operators @@ -139,13 +134,10 @@ r[expr.block.async.function.intro] Async blocks act like a function boundary, much like closures. r[expr.block.async.function.return-try] -Therefore, the `?` operator and `return` expressions both affect the output of the future, not the enclosing function or other context. -That is, `return ` from within an async block will return the result of `` as the output of the future. -Similarly, if `?` propagates an error, that error is propagated as the result of the future. +Therefore, the `?` operator and `return` expressions both affect the output of the future, not the enclosing function or other context. That is, `return ` from within an async block will return the result of `` as the output of the future. Similarly, if `?` propagates an error, that error is propagated as the result of the future. r[expr.block.async.function.control-flow] -Finally, the `break` and `continue` keywords cannot be used to branch out from an async block. -Therefore the following is illegal: +Finally, the `break` and `continue` keywords cannot be used to branch out from an async block. Therefore the following is illegal: ```rust,compile_fail loop { @@ -167,13 +159,10 @@ r[expr.block.const.intro] A *const block* is a variant of a block expression whose body evaluates at compile-time instead of at runtime. r[expr.block.const.context] -Const blocks allows you to define a constant value without having to define new [constant items], and thus they are also sometimes referred as *inline consts*. -It also supports type inference so there is no need to specify the type, unlike [constant items]. +Const blocks allows you to define a constant value without having to define new [constant items], and thus they are also sometimes referred as *inline consts*. It also supports type inference so there is no need to specify the type, unlike [constant items]. r[expr.block.const.generic-params] -Const blocks have the ability to reference generic parameters in scope, unlike [free][free item] constant items. -They are desugared to constant items with generic parameters in scope (similar to associated constants, but without a trait or type they are associated with). -For example, this code: +Const blocks have the ability to reference generic parameters in scope, unlike [free][free item] constant items. They are desugared to constant items with generic parameters in scope (similar to associated constants, but without a trait or type they are associated with). For example, this code: ```rust fn foo() -> usize { @@ -231,8 +220,7 @@ UnsafeBlockExpression -> `unsafe` BlockExpression r[expr.block.unsafe.intro] _See [`unsafe` blocks] for more information on when to use `unsafe`_. -A block of code can be prefixed with the `unsafe` keyword to permit [unsafe operations]. -Examples: +A block of code can be prefixed with the `unsafe` keyword to permit [unsafe operations]. Examples: ```rust unsafe { @@ -260,8 +248,7 @@ r[expr.block.attributes.inner-attributes] * [Function] and [method] bodies. * Loop bodies ([`loop`], [`while`], and [`for`]). * Block expressions used as a [statement]. -* Block expressions as elements of [array expressions], [tuple expressions], - [call expressions], and tuple-style [struct] expressions. +* Block expressions as elements of [array expressions], [tuple expressions], [call expressions], and tuple-style [struct] expressions. * A block expression as the tail expression of another block expression. diff --git a/src/expressions/call-expr.md b/src/expressions/call-expr.md index 53e6ccff46..09b8aeacc8 100644 --- a/src/expressions/call-expr.md +++ b/src/expressions/call-expr.md @@ -9,8 +9,7 @@ CallParams -> Expression ( `,` Expression )* `,`? ``` r[expr.call.intro] -A *call expression* calls a function. -The syntax of a call expression is an expression, called the *function operand*, followed by a parenthesized comma-separated list of expression, called the *argument operands*. +A *call expression* calls a function. The syntax of a call expression is an expression, called the *function operand*, followed by a parenthesized comma-separated list of expression, called the *argument operands*. r[expr.call.convergence] If the function eventually returns, then the expression completes. @@ -23,8 +22,7 @@ For [non-function types], the expression `f(...)` uses the method on one of the - [`FnOnce`] or [`AsyncFnOnce`] --- value. r[expr.call.autoref-deref] -An automatic borrow will be taken if needed. -The function operand will also be [automatically dereferenced] as required. +An automatic borrow will be taken if needed. The function operand will also be [automatically dereferenced] as required. Some examples of call expressions: @@ -47,8 +45,7 @@ Function calls may need to be fully qualified, depending on the ambiguity of a c > In the past, the terms "Unambiguous Function Call Syntax", "Universal Function Call Syntax", or "UFCS", have been used in documentation, issues, RFCs, and other community writings. However, these terms lack descriptive power and potentially confuse the issue at hand. We mention them here for searchability's sake. r[expr.call.desugar.limits] -Several situations often occur which result in ambiguities about the receiver or referent of method or associated function calls. -These situations may include: +Several situations often occur which result in ambiguities about the receiver or referent of method or associated function calls. These situations may include: * Multiple in-scope traits define methods with the same name for the same types * Auto-`deref` is undesirable; for example, distinguishing between methods on a smart pointer itself and the pointer's referent diff --git a/src/expressions/closure-expr.md b/src/expressions/closure-expr.md index 75aaeb7b5d..8f71ddd9b8 100644 --- a/src/expressions/closure-expr.md +++ b/src/expressions/closure-expr.md @@ -17,8 +17,7 @@ ClosureParam -> OuterAttribute* PatternNoTopAlt ( `:` Type )? [^cl-async-edition]: The `async` qualifier is not allowed in the 2015 edition. r[expr.closure.intro] -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 `async` keyword, 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*. +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 `async` keyword, 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*. r[expr.closure.param-type] The optional type after each pattern is a type annotation for the pattern. @@ -27,8 +26,7 @@ r[expr.closure.explicit-type-body] If there is a return type, the closure body must be a [block]. r[expr.closure.parameter-restriction] -A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters. -Just like a [`let` binding], the closure parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given. +A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters. Just like a [`let` binding], the closure parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given. r[expr.closure.unique-type] Each closure expression has a unique, anonymous type. @@ -43,15 +41,12 @@ r[expr.closure.capture-mut-ref] If needed the compiler will infer that instead mutable references should be taken, or that the values should be moved or copied (depending on their type) from the environment. r[expr.closure.capture-move] -A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword. -This is often used to ensure that the closure's lifetime is `'static`. +A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword. This is often used to ensure that the closure's lifetime is `'static`. r[expr.closure.trait-impl] ## Closure trait implementations -Which traits the closure type implement depends on how variables are captured, the types of the captured variables, and the presence of `async`. -See the [call traits and coercions] chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`. -The closure type implements [`Send`] and [`Sync`] if the type of every captured variable also implements the trait. +Which traits the closure type implement depends on how variables are captured, the types of the captured variables, and the presence of `async`. See the [call traits and coercions] chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`. The closure type implements [`Send`] and [`Sync`] if the type of every captured variable also implements the trait. r[expr.closure.async] ## Async closures diff --git a/src/expressions/field-expr.md b/src/expressions/field-expr.md index 8835e6fab1..2073979610 100644 --- a/src/expressions/field-expr.md +++ b/src/expressions/field-expr.md @@ -16,8 +16,7 @@ r[expr.field.form] The syntax for a field expression is an expression, called the *container operand*, then a `.`, and finally an [identifier]. r[expr.field.not-method-call] -Field expressions cannot be followed by a parenthetical comma-separated list of expressions, as that is instead parsed as a [method call expression]. -That is, they cannot be the function operand of a [call expression]. +Field expressions cannot be followed by a parenthetical comma-separated list of expressions, as that is instead parsed as a [method call expression]. That is, they cannot be the function operand of a [call expression]. > [!NOTE] > Wrap the field expression in a [parenthesized expression] to use it in a call expression. @@ -46,15 +45,12 @@ foo().x; r[expr.field.autoref-deref] ## Automatic dereferencing -If the type of the container operand implements [`Deref`] or [`DerefMut`][`Deref`] depending on whether the operand is [mutable], it is *automatically dereferenced* as many times as necessary to make the field access possible. -This process is also called *autoderef* for short. +If the type of the container operand implements [`Deref`] or [`DerefMut`][`Deref`] depending on whether the operand is [mutable], it is *automatically dereferenced* as many times as necessary to make the field access possible. This process is also called *autoderef* for short. r[expr.field.borrow] ## Borrowing -The fields of a struct or a reference to a struct are treated as separate entities when borrowing. -If the struct does not implement [`Drop`] and is stored in a local variable, this also applies to moving out of each of its fields. -This also does not apply if automatic dereferencing is done through user-defined types other than [`Box`]. +The fields of a struct or a reference to a struct are treated as separate entities when borrowing. If the struct does not implement [`Drop`] and is stored in a local variable, this also applies to moving out of each of its fields. This also does not apply if automatic dereferencing is done through user-defined types other than [`Box`]. ```rust struct A { f1: String, f2: String, f3: String } diff --git a/src/expressions/grouped-expr.md b/src/expressions/grouped-expr.md index 2ac62d416b..107bd48371 100644 --- a/src/expressions/grouped-expr.md +++ b/src/expressions/grouped-expr.md @@ -7,15 +7,13 @@ GroupedExpression -> `(` Expression `)` ``` r[expr.paren.intro] -A *parenthesized expression* wraps a single expression, evaluating to that expression. -The syntax for a parenthesized expression is a `(`, then an expression, called the *enclosed operand*, and then a `)`. +A *parenthesized expression* wraps a single expression, evaluating to that expression. The syntax for a parenthesized expression is a `(`, then an expression, called the *enclosed operand*, and then a `)`. r[expr.paren.evaluation] Parenthesized expressions evaluate to the value of the enclosed operand. r[expr.paren.place-or-value] -Unlike other expressions, parenthesized expressions are both [place expressions and value expressions][place]. -When the enclosed operand is a place expression, it is a place expression and when the enclosed operand is a value expression, it is a value expression. +Unlike other expressions, parenthesized expressions are both [place expressions and value expressions][place]. When the enclosed operand is a place expression, it is a place expression and when the enclosed operand is a value expression, it is a value expression. r[expr.paren.override-precedence] Parentheses can be used to explicitly modify the precedence order of subexpressions within an expression. diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index 46636112f7..96772782f8 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -31,19 +31,16 @@ LetChainCondition -> --> r[expr.if.intro] -The syntax of an `if` expression is a sequence of one or more condition operands separated by `&&`, -followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. +The syntax of an `if` expression is a sequence of one or more condition operands separated by `&&`, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. r[expr.if.condition] Condition operands must be either an [Expression] with a [boolean type] or a conditional `let` match. r[expr.if.condition-true] -If all of the condition operands evaluate to `true` and all of the `let` patterns successfully match their [scrutinee]s, -the consequent block is executed and any subsequent `else if` or `else` block is skipped. +If all of the condition operands evaluate to `true` and all of the `let` patterns successfully match their [scrutinee]s, the consequent block is executed and any subsequent `else if` or `else` block is skipped. r[expr.if.else-if] -If any condition operand evaluates to `false` or any `let` pattern does not match its scrutinee, -the consequent block is skipped and any subsequent `else if` condition is evaluated. +If any condition operand evaluates to `false` or any `let` pattern does not match its scrutinee, the consequent block is skipped and any subsequent `else if` condition is evaluated. r[expr.if.else] If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed. @@ -103,8 +100,7 @@ if let _ = 5 { ``` r[expr.if.let.or-pattern] -Multiple patterns may be specified with the `|` operator. -This has the same semantics as with `|` in [`match` expressions]: +Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in [`match` expressions]: ```rust enum E { @@ -125,8 +121,7 @@ r[expr.if.chains.intro] Multiple condition operands can be separated with `&&`. r[expr.if.chains.order] -Similar to a `&&` [LazyBooleanExpression], each operand is evaluated from left-to-right until an operand evaluates as `false` or a `let` match fails, -in which case the subsequent operands are not evaluated. +Similar to a `&&` [LazyBooleanExpression], each operand is evaluated from left-to-right until an operand evaluates as `false` or a `let` match fails, in which case the subsequent operands are not evaluated. r[expr.if.chains.bindings] The bindings of each pattern are put into scope to be available for the next condition operand and the consequent block. @@ -163,8 +158,7 @@ fn nested() { ``` r[expr.if.chains.or] -If any condition operand is a `let` pattern, then none of the condition operands can be a `||` [lazy boolean operator expression][expr.bool-logic] due to ambiguity and precedence with the `let` scrutinee. -If a `||` expression is needed, then parentheses can be used. For example: +If any condition operand is a `let` pattern, then none of the condition operands can be a `||` [lazy boolean operator expression][expr.bool-logic] due to ambiguity and precedence with the `let` scrutinee. If a `||` expression is needed, then parentheses can be used. For example: ```rust # let foo = Some(123); diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 51b3c7ae26..15890e19fe 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -101,8 +101,7 @@ The escaped value is the character whose [Unicode scalar value] is the result of r[expr.literal.continuation] ### String continuation escapes -The escape sequence consists of `\` followed immediately by `U+000A` (LF), and all following whitespace characters before the next non-whitespace character. -For this purpose, the whitespace characters are `U+0009` (HT), `U+000A` (LF), `U+000D` (CR), and `U+0020` (SPACE). +The escape sequence consists of `\` followed immediately by `U+000A` (LF), and all following whitespace characters before the next non-whitespace character. For this purpose, the whitespace characters are `U+0009` (HT), `U+000A` (LF), `U+000D` (CR), and `U+0020` (SPACE). The escaped value is an empty sequence of characters. @@ -172,8 +171,7 @@ r[expr.literal.string.intro] A string literal expression consists of a single [STRING_LITERAL] or [RAW_STRING_LITERAL] token. r[expr.literal.string.type] -The expression's type is a shared reference (with `static` lifetime) to the primitive [`str`][textual types] type. -That is, the type is `&'static str`. +The expression's type is a shared reference (with `static` lifetime) to the primitive [`str`][textual types] type. That is, the type is `&'static str`. r[expr.literal.string.no-suffix] The token must not have a suffix. @@ -191,8 +189,7 @@ r[expr.literal.string.escape] * [Unicode escapes] * [String continuation escapes] - These replacements take place in left-to-right order. - For example, the token `"\\x41"` is converted to the characters `\` `x` `4` `1`. + These replacements take place in left-to-right order. For example, the token `"\\x41"` is converted to the characters `\` `x` `4` `1`. r[expr.literal.string.raw] * If the token is a [RAW_STRING_LITERAL], the represented string is identical to the literal content. @@ -261,8 +258,7 @@ r[expr.literal.byte-string.intro] A byte string literal expression consists of a single [BYTE_STRING_LITERAL] or [RAW_BYTE_STRING_LITERAL] token. r[expr.literal.byte-string.type] -The expression's type is a shared reference (with `static` lifetime) to an array whose element type is [`u8`][numeric types]. -That is, the type is `&'static [u8; N]`, where `N` is the number of bytes in the represented string described below. +The expression's type is a shared reference (with `static` lifetime) to an array whose element type is [`u8`][numeric types]. That is, the type is `&'static [u8; N]`, where `N` is the number of bytes in the represented string described below. r[expr.literal.byte-string.no-suffix] The token must not have a suffix. @@ -279,8 +275,7 @@ r[expr.literal.byte-string.escape] * [8-bit escapes] * [String continuation escapes] - These replacements take place in left-to-right order. - For example, the token `b"\\x41"` is converted to the characters `\` `x` `4` `1`. + These replacements take place in left-to-right order. For example, the token `b"\\x41"` is converted to the characters `\` `x` `4` `1`. r[expr.literal.byte-string.raw] * If the token is a [RAW_BYTE_STRING_LITERAL], the represented string is identical to the literal content. @@ -311,8 +306,7 @@ r[expr.literal.c-string.intro] A C string literal expression consists of a single [C_STRING_LITERAL] or [RAW_C_STRING_LITERAL] token. r[expr.literal.c-string.type] -The expression's type is a shared reference (with `static` lifetime) to the standard library [CStr] type. -That is, the type is `&'static core::ffi::CStr`. +The expression's type is a shared reference (with `static` lifetime) to the standard library [CStr] type. That is, the type is `&'static core::ffi::CStr`. r[expr.literal.c-string.no-suffix] The token must not have a suffix. @@ -324,8 +318,7 @@ r[expr.literal.c-string.represented] The literal expression's _represented bytes_ are a sequence of bytes derived from the literal content as follows: r[expr.literal.c-string.escape] -* If the token is a [C_STRING_LITERAL], the literal content is treated as a sequence of items, each of which is either a single Unicode character other than `\` or an [escape]. -The sequence of items is converted to a sequence of bytes as follows: +* If the token is a [C_STRING_LITERAL], the literal content is treated as a sequence of items, each of which is either a single Unicode character other than `\` or an [escape]. The sequence of items is converted to a sequence of bytes as follows: * Each single Unicode character contributes its UTF-8 representation. * Each [simple escape] contributes the [Unicode scalar value] of its escaped value. * Each [8-bit escape] contributes a single byte containing the [Unicode scalar value] of its escaped value. @@ -424,8 +417,7 @@ r[expr.literal.int.separators-stripped] * Any underscores are removed from the string. r[expr.literal.int.u128-value] -* The string is converted to a `u128` value as if by [`u128::from_str_radix`] with the chosen radix. -If the value does not fit in `u128`, it is a compiler error. +* The string is converted to a `u128` value as if by [`u128::from_str_radix`] with the chosen radix. If the value does not fit in `u128`, it is a compiler error. r[expr.literal.int.cast] * The `u128` value is converted to the expression's type via a [numeric cast]. diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 043077e56e..cc4100dd49 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -38,8 +38,7 @@ InfiniteLoopExpression -> `loop` BlockExpression ``` r[expr.loop.infinite.intro] -A `loop` expression repeats execution of its body continuously: -`loop { println!("I live."); }`. +A `loop` expression repeats execution of its body continuously: `loop { println!("I live."); }`. r[expr.loop.infinite.diverging] A `loop` expression without an associated `break` expression is diverging and has type [`!`](../types/never.md). @@ -59,20 +58,16 @@ r[expr.loop.while.intro] A `while` loop expression allows repeating the evaluation of a block while a set of conditions remain true. r[expr.loop.while.syntax] -The syntax of a `while` expression is a sequence of one or more condition operands separated by `&&`, -followed by a [BlockExpression]. +The syntax of a `while` expression is a sequence of one or more condition operands separated by `&&`, followed by a [BlockExpression]. r[expr.loop.while.condition] -Condition operands must be either an [Expression] with a [boolean type] or a conditional `let` match. -If all of the condition operands evaluate to `true` and all of the `let` patterns successfully match their [scrutinee]s, -then the loop body block executes. +Condition operands must be either an [Expression] with a [boolean type] or a conditional `let` match. If all of the condition operands evaluate to `true` and all of the `let` patterns successfully match their [scrutinee]s, then the loop body block executes. r[expr.loop.while.repeat] After the loop body successfully executes, the condition operands are re-evaluated to determine if the body should be executed again. r[expr.loop.while.exit] -If any condition operand evaluates to `false` or any `let` pattern does not match its scrutinee, -the body is not executed and execution continues after the `while` expression. +If any condition operand evaluates to `false` or any `let` pattern does not match its scrutinee, the body is not executed and execution continues after the `while` expression. r[expr.loop.while.eval] A `while` expression evaluates to `()`. @@ -92,8 +87,7 @@ r[expr.loop.while.let] ### `while let` patterns r[expr.loop.while.let.intro] -`let` patterns in a `while` condition allow binding new variables into scope when the pattern matches successfully. -The following examples illustrate bindings using `let` patterns: +`let` patterns in a `while` condition allow binding new variables into scope when the pattern matches successfully. The following examples illustrate bindings using `let` patterns: ```rust let mut x = vec![1, 2, 3]; @@ -131,8 +125,7 @@ is equivalent to ``` r[expr.loop.while.let.or-pattern] -Multiple patterns may be specified with the `|` operator. -This has the same semantics as with `|` in `match` expressions: +Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions: ```rust let mut vals = vec![2, 3, 1, 2, 2]; @@ -146,8 +139,7 @@ r[expr.loop.while.chains] ### `while` condition chains r[expr.loop.while.chains.intro] -Multiple condition operands can be separated with `&&`. -These have the same semantics and restrictions as [`if` condition chains]. +Multiple condition operands can be separated with `&&`. These have the same semantics and restrictions as [`if` condition chains]. The following is an example of chaining multiple expressions, mixing `let` bindings and boolean expressions, and with expressions able to reference pattern bindings from previous expressions: @@ -179,8 +171,7 @@ r[expr.loop.for.intro] A `for` expression is a syntactic construct for looping over elements provided by an implementation of `std::iter::IntoIterator`. r[expr.loop.for.condition] -If the iterator yields a value, that value is matched against the irrefutable pattern, the body of the loop is executed, and then control returns to the head of the `for` loop. -If the iterator is empty, the `for` expression completes. +If the iterator yields a value, that value is matched against the irrefutable pattern, the body of the loop is executed, and then control returns to the head of the `for` loop. If the iterator is empty, the `for` expression completes. An example of a `for` loop over the contents of an array: @@ -252,8 +243,7 @@ r[expr.loop.label.intro] A loop expression may optionally have a _label_. The label is written as a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`, `'bar: while false {}`, `'humbug: for _ in 0..0 {}`. r[expr.loop.label.control-flow] -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). +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). r[expr.loop.label.ref] Labels follow the hygiene and shadowing rules of local variables. For example, this code will print "outer loop": @@ -293,9 +283,7 @@ assert_eq!(last, 12); ``` r[expr.loop.break.label] -A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression, -but a [label](#loop-labels) can be used to specify which enclosing loop is affected. -Example: +A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression, but a [label](#loop-labels) can be used to specify which enclosing loop is affected. Example: ```rust 'outer: loop { @@ -371,8 +359,7 @@ r[expr.loop.break-value] ## `break` and loop values r[expr.loop.break-value.intro] -When associated with a `loop`, a break expression may be used to return a value from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where `EXPR` is an expression whose result is returned from the `loop`. -For example: +When associated with a `loop`, a break expression may be used to return a value from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where `EXPR` is an expression whose result is returned from the `loop`. For example: ```rust let (mut a, mut b) = (1, 1); @@ -389,8 +376,7 @@ assert_eq!(result, 13); ``` r[expr.loop.break-value.loop] -In the case a `loop` has an associated `break`, it is not considered diverging, and the `loop` must have a type compatible with each `break` expression. -`break` without an expression is considered identical to `break` with expression `()`. +In the case a `loop` has an associated `break`, it is not considered diverging, and the `loop` must have a type compatible with each `break` expression. `break` without an expression is considered identical to `break` with expression `()`. [`if` condition chains]: if-expr.md#chains-of-conditions [`if` expressions]: if-expr.md diff --git a/src/expressions/match-expr.md b/src/expressions/match-expr.md index 5bfbbc76db..72fe7ab2ce 100644 --- a/src/expressions/match-expr.md +++ b/src/expressions/match-expr.md @@ -22,8 +22,7 @@ MatchArmGuard -> `if` Expression r[expr.match.intro] -A *`match` expression* branches on a pattern. -The exact form of matching that occurs depends on the [pattern]. +A *`match` expression* branches on a pattern. The exact form of matching that occurs depends on the [pattern]. r[expr.match.scrutinee] A `match` expression has a *[scrutinee] expression*, which is the value to compare to the patterns. @@ -35,13 +34,10 @@ r[expr.match.scrutinee-behavior] A `match` behaves differently depending on whether or not the scrutinee expression is a [place expression or value expression][place expression]. r[expr.match.scrutinee-value] -If the scrutinee expression is a [value expression], it is first evaluated into a temporary location, and the resulting value is sequentially compared to the patterns in the arms until a match is found. -The first arm with a matching pattern is chosen as the branch target of the `match`, any variables bound by the pattern are assigned to local variables in the arm's block, and control enters the block. +If the scrutinee expression is a [value expression], it is first evaluated into a temporary location, and the resulting value is sequentially compared to the patterns in the arms until a match is found. The first arm with a matching pattern is chosen as the branch target of the `match`, any variables bound by the pattern are assigned to local variables in the arm's block, and control enters the block. r[expr.match.scrutinee-place] -When the scrutinee expression is a [place expression], the match does not allocate a temporary location; -however, a by-value binding may copy or move from the memory location. -When possible, it is preferable to match on place expressions, as the lifetime of these matches inherits the lifetime of the place expression rather than being restricted to the inside of the match. +When the scrutinee expression is a [place expression], the match does not allocate a temporary location; however, a by-value binding may copy or move from the memory location. When possible, it is preferable to match on place expressions, as the lifetime of these matches inherits the lifetime of the place expression rather than being restricted to the inside of the match. An example of a `match` expression: @@ -65,8 +61,7 @@ r[expr.match.pattern-var-binding] The [binding mode] (move, copy, or reference) depends on the pattern. r[expr.match.or-pattern] -Multiple match patterns may be joined with the `|` operator. -Each pattern will be tested in left-to-right sequence until a successful match is found. +Multiple match patterns may be joined with the `|` operator. Each pattern will be tested in left-to-right sequence until a successful match is found. ```rust let x = 9; @@ -106,8 +101,7 @@ r[expr.match.guard.type] Pattern guards appear after the pattern and consist of a `bool`-typed expression following the `if` keyword. r[expr.match.guard.behavior] -When the pattern matches successfully, the pattern guard expression is executed. -If the expression evaluates to true, the pattern is successfully matched against. +When the pattern matches successfully, the pattern guard expression is executed. If the expression evaluates to true, the pattern is successfully matched against. r[expr.match.guard.next] Otherwise, the next pattern, including other matches with the `|` operator in the same arm, is tested. @@ -140,12 +134,10 @@ r[expr.match.guard.bound-variables] A pattern guard may refer to the variables bound within the pattern they follow. r[expr.match.guard.shared-ref] -Before evaluating the guard, a shared reference is taken to the part of the scrutinee the variable matches on. -While evaluating the guard, this shared reference is then used when accessing the variable. +Before evaluating the guard, a shared reference is taken to the part of the scrutinee the variable matches on. While evaluating the guard, this shared reference is then used when accessing the variable. r[expr.match.guard.value] -Only when the guard evaluates to true is the value moved, or copied, from the scrutinee into the variable. -This allows shared borrows to be used inside guards without moving out of the scrutinee in case guard fails to match. +Only when the guard evaluates to true is the value moved, or copied, from the scrutinee into the variable. This allows shared borrows to be used inside guards without moving out of the scrutinee in case guard fails to match. r[expr.match.guard.no-mutation] Moreover, by holding a shared reference while evaluating the guard, mutation inside guards is also prevented. @@ -154,8 +146,7 @@ r[expr.match.attributes] ## Attributes on match arms r[expr.match.attributes.outer] -Outer attributes are allowed on match arms. -The only attributes that have meaning on match arms are [`cfg`] and the [lint check attributes]. +Outer attributes are allowed on match arms. The only attributes that have meaning on match arms are [`cfg`] and the [lint check attributes]. r[expr.match.attributes.inner] [Inner attributes] are allowed directly after the opening brace of the match expression in the same expression contexts as [attributes on block expressions]. diff --git a/src/expressions/method-call-expr.md b/src/expressions/method-call-expr.md index 8257c083e4..cbfb83503c 100644 --- a/src/expressions/method-call-expr.md +++ b/src/expressions/method-call-expr.md @@ -19,13 +19,10 @@ let log_pi = pi.unwrap_or(1.0).log(2.72); ``` r[expr.method.autoref-deref] -When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method. -This requires a more complex lookup process than for other functions, since there may be a number of possible methods to call. -The following procedure is used: +When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method. This requires a more complex lookup process than for other functions, since there may be a number of possible methods to call. The following procedure is used: r[expr.method.candidate-receivers] -The first step is to build a list of candidate receiver types. -Obtain these by repeatedly [dereferencing][dereference] the receiver expression's type, adding each type encountered to the list, then finally attempting an [unsized coercion] at the end, and adding the result type if that is successful. +The first step is to build a list of candidate receiver types. Obtain these by repeatedly [dereferencing][dereference] the receiver expression's type, adding each type encountered to the list, then finally attempting an [unsized coercion] at the end, and adding the result type if that is successful. r[expr.method.candidate-receivers-refs] Then, for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`. @@ -36,9 +33,7 @@ r[expr.method.candidate-search] Then, for each candidate type `T`, search for a [visible] method with a receiver of that type in the following places: 1. `T`'s inherent methods (methods implemented directly on `T`). -1. Any of the methods provided by a [visible] trait implemented by `T`. - If `T` is a type parameter, methods provided by trait bounds on `T` are looked up first. - Then all remaining methods in scope are looked up. +1. Any of the methods provided by a [visible] trait implemented by `T`. If `T` is a type parameter, methods provided by trait bounds on `T` are looked up first. Then all remaining methods in scope are looked up. > [!NOTE] > The lookup is done for each type in order, which can occasionally lead to surprising results. The below code will print "In trait impl!", because `&self` methods are looked up first, the trait method is found before the struct's `&mut self` method is found. @@ -72,12 +67,10 @@ r[expr.method.ambiguous-target] If this results in multiple possible candidates, then it is an error, and the receiver must be [converted][disambiguate call] to an appropriate receiver type to make the method call. r[expr.method.receiver-constraints] -This process does not take into account the mutability or lifetime of the receiver, or whether a method is `unsafe`. -Once a method is looked up, if it can't be called for one (or more) of those reasons, the result is a compiler error. +This process does not take into account the mutability or lifetime of the receiver, or whether a method is `unsafe`. Once a method is looked up, if it can't be called for one (or more) of those reasons, the result is a compiler error. r[expr.method.ambiguous-search] -If a step is reached where there is more than one possible method, such as where generic methods or traits are considered the same, then it is a compiler error. -These cases require a [disambiguating function call syntax] for method and function invocation. +If a step is reached where there is more than one possible method, such as where generic methods or traits are considered the same, then it is a compiler error. These cases require a [disambiguating function call syntax] for method and function invocation. r[expr.method.edition2021] > [!EDITION-2021] @@ -88,10 +81,7 @@ r[expr.method.edition2021] > This special case may be removed in the future. > [!WARNING] -> For [trait objects], if there is an inherent method of the same name as a trait method, it will give a compiler error when trying to call the method in a method call expression. -> Instead, you can call the method using [disambiguating function call syntax], in which case it calls the trait method, not the inherent method. -> There is no way to call the inherent method. -> Just don't define inherent methods on trait objects with the same name as a trait method and you'll be fine. +> For [trait objects], if there is an inherent method of the same name as a trait method, it will give a compiler error when trying to call the method in a method call expression. Instead, you can call the method using [disambiguating function call syntax], in which case it calls the trait method, not the inherent method. There is no way to call the inherent method. Just don't define inherent methods on trait objects with the same name as a trait method and you'll be fine. [visible]: ../visibility-and-privacy.md [array type]: ../types/array.md diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 735d9cea3a..f071ba05ae 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -26,9 +26,7 @@ r[expr.operator.int-overflow] ## Overflow r[expr.operator.int-overflow.intro] -Integer operators will panic when they overflow when compiled in debug mode. -The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used to control this more directly. -The following things are considered to be overflow: +Integer operators will panic when they overflow when compiled in debug mode. The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used to control this more directly. The following things are considered to be overflow: r[expr.operator.int-overflow.binary-arith] * When `+`, `*` or binary `-` create a value greater than the maximum value, or less than the minimum value that can be stored. @@ -37,8 +35,7 @@ r[expr.operator.int-overflow.unary-neg] * Applying unary `-` to the most negative value of any signed integer type, unless the operand is a [literal expression] (or a literal expression standing alone inside one or more [grouped expressions][grouped expression]). r[expr.operator.int-overflow.div] -* Using `/` or `%`, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is `-1`. - These checks occur even when `-C overflow-checks` is disabled, for legacy reasons. +* Using `/` or `%`, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is `-1`. These checks occur even when `-C overflow-checks` is disabled, for legacy reasons. r[expr.operator.int-overflow.shift] * Using `<<` or `>>` where the right-hand argument is greater than or equal to the number of bits in the type of the left-hand argument, or is negative. @@ -71,9 +68,7 @@ r[expr.operator.borrow.result] When applied to a [place expression], this expressions produces a reference (pointer) to the location that the value refers to. r[expr.operator.borrow.lifetime] -The memory location is also placed into a borrowed state for the duration of the reference. -For a shared borrow (`&`), this implies that the place may not be mutated, but it may be read or shared again. -For a mutable borrow (`&mut`), the place may not be accessed in any way until the borrow expires. +The memory location is also placed into a borrowed state for the duration of the reference. For a shared borrow (`&`), this implies that the place may not be mutated, but it may be read or shared again. For a mutable borrow (`&mut`), the place may not be accessed in any way until the borrow expires. r[expr.operator.borrow.mut] `&mut` evaluates its operand in a mutable place expression context. @@ -123,8 +118,7 @@ r[expr.borrow.raw.result] `&raw const expr` then creates a const raw pointer of type `*const T` to the given place, and `&raw mut expr` creates a mutable raw pointer of type `*mut T`. r[expr.borrow.raw.invalid-ref] -The raw borrow operators must be used instead of a borrow operator whenever the place expression could evaluate to a place that is not properly aligned or does not store a valid value as determined by its type, or whenever creating a reference would introduce incorrect aliasing assumptions. -In those situations, using a borrow operator would cause [undefined behavior] by creating an invalid reference, but a raw pointer may still be constructed. +The raw borrow operators must be used instead of a borrow operator whenever the place expression could evaluate to a place that is not properly aligned or does not store a valid value as determined by its type, or whenever creating a reference would introduce incorrect aliasing assumptions. In those situations, using a borrow operator would cause [undefined behavior] by creating an invalid reference, but a raw pointer may still be constructed. The following is an example of creating a raw pointer to an unaligned place through a `packed` struct: @@ -324,9 +318,7 @@ r[expr.negate.intro] These are the last two unary operators. r[expr.negate.results] -This table summarizes the behavior of them on primitive types and which traits are used to overload these operators for other types. -Remember that signed integers are always represented using two's complement. -The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied. +This table summarizes the behavior of them on primitive types and which traits are used to overload these operators for other types. Remember that signed integers are always represented using two's complement. The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied. | Symbol | Integer | `bool` | Floating Point | Overloading Trait | |--------|-------------|-------------- |----------------|--------------------| @@ -366,9 +358,7 @@ r[expr.arith-logic.intro] Binary operators expressions are all written with infix notation. r[expr.arith-logic.behavior] -This table summarizes the behavior of arithmetic and logical binary operators on primitive types and which traits are used to overload these operators for other types. -Remember that signed integers are always represented using two's complement. -The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied. +This table summarizes the behavior of arithmetic and logical binary operators on primitive types and which traits are used to overload these operators for other types. Remember that signed integers are always represented using two's complement. The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied. | Symbol | Integer | `bool` | Floating Point | Overloading Trait | Overloading Compound Assignment Trait | |--------|-------------------------|---------------|----------------|--------------------| ------------------------------------- | @@ -387,8 +377,7 @@ The operands of all of these operators are evaluated in [value expression contex \*\* Rust uses a remainder defined with [truncating division](https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition). Given `remainder = dividend % divisor`, the remainder will have the same sign as the dividend. -\*\*\* Arithmetic right shift on signed integer types, logical right shift on -unsigned integer types. +\*\*\* Arithmetic right shift on signed integer types, logical right shift on unsigned integer types. † For integer types, division by zero panics. @@ -428,8 +417,7 @@ r[expr.cmp.paren-chaining] Parentheses are required when chaining comparison operators. For example, the expression `a == b == c` is invalid and may be written as `(a == b) == c`. r[expr.cmp.trait] -Unlike arithmetic and logical operators, the traits for overloading these operators are used more generally to show how a type may be compared and will likely be assumed to define actual comparisons by functions that use these traits as bounds. -Many functions and macros in the standard library can then use that assumption (although not to ensure safety). +Unlike arithmetic and logical operators, the traits for overloading these operators are used more generally to show how a type may be compared and will likely be assumed to define actual comparisons by functions that use these traits as bounds. Many functions and macros in the standard library can then use that assumption (although not to ensure safety). r[expr.cmp.place] Unlike the arithmetic and logical operators above, these operators implicitly take shared borrows of their operands, evaluating them in [place expression context][place expression]: @@ -477,12 +465,10 @@ LazyBooleanExpression -> ``` r[expr.bool-logic.intro] -The operators `||` and `&&` may be applied to operands of boolean type. -The `||` operator denotes logical 'or', and the `&&` operator denotes logical 'and'. +The operators `||` and `&&` may be applied to operands of boolean type. The `||` operator denotes logical 'or', and the `&&` operator denotes logical 'and'. r[expr.bool-logic.conditional-evaluation] -They differ from `|` and `&` in that the right-hand operand is only evaluated when the left-hand operand does not already determine the result of the expression. -That is, `||` only evaluates its right-hand operand when the left-hand operand evaluates to `false`, and `&&` only when it evaluates to `true`. +They differ from `|` and `&` in that the right-hand operand is only evaluated when the left-hand operand does not already determine the result of the expression. That is, `||` only evaluates its right-hand operand when the left-hand operand evaluates to `false`, and `&&` only when it evaluates to `true`. ```rust let x = false || true; // true @@ -516,10 +502,7 @@ fn average(values: &[f64]) -> f64 { ``` r[expr.as.coercions] -`as` can be used to explicitly perform [coercions](../type-coercions.md), as well as the following additional casts. -Any cast that does not fit either a coercion rule or an entry in the table is a compiler error. -Here `*T` means either `*const T` or `*mut T`. `m` stands for optional `mut` in -reference types and `mut` or `const` in pointer types. +`as` can be used to explicitly perform [coercions](../type-coercions.md), as well as the following additional casts. Any cast that does not fit either a coercion rule or an entry in the table is a compiler error. Here `*T` means either `*const T` or `*mut T`. `m` stands for optional `mut` in reference types and `mut` or `const` in pointer types. | Type of `e` | `U` | Cast performed by `e as U` | |-----------------------|-----------------------|-------------------------------------------------------| @@ -546,8 +529,7 @@ reference types and `mut` or `const` in pointer types. * **Note**: *adding* auto traits is only allowed if the principal trait has the auto trait as a super trait (given `trait T: Send {}`, `*dyn T` -> `*dyn T + Send` is valid, but `*dyn Debug` -> `*dyn Debug + Send` is not) * **Note**: Generics (including lifetimes) must match (`*dyn T<'a, A>` -> `*dyn T<'b, B>` requires `'a = 'b` and `A = B`) -[^lessmut]: Only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference/pointer to -`const` pointer is allowed. +[^lessmut]: Only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference/pointer to `const` pointer is allowed. [^no-capture]: Only closures that do not capture (close over) any local variables can be cast to function pointers. @@ -557,8 +539,7 @@ r[expr.as.numeric] #### Numeric cast r[expr.as.numeric.int-same-size] -* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op - (Rust uses 2's complement for negative values of fixed integers) +* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op (Rust uses 2's complement for negative values of fixed integers) ```rust assert_eq!(42i8 as u8, 42u8); @@ -568,8 +549,7 @@ r[expr.as.numeric.int-same-size] ``` r[expr.as.numeric.int-truncation] -* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will - truncate +* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will truncate ```rust assert_eq!(42u16 as u8, 42u8); @@ -613,8 +593,7 @@ r[expr.as.numeric.int-as-float] * Casting from an integer to float will produce the closest possible float \* * if necessary, rounding is according to `roundTiesToEven` mode \*\*\* * on overflow, infinity (of the same sign as the input) is produced - * note: with the current set of numeric types, overflow can only happen - on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)` + * note: with the current set of numeric types, overflow can only happen on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)` ```rust assert_eq!(1337i32 as f32, 1337f32); @@ -643,24 +622,17 @@ r[expr.as.numeric.float-narrowing] assert!((std::f64::NAN as f32).is_nan()); ``` -\* if integer-to-float casts with this rounding mode and overflow behavior are -not supported natively by the hardware, these casts will likely be slower than -expected. +\* if integer-to-float casts with this rounding mode and overflow behavior are not supported natively by the hardware, these casts will likely be slower than expected. -\*\* if f64-to-f32 casts with this rounding mode and overflow behavior are not -supported natively by the hardware, these casts will likely be slower than -expected. +\*\* if f64-to-f32 casts with this rounding mode and overflow behavior are not supported natively by the hardware, these casts will likely be slower than expected. -\*\*\* as defined in IEEE 754-2008 §4.3.1: pick the nearest floating point -number, preferring the one with an even least significant digit if exactly -halfway between two floating point numbers. +\*\*\* as defined in IEEE 754-2008 §4.3.1: pick the nearest floating point number, preferring the one with an even least significant digit if exactly halfway between two floating point numbers. r[expr.as.enum] #### Enum cast r[expr.as.enum.discriminant] -Casts an enum to its discriminant, then uses a numeric cast if needed. -Casting is limited to the following kinds of enumerations: +Casts an enum to its discriminant, then uses a numeric cast if needed. Casting is limited to the following kinds of enumerations: * [Unit-only enums] * [Field-less enums] without [explicit discriminants], or where only unit-variants have explicit discriminants @@ -701,8 +673,7 @@ assert_eq!(214u8 as char, 'Ö'); r[expr.as.pointer-as-int] #### Pointer to address cast -Casting from a raw pointer to an integer produces the machine address of the referenced memory. -If the integer type is smaller than the pointer type, the address may be truncated; using `usize` avoids this. +Casting from a raw pointer to an integer produces the machine address of the referenced memory. If the integer type is smaller than the pointer type, the address may be truncated; using `usize` avoids this. r[expr.as.int-as-pointer] #### Address to pointer cast @@ -738,14 +709,9 @@ r[expr.as.pointer.sized] - If `T` and `U` are both sized, the pointer is returned unchanged. r[expr.as.pointer.unsized] -- If `T` and `U` are both unsized, the pointer is also returned unchanged. - In particular, the metadata is preserved exactly. +- If `T` and `U` are both unsized, the pointer is also returned unchanged. In particular, the metadata is preserved exactly. - For instance, a cast from `*const [T]` to `*const [U]` preserves the number of elements. - Note that, as a consequence, such casts do not necessarily preserve the size of the pointer's referent - (e.g., casting `*const [u16]` to `*const [u8]` will result in a raw pointer which refers to an object of half the size of the original). - The same holds for `str` and any compound type whose unsized tail is a slice type, - such as `struct Foo(i32, [u8])` or `(u64, Foo)`. + For instance, a cast from `*const [T]` to `*const [U]` preserves the number of elements. Note that, as a consequence, such casts do not necessarily preserve the size of the pointer's referent (e.g., casting `*const [u16]` to `*const [u8]` will result in a raw pointer which refers to an object of half the size of the original). The same holds for `str` and any compound type whose unsized tail is a slice type, such as `struct Foo(i32, [u8])` or `(u64, Foo)`. r[expr.as.pointer.discard-metadata] - If `T` is unsized and `U` is sized, the cast discards all metadata that completes the wide pointer `T` and produces a thin pointer `U` consisting of the data part of the unsized pointer. @@ -774,8 +740,7 @@ r[expr.assign.basic] ### Basic assignments r[expr.assign.evaluation-order] -Evaluating assignment expressions begins by evaluating its operands. -The assigned value operand is evaluated first, followed by the assignee expression. +Evaluating assignment expressions begins by evaluating its operands. The assigned value operand is evaluated first, followed by the assignee expression. r[expr.assign.destructuring-order] For destructuring assignment, subexpressions of the assignee expression are evaluated left-to-right. @@ -804,8 +769,7 @@ r[expr.assign.destructure] ### Destructuring assignments r[expr.assign.destructure.intro] -Destructuring assignment is a counterpart to destructuring pattern matches for variable declaration, permitting assignment to complex values, such as tuples or structs. -For instance, we may swap two mutable variables: +Destructuring assignment is a counterpart to destructuring pattern matches for variable declaration, permitting assignment to complex values, such as tuples or structs. For instance, we may swap two mutable variables: ```rust let (mut a, mut b) = (0, 1); @@ -814,9 +778,7 @@ let (mut a, mut b) = (0, 1); ``` r[expr.assign.destructure.assignee] -In contrast to destructuring declarations using `let`, patterns may not appear on the left-hand side of an assignment due to syntactic ambiguities. -Instead, a group of expressions that correspond to patterns are designated to be [assignee expressions][assignee expression], and permitted on the left-hand side of an assignment. -Assignee expressions are then desugared to pattern matches followed by sequential assignment. +In contrast to destructuring declarations using `let`, patterns may not appear on the left-hand side of an assignment due to syntactic ambiguities. Instead, a group of expressions that correspond to patterns are designated to be [assignee expressions][assignee expression], and permitted on the left-hand side of an assignment. Assignee expressions are then desugared to pattern matches followed by sequential assignment. r[expr.assign.destructure.irrefutable] The desugared patterns must be irrefutable: in particular, this means that only slice patterns whose length is known at compile-time, and the trivial slice `[..]`, are permitted for destructuring assignment. diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md index afb555dc4c..0046a7dbd5 100644 --- a/src/expressions/struct-expr.md +++ b/src/expressions/struct-expr.md @@ -20,8 +20,7 @@ StructBase -> `..` Expression ``` r[expr.struct.intro] -A *struct expression* creates a struct, enum, or union value. -It consists of a path to a [struct], [enum variant], or [union] item followed by the values for the fields of the item. +A *struct expression* creates a struct, enum, or union value. It consists of a path to a [struct], [enum variant], or [union] item followed by the values for the fields of the item. The following are examples of struct expressions: @@ -85,8 +84,7 @@ r[expr.struct.field] ## Field struct expression r[expr.struct.field.intro] -A struct expression with fields enclosed in curly braces allows you to specify the value for each individual field in any order. -The field name is separated from its value with a colon. +A struct expression with fields enclosed in curly braces allows you to specify the value for each individual field in any order. The field name is separated from its value with a colon. r[expr.struct.field.union-constraint] A value of a [union] type can only be created using this syntax, and it must specify exactly one field. @@ -115,12 +113,10 @@ drop(y_ref); ``` r[expr.struct.brace-restricted-positions] -Struct expressions can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression. -However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses]. +Struct expressions can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression. However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses]. r[expr.struct.tuple-field] -The field names can be decimal integer values to specify indices for constructing tuple structs. -This can be used with base structs to fill out the remaining indices not specified: +The field names can be decimal integer values to specify indices for constructing tuple structs. This can be used with base structs to fill out the remaining indices not specified: ```rust struct Color(u8, u8, u8); @@ -132,9 +128,7 @@ let c3 = Color{1: 0, ..c2}; // Fill out all other fields using a base struct. r[expr.struct.field.named] ### Struct field init shorthand -When initializing a data structure (struct, enum, union) with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. -This allows a compact syntax with less duplication. -For example: +When initializing a data structure (struct, enum, union) with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. This allows a compact syntax with less duplication. For example: ```rust # struct Point3d { x: i32, y: i32, z: i32 } diff --git a/src/expressions/tuple-expr.md b/src/expressions/tuple-expr.md index 69bc238576..f96dfa5cce 100644 --- a/src/expressions/tuple-expr.md +++ b/src/expressions/tuple-expr.md @@ -29,8 +29,7 @@ r[expr.tuple.unit] Tuple expressions without any tuple initializer operands produce the unit tuple. r[expr.tuple.fields] -For other tuple expressions, the first written tuple initializer operand initializes the field `0` and subsequent operands initializes the next highest field. -For example, in the tuple expression `('a', 'b', 'c')`, `'a'` initializes the value of the field `0`, `'b'` field `1`, and `'c'` field `2`. +For other tuple expressions, the first written tuple initializer operand initializes the field `0` and subsequent operands initializes the next highest field. For example, in the tuple expression `('a', 'b', 'c')`, `'a'` initializes the value of the field `0`, `'b'` field `1`, and `'c'` field `2`. Examples of tuple expressions and their types: @@ -55,8 +54,7 @@ A *tuple indexing expression* accesses fields of [tuples][tuple type] and [tuple The syntax for a tuple index expression is an expression, called the *tuple operand*, then a `.`, then finally a tuple index. r[expr.tuple-index.index-syntax] -The syntax for the *tuple index* is a [decimal literal] with no leading zeros, underscores, or suffix. -For example `0` and `2` are valid tuple indices but not `01`, `0_`, nor `0i32`. +The syntax for the *tuple index* is a [decimal literal] with no leading zeros, underscores, or suffix. For example `0` and `2` are valid tuple indices but not `01`, `0_`, nor `0i32`. r[expr.tuple-index.required-type] The type of the tuple operand must be a [tuple type] or a [tuple struct]. @@ -65,8 +63,7 @@ r[expr.tuple-index.index-name-operand] The tuple index must be a name of a field of the type of the tuple operand. r[expr.tuple-index.result] -Evaluation of tuple index expressions has no side effects beyond evaluation of its tuple operand. -As a [place expression], it evaluates to the location of the field of the tuple operand with the same name as the tuple index. +Evaluation of tuple index expressions has no side effects beyond evaluation of its tuple operand. As a [place expression], it evaluates to the location of the field of the tuple operand with the same name as the tuple index. Examples of tuple indexing expressions: diff --git a/src/expressions/underscore-expr.md b/src/expressions/underscore-expr.md index e269f1cfa7..d717213280 100644 --- a/src/expressions/underscore-expr.md +++ b/src/expressions/underscore-expr.md @@ -7,8 +7,7 @@ UnderscoreExpression -> `_` ``` r[expr.placeholder.intro] -Underscore expressions, denoted with the symbol `_`, are used to signify a -placeholder in a destructuring assignment. +Underscore expressions, denoted with the symbol `_`, are used to signify a placeholder in a destructuring assignment. r[expr.placeholder.lhs-assignment-only] They may only appear in the left-hand side of an assignment. diff --git a/src/interior-mutability.md b/src/interior-mutability.md index 117a79cbad..7748ea2080 100644 --- a/src/interior-mutability.md +++ b/src/interior-mutability.md @@ -2,38 +2,28 @@ r[interior-mut] # Interior mutability r[interior-mut.intro] -Sometimes a type needs to be mutated while having multiple aliases. In Rust this -is achieved using a pattern called _interior mutability_. +Sometimes a type needs to be mutated while having multiple aliases. In Rust this is achieved using a pattern called _interior mutability_. r[interior-mut.shared-ref] -A type has interior mutability if its internal state can be changed through a [shared reference] to -it. +A type has interior mutability if its internal state can be changed through a [shared reference] to it. r[interior-mut.no-constraint] -This goes against the usual [requirement][ub] that the value pointed to by a -shared reference is not mutated. +This goes against the usual [requirement][ub] that the value pointed to by a shared reference is not mutated. r[interior-mut.unsafe-cell] -[`std::cell::UnsafeCell`] type is the only allowed way to disable -this requirement. When `UnsafeCell` is immutably aliased, it is still safe to -mutate, or obtain a mutable reference to, the `T` it contains. +[`std::cell::UnsafeCell`] type is the only allowed way to disable this requirement. When `UnsafeCell` is immutably aliased, it is still safe to mutate, or obtain a mutable reference to, the `T` it contains. r[interior-mut.mut-unsafe-cell] -As with all other types, it is undefined behavior to have multiple `&mut UnsafeCell` -aliases. +As with all other types, it is undefined behavior to have multiple `&mut UnsafeCell` aliases. r[interior-mut.abstraction] -Other types with interior mutability can be created by using `UnsafeCell` as -a field. The standard library provides a variety of types that provide safe -interior mutability APIs. +Other types with interior mutability can be created by using `UnsafeCell` as a field. The standard library provides a variety of types that provide safe interior mutability APIs. r[interior-mut.ref-cell] For example, [`std::cell::RefCell`] uses run-time borrow checks to ensure the usual rules around multiple references. r[interior-mut.atomic] -The [`std::sync::atomic`] module contains types that wrap a value that is only -accessed with atomic operations, allowing the value to be shared and mutated -across threads. +The [`std::sync::atomic`] module contains types that wrap a value that is only accessed with atomic operations, allowing the value to be shared and mutated across threads. [shared reference]: types/pointer.md#shared-references- [ub]: behavior-considered-undefined.md diff --git a/src/items.md b/src/items.md index e4fa22f90a..1f81e10c1e 100644 --- a/src/items.md +++ b/src/items.md @@ -30,14 +30,10 @@ MacroItem -> ``` r[items.intro] -An _item_ is a component of a crate. Items are organized within a crate by a -nested set of [modules]. Every crate has a single "outermost" anonymous module; -all further items within the crate have [paths] within the module tree of the -crate. +An _item_ is a component of a crate. Items are organized within a crate by a nested set of [modules]. Every crate has a single "outermost" anonymous module; all further items within the crate have [paths] within the module tree of the crate. r[items.static-def] -Items are entirely determined at compile-time, generally remain fixed during -execution, and may reside in read-only memory. +Items are entirely determined at compile-time, generally remain fixed during execution, and may reside in read-only memory. r[items.kinds] There are several kinds of items: diff --git a/src/items/associated-items.md b/src/items/associated-items.md index c0d0fd0958..0c8d0c5906 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -11,31 +11,23 @@ AssociatedItem -> ``` r[items.associated.intro] -*Associated Items* are the items declared in [traits] or defined in -[implementations]. They are called this because they are defined on an associate -type — the type in the implementation. +*Associated Items* are the items declared in [traits] or defined in [implementations]. They are called this because they are defined on an associate type — the type in the implementation. r[items.associated.kinds] -They are a subset of the kinds of items you can declare in a module. -Specifically, there are [associated functions] (including methods), [associated types], and [associated constants]. +They are a subset of the kinds of items you can declare in a module. Specifically, there are [associated functions] (including methods), [associated types], and [associated constants]. [associated functions]: #associated-functions-and-methods [associated types]: #associated-types [associated constants]: #associated-constants r[items.associated.related] -Associated items are useful when the associated item is logically related to the -associating item. For example, the `is_some` method on `Option` is intrinsically -related to Options, so should be associated. +Associated items are useful when the associated item is logically related to the associating item. For example, the `is_some` method on `Option` is intrinsically related to Options, so should be associated. r[items.associated.decl-def] -Every associated item kind comes in two varieties: definitions that contain the -actual implementation and declarations that declare signatures for -definitions. +Every associated item kind comes in two varieties: definitions that contain the actual implementation and declarations that declare signatures for definitions. r[items.associated.trait-items] -It is the declarations that make up the contract of traits and what is available -on generic types. +It is the declarations that make up the contract of traits and what is available on generic types. r[items.associated.fn] ## Associated functions and methods @@ -44,20 +36,16 @@ r[items.associated.fn.intro] *Associated functions* are [functions] associated with a type. r[items.associated.fn.decl] -An *associated function declaration* declares a signature for an associated -function definition. It is written as a function item, except the -function body is replaced with a `;`. +An *associated function declaration* declares a signature for an associated function definition. It is written as a function item, except the function body is replaced with a `;`. r[items.associated.name] The identifier is the name of the function. r[items.associated.same-signature] -The generics, parameter list, return type, and where clause of the associated function must be the same as the -associated function declarations's. +The generics, parameter list, return type, and where clause of the associated function must be the same as the associated function declarations's. r[items.associated.fn.def] -An *associated function definition* defines a function associated with another -type. It is written the same as a [function item]. +An *associated function definition* defines a function associated with another type. It is written the same as a [function item]. > [!NOTE] > A common example is an associated function named `new` that returns a value of the type with which it is associated. @@ -81,9 +69,7 @@ fn main () { ``` r[items.associated.fn.qualified-self] -When the associated function is declared on a trait, the function can also be -called with a [path] that is a path to the trait appended by the name of the -trait. When this happens, it is substituted for `<_ as Trait>::function_name`. +When the associated function is declared on a trait, the function can also be called with a [path] that is a path to the trait appended by the name of the trait. When this happens, it is substituted for `<_ as Trait>::function_name`. ```rust trait Num { @@ -105,23 +91,17 @@ r[items.associated.fn.method] ### Methods r[items.associated.fn.method.intro] -Associated functions whose first parameter is named `self` are called *methods* -and may be invoked using the [method call operator], for example, `x.foo()`, as -well as the usual function call notation. +Associated functions whose first parameter is named `self` are called *methods* and may be invoked using the [method call operator], for example, `x.foo()`, as well as the usual function call notation. r[items.associated.fn.method.self-ty] -If the type of the `self` parameter is specified, it is limited to types resolving -to one generated by the following grammar (where `'lt` denotes some arbitrary -lifetime): +If the type of the `self` parameter is specified, it is limited to types resolving to one generated by the following grammar (where `'lt` denotes some arbitrary lifetime): ```text P = &'lt S | &'lt mut S | Box | Rc | Arc | Pin

S = Self | P ``` -The `Self` terminal in this grammar denotes a type resolving to the implementing type. -This can also include the contextual type alias `Self`, other type aliases, -or associated type projections resolving to the implementing type. +The `Self` terminal in this grammar denotes a type resolving to the implementing type. This can also include the contextual type alias `Self`, other type aliases, or associated type projections resolving to the implementing type. ```rust # use std::rc::Rc; @@ -148,8 +128,7 @@ impl Example { ``` r[associated.fn.method.self-pat-shorthands] -Shorthand syntax can be used without specifying a type, which have the -following equivalents: +Shorthand syntax can be used without specifying a type, which have the following equivalents: Shorthand | Equivalent ----------------------|----------- @@ -161,8 +140,7 @@ Shorthand | Equivalent > Lifetimes can be, and usually are, elided with this shorthand. r[associated.fn.method.self-pat-mut] -If the `self` parameter is prefixed with `mut`, it becomes a mutable variable, -similar to regular parameters using a `mut` [identifier pattern]. For example: +If the `self` parameter is prefixed with `mut`, it becomes a mutable variable, similar to regular parameters using a `mut` [identifier pattern]. For example: ```rust trait Changer: Sized { @@ -182,9 +160,7 @@ trait Shape { } ``` -This defines a trait with two methods. All values that have [implementations] -of this trait while the trait is in scope can have their `draw` and -`bounding_box` methods called. +This defines a trait with two methods. All values that have [implementations] of this trait while the trait is in scope can have their `draw` and `bounding_box` methods called. ```rust # type Surface = i32; @@ -219,8 +195,7 @@ r[items.associated.fn.params.edition2018] r[items.associated.fn.param-attributes] #### Attributes on method parameters -Attributes on method parameters follow the same rules and restrictions as -[regular function parameters]. +Attributes on method parameters follow the same rules and restrictions as [regular function parameters]. r[items.associated.type] ## Associated types @@ -229,16 +204,10 @@ r[items.associated.type.intro] *Associated types* are [type aliases] associated with another type. r[items.associated.type.restrictions] -Associated types cannot be defined in [inherent implementations] nor can they be given a -default implementation in traits. +Associated types cannot be defined in [inherent implementations] nor can they be given a default implementation in traits. r[items.associated.type.decl] -An *associated type declaration* declares a signature for associated type -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: +An *associated type declaration* declares a signature for associated type 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: ```rust,ignore @@ -260,8 +229,7 @@ r[items.associated.type.sized] There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound. r[items.associated.type.def] -An *associated type definition* defines a type alias for the implementation -of a trait on a type. +An *associated type definition* defines a type alias for the implementation of a trait on a type. r[items.associated.type.def.restriction] They are written similarly to an *associated type declaration*, but cannot contain `Bounds`, but instead must contain a `Type`: @@ -275,20 +243,13 @@ type Assoc where WhereBounds = Type; // deprecated, prefer the form abov ``` r[items.associated.type.alias] -If a type `Item` has an associated type `Assoc` from a trait `Trait`, then -`::Assoc` is a type that is an alias of the type specified in the -associated type definition. +If a type `Item` has an associated type `Assoc` from a trait `Trait`, then `::Assoc` is a type that is an alias of the type specified in the associated type definition. r[items.associated.type.param] Furthermore, if `Item` is a type parameter, then `Item::Assoc` can be used in type parameters. r[items.associated.type.generic] -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 `::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. +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 `::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 { @@ -349,8 +310,7 @@ fn main() { ### Associated types container example -Consider the following example of a `Container` trait. Notice that the type is -available for use in the method signatures: +Consider the following example of a `Container` trait. Notice that the type is available for use in the method signatures: ```rust trait Container { @@ -360,9 +320,7 @@ trait Container { } ``` -In order for a type to implement this trait, it must not only provide -implementations for every method, but it must specify the type `E`. Here's an -implementation of `Container` for the standard library type `Vec`: +In order for a type to implement this trait, it must not only provide implementations for every method, but it must specify the type `E`. Here's an implementation of `Container` for the standard library type `Vec`: ```rust # trait Container { @@ -394,16 +352,10 @@ r[items.associated.type.generic-where-clause] ### Required where clauses on generic associated types r[items.associated.type.generic-where-clause.intro] -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). +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). r[items.associated.type.generic-where-clause.valid-fn] -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. +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 { @@ -412,14 +364,10 @@ trait LendingIterator { } ``` -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`. +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`. r[items.associated.type.generic-where-clause.intersection] -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. +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 { @@ -429,10 +377,7 @@ trait Check { } ``` -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`. +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`. r[items.associated.type.generic-where-clause.forward] The bounds on associated types also propagate required where clauses. @@ -445,13 +390,10 @@ trait Iterable { } ``` -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. +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. r[items.associated.type.generic-where-clause.static] -Finally, any explicit uses of `'static` on GATs in the trait do not count towards -the required bounds. +Finally, any explicit uses of `'static` on GATs in the trait do not count towards the required bounds. ```rust trait StaticReturn { @@ -467,22 +409,16 @@ r[items.associated.const.intro] *Associated constants* are [constants] associated with a type. r[items.associated.const.decl] -An *associated constant declaration* declares a signature for associated -constant definitions. It is written as `const`, then an identifier, -then `:`, then a type, finished by a `;`. +An *associated constant declaration* declares a signature for associated constant definitions. It is written as `const`, then an identifier, then `:`, then a type, finished by a `;`. r[items.associated.const.name] -The identifier is the name of the constant used in the path. The type is the -type that the definition has to implement. +The identifier is the name of the constant used in the path. The type is the type that the definition has to implement. r[items.associated.const.def] -An *associated constant definition* defines a constant associated with a -type. It is written the same as a [constant item]. +An *associated constant definition* defines a constant associated with a type. It is written the same as a [constant item]. r[items.associated.const.eval] -Associated constant definitions undergo [constant evaluation] only when -referenced. Further, definitions that include [generic parameters] are -evaluated after monomorphization. +Associated constant definitions undergo [constant evaluation] only when referenced. Further, definitions that include [generic parameters] are evaluated after monomorphization. ```rust,compile_fail struct Struct; diff --git a/src/items/constant-items.md b/src/items/constant-items.md index 0b2f223c44..4e21e8c0ae 100644 --- a/src/items/constant-items.md +++ b/src/items/constant-items.md @@ -8,27 +8,19 @@ ConstantItem -> ``` r[items.const.intro] -A *constant item* is an optionally named _[constant value]_ which is not associated -with a specific memory location in the program. +A *constant item* is an optionally named _[constant value]_ which is not associated with a specific memory location in the program. r[items.const.behavior] -Constants are essentially inlined wherever they are used, meaning that they are copied directly into the relevant -context when used. This includes usage of constants from external crates, and -non-[`Copy`] types. References to the same constant are not necessarily -guaranteed to refer to the same memory address. +Constants are essentially inlined wherever they are used, meaning that they are copied directly into the relevant context when used. This includes usage of constants from external crates, and non-[`Copy`] types. References to the same constant are not necessarily guaranteed to refer to the same memory address. r[items.const.namespace] The constant declaration defines the constant value in the [value namespace] of the module or block where it is located. r[items.const.static] -Constants must be explicitly typed. The type must have a `'static` lifetime: any -references in the initializer must have `'static` lifetimes. References -in the type of a constant default to `'static` lifetime; see [static lifetime -elision]. +Constants must be explicitly typed. The type must have a `'static` lifetime: any references in the initializer must have `'static` lifetimes. References in the type of a constant default to `'static` lifetime; see [static lifetime elision]. r[items.const.static-temporary] -A reference to a constant will have `'static` lifetime if the constant value is eligible for -[promotion]; otherwise, a temporary will be created. +A reference to a constant will have `'static` lifetime if the constant value is eligible for [promotion]; otherwise, a temporary will be created. ```rust const BIT1: u32 = 1 << 0; @@ -54,8 +46,7 @@ The constant expression may only be omitted in a [trait definition]. r[items.const.destructor] ## Constants with destructors -Constants can contain destructors. Destructors are run when the value goes out -of scope. +Constants can contain destructors. Destructors are run when the value goes out of scope. ```rust struct TypeWithDestructor(i32); @@ -79,8 +70,7 @@ r[items.const.unnamed] ## Unnamed constant r[items.const.unnamed.intro] -Unlike an [associated constant], a [free] constant may be unnamed by using -an underscore instead of the name. For example: +Unlike an [associated constant], a [free] constant may be unnamed by using an underscore instead of the name. For example: ```rust const _: () = { struct _SameNameTwice; }; @@ -90,8 +80,7 @@ const _: () = { struct _SameNameTwice; }; ``` r[items.const.unnamed.repetition] -As with [underscore imports], macros may safely emit the same unnamed constant in -the same scope more than once. For example, the following should not produce an error: +As with [underscore imports], macros may safely emit the same unnamed constant in the same scope more than once. For example, the following should not produce an error: ```rust macro_rules! m { @@ -107,8 +96,7 @@ m!(const _: () = ();); r[items.const.eval] ## Evaluation -[Free][free] constants are always [evaluated][const_eval] at compile-time to surface -panics. This happens even within an unused function: +[Free][free] constants are always [evaluated][const_eval] at compile-time to surface panics. This happens even within an unused function: ```rust,compile_fail // Compile-time panic diff --git a/src/items/enumerations.md b/src/items/enumerations.md index 04794915a8..80bf2ac034 100644 --- a/src/items/enumerations.md +++ b/src/items/enumerations.md @@ -20,9 +20,7 @@ EnumVariantDiscriminant -> `=` Expression ``` r[items.enum.intro] -An *enumeration*, also referred to as an *enum*, is a simultaneous definition of a -nominal [enumerated type] as well as a set of *constructors*, that can be used -to create or pattern-match values of the corresponding enumerated type. +An *enumeration*, also referred to as an *enum*, is a simultaneous definition of a nominal [enumerated type] as well as a set of *constructors*, that can be used to create or pattern-match values of the corresponding enumerated type. r[items.enum.decl] Enumerations are declared with the keyword `enum`. @@ -55,12 +53,10 @@ let mut a: Animal = Animal::Dog("Cocoa".to_string(), 37.2); a = Animal::Cat { name: "Spotty".to_string(), weight: 2.7 }; ``` -In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply -called an enum variant. +In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply called an enum variant. r[items.enum.fieldless] -An enum where no constructors contain fields is called a -*field-less enum*. For example, this is a fieldless enum: +An enum where no constructors contain fields is called a *field-less enum*. For example, this is a fieldless enum: ```rust enum Fieldless { @@ -71,8 +67,7 @@ enum Fieldless { ``` r[items.enum.unit-only] -If a field-less enum only contains unit variants, the enum is called an -*unit-only enum*. For example: +If a field-less enum only contains unit variants, the enum is called an *unit-only enum*. For example: ```rust enum Enum { @@ -86,8 +81,7 @@ r[items.enum.constructor-names] Variant constructors are similar to [struct] definitions, and can be referenced by a path from the enumeration name, including in [use declarations]. r[items.enum.constructor-namespace] -Each variant defines its type in the [type namespace], though that type cannot be used as a type specifier. -Tuple-like and unit-like variants also define a constructor in the [value namespace]. +Each variant defines its type in the [type namespace], though that type cannot be used as a type specifier. Tuple-like and unit-like variants also define a constructor in the [value namespace]. r[items.enum.struct-expr] A struct-like variant can be instantiated with a [struct expression]. @@ -96,8 +90,7 @@ r[items.enum.tuple-expr] A tuple-like variant can be instantiated with a [call expression] or a [struct expression]. r[items.enum.path-expr] -A unit-like variant can be instantiated with a [path expression] or a [struct expression]. -For example: +A unit-like variant can be instantiated with a [path expression] or a [struct expression]. For example: ```rust enum Examples { @@ -119,13 +112,10 @@ r[items.enum.discriminant] ## Discriminants r[items.enum.discriminant.intro] -Each enum instance has a _discriminant_: an integer logically associated to it -that is used to determine which variant it holds. +Each enum instance has a _discriminant_: an integer logically associated to it that is used to determine which variant it holds. r[items.enum.discriminant.repr-rust] -Under the [`Rust` representation], the discriminant is interpreted as -an `isize` value. However, the compiler is allowed to use a smaller type (or -another means of distinguishing variants) in its actual memory layout. +Under the [`Rust` representation], the discriminant is interpreted as an `isize` value. However, the compiler is allowed to use a smaller type (or another means of distinguishing variants) in its actual memory layout. ### Assigning discriminant values @@ -133,8 +123,7 @@ r[items.enum.discriminant.explicit] #### Explicit discriminants r[items.enum.discriminant.explicit.intro] -In two circumstances, the discriminant of a variant may be explicitly set by -following the variant name with `=` and a [constant expression]: +In two circumstances, the discriminant of a variant may be explicitly set by following the variant name with `=` and a [constant expression]: r[items.enum.discriminant.explicit.unit-only] 1. if the enumeration is "[unit-only]". @@ -157,10 +146,7 @@ r[items.enum.discriminant.explicit.primitive-repr] r[items.enum.discriminant.implicit] #### Implicit discriminants -If a discriminant for a variant is not specified, then it is set to one higher -than the discriminant of the previous variant in the declaration. If the -discriminant of the first variant in the declaration is unspecified, then -it is set to zero. +If a discriminant for a variant is not specified, then it is set to one higher than the discriminant of the previous variant in the declaration. If the discriminant of the first variant in the declaration is unspecified, then it is set to zero. ```rust enum Foo { @@ -193,8 +179,7 @@ enum SharedDiscriminantError2 { ``` r[items.enum.discriminant.restrictions.above-max-discriminant] -It is also an error to have an unspecified discriminant where the previous -discriminant is the maximum value for the size of the discriminant. +It is also an error to have an unspecified discriminant where the previous discriminant is the maximum value for the size of the discriminant. ```rust,compile_fail #[repr(u8)] @@ -217,16 +202,13 @@ enum OverflowingDiscriminantError2 { r[items.enum.discriminant.access-opaque] -[`std::mem::discriminant`] returns an opaque reference to the discriminant of -an enum value which can be compared. This cannot be used to get the value -of the discriminant. +[`std::mem::discriminant`] returns an opaque reference to the discriminant of an enum value which can be compared. This cannot be used to get the value of the discriminant. r[items.enum.discriminant.coercion] #### Casting r[items.enum.discriminant.coercion.intro] -If an enumeration is [unit-only] (with no tuple and struct variants), then its -discriminant can be directly accessed with a [numeric cast]; e.g.: +If an enumeration is [unit-only] (with no tuple and struct variants), then its discriminant can be directly accessed with a [numeric cast]; e.g.: ```rust enum Enum { @@ -274,8 +256,7 @@ assert_eq!(22, FieldlessWithDiscriminants::Unit as u8); r[items.enum.discriminant.access-memory] -If the enumeration specifies a [primitive representation], then the -discriminant may be reliably accessed via unsafe pointer casting: +If the enumeration specifies a [primitive representation], then the discriminant may be reliably accessed via unsafe pointer casting: ```rust #[repr(u8)] @@ -304,16 +285,14 @@ r[items.enum.empty] ## Zero-variant enums r[items.enum.empty.intro] -Enums with zero variants are known as *zero-variant enums*. As they have -no valid values, they cannot be instantiated. +Enums with zero variants are known as *zero-variant enums*. As they have no valid values, they cannot be instantiated. ```rust enum ZeroVariants {} ``` r[items.enum.empty.uninhabited] -Zero-variant enums are equivalent to the [never type], but they cannot be -coerced into other types. +Zero-variant enums are equivalent to the [never type], but they cannot be coerced into other types. ```rust,compile_fail # enum ZeroVariants {} @@ -324,9 +303,7 @@ let y: u32 = x; // mismatched type error r[items.enum.variant-visibility] ## Variant visibility -Enum variants syntactically allow a [Visibility] annotation, but this is -rejected when the enum is validated. This allows items to be parsed with a -unified syntax across different contexts where they are used. +Enum variants syntactically allow a [Visibility] annotation, but this is rejected when the enum is validated. This allows items to be parsed with a unified syntax across different contexts where they are used. ```rust macro_rules! mac_variant { diff --git a/src/items/extern-crates.md b/src/items/extern-crates.md index 355646f3f1..ffad1d9836 100644 --- a/src/items/extern-crates.md +++ b/src/items/extern-crates.md @@ -23,17 +23,10 @@ r[items.extern-crate.as] The `as` clause can be used to bind the imported crate to a different name. r[items.extern-crate.lookup] -The external crate is resolved to a specific `soname` at compile time, and a -runtime linkage requirement to that `soname` is passed to the linker for -loading at runtime. The `soname` is resolved at compile time by scanning the -compiler's library path and matching the optional `crate_name` provided against -the [`crate_name` attributes] that were declared on the external crate when it was -compiled. If no `crate_name` is provided, a default `name` attribute is assumed, -equal to the [identifier] given in the `extern crate` declaration. +The external crate is resolved to a specific `soname` at compile time, and a runtime linkage requirement to that `soname` is passed to the linker for loading at runtime. The `soname` is resolved at compile time by scanning the compiler's library path and matching the optional `crate_name` provided against the [`crate_name` attributes] that were declared on the external crate when it was compiled. If no `crate_name` is provided, a default `name` attribute is assumed, equal to the [identifier] given in the `extern crate` declaration. r[items.extern-crate.self] -The `self` crate may be imported which creates a binding to the current crate. -In this case the `as` clause must be used to specify the name to bind it to. +The `self` crate may be imported which creates a binding to the current crate. In this case the `as` clause must be used to specify the name to bind it to. Three examples of `extern crate` declarations: @@ -47,10 +40,7 @@ extern crate std as ruststd; // linking to 'std' under another name ``` r[items.extern-crate.name-restrictions] -When naming Rust crates, hyphens are disallowed. However, Cargo packages may -make use of them. In such case, when `Cargo.toml` doesn't specify a crate name, -Cargo will transparently replace `-` with `_` (Refer to [RFC 940] for more -details). +When naming Rust crates, hyphens are disallowed. However, Cargo packages may make use of them. In such case, when `Cargo.toml` doesn't specify a crate name, Cargo will transparently replace `-` with `_` (Refer to [RFC 940] for more details). Here is an example: @@ -64,14 +54,10 @@ r[items.extern-crate.underscore] ## Underscore imports r[items.extern-crate.underscore.intro] -An external crate dependency can be declared without binding its name in scope -by using an underscore with the form `extern crate foo as _`. This may be -useful for crates that only need to be linked, but are never referenced, and -will avoid being reported as unused. +An external crate dependency can be declared without binding its name in scope by using an underscore with the form `extern crate foo as _`. This may be useful for crates that only need to be linked, but are never referenced, and will avoid being reported as unused. r[items.extern-crate.underscore.macro_use] -The [`macro_use` attribute] works as usual and imports the macro names -into the [`macro_use` prelude]. +The [`macro_use` attribute] works as usual and imports the macro names into the [`macro_use` prelude]. r[items.extern-crate.no_link] diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 91fd18d66e..6fdb70028f 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -20,13 +20,10 @@ ExternalItem -> [^unsafe-2024]: Starting with the 2024 Edition, the `unsafe` keyword is required semantically. r[items.extern.intro] -External blocks provide _declarations_ of items that are not _defined_ in the -current crate and are the basis of Rust's foreign function interface. These are -akin to unchecked imports. +External blocks provide _declarations_ of items that are not _defined_ in the current crate and are the basis of Rust's foreign function interface. These are akin to unchecked imports. r[items.extern.allowed-kinds] -Two kinds of item _declarations_ are allowed in external blocks: [functions] and -[statics]. +Two kinds of item _declarations_ are allowed in external blocks: [functions] and [statics]. r[items.extern.safety] Calling unsafe functions or accessing unsafe statics that are declared in external blocks is only allowed in an [`unsafe` context]. @@ -45,54 +42,37 @@ r[items.extern.fn] ## Functions r[items.extern.fn.body] -Functions within external blocks are declared in the same way as other Rust -functions, with the exception that they must not have a body and are instead -terminated by a semicolon. +Functions within external blocks are declared in the same way as other Rust functions, with the exception that they must not have a body and are instead terminated by a semicolon. r[items.extern.fn.param-patterns] Patterns are not allowed in parameters, only [IDENTIFIER] or `_` may be used. r[items.extern.fn.qualifiers] -The `safe` and `unsafe` function qualifiers are -allowed, but other function qualifiers (e.g. `const`, `async`, `extern`) are -not. +The `safe` and `unsafe` function qualifiers are allowed, but other function qualifiers (e.g. `const`, `async`, `extern`) are not. r[items.extern.fn.foreign-abi] -Functions within external blocks may be called by Rust code, just like -functions defined in Rust. The Rust compiler automatically translates between -the Rust ABI and the foreign ABI. +Functions within external blocks may be called by Rust code, just like functions defined in Rust. The Rust compiler automatically translates between the Rust ABI and the foreign ABI. r[items.extern.fn.safety] -A function declared in an extern block is implicitly `unsafe` unless the `safe` -function qualifier is present. +A function declared in an extern block is implicitly `unsafe` unless the `safe` function qualifier is present. r[items.extern.fn.fn-ptr] -When coerced to a function pointer, a function declared in an extern block has -type `extern "abi" for<'l1, ..., 'lm> fn(A1, ..., An) -> R`, where `'l1`, -... `'lm` are its lifetime parameters, `A1`, ..., `An` are the declared types of -its parameters, and `R` is the declared return type. +When coerced to a function pointer, a function declared in an extern block has type `extern "abi" for<'l1, ..., 'lm> fn(A1, ..., An) -> R`, where `'l1`, ... `'lm` are its lifetime parameters, `A1`, ..., `An` are the declared types of its parameters, and `R` is the declared return type. r[items.extern.static] ## Statics r[items.extern.static.intro] -Statics within external blocks are declared in the same way as [statics] outside of external blocks, -except that they do not have an expression initializing their value. +Statics within external blocks are declared in the same way as [statics] outside of external blocks, except that they do not have an expression initializing their value. r[items.extern.static.safety] -Unless a static item declared in an extern block is qualified as `safe`, it is `unsafe` to access that item, whether or -not it's mutable, because there is nothing guaranteeing that the bit pattern at the static's -memory is valid for the type it is declared with, since some arbitrary (e.g. C) code is in charge -of initializing the static. +Unless a static item declared in an extern block is qualified as `safe`, it is `unsafe` to access that item, whether or not it's mutable, because there is nothing guaranteeing that the bit pattern at the static's memory is valid for the type it is declared with, since some arbitrary (e.g. C) code is in charge of initializing the static. r[items.extern.static.mut] Extern statics can be either immutable or mutable just like [statics] outside of external blocks. r[items.extern.static.read-only] -An immutable static *must* be initialized before any Rust code is executed. It is not enough for -the static to be initialized before Rust code reads from it. -Once Rust code runs, mutating an immutable static (from inside or outside Rust) is UB, -except if the mutation happens to bytes inside of an `UnsafeCell`. +An immutable static *must* be initialized before any Rust code is executed. It is not enough for the static to be initialized before Rust code reads from it. Once Rust code runs, mutating an immutable static (from inside or outside Rust) is UB, except if the mutation happens to bytes inside of an `UnsafeCell`. r[items.extern.abi] ## ABI @@ -232,9 +212,7 @@ Like `"C"` and `"system"`, most platform-specific ABI strings also have a [corre r[items.extern.variadic] ## Variadic functions -Functions within external blocks may be variadic by specifying `...` as the -last argument. The variadic parameter may optionally be specified with an -identifier. +Functions within external blocks may be variadic by specifying `...` as the last argument. The variadic parameter may optionally be specified with an identifier. ```rust unsafe extern "C" { @@ -271,52 +249,37 @@ r[items.extern.attributes.link] ### The `link` attribute r[items.extern.attributes.link.intro] -The *`link` attribute* specifies the name of a native library that the -compiler should link with for the items within an `extern` block. +The *`link` attribute* specifies the name of a native library that the compiler should link with for the items within an `extern` block. r[items.extern.attributes.link.syntax] -It uses the [MetaListNameValueStr] syntax to specify its inputs. The `name` key is the -name of the native library to link. The `kind` key is an optional value which -specifies the kind of library with the following possible values: +It uses the [MetaListNameValueStr] syntax to specify its inputs. The `name` key is the name of the native library to link. The `kind` key is an optional value which specifies the kind of library with the following possible values: r[items.extern.attributes.link.dylib] -- `dylib` --- Indicates a dynamic library. This is the default if `kind` is not - specified. +- `dylib` --- Indicates a dynamic library. This is the default if `kind` is not specified. r[items.extern.attributes.link.static] - `static` --- Indicates a static library. r[items.extern.attributes.link.framework] -- `framework` --- Indicates a macOS framework. This is only valid for macOS - targets. +- `framework` --- Indicates a macOS framework. This is only valid for macOS targets. r[items.extern.attributes.link.raw-dylib] -- `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. +- `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. r[items.extern.attributes.link.name-requirement] The `name` key must be included if `kind` is specified. r[items.extern.attributes.link.modifiers] -The optional `modifiers` argument is a way to specify linking modifiers for the -library to link. +The optional `modifiers` argument is a way to specify linking modifiers for the library to link. r[items.extern.attributes.link.modifiers.syntax] -Modifiers are specified as a comma-delimited string with each modifier prefixed -with either a `+` or `-` to indicate that the modifier is enabled or disabled, -respectively. +Modifiers are specified as a comma-delimited string with each modifier prefixed with either a `+` or `-` to indicate that the modifier is enabled or disabled, respectively. r[items.extern.attributes.link.modifiers.multiple] -Specifying multiple `modifiers` arguments in a single `link` attribute, -or multiple identical modifiers in the same `modifiers` argument is not currently supported. \ -Example: `#[link(name = "mylib", kind = "static", modifiers = "+whole-archive")]`. +Specifying multiple `modifiers` arguments in a single `link` attribute, or multiple identical modifiers in the same `modifiers` argument is not currently supported. Example: `#[link(name = "mylib", kind = "static", modifiers = "+whole-archive")]`. r[items.extern.attributes.link.wasm_import_module] -The `wasm_import_module` key may be used to specify the [WebAssembly module] -name for the items within an `extern` block when importing symbols from the -host environment. The default module name is `env` if `wasm_import_module` is -not specified. +The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is not specified. ```rust,ignore @@ -337,30 +300,19 @@ unsafe extern { ``` r[items.extern.attributes.link.empty-block] -It is valid to add the `link` attribute on an empty extern block. You can use -this to satisfy the linking requirements of extern blocks elsewhere in your -code (including upstream crates) instead of adding the attribute to each extern -block. +It is valid to add the `link` attribute on an empty extern block. You can use this to satisfy the linking requirements of extern blocks elsewhere in your code (including upstream crates) instead of adding the attribute to each extern block. r[items.extern.attributes.link.modifiers.bundle] #### Linking modifiers: `bundle` r[items.extern.attributes.link.modifiers.bundle.allowed-kinds] -This modifier is only compatible with the `static` linking kind. -Using any other kind will result in a compiler error. +This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. r[items.extern.attributes.link.modifiers.bundle.behavior] -When building a rlib or staticlib `+bundle` means that the native static library -will be packed into the rlib or staticlib archive, and then retrieved from there -during linking of the final binary. +When building a rlib or staticlib `+bundle` means that the native static library will be packed into the rlib or staticlib archive, and then retrieved from there during linking of the final binary. r[items.extern.attributes.link.modifiers.bundle.behavior-negative] -When building a rlib `-bundle` means that the native static library is registered as a dependency -of that rlib "by name", and object files from it are included only during linking of the final -binary, the file search by that name is also performed during final linking. \ -When building a staticlib `-bundle` means that the native static library is simply not included -into the archive and some higher level build system will need to add it later during linking of -the final binary. +When building a rlib `-bundle` means that the native static library is registered as a dependency of that rlib "by name", and object files from it are included only during linking of the final binary, the file search by that name is also performed during final linking. When building a staticlib `-bundle` means that the native static library is simply not included into the archive and some higher level build system will need to add it later during linking of the final binary. r[items.extern.attributes.link.modifiers.bundle.no-effect] This modifier has no effect when building other targets like executables or dynamic libraries. @@ -368,25 +320,21 @@ This modifier has no effect when building other targets like executables or dyna r[items.extern.attributes.link.modifiers.bundle.default] The default for this modifier is `+bundle`. -More implementation details about this modifier can be found in -[`bundle` documentation for rustc]. +More implementation details about this modifier can be found in [`bundle` documentation for rustc]. r[items.extern.attributes.link.modifiers.whole-archive] #### Linking modifiers: `whole-archive` r[items.extern.attributes.link.modifiers.whole-archive.allowed-kinds] -This modifier is only compatible with the `static` linking kind. -Using any other kind will result in a compiler error. +This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. r[items.extern.attributes.link.modifiers.whole-archive.behavior] -`+whole-archive` means that the static library is linked as a whole archive -without throwing any object files away. +`+whole-archive` means that the static library is linked as a whole archive without throwing any object files away. r[items.extern.attributes.link.modifiers.whole-archive.default] The default for this modifier is `-whole-archive`. -More implementation details about this modifier can be found in -[`whole-archive` documentation for rustc]. +More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. r[items.extern.attributes.link.modifiers.verbatim] ### Linking modifiers: `verbatim` @@ -395,75 +343,49 @@ r[items.extern.attributes.link.modifiers.verbatim.allowed-kinds] This modifier is compatible with all linking kinds. r[items.extern.attributes.link.modifiers.verbatim.behavior] -`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes -(like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the -linker. +`+verbatim` means that rustc itself won't add any target-specified library prefixes or suffixes (like `lib` or `.a`) to the library name, and will try its best to ask for the same thing from the linker. r[items.extern.attributes.link.modifiers.verbatim.behavior-negative] -`-verbatim` means that rustc will either add a target-specific prefix and suffix to the library -name before passing it to linker, or won't prevent linker from implicitly adding it. +`-verbatim` means that rustc will either add a target-specific prefix and suffix to the library name before passing it to linker, or won't prevent linker from implicitly adding it. r[items.extern.attributes.link.modifiers.verbatim.default] The default for this modifier is `-verbatim`. -More implementation details about this modifier can be found in -[`verbatim` documentation for rustc]. +More implementation details about this modifier can be found in [`verbatim` documentation for rustc]. r[items.extern.attributes.link.kind-raw-dylib] #### `dylib` versus `raw-dylib` r[items.extern.attributes.link.kind-raw-dylib.intro] -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. +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. r[items.extern.attributes.link.kind-raw-dylib.import] -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. +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. r[items.extern.attributes.link.kind-raw-dylib.platform-specific] -`raw-dylib` is only supported on Windows. Using it when targeting other -platforms will result in a compiler error. +`raw-dylib` is only supported on Windows. Using it when targeting other platforms will result in a compiler error. r[items.extern.attributes.link.import_name_type] #### The `import_name_type` key r[items.extern.attributes.link.import_name_type.intro] -On x86 Windows, names of functions are "decorated" (i.e., have a specific prefix -and/or suffix added) to indicate their calling convention. For example, a -`stdcall` calling convention function with the name `fn1` that has no arguments -would be decorated as `_fn1@0`. However, the [PE Format] does also permit names -to have no prefix or be undecorated. Additionally, the MSVC and GNU toolchains -use different decorations for the same calling conventions which means, by -default, some Win32 functions cannot be called using the `raw-dylib` link kind -via the GNU toolchain. +On x86 Windows, names of functions are "decorated" (i.e., have a specific prefix and/or suffix added) to indicate their calling convention. For example, a `stdcall` calling convention function with the name `fn1` that has no arguments would be decorated as `_fn1@0`. However, the [PE Format] does also permit names to have no prefix or be undecorated. Additionally, the MSVC and GNU toolchains use different decorations for the same calling conventions which means, by default, some Win32 functions cannot be called using the `raw-dylib` link kind via the GNU toolchain. r[items.extern.attributes.link.import_name_type.values] -To allow for these differences, when using the `raw-dylib` link kind you may -also specify the `import_name_type` key with one of the following values to -change how functions are named in the generated import library: - -* `decorated`: The function name will be fully-decorated using the MSVC - toolchain format. -* `noprefix`: The function name will be decorated using the MSVC toolchain - format, but skipping the leading `?`, `@`, or optionally `_`. +To allow for these differences, when using the `raw-dylib` link kind you may also specify the `import_name_type` key with one of the following values to change how functions are named in the generated import library: + +* `decorated`: The function name will be fully-decorated using the MSVC toolchain format. +* `noprefix`: The function name will be decorated using the MSVC toolchain format, but skipping the leading `?`, `@`, or optionally `_`. * `undecorated`: The function name will not be decorated. r[items.extern.attributes.link.import_name_type.default] -If the `import_name_type` key is not specified, then the function name will be -fully-decorated using the target toolchain's format. +If the `import_name_type` key is not specified, then the function name will be fully-decorated using the target toolchain's format. r[items.extern.attributes.link.import_name_type.variables] -Variables are never decorated and so the `import_name_type` key has no effect on -how they are named in the generated import library. +Variables are never decorated and so the `import_name_type` key has no effect on how they are named in the generated import library. r[items.extern.attributes.link.import_name_type.platform-specific] -The `import_name_type` key is only supported on x86 Windows. Using it when -targeting other platforms will result in a compiler error. +The `import_name_type` key is only supported on x86 Windows. Using it when targeting other platforms will result in a compiler error. r[items.extern.attributes.link_name] @@ -502,11 +424,7 @@ r[items.extern.attributes.link_ordinal] ### The `link_ordinal` attribute r[items.extern.attributes.link_ordinal.intro] -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. +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. > [!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. @@ -521,18 +439,15 @@ unsafe extern "stdcall" { ``` r[items.extern.attributes.link_ordinal.allowed-kinds] -This attribute is only used with the `raw-dylib` linking kind. -Using any other kind will result in a compiler error. +This attribute is only used with the `raw-dylib` linking kind. Using any other kind will result in a compiler error. r[items.extern.attributes.link_ordinal.exclusive] -Using this attribute with the `link_name` attribute will result in a -compiler error. +Using this attribute with the `link_name` attribute will result in a compiler error. r[items.extern.attributes.fn-parameters] ### Attributes on function parameters -Attributes on extern function parameters follow the same rules and -restrictions as [regular function parameters]. +Attributes on extern function parameters follow the same rules and restrictions as [regular function parameters]. [ABI]: glossary.abi [PE Format]: https://learn.microsoft.com/windows/win32/debug/pe-format#import-name-type diff --git a/src/items/functions.md b/src/items/functions.md index 468c50574f..cf3d114886 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -34,20 +34,14 @@ FunctionReturnType -> `->` Type [^async-edition]: The `async` qualifier is not allowed in the 2015 edition. -[^extern-safe]: The `safe` function qualifier is only allowed semantically within - `extern` blocks. +[^extern-safe]: The `safe` function qualifier is only allowed semantically within `extern` blocks. -[^extern-qualifiers]: *Relevant to editions earlier than Rust 2024*: Within - `extern` blocks, the `safe` or `unsafe` function qualifier is only allowed - when the `extern` is qualified as `unsafe`. +[^extern-qualifiers]: *Relevant to editions earlier than Rust 2024*: Within `extern` blocks, the `safe` or `unsafe` function qualifier is only allowed when the `extern` is qualified as `unsafe`. -[^fn-param-2015]: Function parameters with only a type are only allowed - in an associated function of a [trait item] in the 2015 edition. +[^fn-param-2015]: Function parameters with only a type are only allowed in an associated function of a [trait item] in the 2015 edition. r[items.fn.intro] -A _function_ consists of a [block] (that's the _body_ of the function), -along with a name, a set of parameters, and an output type. -Other than a name, all these are optional. +A _function_ consists of a [block] (that's the _body_ of the function), along with a name, a set of parameters, and an output type. Other than a name, all these are optional. r[items.fn.namespace] Functions are declared with the keyword `fn` which defines the given name in the [value namespace] of the module or block where it is located. @@ -62,6 +56,7 @@ r[items.fn.fn-item-type] When referred to, a _function_ yields a first-class *value* of the corresponding zero-sized [*function item type*], which when called evaluates to a direct call to the function. For example, this is a simple function: + ```rust fn answer_to_life_the_universe_and_everything() -> i32 { return 42; @@ -75,35 +70,26 @@ r[items.fn.params] ## Function parameters r[items.fn.params.intro] -Function parameters are irrefutable [patterns], so any pattern that is valid in -an else-less `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 } ``` r[items.fn.params.self-pat] -If the first parameter is a [SelfParam], this indicates that the function is a -[method]. +If the first parameter is a [SelfParam], this indicates that the function is a [method]. r[items.fn.params.self-restriction] -Functions with a self parameter may only appear as an [associated -function] in a [trait] or [implementation]. +Functions with a self parameter may only appear as an [associated function] in a [trait] or [implementation]. r[items.fn.params.varargs] -A parameter with the `...` token indicates a [variadic function], and may only -be used as the last parameter of an [external block] function. The variadic -parameter may have an optional identifier, such as `args: ...`. +A parameter with the `...` token indicates a [variadic function], and may only be used as the last parameter of an [external block] function. The variadic parameter may have an optional identifier, such as `args: ...`. r[items.fn.body] ## Function body r[items.fn.body.intro] -The body block of a function is conceptually wrapped in another block that first binds the -argument patterns and then `return`s the value of the function's body. This -means that the tail expression of the block, if evaluated, ends up being -returned to the caller. As usual, an explicit return expression within -the body of the function will short-cut that implicit return, if reached. +The body block of a function is conceptually wrapped in another block that first binds the argument patterns and then `return`s the value of the function's body. This means that the tail expression of the block, if evaluated, ends up being returned to the caller. As usual, an explicit return expression within the body of the function will short-cut that implicit return, if reached. For example, the function above behaves as if it was written as: @@ -117,16 +103,13 @@ return { ``` r[items.fn.body.bodyless] -Functions without a body block are terminated with a semicolon. This form -may only appear in a [trait] or [external block]. +Functions without a body block are terminated with a semicolon. This form may only appear in a [trait] or [external block]. r[items.fn.generics] ## Generic functions r[items.fn.generics.intro] -A _generic function_ allows one or more _parameterized types_ to appear in its -signature. Each type parameter must be explicitly declared in an -angle-bracket-enclosed and comma-separated list, following the function name. +A _generic function_ allows one or more _parameterized types_ to appear in its signature. Each type parameter must be explicitly declared in an angle-bracket-enclosed and comma-separated list, following the function name. ```rust // foo is generic over A and B @@ -136,13 +119,10 @@ fn foo(x: A, y: B) { ``` r[items.fn.generics.param-names] -Inside the function signature and body, the name of the type parameter can be -used as a type name. +Inside the function signature and body, the name of the type parameter can be used as a type name. r[items.fn.generics.param-bounds] -[Trait] bounds can be specified for type -parameters to allow methods with that trait to be called on values of that -type. This is specified using the `where` syntax: +[Trait] bounds can be specified for type parameters to allow methods with that trait to be called on values of that type. This is specified using the `where` syntax: ```rust # use std::fmt::Debug; @@ -151,8 +131,7 @@ fn foo(x: T) where T: Debug { ``` r[items.fn.generics.mono] -When a generic function is referenced, its type is instantiated based on the -context of the reference. For example, calling the `foo` function here: +When a generic function is referenced, its type is instantiated based on the context of the reference. For example, calling the `foo` function here: ```rust use std::fmt::Debug; @@ -167,17 +146,13 @@ foo(&[1, 2]); will instantiate type parameter `T` with `i32`. r[items.fn.generics.explicit-arguments] -The type parameters can also be explicitly supplied in a trailing [path] -component after the function name. This might be necessary if there is not -sufficient context to determine the type parameters. For example, -`mem::size_of::() == 4`. +The type parameters can also be explicitly supplied in a trailing [path] component after the function name. This might be necessary if there is not sufficient context to determine the type parameters. For example, `mem::size_of::() == 4`. r[items.fn.extern] ## Extern function qualifier r[items.fn.extern.intro] -The `extern` function qualifier allows providing function _definitions_ that can -be called with a particular ABI: +The `extern` function qualifier allows providing function _definitions_ that can be called with a particular ABI: ```rust,ignore @@ -185,9 +160,7 @@ extern "ABI" fn foo() { /* ... */ } ``` r[items.fn.extern.def] -These are often used in combination with [external block] items which provide -function _declarations_ that can be used to call functions without providing -their _definition_: +These are often used in combination with [external block] items which provide function _declarations_ that can be used to call functions without providing their _definition_: ```rust,ignore @@ -200,8 +173,7 @@ bar(); ``` r[items.fn.extern.default-abi] -When `"extern" Abi?*` is omitted from `FunctionQualifiers` in function items, -the ABI `"Rust"` is assigned. For example: +When `"extern" Abi?*` is omitted from `FunctionQualifiers` in function items, the ABI `"Rust"` is assigned. For example: ```rust fn foo() {} @@ -214,9 +186,7 @@ extern "Rust" fn foo() {} ``` r[items.fn.extern.foreign-call] -Functions can be called by foreign code, and using an ABI that -differs from Rust allows, for example, to provide functions that can be -called from other programming languages like C: +Functions can be called by foreign code, and using an ABI that differs from Rust allows, for example, to provide functions that can be called from other programming languages like C: ```rust // Declares a function with the "C" ABI @@ -228,8 +198,7 @@ extern "stdcall" fn new_i32_stdcall() -> i32 { 0 } ``` r[items.fn.extern.default-extern] -Just as with [external block], when the `extern` keyword is used and the `"ABI"` -is omitted, the ABI used defaults to `"C"`. That is, this: +Just as with [external block], when the `extern` keyword is used and the `"ABI"` is omitted, the ABI used defaults to `"C"`. That is, this: ```rust extern fn new_i32() -> i32 { 0 } @@ -285,8 +254,7 @@ r[items.fn.async] ## Async functions r[items.fn.async.intro] -Functions may be qualified as async, and this can also be combined with the -`unsafe` qualifier: +Functions may be qualified as async, and this can also be combined with the `unsafe` qualifier: ```rust async fn regular_example() { } @@ -294,14 +262,10 @@ async unsafe fn unsafe_example() { } ``` r[items.fn.async.future] -Async functions do no work when called: instead, they -capture their arguments into a future. When polled, that future will -execute the function's body. +Async functions do no work when called: instead, they capture their arguments into a future. When polled, that future will execute the function's body. r[items.fn.async.desugar-brief] -An async function is roughly equivalent to a function -that returns [`impl Future`] and with an [`async move` block][async-blocks] as -its body: +An async function is roughly equivalent to a function that returns [`impl Future`] and with an [`async move` block][async-blocks] as its body: ```rust // Source @@ -324,18 +288,10 @@ r[items.fn.async.desugar] The actual desugaring is more complex: r[items.fn.async.lifetime-capture] -- The return type in the desugaring is assumed to capture all lifetime - parameters from the `async fn` declaration. This can be seen in the - desugared example above, which explicitly outlives, and hence - captures, `'a`. +- The return type in the desugaring is assumed to capture all lifetime parameters from the `async fn` declaration. This can be seen in the desugared example above, which explicitly outlives, and hence captures, `'a`. r[items.fn.async.param-capture] -- The [`async move` block][async-blocks] in the body captures all function - parameters, including those that are unused or bound to a `_` - pattern. This ensures that function parameters are dropped in the - same order as they would be if the function were not async, except - that the drop occurs when the returned future has been fully - awaited. +- The [`async move` block][async-blocks] in the body captures all function parameters, including those that are unused or bound to a `_` pattern. This ensures that function parameters are dropped in the same order as they would be if the function were not async, except that the drop occurs when the returned future has been fully awaited. For more information on the effect of async, see [`async` blocks][async-blocks]. @@ -350,10 +306,7 @@ r[items.fn.async.safety] ### Combining `async` and `unsafe` r[items.fn.async.safety.intro] -It is legal to declare a function that is both async and unsafe. The -resulting function is unsafe to call and (like any async function) -returns a future. This future is just an ordinary future and thus an -`unsafe` context is not required to "await" it: +It is legal to declare a function that is both async and unsafe. The resulting function is unsafe to call and (like any async function) returns a future. This future is just an ordinary future and thus an `unsafe` context is not required to "await" it: ```rust // Returns a future that, when awaited, dereferences `x`. @@ -375,30 +328,17 @@ async fn safe_example() { } ``` -Note that this behavior is a consequence of the desugaring to a -function that returns an `impl Future` -- in this case, the function -we desugar to is an `unsafe` function, but the return value remains -the same. - -Unsafe is used on an async function in precisely the same way that it -is used on other functions: it indicates that the function imposes -some additional obligations on its caller to ensure soundness. As in any -other unsafe function, these conditions may extend beyond the initial -call itself -- in the snippet above, for example, the `unsafe_example` -function took a pointer `x` as argument, and then (when awaited) -dereferenced that pointer. This implies that `x` would have to be -valid until the future is finished executing, and it is the caller's -responsibility to ensure that. +Note that this behavior is a consequence of the desugaring to a function that returns an `impl Future` -- in this case, the function we desugar to is an `unsafe` function, but the return value remains the same. + +Unsafe is used on an async function in precisely the same way that it is used on other functions: it indicates that the function imposes some additional obligations on its caller to ensure soundness. As in any other unsafe function, these conditions may extend beyond the initial call itself -- in the snippet above, for example, the `unsafe_example` function took a pointer `x` as argument, and then (when awaited) dereferenced that pointer. This implies that `x` would have to be valid until the future is finished executing, and it is the caller's responsibility to ensure that. r[items.fn.attributes] ## Attributes on functions r[items.fn.attributes.intro] -[Outer attributes][attributes] are allowed on functions. [Inner -attributes][attributes] are allowed directly after the `{` inside its body [block]. +[Outer attributes][attributes] are allowed on functions. [Inner attributes][attributes] are allowed directly after the `{` inside its body [block]. -This example shows an inner attribute on a function. The function is documented -with just the word "Example". +This example shows an inner attribute on a function. The function is documented with just the word "Example". ```rust fn documented() { @@ -430,9 +370,7 @@ r[items.fn.param-attributes] ## Attributes on function parameters r[items.fn.param-attributes.intro] -[Outer attributes][attributes] are allowed on function parameters and the -permitted [built-in attributes] are restricted to `cfg`, `cfg_attr`, `allow`, -`warn`, `deny`, and `forbid`. +[Outer attributes][attributes] are allowed on function parameters and the permitted [built-in attributes] are restricted to `cfg`, `cfg_attr`, `allow`, `warn`, `deny`, and `forbid`. ```rust fn len( @@ -444,12 +382,9 @@ fn len( ``` r[items.fn.param-attributes.parsed-attributes] -Inert helper attributes used by procedural macro attributes applied to items are also -allowed but be careful to not include these inert attributes in your final `TokenStream`. +Inert helper attributes used by procedural macro attributes applied to items are also allowed but be careful to not include these inert attributes in your final `TokenStream`. -For example, the following code defines an inert `some_inert_attribute` attribute that -is not formally defined anywhere and the `some_proc_macro_attribute` procedural macro is -responsible for detecting its presence and removing it from the output token stream. +For example, the following code defines an inert `some_inert_attribute` attribute that is not formally defined anywhere and the `some_proc_macro_attribute` procedural macro is responsible for detecting its presence and removing it from the output token stream. ```rust,ignore diff --git a/src/items/generics.md b/src/items/generics.md index a8cb27ba6e..a31f513841 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -17,11 +17,7 @@ ConstParam -> ``` r[items.generics.syntax.intro] -[Functions], [type aliases], [structs], [enumerations], [unions], [traits], and -[implementations] may be *parameterized* by types, constants, and lifetimes. These -parameters are listed in angle brackets (`<...>`), -usually immediately after the name of the item and before its definition. For -implementations, which don't have a name, they come directly after `impl`. +[Functions], [type aliases], [structs], [enumerations], [unions], [traits], and [implementations] may be *parameterized* by types, constants, and lifetimes. These parameters are listed in angle brackets (`<...>`), usually immediately after the name of the item and before its definition. For implementations, which don't have a name, they come directly after `impl`. r[items.generics.syntax.decl-order] The order of generic parameters is restricted to lifetime parameters and then type and const parameters intermixed. @@ -40,15 +36,10 @@ struct EitherOrderWorks(U); ``` r[items.generics.syntax.scope] -Generic parameters are in scope within the item definition where they are -declared. They are not in scope for items declared within the body of a -function as described in [item declarations]. -See [generic parameter scopes] for more details. +Generic parameters are in scope within the item definition where they are declared. They are not in scope for items declared within the body of a function as described in [item declarations]. See [generic parameter scopes] for more details. r[items.generics.builtin-generic-types] -[References], [raw pointers], [arrays], [slices], [tuples], and -[function pointers] have lifetime or type parameters as well, but are not -referred to with path syntax. +[References], [raw pointers], [arrays], [slices], [tuples], and [function pointers] have lifetime or type parameters as well, but are not referred to with path syntax. r[items.generics.invalid-lifetimes] `'_` and `'static` are not valid lifetime parameter names. @@ -63,21 +54,14 @@ r[items.generics.const.namespace] The const identifier introduces a name in the [value namespace] for the constant parameter, and all instances of the item must be instantiated with a value of the given type. r[items.generics.const.allowed-types] -The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, -`i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `char` and `bool`. +The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `char` and `bool`. r[items.generics.const.usage] -Const parameters can be used anywhere a [const item] can be used, with the -exception that when used in a [type] or [array repeat expression], it must be -standalone (as described below). That is, they are allowed in the following -places: - -1. As an applied const to any type which forms a part of the signature of the - item in question. -2. As part of a const expression used to define an [associated const], or as a - parameter to an [associated type]. -3. As a value in any runtime expression in the body of any functions in the - item. +Const parameters can be used anywhere a [const item] can be used, with the exception that when used in a [type] or [array repeat expression], it must be standalone (as described below). That is, they are allowed in the following places: + +1. As an applied const to any type which forms a part of the signature of the item in question. +2. As part of a const expression used to define an [associated const], or as a parameter to an [associated type]. +3. As a value in any runtime expression in the body of any functions in the item. 4. As a parameter to any type used in the body of any functions in the item. 5. As a part of the type of any fields in the item. @@ -125,11 +109,7 @@ fn foo() { ``` r[items.generics.const.standalone] -As a further restriction, const parameters may only appear as a standalone -argument inside of a [type] or [array repeat expression]. In those contexts, -they may only be used as a single segment [path expression], possibly inside a -[block] (such as `N` or `{N}`). That is, they cannot be combined with other -expressions. +As a further restriction, const parameters may only appear as a standalone argument inside of a [type] or [array repeat expression]. In those contexts, they may only be used as a single segment [path expression], possibly inside a [block] (such as `N` or `{N}`). That is, they cannot be combined with other expressions. ```rust,compile_fail // Examples where const parameters may not be used. @@ -198,13 +178,9 @@ fn f(x: [u8; N]) -> [u8; _] { x } ``` r[items.generics.const.type-ambiguity] -When there is ambiguity if a generic argument could be resolved as either a -type or const argument, it is always resolved as a type. Placing the argument -in a block expression can force it to be interpreted as a const argument. +When there is ambiguity if a generic argument could be resolved as either a type or const argument, it is always resolved as a type. Placing the argument in a block expression can force it to be interpreted as a const argument. - + ```rust,compile_fail type N = u32; @@ -217,9 +193,7 @@ fn bar() -> Foo<{ N }> { todo!() } // ok ``` r[items.generics.const.variance] -Unlike type and lifetime parameters, const parameters can be declared without -being used inside of a parameterized item, with the exception of -implementations as described in [generic implementations]: +Unlike type and lifetime parameters, const parameters can be declared without being used inside of a parameterized item, with the exception of implementations as described in [generic implementations]: ```rust,compile_fail // ok @@ -234,11 +208,7 @@ impl Unconstrained {} ``` r[items.generics.const.exhaustiveness] -When resolving a trait bound obligation, the exhaustiveness of all -implementations of const parameters is not considered when determining if the -bound is satisfied. For example, in the following, even though all possible -const values for the `bool` type are implemented, it is still an error that -the trait bound is not satisfied: +When resolving a trait bound obligation, the exhaustiveness of all implementations of const parameters is not considered when determining if the bound is satisfied. For example, in the following, even though all possible const values for the `bool` type are implemented, it is still an error that the trait bound is not satisfied: ```rust,compile_fail struct Foo; @@ -270,13 +240,10 @@ TypeBoundWhereClauseItem -> ForLifetimes? Type `:` TypeParamBounds? ``` r[items.generics.where.intro] -*Where clauses* provide another way to specify bounds on type and lifetime -parameters as well as a way to specify bounds on types that aren't type -parameters. +*Where clauses* provide another way to specify bounds on type and lifetime parameters as well as a way to specify bounds on types that aren't type parameters. r[items.generics.where.higher-ranked-lifetimes] -The `for` keyword can be used to introduce [higher-ranked lifetimes]. It only -allows [LifetimeParam] parameters. +The `for` keyword can be used to introduce [higher-ranked lifetimes]. It only allows [LifetimeParam] parameters. ```rust struct A @@ -293,12 +260,9 @@ where r[items.generics.attributes] ## Attributes -Generic lifetime and type parameters allow [attributes] on them. There are no -built-in attributes that do anything in this position, although custom derive -attributes may give meaning to it. +Generic lifetime and type parameters allow [attributes] on them. There are no built-in attributes that do anything in this position, although custom derive attributes may give meaning to it. -This example shows using a custom derive attribute to modify the meaning of a -generic parameter. +This example shows using a custom derive attribute to modify the meaning of a generic parameter. ```rust,ignore diff --git a/src/items/implementations.md b/src/items/implementations.md index 4838c6f04c..a97af7eaaf 100644 --- a/src/items/implementations.md +++ b/src/items/implementations.md @@ -21,10 +21,7 @@ TraitImpl -> ``` r[items.impl.intro] -An _implementation_ is an item that associates items with an _implementing type_. -Implementations are defined with the keyword `impl` and contain functions -that belong to an instance of the type that is being implemented or to the -type statically. +An _implementation_ is an item that associates items with an _implementing type_. Implementations are defined with the keyword `impl` and contain functions that belong to an instance of the type that is being implemented or to the type statically. r[items.impl.kinds] There are two types of implementations: @@ -36,17 +33,13 @@ r[items.impl.inherent] ## Inherent implementations r[items.impl.inherent.intro] -An inherent implementation is defined as the sequence of the `impl` keyword, -generic type declarations, a path to a nominal type, a where clause, and a -bracketed set of associable items. +An inherent implementation is defined as the sequence of the `impl` keyword, generic type declarations, a path to a nominal type, a where clause, and a bracketed set of associable items. r[items.impl.inherent.implementing-type] -The nominal type is called the _implementing type_ and the associable items are -the _associated items_ to the implementing type. +The nominal type is called the _implementing type_ and the associable items are the _associated items_ to the implementing type. r[items.impl.inherent.associated-items] -Inherent implementations associate the contained items to the -implementing type. +Inherent implementations associate the contained items to the implementing type. r[items.impl.inherent.associated-items.allowed-items] Inherent implementations can contain [associated functions] (including [methods]) and [associated constants]. @@ -55,13 +48,10 @@ r[items.impl.inherent.type-alias] They cannot contain associated type aliases. r[items.impl.inherent.associated-item-path] -The [path] to an associated item is any path to the implementing type, -followed by the associated item's identifier as the final path -component. +The [path] to an associated item is any path to the implementing type, followed by the associated item's identifier as the final path component. r[items.impl.inherent.coherence] -A type can also have multiple inherent implementations. An implementing type -must be defined within the same crate as the original type definition. +A type can also have multiple inherent implementations. An implementing type must be defined within the same crate as the original type definition. ``` rust pub mod color { @@ -101,29 +91,21 @@ r[items.impl.trait] ## Trait implementations r[items.impl.trait.intro] -A _trait implementation_ is defined like an inherent implementation except that -the optional generic type declarations are followed by a [trait], followed -by the keyword `for`, followed by a path to a nominal type. +A _trait implementation_ is defined like an inherent implementation except that the optional generic type declarations are followed by a [trait], followed by the keyword `for`, followed by a path to a nominal type. r[items.impl.trait.implemented-trait] -The trait is known as the _implemented trait_. The implementing type -implements the implemented trait. +The trait is known as the _implemented trait_. The implementing type implements the implemented trait. r[items.impl.trait.def-requirement] -A trait implementation must define all non-default associated items declared -by the implemented trait, may redefine default associated items defined by the -implemented trait, and cannot define any other items. +A trait implementation must define all non-default associated items declared by the implemented trait, may redefine default associated items defined by the implemented trait, and cannot define any other items. r[items.impl.trait.associated-item-path] -The path to the associated items is `<` followed by a path to the implementing -type followed by `as` followed by a path to the trait followed by `>` as a path -component followed by the associated item's path component. +The path to the associated items is `<` followed by a path to the implementing type followed by `as` followed by a path to the trait followed by `>` as a path component followed by the associated item's path component. r[items.impl.trait.safety] -[Unsafe traits] require the trait implementation to begin with the `unsafe` -keyword. +[Unsafe traits] require the trait implementation to begin with the `unsafe` keyword. ```rust # #[derive(Copy, Clone)] @@ -161,14 +143,10 @@ r[items.impl.trait.coherence] ### Trait implementation coherence r[items.impl.trait.coherence.intro] -A trait implementation is considered incoherent if either the orphan rules check fails -or there are overlapping implementation instances. +A trait implementation is considered incoherent if either the orphan rules check fails or there are overlapping implementation instances. r[items.impl.trait.coherence.overlapping] -Two trait implementations overlap when there is a non-empty intersection of the -traits the implementation is for, the implementations can be instantiated with -the same type. +Two trait implementations overlap when there is a non-empty intersection of the traits the implementation is for, the implementations can be instantiated with the same type. r[items.impl.trait.orphan-rule] #### Orphan rules @@ -181,31 +159,24 @@ An orphan implementation is one that implements a foreign trait for a foreign ty The orphan rule enables library authors to add new implementations to their traits without fear that they'll break downstream code. Without these restrictions, a library couldn't add an implementation like `impl MyTrait for T` without potentially conflicting with downstream implementations. r[items.impl.trait.orphan-rule.def] -Given `impl Trait for T0`, an `impl` is valid only if at -least one of the following is true: +Given `impl Trait for T0`, an `impl` is valid only if at least one of the following is true: - `Trait` is a [local trait] - All of - - At least one of the types `T0..=Tn` must be a [local type]. Let `Ti` be the - first such type. - - No [uncovered type] parameters `P1..=Pn` may appear in `T0..Ti` (excluding - `Ti`) + - At least one of the types `T0..=Tn` must be a [local type]. Let `Ti` be the first such type. + - No [uncovered type] parameters `P1..=Pn` may appear in `T0..Ti` (excluding `Ti`) r[items.impl.trait.uncovered-param] Only the appearance of *uncovered* type parameters is restricted. r[items.impl.trait.fundamental] -Note that for the purposes of coherence, [fundamental types] are -special. The `T` in `Box` is not considered covered, and `Box` -is considered local. +Note that for the purposes of coherence, [fundamental types] are special. The `T` in `Box` is not considered covered, and `Box` is considered local. r[items.impl.generics] ## Generic implementations r[items.impl.generics.intro] -An implementation can take [generic parameters], which can be used in the rest -of the implementation. Implementation parameters are written directly after the -`impl` keyword. +An implementation can take [generic parameters], which can be used in the rest of the implementation. Implementation parameters are written directly after the `impl` keyword. ```rust # trait Seq { fn dummy(&self, _: T) { } } @@ -218,17 +189,14 @@ impl Seq for u32 { ``` r[items.impl.generics.usage] -Generic parameters *constrain* an implementation if the parameter appears at -least once in one of: +Generic parameters *constrain* an implementation if the parameter appears at least once in one of: * The implemented trait, if it has one * The implementing type -* As an [associated type] in the [bounds] of a type that contains another - parameter that constrains the implementation +* As an [associated type] in the [bounds] of a type that contains another parameter that constrains the implementation r[items.impl.generics.constrain] -Type and const parameters must always constrain the implementation. Lifetimes -must constrain the implementation if the lifetime is used in an associated type. +Type and const parameters must always constrain the implementation. Lifetimes must constrain the implementation if the lifetime is used in an associated type. Examples of constraining situations: @@ -301,11 +269,7 @@ impl<'a> HasAssocType for Struct { r[items.impl.attributes] ## Attributes on implementations -Implementations may contain outer [attributes] before the `impl` keyword and -inner [attributes] inside the brackets that contain the associated items. Inner -attributes must come before any associated items. The attributes that have -meaning here are [`cfg`], [`deprecated`], [`doc`], and [the lint check -attributes]. +Implementations may contain outer [attributes] before the `impl` keyword and inner [attributes] inside the brackets that contain the associated items. Inner attributes must come before any associated items. The attributes that have meaning here are [`cfg`], [`deprecated`], [`doc`], and [the lint check attributes]. [trait]: traits.md [associated constants]: associated-items.md#associated-constants diff --git a/src/items/modules.md b/src/items/modules.md index 46fb9957fa..3cc015025b 100644 --- a/src/items/modules.md +++ b/src/items/modules.md @@ -15,9 +15,7 @@ r[items.mod.intro] A module is a container for zero or more [items]. r[items.mod.def] -A _module item_ is a module, surrounded in braces, named, and prefixed with the -keyword `mod`. A module item introduces a new, named module into the tree of -modules making up a crate. +A _module item_ is a module, surrounded in braces, named, and prefixed with the keyword `mod`. A module item introduces a new, named module into the tree of modules making up a crate. r[items.mod.nesting] Modules can nest arbitrarily. @@ -46,28 +44,19 @@ r[items.mod.namespace] Modules are defined in the [type namespace] of the module or block where they are located. r[items.mod.multiple-items] -It is an error to define multiple items with the same name in the same namespace within a module. -See the [scopes chapter] for more details on restrictions and shadowing behavior. +It is an error to define multiple items with the same name in the same namespace within a module. See the [scopes chapter] for more details on restrictions and shadowing behavior. r[items.mod.unsafe] -The `unsafe` keyword is syntactically allowed to appear before the `mod` -keyword, but it is rejected at a semantic level. This allows macros to consume -the syntax and make use of the `unsafe` keyword, before removing it from the -token stream. +The `unsafe` keyword is syntactically allowed to appear before the `mod` keyword, but it is rejected at a semantic level. This allows macros to consume the syntax and make use of the `unsafe` keyword, before removing it from the token stream. r[items.mod.outlined] ## Module source filenames r[items.mod.outlined.intro] -A module without a body is loaded from an external file. When the module does -not have a `path` attribute, the path to the file mirrors the logical [module -path]. +A module without a body is loaded from an external file. When the module does not have a `path` attribute, the path to the file mirrors the logical [module path]. r[items.mod.outlined.search] -Ancestor module path components are directories, and the module's -contents are in a file with the name of the module plus the `.rs` extension. -For example, the following module structure can have this corresponding -filesystem structure: +Ancestor module path components are directories, and the module's contents are in a file with the name of the module plus the `.rs` extension. For example, the following module structure can have this corresponding filesystem structure: Module Path | Filesystem Path | File Contents ------------------------- | --------------- | ------------- @@ -76,10 +65,7 @@ Module Path | Filesystem Path | File Contents `crate::util::config` | `util/config.rs` | r[items.mod.outlined.search-mod] -Module filenames may also be the name of the module as a directory with the -contents in a file named `mod.rs` within that directory. The above example can -alternately be expressed with `crate::util`'s contents in a file named -`util/mod.rs`. It is not allowed to have both `util.rs` and `util/mod.rs`. +Module filenames may also be the name of the module as a directory with the contents in a file named `mod.rs` within that directory. The above example can alternately be expressed with `crate::util`'s contents in a file named `util/mod.rs`. It is not allowed to have both `util.rs` and `util/mod.rs`. > [!NOTE] > Prior to `rustc` 1.30, using `mod.rs` files was the way to load a module with nested children. It is encouraged to use the new naming convention as it is more consistent, and avoids having many files named `mod.rs` within a project. @@ -88,13 +74,10 @@ r[items.mod.outlined.path] ### The `path` attribute r[items.mod.outlined.path.intro] -The directories and files used for loading external file modules can be -influenced with the `path` attribute. +The directories and files used for loading external file modules can be influenced with the `path` attribute. r[items.mod.outlined.path.search] -For `path` attributes on modules not inside inline module blocks, the file -path is relative to the directory the source file is located. For example, the -following code snippet would use the paths shown based on where it is located: +For `path` attributes on modules not inside inline module blocks, the file path is relative to the directory the source file is located. For example, the following code snippet would use the paths shown based on where it is located: ```rust,ignore @@ -108,16 +91,7 @@ Source File | `c`'s File Location | `c`'s Module Path `src/a/mod.rs` | `src/a/foo.rs` | `crate::a::c` r[items.mod.outlined.path.search-nested] -For `path` attributes inside inline module blocks, the relative location of -the file path depends on the kind of source file the `path` attribute is -located in. "mod-rs" source files are root modules (such as `lib.rs` or -`main.rs`) and modules with files named `mod.rs`. "non-mod-rs" source files -are all other module files. Paths for `path` attributes inside inline module -blocks in a mod-rs file are relative to the directory of the mod-rs file -including the inline module components as directories. For non-mod-rs files, -it is the same except the path starts with a directory with the name of the -non-mod-rs module. For example, the following code snippet would use the paths -shown based on where it is located: +For `path` attributes inside inline module blocks, the relative location of the file path depends on the kind of source file the `path` attribute is located in. "mod-rs" source files are root modules (such as `lib.rs` or `main.rs`) and modules with files named `mod.rs`. "non-mod-rs" source files are all other module files. Paths for `path` attributes inside inline module blocks in a mod-rs file are relative to the directory of the mod-rs file including the inline module components as directories. For non-mod-rs files, it is the same except the path starts with a directory with the name of the non-mod-rs module. For example, the following code snippet would use the paths shown based on where it is located: ```rust,ignore @@ -132,8 +106,7 @@ Source File | `inner`'s File Location | `inner`'s Module Path `src/a/b.rs` | `src/a/b/inline/other.rs` | `crate::a::b::inline::inner` `src/a/mod.rs` | `src/a/inline/other.rs` | `crate::a::inline::inner` -An example of combining the above rules of `path` attributes on inline modules -and nested modules within (applies to both mod-rs and non-mod-rs files): +An example of combining the above rules of `path` attributes on inline modules and nested modules within (applies to both mod-rs and non-mod-rs files): ```rust,ignore @@ -150,14 +123,10 @@ r[items.mod.attributes] ## Attributes on modules r[items.mod.attributes.intro] -Modules, like all items, accept outer attributes. They also accept inner -attributes: either after `{` for a module with a body, or at the beginning of the -source file, after the optional BOM and shebang. +Modules, like all items, accept outer attributes. They also accept inner attributes: either after `{` for a module with a body, or at the beginning of the source file, after the optional BOM and shebang. r[items.mod.attributes.supported] -The built-in attributes that have meaning on a module are [`cfg`], -[`deprecated`], [`doc`], [the lint check attributes], [`path`], and -[`no_implicit_prelude`]. Modules also accept macro attributes. +The built-in attributes that have meaning on a module are [`cfg`], [`deprecated`], [`doc`], [the lint check attributes], [`path`], and [`no_implicit_prelude`]. Modules also accept macro attributes. [`cfg`]: ../conditional-compilation.md [`deprecated`]: ../attributes/diagnostics.md#the-deprecated-attribute diff --git a/src/items/static-items.md b/src/items/static-items.md index b8fbc54e74..395d69c3ce 100644 --- a/src/items/static-items.md +++ b/src/items/static-items.md @@ -10,42 +10,31 @@ StaticItem -> [^extern-safety]: The `safe` and `unsafe` function qualifiers are only allowed semantically within `extern` blocks. r[items.static.intro] -A *static item* is similar to a [constant], except that it represents an allocation in the -program that is initialized with the initializer expression. All references and raw pointers to the -static refer to the same allocation. +A *static item* is similar to a [constant], except that it represents an allocation in the program that is initialized with the initializer expression. All references and raw pointers to the static refer to the same allocation. r[items.static.lifetime] -Static items have the `static` lifetime, which outlives all other lifetimes in a Rust program. -Static items do not call [`drop`] at the end of the program. +Static items have the `static` lifetime, which outlives all other lifetimes in a Rust program. Static items do not call [`drop`] at the end of the program. r[items.static.storage-disjointness] -If the `static` has a size of at least 1 byte, this allocation is disjoint from all other such -`static` allocations as well as heap allocations and stack-allocated variables. However, the storage of -immutable `static` items can overlap with allocations that do not themselves have a unique address, such -as [promoteds] and [`const` items][constant]. +If the `static` has a size of at least 1 byte, this allocation is disjoint from all other such `static` allocations as well as heap allocations and stack-allocated variables. However, the storage of immutable `static` items can overlap with allocations that do not themselves have a unique address, such as [promoteds] and [`const` items][constant]. r[items.static.namespace] The static declaration defines a static value in the [value namespace] of the module or block where it is located. r[items.static.init] -The static initializer is a [constant expression] evaluated at compile time. -Static initializers may refer to and read from other statics. -When reading from mutable statics, they read the initial value of that static. +The static initializer is a [constant expression] evaluated at compile time. Static initializers may refer to and read from other statics. When reading from mutable statics, they read the initial value of that static. r[items.static.read-only] -Non-`mut` static items that contain a type that is not [interior mutable] may -be placed in read-only memory. +Non-`mut` static items that contain a type that is not [interior mutable] may be placed in read-only memory. r[items.static.safety] -All access to a static is safe, but there are a number of restrictions on -statics: +All access to a static is safe, but there are a number of restrictions on statics: r[items.static.sync] * The type must have the [`Sync`](std::marker::Sync) trait bound to allow thread-safe access. r[items.static.init.omission] -The initializer expression must be omitted in an [external block], and must be -provided for free static items. +The initializer expression must be omitted in an [external block], and must be provided for free static items. r[items.static.safety-qualifiers] The `safe` and `unsafe` qualifiers are semantically only allowed when used in an [external block]. @@ -53,10 +42,7 @@ The `safe` and `unsafe` qualifiers are semantically only allowed when used in an r[items.static.generics] ## Statics & generics -A static item defined in a generic scope (for example in a blanket or default -implementation) will result in exactly one static item being defined, as if -the static definition was pulled out of the current scope into the module. -There will *not* be one item per monomorphization. +A static item defined in a generic scope (for example in a blanket or default implementation) will result in exactly one static item being defined, as if the static definition was pulled out of the current scope into the module. There will *not* be one item per monomorphization. This code: @@ -103,20 +89,13 @@ r[items.static.mut] ## Mutable statics r[items.static.mut.intro] -If a static item is declared with the `mut` keyword, then it is allowed to be -modified by the program. One of Rust's goals is to make concurrency bugs hard -to run into, and this is obviously a very large source of race conditions or -other bugs. +If a static item is declared with the `mut` keyword, then it is allowed to be modified by the program. One of Rust's goals is to make concurrency bugs hard to run into, and this is obviously a very large source of race conditions or other bugs. r[items.static.mut.safety] -For this reason, an `unsafe` block is required when either reading -or writing a mutable static variable. Care should be taken to ensure that -modifications to a mutable static are safe with respect to other threads -running in the same process. +For this reason, an `unsafe` block is required when either reading or writing a mutable static variable. Care should be taken to ensure that modifications to a mutable static are safe with respect to other threads running in the same process. r[items.static.mut.extern] -Mutable statics are still very useful, however. They can be used with C -libraries and can also be bound from C libraries in an `extern` block. +Mutable statics are still very useful, however. They can be used with C libraries and can also be bound from C libraries in an `extern` block. ```rust # fn atomic_add(_: *mut u32, _: u32) -> u32 { 2 } @@ -147,15 +126,12 @@ fn bump_levels_safe() -> u32 { ``` r[items.static.mut.sync] -Mutable statics have the same restrictions as normal statics, except that the -type does not have to implement the `Sync` trait. +Mutable statics have the same restrictions as normal statics, except that the type does not have to implement the `Sync` trait. r[items.static.alternate] ## Using statics or consts -It can be confusing whether or not you should use a constant item or a static -item. Constants should, in general, be preferred over statics unless one of the -following are true: +It can be confusing whether or not you should use a constant item or a static item. Constants should, in general, be preferred over statics unless one of the following are true: * Large amounts of data are being stored. * The single-address property of statics is required. diff --git a/src/items/structs.md b/src/items/structs.md index 77809007d3..6374a0ffd7 100644 --- a/src/items/structs.md +++ b/src/items/structs.md @@ -37,10 +37,7 @@ let px: i32 = p.x; ``` r[items.struct.tuple] -A _tuple struct_ is a nominal [tuple type], and is also defined with the keyword `struct`. -In addition to defining a type, it also defines a constructor of the same name in the [value namespace]. -The constructor is a function which can be called to create a new instance of the struct. -For example: +A _tuple struct_ is a nominal [tuple type], and is also defined with the keyword `struct`. In addition to defining a type, it also defines a constructor of the same name in the [value namespace]. The constructor is a function which can be called to create a new instance of the struct. For example: ```rust struct Point(i32, i32); @@ -49,9 +46,7 @@ let px: i32 = match p { Point(x, _) => x }; ``` r[items.struct.unit] -A _unit-like struct_ is a struct without any fields, defined by leaving off the -list of fields entirely. Such a struct implicitly defines a [constant] of its -type with the same name. For example: +A _unit-like struct_ is a struct without any fields, defined by leaving off the list of fields entirely. Such a struct implicitly defines a [constant] of its type with the same name. For example: ```rust struct Cookie; @@ -67,8 +62,7 @@ let c = [Cookie, Cookie {}, Cookie, Cookie {}]; ``` r[items.struct.layout] -The precise memory layout of a struct is not specified. One can specify a -particular layout using the [`repr` attribute]. +The precise memory layout of a struct is not specified. One can specify a particular layout using the [`repr` attribute]. [`repr` attribute]: ../type-layout.md#representations [constant]: constant-items.md diff --git a/src/items/traits.md b/src/items/traits.md index 4232b1d503..54239ca749 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -12,8 +12,7 @@ Trait -> ``` r[items.traits.intro] -A _trait_ describes an abstract interface that types can implement. This -interface consists of [associated items], which come in three varieties: +A _trait_ describes an abstract interface that types can implement. This interface consists of [associated items], which come in three varieties: - [functions](associated-items.md#associated-functions-and-methods) - [types](associated-items.md#associated-types) @@ -26,22 +25,13 @@ r[items.traits.associated-item-namespaces] Associated items are defined as members of the trait within their respective namespaces. Associated types are defined in the type namespace. Associated constants and associated functions are defined in the value namespace. r[items.traits.self-param] -All traits define an implicit type parameter `Self` that refers to "the type -that is implementing this interface". Traits may also contain additional type -parameters. These type parameters, including `Self`, may be constrained by -other traits and so forth [as usual][generics]. +All traits define an implicit type parameter `Self` that refers to "the type that is implementing this interface". Traits may also contain additional type parameters. These type parameters, including `Self`, may be constrained by other traits and so forth [as usual][generics]. r[items.traits.impls] Traits are implemented for specific types through separate [implementations]. r[items.traits.associated-item-decls] -Trait functions may omit the function body by replacing it with a semicolon. -This indicates that the implementation must define the function. If the trait -function defines a body, this definition acts as a default for any -implementation which does not override it. Similarly, associated constants may -omit the equals sign and expression to indicate implementations must define -the constant value. Associated types must never define the type, the type may -only be specified in an implementation. +Trait functions may omit the function body by replacing it with a semicolon. This indicates that the implementation must define the function. If the trait function defines a body, this definition acts as a default for any implementation which does not override it. Similarly, associated constants may omit the equals sign and expression to indicate implementations must define the constant value. Associated types must never define the type, the type may only be specified in an implementation. ```rust // Examples of associated trait items with and without definitions. @@ -65,8 +55,7 @@ Generic items may use traits as [bounds] on their type parameters. r[items.traits.generic] ## Generic traits -Type parameters can be specified for a trait to make it generic. These appear -after the trait name, using the same syntax used in [generic functions]. +Type parameters can be specified for a trait to make it generic. These appear after the trait name, using the same syntax used in [generic functions]. ```rust trait Seq { @@ -81,8 +70,7 @@ r[items.traits.dyn-compatible] ## Dyn compatibility r[items.traits.dyn-compatible.intro] -A dyn-compatible trait can be the base trait of a [trait object]. A trait is -*dyn compatible* if it has the following qualities: +A dyn-compatible trait can be the base trait of a [trait object]. A trait is *dyn compatible* if it has the following qualities: r[items.traits.dyn-compatible.supertraits] * All [supertraits] must also be dyn compatible. @@ -207,14 +195,10 @@ r[items.traits.supertraits] ## Supertraits r[items.traits.supertraits.intro] -**Supertraits** are traits that are required to be implemented for a type to -implement a specific trait. Furthermore, anywhere a [generic][generics] or [trait object] -is bounded by a trait, it has access to the associated items of its supertraits. +**Supertraits** are traits that are required to be implemented for a type to implement a specific trait. Furthermore, anywhere a [generic][generics] or [trait object] is bounded by a trait, it has access to the associated items of its supertraits. r[items.traits.supertraits.decl] -Supertraits are declared by trait bounds on the `Self` type of a trait and -transitively the supertraits of the traits declared in those trait bounds. It is -an error for a trait to be its own supertrait. +Supertraits are declared by trait bounds on the `Self` type of a trait and transitively the supertraits of the traits declared in those trait bounds. It is an error for a trait to be its own supertrait. r[items.traits.supertraits.subtrait] The trait with a supertrait is called a **subtrait** of its supertrait. @@ -233,8 +217,7 @@ trait Shape { fn area(&self) -> f64; } trait Circle where Self: Shape { fn radius(&self) -> f64; } ``` -This next example gives `radius` a default implementation using the `area` -function from `Shape`. +This next example gives `radius` a default implementation using the `area` function from `Shape`. ```rust # trait Shape { fn area(&self) -> f64; } @@ -277,9 +260,7 @@ r[items.traits.safety] ## Unsafe traits r[items.traits.safety.intro] -Traits items that begin with the `unsafe` keyword indicate that *implementing* the -trait may be [unsafe]. It is safe to use a correctly implemented unsafe trait. -The [trait implementation] must also begin with the `unsafe` keyword. +Traits items that begin with the `unsafe` keyword indicate that *implementing* the trait may be [unsafe]. It is safe to use a correctly implemented unsafe trait. The [trait implementation] must also begin with the `unsafe` keyword. [`Sync`] and [`Send`] are examples of unsafe traits. @@ -355,11 +336,7 @@ r[items.traits.associated-visibility] ## Item visibility r[items.traits.associated-visibility.intro] -Trait items syntactically allow a [Visibility] annotation, but this is -rejected when the trait is validated. This allows items to be parsed with a -unified syntax across different contexts where they are used. As an example, -an empty `vis` macro fragment specifier can be used for trait items, where the -macro rule may be used in other situations where visibility is allowed. +Trait items syntactically allow a [Visibility] annotation, but this is rejected when the trait is validated. This allows items to be parsed with a unified syntax across different contexts where they are used. As an example, an empty `vis` macro fragment specifier can be used for trait items, where the macro rule may be used in other situations where visibility is allowed. ```rust macro_rules! create_method { diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md index 10a4e740e7..da7d217055 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -10,12 +10,9 @@ TypeAlias -> ``` r[items.type.intro] -A _type alias_ defines a new name for an existing [type] in the [type namespace] of the module or block where it is located. -Type aliases are declared with the keyword `type`. -Every value has a single, specific type, but may implement several different traits, and may be compatible with several different type constraints. +A _type alias_ defines a new name for an existing [type] in the [type namespace] of the module or block where it is located. Type aliases are declared with the keyword `type`. Every value has a single, specific type, but may implement several different traits, and may be compatible with several different type constraints. -For example, the following defines the type `Point` as a synonym for the type -`(u8, u8)`, the type of pairs of unsigned 8 bit integers: +For example, the following defines the type `Point` as a synonym for the type `(u8, u8)`, the type of pairs of unsigned 8 bit integers: ```rust type Point = (u8, u8); @@ -36,21 +33,16 @@ let _ = TypeAlias(5); // Doesn't work ``` r[items.type.associated-type] -A type alias, when not used as an [associated type], must include a [Type][grammar-Type] and -may not include [TypeParamBounds]. +A type alias, when not used as an [associated type], must include a [Type][grammar-Type] and may not include [TypeParamBounds]. r[items.type.associated-trait] -A type alias, when used as an [associated type] in a [trait], must not include a -[Type][grammar-Type] specification but may include [TypeParamBounds]. +A type alias, when used as an [associated type] in a [trait], must not include a [Type][grammar-Type] specification but may include [TypeParamBounds]. r[items.type.associated-impl] -A type alias, when used as an [associated type] in a [trait impl], must include -a [Type][grammar-Type] specification and may not include [TypeParamBounds]. +A type alias, when used as an [associated type] in a [trait impl], must include a [Type][grammar-Type] specification and may not include [TypeParamBounds]. r[items.type.deprecated] -Where clauses before the equals sign on a type alias in a [trait impl] (like -`type TypeAlias where T: Foo = Bar`) are deprecated. Where clauses after -the equals sign (like `type TypeAlias = Bar where T: Foo`) are preferred. +Where clauses before the equals sign on a type alias in a [trait impl] (like `type TypeAlias where T: Foo = Bar`) are deprecated. Where clauses after the equals sign (like `type TypeAlias = Bar where T: Foo`) are preferred. [associated type]: associated-items.md#associated-types [trait impl]: implementations.md#trait-implementations diff --git a/src/items/unions.md b/src/items/unions.md index a07a9b7746..455168231a 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -8,8 +8,7 @@ Union -> ``` r[items.union.intro] -A union declaration uses the same syntax as a struct declaration, except with -`union` in place of `struct`. +A union declaration uses the same syntax as a struct declaration, except with `union` in place of `struct`. r[items.union.namespace] A union declaration defines the given name in the [type namespace] of the module or block where it is located. @@ -23,9 +22,7 @@ union MyUnion { ``` r[items.union.common-storage] -The key property of unions is that all fields of a union share common storage. -As a result, writes to one field of a union can overwrite its other fields, and -size of a union is determined by the size of its largest field. +The key property of unions is that all fields of a union share common storage. As a result, writes to one field of a union can overwrite its other fields, and size of a union is determined by the size of its largest field. r[items.union.field-restrictions] Union field types are restricted to the following subset of types: @@ -43,9 +40,7 @@ r[items.union.field-tuple] - Tuples and arrays containing only allowed union field types r[items.union.drop] -This restriction ensures, in particular, that union fields never need to be -dropped. Like for structs and enums, it is possible to `impl Drop` for a union -to manually define what happens when it gets dropped. +This restriction ensures, in particular, that union fields never need to be dropped. Like for structs and enums, it is possible to `impl Drop` for a union to manually define what happens when it gets dropped. r[items.union.fieldless] Unions without any fields are not accepted by the compiler, but can be accepted by macros. @@ -54,8 +49,7 @@ r[items.union.init] ## Initialization of a union r[items.union.init.intro] -A value of a union type can be created using the same syntax that is used for -struct types, except that it must specify exactly one field: +A value of a union type can be created using the same syntax that is used for struct types, except that it must specify exactly one field: ```rust # union MyUnion { f1: u32, f2: f32 } @@ -64,9 +58,7 @@ let u = MyUnion { f1: 1 }; ``` r[items.union.init.result] -The expression above creates a value of type `MyUnion` and initializes the -storage using field `f1`. The union can be accessed using the same syntax as -struct fields: +The expression above creates a value of type `MyUnion` and initializes the storage using field `f1`. The union can be accessed using the same syntax as struct fields: ```rust # union MyUnion { f1: u32, f2: f32 } @@ -79,23 +71,16 @@ r[items.union.fields] ## Reading and writing union fields r[items.union.fields.intro] -Unions have no notion of an "active field". Instead, every union access just -interprets the storage as the type of the field used for the access. +Unions have no notion of an "active field". Instead, every union access just interprets the storage as the type of the field used for the access. r[items.union.fields.read] Reading a union field reads the bits of the union at the field's type. r[items.union.fields.offset] -Fields might have a non-zero offset (except when [the C representation] is used); in that case the -bits starting at the offset of the fields are read +Fields might have a non-zero offset (except when [the C representation] is used); in that case the bits starting at the offset of the fields are read r[items.union.fields.validity] -It is the programmer's responsibility to make sure that the data is valid at the field's type. Failing -to do so results in [undefined behavior]. For example, reading the value `3` -from a field of the [boolean type] is undefined behavior. Effectively, -writing to and then reading from a union with [the C representation] is -analogous to a [`transmute`] from the type used for writing to the type used for -reading. +It is the programmer's responsibility to make sure that the data is valid at the field's type. Failing to do so results in [undefined behavior]. For example, reading the value `3` from a field of the [boolean type] is undefined behavior. Effectively, writing to and then reading from a union with [the C representation] is analogous to a [`transmute`] from the type used for writing to the type used for reading. r[items.union.fields.read-safety] Consequently, all reads of union fields have to be placed in `unsafe` blocks: @@ -109,14 +94,10 @@ unsafe { } ``` -Commonly, code using unions will provide safe wrappers around unsafe union -field accesses. +Commonly, code using unions will provide safe wrappers around unsafe union field accesses. r[items.union.fields.write-safety] -In contrast, writes to union fields are safe, since they just overwrite -arbitrary data, but cannot cause undefined behavior. (Note that union field -types can never have drop glue, so a union field write will never implicitly -drop anything.) +In contrast, writes to union fields are safe, since they just overwrite arbitrary data, but cannot cause undefined behavior. (Note that union field types can never have drop glue, so a union field write will never implicitly drop anything.) r[items.union.pattern] ## Pattern matching on unions @@ -125,8 +106,7 @@ r[items.union.pattern.intro] Another way to access union fields is to use pattern matching. r[items.union.pattern.one-field] -Pattern matching on union fields uses the same syntax as struct patterns, except that the pattern -must specify exactly one field. +Pattern matching on union fields uses the same syntax as struct patterns, except that the pattern must specify exactly one field. r[items.union.pattern.safety] Since pattern matching is like reading the union with a particular field, it has to be placed in `unsafe` blocks as well. @@ -145,9 +125,7 @@ fn f(u: MyUnion) { ``` r[items.union.pattern.subpattern] -Pattern matching may match a union as a field of a larger structure. In -particular, when using a Rust union to implement a C tagged union via FFI, this -allows matching on the tag and the corresponding field simultaneously: +Pattern matching may match a union as a field of a larger structure. In particular, when using a Rust union to implement a C tagged union via FFI, this allows matching on the tag and the corresponding field simultaneously: ```rust #[repr(u32)] @@ -180,13 +158,10 @@ r[items.union.ref] ## References to union fields r[items.union.ref.intro] -Since union fields share common storage, gaining write access to one field of a -union can give write access to all its remaining fields. +Since union fields share common storage, gaining write access to one field of a union can give write access to all its remaining fields. r[items.union.ref.borrow] -Borrow checking rules have to be adjusted to account for this fact. As a result, if one field of a -union is borrowed, all its remaining fields are borrowed as well for the same -lifetime. +Borrow checking rules have to be adjusted to account for this fact. As a result, if one field of a union is borrowed, all its remaining fields are borrowed as well for the same lifetime. ```rust,compile_fail # union MyUnion { f1: u32, f2: f32 } @@ -206,12 +181,7 @@ fn test() { ``` r[items.union.ref.usage] -As you could see, in many aspects (except for layouts, safety, and ownership) -unions behave exactly like structs, largely as a consequence of inheriting -their syntactic shape from structs. This is also true for many unmentioned -aspects of Rust language (such as privacy, name resolution, type inference, -generics, trait implementations, inherent implementations, coherence, pattern -checking, etc etc etc). +As you could see, in many aspects (except for layouts, safety, and ownership) unions behave exactly like structs, largely as a consequence of inheriting their syntactic shape from structs. This is also true for many unmentioned aspects of Rust language (such as privacy, name resolution, type inference, generics, trait implementations, inherent implementations, coherence, pattern checking, etc etc etc). [`transmute`]: std::mem::transmute [boolean type]: ../types/boolean.md diff --git a/src/items/use-declarations.md b/src/items/use-declarations.md index 5ea891cef2..1afe92ab17 100644 --- a/src/items/use-declarations.md +++ b/src/items/use-declarations.md @@ -12,11 +12,7 @@ UseTree -> ``` r[items.use.intro] -A _use declaration_ creates one or more local name bindings synonymous with -some other [path]. Usually a `use` declaration is used to shorten the path -required to refer to a module item. These declarations may appear in [modules] -and [blocks], usually at the top. -A `use` declaration is also sometimes called an _import_, or, if it is public, a _re-export_. +A _use declaration_ creates one or more local name bindings synonymous with some other [path]. Usually a `use` declaration is used to shorten the path required to refer to a module item. These declarations may appear in [modules] and [blocks], usually at the top. A `use` declaration is also sometimes called an _import_, or, if it is public, a _re-export_. [path]: ../paths.md [modules]: modules.md @@ -26,25 +22,19 @@ r[items.use.forms] Use declarations support a number of convenient shortcuts: r[items.use.forms.multiple] -* Simultaneously binding a list of paths with a common prefix, using the - brace syntax `use a::b::{c, d, e::f, g::h::i};` +* Simultaneously binding a list of paths with a common prefix, using the brace syntax `use a::b::{c, d, e::f, g::h::i};` r[items.use.forms.self] -* Simultaneously binding a list of paths with a common prefix and their common - parent module, using the `self` keyword, such as `use a::b::{self, c, d::e};` +* Simultaneously binding a list of paths with a common prefix and their common parent module, using the `self` keyword, such as `use a::b::{self, c, d::e};` r[items.use.forms.as] -* Rebinding the target name as a new local name, using the syntax `use p::q::r - as x;`. This can also be used with the last two features: - `use a::b::{self as ab, c as abc}`. +* Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`. This can also be used with the last two features: `use a::b::{self as ab, c as abc}`. r[items.use.forms.glob] -* Binding all paths matching a given prefix, using the asterisk wildcard syntax - `use a::b::*;`. +* Binding all paths matching a given prefix, using the asterisk wildcard syntax `use a::b::*;`. r[items.use.forms.nesting] -* Nesting groups of the previous features multiple times, such as - `use a::b::{self as ab, c, d::{*, e::f}};` +* Nesting groups of the previous features multiple times, such as `use a::b::{self as ab, c, d::{*, e::f}};` An example of `use` declarations: @@ -73,16 +63,10 @@ r[items.use.visibility] ## `use` Visibility r[items.use.visibility.intro] -Like items, `use` declarations are private to the containing module, by -default. Also like items, a `use` declaration can be public, if qualified by -the `pub` keyword. Such a `use` declaration serves to _re-export_ a name. A -public `use` declaration can therefore _redirect_ some public name to a -different target definition: even a definition with a private canonical path, -inside a different module. +Like items, `use` declarations are private to the containing module, by default. Also like items, a `use` declaration can be public, if qualified by the `pub` keyword. Such a `use` declaration serves to _re-export_ a name. A public `use` declaration can therefore _redirect_ some public name to a different target definition: even a definition with a private canonical path, inside a different module. r[items.use.visibility.unambiguous] -If a sequence of such redirections form a cycle or -cannot be resolved unambiguously, they represent a compile-time error. +If a sequence of such redirections form a cycle or cannot be resolved unambiguously, they represent a compile-time error. An example of re-exporting: @@ -101,15 +85,13 @@ fn main() { } ``` -In this example, the module `quux` re-exports two public names defined in -`foo`. +In this example, the module `quux` re-exports two public names defined in `foo`. r[items.use.path] ## `use` Paths r[items.use.path.intro] -The [paths] that are allowed in a `use` item follow the [SimplePath] grammar and are similar to the paths that may be used in an expression. -They may create bindings for: +The [paths] that are allowed in a `use` item follow the [SimplePath] grammar and are similar to the paths that may be used in an expression. They may create bindings for: * Nameable [items] * [Enum variants] @@ -122,8 +104,7 @@ r[items.use.path.disallowed] They cannot import [associated items], [generic parameters], [local variables], paths with [`Self`], or [tool attributes]. More restrictions are described below. r[items.use.path.namespace] -`use` will create bindings for all [namespaces] from the imported entities, with the exception that a `self` import will only import from the type namespace (as described below). -For example, the following illustrates creating bindings for the same name in two namespaces: +`use` will create bindings for all [namespaces] from the imported entities, with the exception that a `self` import will only import from the type namespace (as described below). For example, the following illustrates creating bindings for the same name in two namespaces: ```rust mod stuff { @@ -159,15 +140,12 @@ r[items.use.path.edition2018] > # fn main() {} > ``` > -> The 2015 edition does not allow use declarations to reference the [extern prelude]. -> Thus, [`extern crate`] declarations are still required in 2015 to reference an external crate in a `use` declaration. -> Beginning with the 2018 edition, `use` declarations can specify an external crate dependency the same way `extern crate` can. +> The 2015 edition does not allow use declarations to reference the [extern prelude]. Thus, [`extern crate`] declarations are still required in 2015 to reference an external crate in a `use` declaration. Beginning with the 2018 edition, `use` declarations can specify an external crate dependency the same way `extern crate` can. r[items.use.as] ## `as` renames -The `as` keyword can be used to change the name of an imported entity. -For example: +The `as` keyword can be used to change the name of an imported entity. For example: ```rust // Creates a non-public alias `bar` for the function `foo`. @@ -182,8 +160,7 @@ r[items.use.multiple-syntax] ## Brace syntax r[items.use.multiple-syntax.intro] -Braces can be used in the last segment of the path to import multiple entities from the previous segment, or, if there are no previous segments, from the current scope. -Braces can be nested, creating a tree of paths, where each grouping of segments is logically combined with its parent to create a full path. +Braces can be used in the last segment of the path to import multiple entities from the previous segment, or, if there are no previous segments, from the current scope. Braces can be nested, creating a tree of paths, where each grouping of segments is logically combined with its parent to create a full path. ```rust // Creates bindings to: @@ -224,8 +201,7 @@ mod example { ``` r[items.use.self.namespace] -`self` only creates a binding from the [type namespace] of the parent entity. -For example, in the following, only the `foo` mod is imported: +`self` only creates a binding from the [type namespace] of the parent entity. For example, in the following, only the `foo` mod is imported: ```rust,compile_fail mod bar { @@ -249,8 +225,7 @@ r[items.use.glob] ## Glob imports r[items.use.glob.intro] -The `*` character may be used as the last segment of a `use` path to import all importable entities from the entity of the preceding segment. -For example: +The `*` character may be used as the last segment of a `use` path to import all importable entities from the entity of the preceding segment. For example: ```rust // Creates a non-public alias to `bar`. @@ -272,9 +247,7 @@ mod foo { ``` r[items.use.glob.shadowing] -Items and named imports are allowed to shadow names from glob imports in the same [namespace]. -That is, if there is a name already defined by another item in the same namespace, the glob import will be shadowed. -For example: +Items and named imports are allowed to shadow names from glob imports in the same [namespace]. That is, if there is a name already defined by another item in the same namespace, the glob import will be shadowed. For example: ```rust // This creates a binding to the `clashing::Foo` tuple struct @@ -320,15 +293,10 @@ r[items.use.as-underscore] ## Underscore imports r[items.use.as-underscore.intro] -Items can be imported without binding to a name by using an underscore with -the form `use path as _`. This is particularly useful to import a trait so -that its methods may be used without importing the trait's symbol, for example -if the trait's symbol may conflict with another symbol. Another example is to -link an external crate without importing its name. +Items can be imported without binding to a name by using an underscore with the form `use path as _`. This is particularly useful to import a trait so that its methods may be used without importing the trait's symbol, for example if the trait's symbol may conflict with another symbol. Another example is to link an external crate without importing its name. r[items.use.as-underscore.glob] -Asterisk glob imports will import items imported with `_` in their unnameable -form. +Asterisk glob imports will import items imported with `_` in their unnameable form. ```rust mod foo { @@ -349,9 +317,7 @@ fn main() { ``` r[items.use.as-underscore.macro] -The unique, unnameable symbols are created after macro expansion so that -macros may safely emit multiple references to `_` imports. For example, the -following should not produce an error: +The unique, unnameable symbols are created after macro expansion so that macros may safely emit multiple references to `_` imports. For example, the following should not produce an error: ```rust macro_rules! m { diff --git a/src/lifetime-elision.md b/src/lifetime-elision.md index 690b2dad49..2ac65f32c3 100644 --- a/src/lifetime-elision.md +++ b/src/lifetime-elision.md @@ -1,40 +1,33 @@ r[lifetime-elision] # Lifetime elision -Rust has rules that allow lifetimes to be elided in various places where the -compiler can infer a sensible default choice. +Rust has rules that allow lifetimes to be elided in various places where the compiler can infer a sensible default choice. r[lifetime-elision.function] ## Lifetime elision in functions r[lifetime-elision.function.intro] -In order to make common patterns more ergonomic, lifetime arguments can be -*elided* in [function item], [function pointer], and [closure trait] signatures. -The following rules are used to infer lifetime parameters for elided lifetimes. +In order to make common patterns more ergonomic, lifetime arguments can be *elided* in [function item], [function pointer], and [closure trait] signatures. The following rules are used to infer lifetime parameters for elided lifetimes. r[lifetime-elision.function.lifetimes-not-inferred] It is an error to elide lifetime parameters that cannot be inferred. r[lifetime-elision.function.explicit-placeholder] -The placeholder lifetime, `'_`, can also be used to have a lifetime inferred in the -same way. For lifetimes in paths, using `'_` is preferred. +The placeholder lifetime, `'_`, can also be used to have a lifetime inferred in the same way. For lifetimes in paths, using `'_` is preferred. r[lifetime-elision.function.only-functions] -Trait object lifetimes follow different rules discussed -[below](#default-trait-object-lifetimes). +Trait object lifetimes follow different rules discussed [below](#default-trait-object-lifetimes). r[lifetime-elision.function.implicit-lifetime-parameters] * Each elided lifetime in the parameters becomes a distinct lifetime parameter. r[lifetime-elision.function.output-lifetime] -* If there is exactly one lifetime used in the parameters (elided or not), that - lifetime is assigned to *all* elided output lifetimes. +* If there is exactly one lifetime used in the parameters (elided or not), that lifetime is assigned to *all* elided output lifetimes. r[lifetime-elision.function.receiver-lifetime] In method signatures there is another rule -* If the receiver has type `&Self` or `&mut Self`, then the lifetime of that - reference to `Self` is assigned to all elided output lifetime parameters. +* If the receiver has type `&Self` or `&mut Self`, then the lifetime of that reference to `Self` is assigned to all elided output lifetime parameters. Examples: @@ -93,42 +86,34 @@ r[lifetime-elision.trait-object] ## Default trait object lifetimes r[lifetime-elision.trait-object.intro] -The assumed lifetime of references held by a [trait object] is called its -_default object lifetime bound_. These were defined in [RFC 599] and amended in -[RFC 1156]. +The assumed lifetime of references held by a [trait object] is called its _default object lifetime bound_. These were defined in [RFC 599] and amended in [RFC 1156]. r[lifetime-elision.trait-object.explicit-bound] -These default object lifetime bounds are used instead of the lifetime parameter -elision rules defined above when the lifetime bound is omitted entirely. +These default object lifetime bounds are used instead of the lifetime parameter elision rules defined above when the lifetime bound is omitted entirely. r[lifetime-elision.trait-object.explicit-placeholder] -If `'_` is used as the lifetime bound then the bound follows the usual elision -rules. +If `'_` is used as the lifetime bound then the bound follows the usual elision rules. r[lifetime-elision.trait-object.containing-type] -If the trait object is used as a type argument of a generic type then the -containing type is first used to try to infer a bound. +If the trait object is used as a type argument of a generic type then the containing type is first used to try to infer a bound. r[lifetime-elision.trait-object.containing-type-unique] * If there is a unique bound from the containing type then that is the default r[lifetime-elision.trait-object.containing-type-explicit] -* If there is more than one bound from the containing type then an explicit - bound must be specified +* If there is more than one bound from the containing type then an explicit bound must be specified r[lifetime-elision.trait-object.trait-bounds] If neither of those rules apply, then the bounds on the trait are used: r[lifetime-elision.trait-object.trait-unique] -* If the trait is defined with a single lifetime _bound_ then that bound is - used. +* If the trait is defined with a single lifetime _bound_ then that bound is used. r[lifetime-elision.trait-object.static-lifetime] * If `'static` is used for any lifetime bound then `'static` is used. r[lifetime-elision.trait-object.default] -* If the trait has no lifetime bounds, then the lifetime is inferred in - expressions and is `'static` outside of expressions. +* If the trait has no lifetime bounds, then the lifetime is inferred in expressions and is `'static` outside of expressions. ```rust // For the following trait... @@ -165,8 +150,7 @@ type T7<'a, 'b> = TwoBounds<'a, 'b, dyn Foo>; ``` r[lifetime-elision.trait-object.innermost-type] -Note that the innermost object sets the bound, so `&'a Box` is still -`&'a Box`. +Note that the innermost object sets the bound, so `&'a Box` is still `&'a Box`. ```rust // For the following trait... @@ -185,10 +169,7 @@ r[lifetime-elision.const-static] ## `const` and `static` elision r[lifetime-elision.const-static.implicit-static] -Both [constant] and [static] declarations of reference types have *implicit* -`'static` lifetimes unless an explicit lifetime is specified. As such, the -constant declarations involving `'static` above may be written without the -lifetimes. +Both [constant] and [static] declarations of reference types have *implicit* `'static` lifetimes unless an explicit lifetime is specified. As such, the constant declarations involving `'static` above may be written without the lifetimes. ```rust // STRING: &'static str @@ -207,10 +188,7 @@ const BITS_N_STRINGS: BitsNStrings<'_> = BitsNStrings { ``` r[lifetime-elision.const-static.fn-references] -Note that if the `static` or `const` items include function or closure -references, which themselves include references, the compiler will first try -the standard elision rules. If it is unable to resolve the lifetimes by its -usual rules, then it will error. By way of example: +Note that if the `static` or `const` items include function or closure references, which themselves include references, the compiler will first try the standard elision rules. If it is unable to resolve the lifetimes by its usual rules, then it will error. By way of example: ```rust # struct Foo; diff --git a/src/patterns.md b/src/patterns.md index 9a59e6f544..feb3aa7f58 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -25,16 +25,14 @@ PatternWithoutRange -> ``` r[patterns.intro] -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. * 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; @@ -88,9 +86,7 @@ r[patterns.destructure] ## Destructuring r[patterns.destructure.intro] -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. +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. r[patterns.destructure.wildcard] In a pattern whose [scrutinee] expression has a `struct`, `enum` or `tuple` type, a [wildcard pattern](#wildcard-pattern) (`_`) stands in for a *single* data field, whereas an [et cetera](#grammar-StructPatternEtCetera) or [rest pattern][patterns.rest] (`..`) stands in for *all* the remaining fields of a particular variant. @@ -120,9 +116,7 @@ match message { r[patterns.refutable] ## 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 @@ -179,12 +173,10 @@ r[patterns.ident.unique] The identifier must be unique within the pattern. r[patterns.ident.scope] -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). +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). r[patterns.ident.bare] -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; @@ -194,8 +186,7 @@ fn sum(x: i32, y: i32) -> i32 { ``` r[patterns.ident.scrutinized] -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; @@ -225,10 +216,7 @@ 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 { @@ -251,8 +239,7 @@ if let Person { name: ref person_name, age: 18..=150 } = value { } ``` r[patterns.ident.ref-ignored] -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. r[patterns.ident.precedent] [Path patterns](#path-patterns) take precedence over identifier patterns. @@ -292,9 +279,7 @@ r[patterns.ident.binding] ### Binding modes r[patterns.ident.binding.intro] -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: +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 let x: &Option = &Some(3); @@ -352,12 +337,9 @@ r[patterns.ident.binding.mode-limitations-reference.edition2024] > Before the 2024 edition, reference patterns could appear even when the default binding mode was not "move", and had both the effect of matching against the scrutinee and of causing the default binding mode to be reset to "move". r[patterns.ident.binding.mixed] -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. +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: @@ -380,8 +362,7 @@ WildcardPattern -> `_` ``` r[patterns.wildcard.intro] -The _wildcard pattern_ (an underscore symbol) matches any value. -It is used to ignore values when they don't matter. +The _wildcard pattern_ (an underscore symbol) matches any value. It is used to ignore values when they don't matter. r[patterns.wildcard.struct-matcher] Inside other patterns it matches a single data field (as opposed to the `..` which matches the remaining fields). @@ -432,8 +413,7 @@ r[patterns.rest.intro] 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. r[patterns.rest.allowed-patterns] -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. +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. r[patterns.rest.refutable] The rest pattern is always irrefutable. @@ -518,39 +498,32 @@ RangePatternBound -> [^obsolete-range-edition]: The [ObsoleteRangePattern] syntax has been removed in the 2021 edition. r[patterns.range.intro] -*Range patterns* match scalar values within the range defined by their bounds. -They comprise a *sigil* (`..` or `..=`) and a bound on one or both sides. +*Range patterns* match scalar values within the range defined by their bounds. They comprise a *sigil* (`..` or `..=`) and a bound on one or both sides. -A bound on the left of the sigil is called a *lower bound*. -A bound on the right is called an *upper bound*. +A bound on the left of the sigil is called a *lower bound*. A bound on the right is called an *upper bound*. r[patterns.range.exclusive] -The *exclusive range pattern* matches all values from the lower bound up to, but not including the upper bound. -It is written as its lower bound, followed by `..`, followed by the upper bound. +The *exclusive range pattern* matches all values from the lower bound up to, but not including the upper bound. It is written as its lower bound, followed by `..`, followed by the upper bound. For example, a pattern `'m'..'p'` will match only `'m'`, `'n'` and `'o'`, specifically **not** including `'p'`. r[patterns.range.inclusive] -The *inclusive range pattern* matches all values from the lower bound up to and including the upper bound. -It is written as its lower bound, followed by `..=`, followed by the upper bound. +The *inclusive range pattern* matches all values from the lower bound up to and including the upper bound. It is written as its lower bound, followed by `..=`, followed by the upper bound. For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. r[patterns.range.from] -The *from range pattern* matches all values greater than or equal to the lower bound. -It is written as its lower bound followed by `..`. +The *from range pattern* matches all values greater than or equal to the lower bound. It is written as its lower bound followed by `..`. For example, `1..` will match any integer greater than or equal to 1, such as 1, 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers. r[patterns.range.to-exclusive] -The *to exclusive range pattern* matches all values less than the upper bound. -It is written as `..` followed by the upper bound. +The *to exclusive range pattern* matches all values less than the upper bound. It is written as `..` followed by the upper bound. For example, `..10` will match any integer less than 10, such as 9, 1, 0, and for signed integer types, all negative values. r[patterns.range.to-inclusive] -The *to inclusive range pattern* matches all values less than or equal to the upper bound. -It is written as `..=` followed by the upper bound. +The *to inclusive range pattern* matches all values less than or equal to the upper bound. It is written as `..=` followed by the upper bound. For example, `..=10` will match any integer less than or equal to 10, such as 10, 1, 0, and for signed integer types, all negative values. @@ -666,8 +639,7 @@ println!("{}", match 0xfacade { ``` r[patterns.range.refutable] -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. +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. r[patterns.range.refutable-integer] The range of values for an integer type is the closed range from its minimum to maximum value. @@ -676,8 +648,7 @@ r[patterns.range.refutable-char] 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}'`. r[patterns.range.constraint-slice] -[RangeFromPattern] cannot be used as a top-level pattern for subpatterns in [slice patterns](#slice-patterns). -For example, the pattern `[1.., _]` is not a valid pattern. +[RangeFromPattern] cannot be used as a top-level pattern for subpatterns in [slice patterns](#slice-patterns). For example, the pattern `[1.., _]` is not a valid pattern. r[patterns.range.edition2021] > [!EDITION-2021] @@ -743,8 +714,7 @@ StructPatternEtCetera -> `..` ``` r[patterns.struct.intro] -Struct patterns match struct, enum, and union values that match all criteria defined by its subpatterns. -They are also used to [destructure](#destructuring) a struct, enum, or union value. +Struct patterns match struct, enum, and union values that match all criteria defined by its subpatterns. They are also used to [destructure](#destructuring) a struct, enum, or union value. r[patterns.struct.ignore-rest] On a struct pattern, the fields are referenced by name, index (in the case of tuple structs) or ignored by use of `..`: @@ -843,8 +813,7 @@ TupleStructItems -> Pattern ( `,` Pattern )* `,`? ``` r[patterns.tuple-struct.intro] -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. r[patterns.tuple-struct.refutable] A tuple struct pattern is refutable if the [PathInExpression] resolves to a constructor of an enum with more than one variant, or one of its subpatterns is refutable. @@ -903,8 +872,7 @@ TuplePatternItems -> ``` r[patterns.tuple.intro] -Tuple patterns match tuple values that match all criteria defined by its subpatterns. -They are also used to [destructure](#destructuring) a tuple. +Tuple patterns match tuple values that match all criteria defined by its subpatterns. They are also used to [destructure](#destructuring) a tuple. r[patterns.tuple.rest-syntax] The form `(..)` with a single [RestPattern] is a special form that does not require a comma, and matches a tuple of any size. @@ -931,8 +899,7 @@ GroupedPattern -> `(` Pattern `)` ``` r[patterns.paren.intro] -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; @@ -980,8 +947,7 @@ r[patterns.slice.refutable-slice] When matching a slice, it is irrefutable only in the form with a single `..` [rest pattern][patterns.rest] or [identifier pattern](#identifier-patterns) with the `..` rest pattern as a subpattern. r[patterns.slice.restriction] -Within a slice, a range pattern without both lower and upper bound must be enclosed in parentheses, as in `(a..)`, to clarify it is intended to match against a single slice element. -A range pattern with both lower and upper bound, like `a..=b`, is not required to be enclosed in parentheses. +Within a slice, a range pattern without both lower and upper bound must be enclosed in parentheses, as in `(a..)`, to clarify it is intended to match against a single slice element. A range pattern with both lower and upper bound, like `a..=b`, is not required to be enclosed in parentheses. r[patterns.path] ## Path patterns @@ -992,8 +958,7 @@ PathPattern -> PathExpression ``` r[patterns.path.intro] -_Path patterns_ are patterns that refer either to constant values or -to structs or enum variants that have no fields. +_Path patterns_ are patterns that refer either to constant values or to structs or enum variants that have no fields. r[patterns.path.unqualified] Unqualified path patterns can refer to: @@ -1007,8 +972,7 @@ r[patterns.path.qualified] Qualified path patterns can only refer to associated constants. r[patterns.path.refutable] -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. r[patterns.const] ### Constant patterns @@ -1023,15 +987,13 @@ r[patterns.const.primitive] - Integers as well as `str`, `bool` and `char` values always have structural equality. r[patterns.const.builtin-aggregate] -- Tuples, arrays, and slices have structural equality if all their fields/elements have structural equality. - (In particular, `()` and `[]` always have structural equality.) +- Tuples, arrays, and slices have structural equality if all their fields/elements have structural equality. (In particular, `()` and `[]` always have structural equality.) r[patterns.const.ref] - References have structural equality if the value they point to has structural equality. r[patterns.const.aggregate] -- A value of `struct` or `enum` type has structural equality if its `PartialEq` instance is derived via `#[derive(PartialEq)]`, - and all fields (for enums: of the active variant) have structural equality. +- A value of `struct` or `enum` type has structural equality if its `PartialEq` instance is derived via `#[derive(PartialEq)]`, and all fields (for enums: of the active variant) have structural equality. r[patterns.const.pointer] - A raw pointer has structural equality if it was defined as a constant integer (and then cast/transmuted). @@ -1043,23 +1005,18 @@ r[patterns.const.exhaustive] - Nothing else has structural equality. r[patterns.const.generic] -In particular, the value of `C` must be known at pattern-building time (which is pre-monomorphization). -This means that associated consts that involve generic parameters cannot be used as patterns. +In particular, the value of `C` must be known at pattern-building time (which is pre-monomorphization). This means that associated consts that involve generic parameters cannot be used as patterns. r[patterns.const.immutable] The value of `C` must not contain any references to mutable statics (`static mut` items or interior mutable `static` items) or `extern` statics. r[patterns.const.translation] -After ensuring all conditions are met, the constant value is translated into a pattern, and now behaves exactly as-if that pattern had been written directly. -In particular, it fully participates in exhaustiveness checking. -(For raw pointers, constants are the only way to write such patterns. Only `_` is ever considered exhaustive for these types.) +After ensuring all conditions are met, the constant value is translated into a pattern, and now behaves exactly as-if that pattern had been written directly. In particular, it fully participates in exhaustiveness checking. (For raw pointers, constants are the only way to write such patterns. Only `_` is ever considered exhaustive for these types.) r[patterns.or] ## Or-patterns -_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 parameters (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 parameters (represented by the [PatternNoTopAlt] production). r[patterns.constraints] ### Static semantics @@ -1074,37 +1031,23 @@ r[patterns.constraints.pattern] Unification of types is in all instances aforementioned exact and implicit [type coercions] do not apply. r[patterns.constraints.match-type-check] -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`, - the pattern `p_i | q_i` is considered ill formed if, - 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`. +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`, the pattern `p_i | q_i` is considered ill formed if, 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`. r[patterns.constraints.exhaustiveness-or-pattern] -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. r[patterns.behavior] ### Dynamic semantics r[patterns.behavior.nested-or-patterns] -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)`. r[patterns.precedence] ### 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. [PR #138458]: https://github.com/rust-lang/rust/pull/138458 [PR #140593]: https://github.com/rust-lang/rust/pull/140593#issuecomment-2972338457 diff --git a/src/statements-and-expressions.md b/src/statements-and-expressions.md index f2bd2f3e7a..fdd1522af3 100644 --- a/src/statements-and-expressions.md +++ b/src/statements-and-expressions.md @@ -1,8 +1,6 @@ r[stmt-expr] # 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. diff --git a/src/statements.md b/src/statements.md index 2fc0be919a..f194e343a6 100644 --- a/src/statements.md +++ b/src/statements.md @@ -20,8 +20,7 @@ Rust has two kinds of statement: [declaration statements](#declaration-statement r[statement.decl] ## 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. @@ -32,16 +31,13 @@ r[statement.item.intro] An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module]. r[statement.item.scope] -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. +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. r[statement.item.associated-scope] -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. +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. r[statement.item.outer-generics] -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() { @@ -67,8 +63,7 @@ LetStatement -> ``` r[statement.let.intro] -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. +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. r[statement.let.inference] 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. @@ -77,12 +72,10 @@ r[statement.let.scope] 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. r[statement.let.constraint] -If an `else` block is not present, the pattern must be irrefutable. -If an `else` block is present, the pattern may be refutable. +If an `else` block is not present, the pattern must be irrefutable. If an `else` block is present, the pattern may be refutable. r[statement.let.behavior] -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]). +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]). ```rust let (mut v, w) = (vec![1, 2, 3], 42); // The bindings may be mut or const @@ -106,13 +99,10 @@ ExpressionStatement -> ``` r[statement.expr.intro] -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. r[statement.expr.restriction-semicolon] -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. +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. r[statement.expr.constraint-block] The type of [ExpressionWithBlock] expressions when used as statements must be the unit type. @@ -148,8 +138,7 @@ if true { r[statement.attribute] ## 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 diff --git a/src/subtyping.md b/src/subtyping.md index 6dba240791..1e9d6c15ea 100644 --- a/src/subtyping.md +++ b/src/subtyping.md @@ -2,17 +2,12 @@ r[subtype] # Subtyping and variance r[subtype.intro] -Subtyping is implicit and can occur at any stage in type checking or -inference. +Subtyping is implicit and can occur at any stage in type checking or inference. r[subtype.kinds] -Subtyping is restricted to two cases: -variance with respect to lifetimes and between types with higher ranked -lifetimes. If we were to erase lifetimes from types, then the only subtyping -would be due to type equality. +Subtyping is restricted to two cases: variance with respect to lifetimes and between types with higher ranked lifetimes. If we were to erase lifetimes from types, then the only subtyping would be due to type equality. -Consider the following example: string literals always have `'static` -lifetime. Nevertheless, we can assign `s` to `t`: +Consider the following example: string literals always have `'static` lifetime. Nevertheless, we can assign `s` to `t`: ```rust fn bar<'a>() { @@ -21,13 +16,10 @@ fn bar<'a>() { } ``` -Since `'static` outlives the lifetime parameter `'a`, `&'static str` is a -subtype of `&'a str`. +Since `'static` outlives the lifetime parameter `'a`, `&'static str` is a subtype of `&'a str`. r[subtype.higher-ranked] -[Higher-ranked] [function pointers] and [trait objects] have another -subtype relation. They are subtypes of types that are given by substitutions of -the higher-ranked lifetimes. Some examples: +[Higher-ranked] [function pointers] and [trait objects] have another subtype relation. They are subtypes of types that are given by substitutions of the higher-ranked lifetimes. Some examples: ```rust // Here 'a is substituted for 'static @@ -47,21 +39,16 @@ r[subtyping.variance] ## Variance r[subtyping.variance.intro] -Variance is a property that generic types have with respect to their arguments. -A generic type's *variance* in a parameter is how the subtyping of the -parameter affects the subtyping of the type. +Variance is a property that generic types have with respect to their arguments. A generic type's *variance* in a parameter is how the subtyping of the parameter affects the subtyping of the type. r[subtyping.variance.covariant] -* `F` is *covariant* over `T` if `T` being a subtype of `U` implies that - `F` is a subtype of `F` (subtyping "passes through") +* `F` is *covariant* over `T` if `T` being a subtype of `U` implies that `F` is a subtype of `F` (subtyping "passes through") r[subtyping.variance.contravariant] -* `F` is *contravariant* over `T` if `T` being a subtype of `U` implies that - `F` is a subtype of `F` +* `F` is *contravariant* over `T` if `T` being a subtype of `U` implies that `F` is a subtype of `F` r[subtyping.variance.invariant] -* `F` is *invariant* over `T` otherwise (no subtyping relation can be - derived) +* `F` is *invariant* over `T` otherwise (no subtyping relation can be derived) r[subtyping.variance.builtin-types] Variance of types is automatically determined as follows @@ -80,11 +67,7 @@ Variance of types is automatically determined as follows | `dyn Trait + 'a` | covariant | invariant | r[subtyping.variance.user-composite-types] -The variance of other `struct`, `enum`, and `union` types is decided by -looking at the variance of the types of their fields. If the parameter is used -in positions with different variances then the parameter is invariant. For -example the following struct is covariant in `'a` and `T` and invariant in `'b`, `'c`, -and `U`. +The variance of other `struct`, `enum`, and `union` types is decided by looking at the variance of the types of their fields. If the parameter is used in positions with different variances then the parameter is invariant. For example the following struct is covariant in `'a` and `T` and invariant in `'b`, `'c`, and `U`. ```rust use std::cell::UnsafeCell; diff --git a/src/trait-bounds.md b/src/trait-bounds.md index f31265fbc0..3493e8ac21 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -31,29 +31,18 @@ UseBoundGenericArg -> ``` r[bound.intro] -[Trait] and lifetime bounds provide a way for [generic items][generic] to -restrict which types and lifetimes are used as their parameters. Bounds can be -provided on any type in a [where clause]. There are also shorter forms for -certain common cases: - -* Bounds written after declaring a [generic parameter][generic]: - `fn f() {}` is the same as `fn f() where A: Copy {}`. -* In trait declarations as [supertraits]: `trait Circle : Shape {}` is - equivalent to `trait Circle where Self : Shape {}`. -* In trait declarations as bounds on [associated types]: - `trait A { type B: Copy; }` is equivalent to - `trait A where Self::B: Copy { type B; }`. +[Trait] and lifetime bounds provide a way for [generic items][generic] to restrict which types and lifetimes are used as their parameters. Bounds can be provided on any type in a [where clause]. There are also shorter forms for certain common cases: + +* Bounds written after declaring a [generic parameter][generic]: `fn f() {}` is the same as `fn f() where A: Copy {}`. +* In trait declarations as [supertraits]: `trait Circle : Shape {}` is equivalent to `trait Circle where Self : Shape {}`. +* In trait declarations as bounds on [associated types]: `trait A { type B: Copy; }` is equivalent to `trait A where Self::B: Copy { type B; }`. r[bound.satisfaction] -Bounds on an item must be satisfied when using the item. When type checking and -borrow checking a generic item, the bounds can be used to determine that a -trait is implemented for a type. For example, given `Ty: Trait` +Bounds on an item must be satisfied when using the item. When type checking and borrow checking a generic item, the bounds can be used to determine that a trait is implemented for a type. For example, given `Ty: Trait` -* In the body of a generic function, methods from `Trait` can be called on `Ty` - values. Likewise associated constants on the `Trait` can be used. +* In the body of a generic function, methods from `Trait` can be called on `Ty` values. Likewise associated constants on the `Trait` can be used. * Associated types from `Trait` can be used. -* Generic functions and types with a `T: Trait` bounds can be used with `Ty` - being used for `T`. +* Generic functions and types with a `T: Trait` bounds can be used with `Ty` being used for `T`. ```rust # type Surface = i32; @@ -85,13 +74,10 @@ fn name_figure( ``` r[bound.trivial] -Bounds that don't use the item's parameters or [higher-ranked lifetimes] are checked when the item is defined. -It is an error for such a bound to be false. +Bounds that don't use the item's parameters or [higher-ranked lifetimes] are checked when the item is defined. It is an error for such a bound to be false. r[bound.special] -[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic types when using the item, even if the use does not provide a concrete type. -It is an error to have `Copy` or `Clone` as a bound on a mutable reference, [trait object], or [slice]. -It is an error to have `Sized` as a bound on a trait object or slice. +[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic types when using the item, even if the use does not provide a concrete type. It is an error to have `Copy` or `Clone` as a bound on a mutable reference, [trait object], or [slice]. It is an error to have `Sized` as a bound on a trait object or slice. ```rust,compile_fail struct A<'a, T> @@ -112,8 +98,7 @@ Trait and lifetime bounds are also used to name [trait objects]. r[bound.sized] ## `?Sized` -`?` is only used to relax the implicit [`Sized`] trait bound for [type parameters] or [associated types]. -`?Sized` may not be used as a bound for other types. +`?` is only used to relax the implicit [`Sized`] trait bound for [type parameters] or [associated types]. `?Sized` may not be used as a bound for other types. r[bound.lifetime] ## Lifetime bounds @@ -122,8 +107,7 @@ r[bound.lifetime.intro] Lifetime bounds can be applied to types or to other lifetimes. r[bound.lifetime.outlive-lifetime] -The bound `'a: 'b` is usually read as `'a` *outlives* `'b`. -`'a: 'b` means that `'a` lasts at least as long as `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid. +The bound `'a: 'b` is usually read as `'a` *outlives* `'b`. `'a: 'b` means that `'a` lasts at least as long as `'b`, so a reference `&'a ()` is valid whenever `&'b ()` is valid. ```rust fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b { @@ -133,8 +117,7 @@ fn f<'a, 'b>(x: &'a i32, mut y: &'b i32) where 'a: 'b { ``` r[bound.lifetime.outlive-type] -`T: 'a` means that all lifetime parameters of `T` outlive `'a`. -For example, if `'a` is an unconstrained lifetime parameter, then `i32: 'static` and `&'static str: 'a` are satisfied, but `Vec<&'a ()>: 'static` is not. +`T: 'a` means that all lifetime parameters of `T` outlive `'a`. For example, if `'a` is an unconstrained lifetime parameter, then `i32: 'static` and `&'static str: 'a` are satisfied, but `Vec<&'a ()>: 'static` is not. r[bound.higher-ranked] ## Higher-ranked trait bounds @@ -145,9 +128,7 @@ ForLifetimes -> `for` GenericParams ``` r[bound.higher-ranked.intro] -Trait bounds may be *higher ranked* over lifetimes. These bounds specify a bound -that is true *for all* lifetimes. For example, a bound such as `for<'a> &'a T: -PartialEq` would require an implementation like +Trait bounds may be *higher ranked* over lifetimes. These bounds specify a bound that is true *for all* lifetimes. For example, a bound such as `for<'a> &'a T: PartialEq` would require an implementation like ```rust # struct T; @@ -169,10 +150,7 @@ fn call_on_ref_zero(f: F) where for<'a> F: Fn(&'a i32) { ``` r[bound.higher-ranked.trait] -Higher-ranked lifetimes may also be specified just before the trait: the only -difference is the [scope][hrtb-scopes] of the lifetime parameter, which extends only to the -end of the following trait instead of the whole bound. This function is -equivalent to the last one. +Higher-ranked lifetimes may also be specified just before the trait: the only difference is the [scope][hrtb-scopes] of the lifetime parameter, which extends only to the end of the following trait instead of the whole bound. This function is equivalent to the last one. ```rust fn call_on_ref_zero(f: F) where F: for<'a> Fn(&'a i32) { @@ -191,13 +169,10 @@ Lifetime bounds required for types to be well-formed are sometimes inferred. fn requires_t_outlives_a<'a, T>(x: &'a T) {} ``` -The type parameter `T` is required to outlive `'a` for the type `&'a T` to be well-formed. -This is inferred because the function signature contains the type `&'a T` which is -only valid if `T: 'a` holds. +The type parameter `T` is required to outlive `'a` for the type `&'a T` to be well-formed. This is inferred because the function signature contains the type `&'a T` which is only valid if `T: 'a` holds. r[bound.implied.context] -Implied bounds are added for all parameters and outputs of functions. Inside of `requires_t_outlives_a` -you can assume `T: 'a` to hold even if you don't explicitly specify this: +Implied bounds are added for all parameters and outputs of functions. Inside of `requires_t_outlives_a` you can assume `T: 'a` to hold even if you don't explicitly specify this: ```rust fn requires_t_outlives_a_not_implied<'a, T: 'a>() {} @@ -219,8 +194,7 @@ fn not_implied<'a, T>() { ``` r[bound.implied.trait] -Only lifetime bounds are implied, trait bounds still have to be explicitly added. -The following example therefore causes an error: +Only lifetime bounds are implied, trait bounds still have to be explicitly added. The following example therefore causes an error: ```rust,compile_fail,E0277 use std::fmt::Debug; diff --git a/src/type-coercions.md b/src/type-coercions.md index 91b773ee91..ae60c3df96 100644 --- a/src/type-coercions.md +++ b/src/type-coercions.md @@ -2,13 +2,10 @@ r[coerce] # Type coercions r[coerce.intro] -**Type coercions** are implicit operations that change the type of a value. -They happen automatically at specific locations and are highly restricted in -what types actually coerce. +**Type coercions** are implicit operations that change the type of a value. They happen automatically at specific locations and are highly restricted in what types actually coerce. r[coerce.as] -Any conversions allowed by coercion can also be explicitly performed by the -[type cast operator], `as`. +Any conversions allowed by coercion can also be explicitly performed by the [type cast operator], `as`. Coercions are originally defined in [RFC 401] and expanded upon in [RFC 1558]. @@ -16,10 +13,7 @@ r[coerce.site] ## Coercion sites r[coerce.site.intro] -A coercion can only occur at certain coercion sites in a program; these are -typically places where the desired type is explicit or can be derived by -propagation from explicit types (without type inference). Possible coercion -sites are: +A coercion can only occur at certain coercion sites in a program; these are typically places where the desired type is explicit or can be derived by propagation from explicit types (without type inference). Possible coercion sites are: r[coerce.site.let] * `let` statements where an explicit type is given. @@ -36,8 +30,7 @@ r[coerce.site.value] r[coerce.site.argument] * Arguments for function calls - The value being coerced is the actual parameter, and it is coerced to - the type of the formal parameter. + The value being coerced is the actual parameter, and it is coerced to the type of the formal parameter. For example, `&mut 42` is coerced to have type `&i8` in the following: @@ -49,8 +42,7 @@ r[coerce.site.argument] } ``` - For method calls, the receiver (`self` parameter) type is coerced - differently, see the documentation on [method-call expressions] for details. + For method calls, the receiver (`self` parameter) type is coerced differently, see the documentation on [method-call expressions] for details. r[coerce.site.constructor] * Instantiations of struct, union, or enum variant fields @@ -66,8 +58,7 @@ r[coerce.site.constructor] ``` r[coerce.site.return] -* Function results—either the final line of a block if it is not - semicolon-terminated or any expression in a `return` statement +* Function results—either the final line of a block if it is not semicolon-terminated or any expression in a `return` statement For example, `x` is coerced to have type `&dyn Display` in the following: @@ -79,33 +70,22 @@ r[coerce.site.return] ``` r[coerce.site.subexpr] -If the expression in one of these coercion sites is a coercion-propagating -expression, then the relevant sub-expressions in that expression are also -coercion sites. Propagation recurses from these new coercion sites. -Propagating expressions and their relevant sub-expressions are: +If the expression in one of these coercion sites is a coercion-propagating expression, then the relevant sub-expressions in that expression are also coercion sites. Propagation recurses from these new coercion sites. Propagating expressions and their relevant sub-expressions are: r[coerce.site.array] -* Array literals, where the array has type `[U; n]`. Each sub-expression in -the array literal is a coercion site for coercion to type `U`. +* Array literals, where the array has type `[U; n]`. Each sub-expression in the array literal is a coercion site for coercion to type `U`. r[coerce.site.repeat] -* Array literals with repeating syntax, where the array has type `[U; n]`. The -repeated sub-expression is a coercion site for coercion to type `U`. +* Array literals with repeating syntax, where the array has type `[U; n]`. The repeated sub-expression is a coercion site for coercion to type `U`. r[coerce.site.tuple] -* Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`. -Each sub-expression is a coercion site to the respective type, e.g. the -zeroth sub-expression is a coercion site to type `U_0`. +* Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`. Each sub-expression is a coercion site to the respective type, e.g. the zeroth sub-expression is a coercion site to type `U_0`. r[coerce.site.parenthesis] -* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then -the sub-expression is a coercion site to `U`. +* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then the sub-expression is a coercion site to `U`. r[coerce.site.block] -* Blocks: if a block has type `U`, then the last expression in the block (if -it is not semicolon-terminated) is a coercion site to `U`. This includes -blocks which are part of control flow statements, such as `if`/`else`, if -the block has a known type. +* Blocks: if a block has type `U`, then the last expression in the block (if it is not semicolon-terminated) is a coercion site to `U`. This includes blocks which are part of control flow statements, such as `if`/`else`, if the block has a known type. r[coerce.types] ## Coercion types @@ -117,8 +97,7 @@ r[coerce.types.reflexive] * `T` to `U` if `T` is a [subtype] of `U` (*reflexive case*) r[coerce.types.transitive] -* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` -(*transitive case*) +* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3` (*transitive case*) Note that this is not fully supported yet. @@ -190,16 +169,10 @@ r[coerce.unsize] ### Unsized coercions r[coerce.unsize.intro] -The following coercions are called `unsized coercions`, since they -relate to converting types to unsized types, and are permitted in a few -cases where other coercions are not, as described above. They can still happen -anywhere else a coercion can occur. +The following coercions are called `unsized coercions`, since they relate to converting types to unsized types, and are permitted in a few cases where other coercions are not, as described above. They can still happen anywhere else a coercion can occur. r[coerce.unsize.trait] -Two traits, [`Unsize`] and [`CoerceUnsized`], are used -to assist in this process and expose it for library use. The following -coercions are built-ins and, if `T` can be coerced to `U` with one of them, then -an implementation of `Unsize` for `T` will be provided: +Two traits, [`Unsize`] and [`CoerceUnsized`], are used to assist in this process and expose it for library use. The following coercions are built-ins and, if `T` can be coerced to `U` with one of them, then an implementation of `Unsize` for `T` will be provided: r[coerce.unsize.slice] * `[T; n]` to `[T]`. @@ -221,9 +194,7 @@ r[coerce.unsized.composite] * T is not part of the type of any other fields. r[coerce.unsized.pointer] -Additionally, a type `Foo` can implement `CoerceUnsized>` when `T` -implements `Unsize` or `CoerceUnsized>`. This allows it to provide an -unsized coercion to `Foo`. +Additionally, a type `Foo` can implement `CoerceUnsized>` when `T` implements `Unsize` or `CoerceUnsized>`. This allows it to provide an unsized coercion to `Foo`. > [!NOTE] > While the definition of the unsized coercions and their implementation has been stabilized, the traits themselves are not yet stable and therefore can't be used directly in stable Rust. @@ -232,9 +203,7 @@ r[coerce.least-upper-bound] ## Least upper bound coercions r[coerce.least-upper-bound.intro] -In some contexts, the compiler must coerce together multiple types to try and -find the most general type. This is called a "Least Upper Bound" coercion. -LUB coercion is used and only used in the following situations: +In some contexts, the compiler must coerce together multiple types to try and find the most general type. This is called a "Least Upper Bound" coercion. LUB coercion is used and only used in the following situations: + To find the common type for a series of if branches. + To find the common type for a series of match arms. @@ -243,21 +212,16 @@ LUB coercion is used and only used in the following situations: + To check the type for the return type of a function with multiple return statements. r[coerce.least-upper-bound.target] -In each such case, there are a set of types `T0..Tn` to be mutually coerced -to some target type `T_t`, which is unknown to start. +In each such case, there are a set of types `T0..Tn` to be mutually coerced to some target type `T_t`, which is unknown to start. r[coerce.least-upper-bound.computation] -Computing the LUB -coercion is done iteratively. The target type `T_t` begins as the type `T0`. -For each new type `Ti`, we consider whether +Computing the LUB coercion is done iteratively. The target type `T_t` begins as the type `T0`. For each new type `Ti`, we consider whether r[coerce.least-upper-bound.computation-identity] + If `Ti` can be coerced to the current target type `T_t`, then no change is made. r[coerce.least-upper-bound.computation-replace] -+ Otherwise, check whether `T_t` can be coerced to `Ti`; if so, the `T_t` is -changed to `Ti`. (This check is also conditioned on whether all of the source -expressions considered thus far have implicit coercions.) ++ Otherwise, check whether `T_t` can be coerced to `Ti`; if so, the `T_t` is changed to `Ti`. (This check is also conditioned on whether all of the source expressions considered thus far have implicit coercions.) r[coerce.least-upper-bound.computation-unify] + If not, try to compute a mutual supertype of `T_t` and `Ti`, which will become the new target type. @@ -308,15 +272,11 @@ fn foo() -> i32 { } ``` -In these examples, types of the `ba*` are found by LUB coercion. And the -compiler checks whether LUB coercion result of `a`, `b`, `c` is `i32` in the -processing of the function `foo`. +In these examples, types of the `ba*` are found by LUB coercion. And the compiler checks whether LUB coercion result of `a`, `b`, `c` is `i32` in the processing of the function `foo`. ### Caveat -This description is obviously informal. Making it more precise is expected to -proceed as part of a general effort to specify the Rust type checker more -precisely. +This description is obviously informal. Making it more precise is expected to proceed as part of a general effort to specify the Rust type checker more precisely. [RFC 401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md [RFC 1558]: https://github.com/rust-lang/rfcs/blob/master/text/1558-closure-to-fn-coercion.md diff --git a/src/type-layout.md b/src/type-layout.md index 771803fbb1..7f946ba791 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -2,17 +2,12 @@ r[layout] # Type layout r[layout.intro] -The layout of a type is its size, alignment, and the relative offsets of its -fields. For enums, how the discriminant is laid out and interpreted is also part -of type layout. +The layout of a type is its size, alignment, and the relative offsets of its fields. For enums, how the discriminant is laid out and interpreted is also part of type layout. r[layout.guarantees] -Type layout can be changed with each compilation. Instead of trying to document -exactly what is done, we only document what is guaranteed today. +Type layout can be changed with each compilation. Instead of trying to document exactly what is done, we only document what is guaranteed today. -Note that even types with the same layout can still differ in how they are passed -across function boundaries. For function call ABI compatibility of types, -see [here][fn-abi-compatibility]. +Note that even types with the same layout can still differ in how they are passed across function boundaries. For function call ABI compatibility of types, see [here][fn-abi-compatibility]. r[layout.properties] ## Size and alignment @@ -20,28 +15,13 @@ r[layout.properties] All values have an alignment and size. r[layout.properties.align] -The *alignment* of a value specifies what addresses are valid to store the value -at. A value of alignment `n` must only be stored at an address that is a -multiple of n. For example, a value with an alignment of 2 must be stored at an -even address, while a value with an alignment of 1 can be stored at any address. -Alignment is measured in bytes, and must be at least 1, and always a power of 2. -The alignment of a value can be checked with the [`align_of_val`] function. +The *alignment* of a value specifies what addresses are valid to store the value at. A value of alignment `n` must only be stored at an address that is a multiple of n. For example, a value with an alignment of 2 must be stored at an even address, while a value with an alignment of 1 can be stored at any address. Alignment is measured in bytes, and must be at least 1, and always a power of 2. The alignment of a value can be checked with the [`align_of_val`] function. r[layout.properties.size] -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. 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. +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. 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. r[layout.properties.sized] -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 -[`size_of`] and [`align_of`] functions. Types that are not [`Sized`] are known -as [dynamically sized types]. Since all values of a `Sized` type share the same -size and alignment, we refer to those shared values as the size of the type and -the alignment of the type respectively. +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 [`size_of`] and [`align_of`] functions. Types that are not [`Sized`] are known as [dynamically sized types]. Since all values of a `Sized` type share the same size and alignment, we refer to those shared values as the size of the type and the alignment of the type respectively. r[layout.primitive] ## Primitive data layout @@ -63,30 +43,22 @@ The size of most primitives is given in this table. | `char` | 4 | r[layout.primitive.size-int] -`usize` and `isize` have a size big enough to contain every address on the -target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64 -bit target, this is 8 bytes. +`usize` and `isize` have a size big enough to contain every address on the target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64 bit target, this is 8 bytes. r[layout.primitive.align] -The alignment of primitives is platform-specific. -In most cases, their alignment is equal to their size, but it may be less. -In particular, `i128` and `u128` are often aligned to 4 or 8 bytes even though -their size is 16, and on many 32-bit platforms, `i64`, `u64`, and `f64` are only -aligned to 4 bytes, not 8. +The alignment of primitives is platform-specific. In most cases, their alignment is equal to their size, but it may be less. In particular, `i128` and `u128` are often aligned to 4 or 8 bytes even though their size is 16, and on many 32-bit platforms, `i64`, `u64`, and `f64` are only aligned to 4 bytes, not 8. r[layout.pointer] ## Pointers and references layout r[layout.pointer.intro] -Pointers and references have the same layout. Mutability of the pointer or -reference does not change the layout. +Pointers and references have the same layout. Mutability of the pointer or reference does not change the layout. r[layout.pointer.thin] Pointers to sized types have the same size and alignment as `usize`. r[layout.pointer.unsized] -Pointers to unsized types are sized. The size and alignment is guaranteed to be -at least equal to the size and alignment of a pointer. +Pointers to unsized types are sized. The size and alignment is guaranteed to be at least equal to the size and alignment of a pointer. > [!NOTE] > Though you should not rely on this, all pointers to DSTs are currently twice the size of the size of `usize` and have the same alignment. @@ -94,9 +66,7 @@ at least equal to the size and alignment of a pointer. r[layout.array] ## Array layout -An array of `[T; N]` has a size of `size_of::() * N` and the same alignment -of `T`. Arrays are laid out so that the zero-based `nth` element of the array -is offset from the start of the array by `n * size_of::()` bytes. +An array of `[T; N]` has a size of `size_of::() * N` and the same alignment of `T`. Arrays are laid out so that the zero-based `nth` element of the array is offset from the start of the array by `n * size_of::()` bytes. r[layout.slice] ## Slice layout @@ -118,8 +88,7 @@ r[layout.tuple.def] Tuples are laid out according to the [`Rust` representation][`Rust`]. r[layout.tuple.unit] -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. +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. r[layout.trait-object] ## Trait object layout @@ -138,8 +107,7 @@ r[layout.repr] ## Representations r[layout.repr.intro] -All user-defined composite types (`struct`s, `enum`s, and `union`s) have a -*representation* that specifies what the layout is for the type. +All user-defined composite types (`struct`s, `enum`s, and `union`s) have a *representation* that specifies what the layout is for the type. r[layout.repr.kinds] The possible representations for a type are: @@ -150,8 +118,7 @@ The possible representations for a type are: - [`transparent`] r[layout.repr.attribute] -The representation of a type can be changed by applying the `repr` attribute -to it. The following example shows a struct with a `C` representation. +The representation of a type can be changed by applying the `repr` attribute to it. The following example shows a struct with a `C` representation. ```rust #[repr(C)] @@ -163,9 +130,7 @@ struct ThreeInts { ``` r[layout.repr.align-packed] -The alignment may be raised or lowered with the `align` and `packed` modifiers -respectively. They alter the representation specified in the attribute. -If no representation is specified, the default one is altered. +The alignment may be raised or lowered with the `align` and `packed` modifiers respectively. They alter the representation specified in the attribute. If no representation is specified, the default one is altered. ```rust // Default representation, alignment lowered to 2. @@ -189,43 +154,29 @@ struct AlignedStruct { > As a consequence of the representation being an attribute on the item, the representation does not depend on generic parameters. Any two types with the same name have the same representation. For example, `Foo` and `Foo` both have the same representation. r[layout.repr.inter-field] -The representation of a type can change the padding between fields, but does -not change the layout of the fields themselves. For example, a struct with a -`C` representation that contains a struct `Inner` with the `Rust` -representation will not change the layout of `Inner`. +The representation of a type can change the padding between fields, but does not change the layout of the fields themselves. For example, a struct with a `C` representation that contains a struct `Inner` with the `Rust` representation will not change the layout of `Inner`. r[layout.repr.rust] ### The `Rust` representation r[layout.repr.rust.intro] -The `Rust` representation is the default representation for nominal types -without a `repr` attribute. Using this representation explicitly through a -`repr` attribute is guaranteed to be the same as omitting the attribute -entirely. +The `Rust` representation is the default representation for nominal types without a `repr` attribute. Using this representation explicitly through a `repr` attribute is guaranteed to be the same as omitting the attribute entirely. r[layout.repr.rust.layout] -The only data layout guarantees made by this representation are those required -for soundness. They are: +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. r[layout.repr.rust.alignment] -Formally, the first guarantee means that the offset of any field is divisible by -that field's alignment. +Formally, the first guarantee means that the offset of any field is divisible by that field's alignment. r[layout.repr.rust.field-storage] -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. +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. +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. r[layout.repr.rust.unspecified] There are no other guarantees of data layout made by this representation. @@ -234,17 +185,12 @@ r[layout.repr.c] ### The `C` representation r[layout.repr.c.intro] -The `C` representation is designed for dual purposes. One purpose is for -creating types that are interoperable with the C Language. The second purpose is -to create types that you can soundly perform operations on that rely on data -layout such as reinterpreting values as a different type. +The `C` representation is designed for dual purposes. One purpose is for creating types that are interoperable with the C Language. The second purpose is to create types that you can soundly perform operations on that rely on data layout such as reinterpreting values as a different type. -Because of this dual purpose, it is possible to create types that are not useful -for interfacing with the C programming language. +Because of this dual purpose, it is possible to create types that are not useful for interfacing with the C programming language. r[layout.repr.c.constraint] -This representation can be applied to structs, unions, and enums. The exception -is [zero-variant enums] for which the `C` representation is an error. +This representation can be applied to structs, unions, and enums. The exception is [zero-variant enums] for which the `C` representation is an error. r[layout.repr.c.struct] #### `#[repr(C)]` Structs @@ -257,14 +203,9 @@ The size and offset of fields is determined by the following algorithm. Start with a current offset of 0 bytes. -For each field in declaration order in the struct, first determine the size and -alignment of the field. If the current offset is not a multiple of the field's -alignment, then add padding bytes to the current offset until it is a multiple -of the field's alignment. The offset for the field is what the current offset -is now. Then increase the current offset by the size of the field. +For each field in declaration order in the struct, first determine the size and alignment of the field. If the current offset is not a multiple of the field's alignment, then add padding bytes to the current offset until it is a multiple of the field's alignment. The offset for the field is what the current offset is now. Then increase the current offset by the size of the field. -Finally, the size of the struct is the current offset rounded up to the nearest -multiple of the struct's alignment. +Finally, the size of the struct is the current offset rounded up to the nearest multiple of the struct's alignment. Here is this algorithm described in pseudocode. @@ -311,13 +252,10 @@ r[layout.repr.c.union] #### `#[repr(C)]` Unions r[layout.repr.c.union.intro] -A union declared with `#[repr(C)]` will have the same size and alignment as an -equivalent C union declaration in the C language for the target platform. +A union declared with `#[repr(C)]` will have the same size and alignment as an equivalent C union declaration in the C language for the target platform. r[layout.repr.c.union.size-align] -The union will have a size of the maximum size of all of its fields rounded to -its alignment, and an alignment of the maximum alignment of all of its fields. -These maximums may come from different fields. +The union will have a size of the maximum size of all of its fields rounded to its alignment, and an alignment of the maximum alignment of all of its fields. These maximums may come from different fields. ```rust #[repr(C)] @@ -344,8 +282,7 @@ assert_eq!(std::mem::align_of::(), 4); // From a r[layout.repr.c.enum] #### `#[repr(C)]` Field-less Enums -For [field-less enums], the `C` representation has the size and alignment of -the default `enum` size and alignment for the target platform's C ABI. +For [field-less enums], the `C` representation has the size and alignment of the default `enum` size and alignment for the target platform's C ABI. > [!NOTE] > The enum representation in C is implementation defined, so this is really a "best guess". In particular, this may be incorrect when the C code of interest is compiled with certain flags. @@ -357,15 +294,13 @@ r[layout.repr.c.adt] #### `#[repr(C)]` Enums With Fields r[layout.repr.c.adt.intro] -The representation of a `repr(C)` enum with fields is a `repr(C)` struct with -two fields, also called a "tagged union" in C: +The representation of a `repr(C)` enum with fields is a `repr(C)` struct with two fields, also called a "tagged union" in C: r[layout.repr.c.adt.tag] - a `repr(C)` version of the enum with all fields removed ("the tag") r[layout.repr.c.adt.fields] -- a `repr(C)` union of `repr(C)` structs for the fields of each variant that had - them ("the payload") +- a `repr(C)` union of `repr(C)` structs for the fields of each variant that had them ("the payload") > [!NOTE] > Due to the representation of `repr(C)` structs and unions, if a variant has a single field there is no difference between putting that field directly in the union or wrapping it in a struct; any system which wishes to manipulate such an `enum`'s representation may therefore use whichever form is more convenient or consistent for them. @@ -423,31 +358,20 @@ r[layout.repr.primitive] ### Primitive representations r[layout.repr.primitive.intro] -The *primitive representations* are the representations with the same names as -the primitive integer types. That is: `u8`, `u16`, `u32`, `u64`, `u128`, -`usize`, `i8`, `i16`, `i32`, `i64`, `i128`, and `isize`. +The *primitive representations* are the representations with the same names as the primitive integer types. That is: `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, and `isize`. r[layout.repr.primitive.constraint] -Primitive representations can only be applied to enumerations and have -different behavior whether the enum has fields or no fields. It is an error -for [zero-variant enums] to have a primitive representation. Combining -two primitive representations together is an error. +Primitive representations can only be applied to enumerations and have different behavior whether the enum has fields or no fields. It is an error for [zero-variant enums] to have a primitive representation. Combining two primitive representations together is an error. r[layout.repr.primitive.enum] #### Primitive representation of field-less enums -For [field-less enums], primitive representations set the size and alignment to -be the same as the primitive type of the same name. For example, a field-less -enum with a `u8` representation can only have discriminants between 0 and 255 -inclusive. +For [field-less enums], primitive representations set the size and alignment to be the same as the primitive type of the same name. For example, a field-less enum with a `u8` representation can only have discriminants between 0 and 255 inclusive. r[layout.repr.primitive.adt] #### Primitive representation of enums with fields -The representation of a primitive representation enum is a `repr(C)` union of -`repr(C)` structs for each variant with a field. The first field of each struct -in the union is the primitive representation version of the enum with all fields -removed ("the tag") and the remaining fields are the fields of that variant. +The representation of a primitive representation enum is a `repr(C)` union of `repr(C)` structs for each variant with a field. The first field of each struct in the union is the primitive representation version of the enum with all fields removed ("the tag") and the remaining fields are the fields of that variant. > [!NOTE] > This representation is unchanged if the tag is given its own member in the union, should that make manipulation more clear for you (although to follow the C++ standard the tag member should be wrapped in a `struct`). @@ -496,11 +420,7 @@ struct MyVariantD(MyEnumDiscriminant); r[layout.repr.primitive-c] #### Combining primitive representations of enums with fields and `#[repr(C)]` -For enums with fields, it is also possible to combine `repr(C)` and a -primitive representation (e.g., `repr(C, u8)`). This modifies the [`repr(C)`] by -changing the representation of the discriminant enum to the chosen primitive -instead. So, if you chose the `u8` representation, then the discriminant enum -would have a size and alignment of 1 byte. +For enums with fields, it is also possible to combine `repr(C)` and a primitive representation (e.g., `repr(C, u8)`). This modifies the [`repr(C)`] by changing the representation of the discriminant enum to the chosen primitive instead. So, if you chose the `u8` representation, then the discriminant enum would have a size and alignment of 1 byte. The discriminant enum from the example [earlier][`repr(C)`] then becomes: @@ -521,12 +441,9 @@ enum MyEnumDiscriminant { A, B, C, D } // ... ``` -For example, with a `repr(C, u8)` enum it is not possible to have 257 unique -discriminants ("tags") whereas the same enum with only a `repr(C)` attribute -will compile without any problems. +For example, with a `repr(C, u8)` enum it is not possible to have 257 unique discriminants ("tags") whereas the same enum with only a `repr(C)` attribute will compile without any problems. -Using a primitive representation in addition to `repr(C)` can change the size of -an enum from the `repr(C)` form: +Using a primitive representation in addition to `repr(C)` can change the size of an enum from the `repr(C)` form: ```rust #[repr(C)] @@ -562,48 +479,28 @@ r[layout.repr.alignment] ### The alignment modifiers r[layout.repr.alignment.intro] -The `align` and `packed` modifiers can be used to respectively raise or lower -the alignment of `struct`s and `union`s. `packed` may also alter the padding -between fields (although it will not alter the padding inside of any field). -On their own, `align` and `packed` do not provide guarantees about the order -of fields in the layout of a struct or the layout of an enum variant, although -they may be combined with representations (such as `C`) which do provide such -guarantees. +The `align` and `packed` modifiers can be used to respectively raise or lower the alignment of `struct`s and `union`s. `packed` may also alter the padding between fields (although it will not alter the padding inside of any field). On their own, `align` and `packed` do not provide guarantees about the order of fields in the layout of a struct or the layout of an enum variant, although they may be combined with representations (such as `C`) which do provide such guarantees. r[layout.repr.alignment.constraint-alignment] -The alignment is specified as an integer parameter in the form of -`#[repr(align(x))]` or `#[repr(packed(x))]`. The alignment value must be a -power of two from 1 up to 229. For `packed`, if no value is given, -as in `#[repr(packed)]`, then the value is 1. +The alignment is specified as an integer parameter in the form of `#[repr(align(x))]` or `#[repr(packed(x))]`. The alignment value must be a power of two from 1 up to 229. For `packed`, if no value is given, as in `#[repr(packed)]`, then the value is 1. r[layout.repr.alignment.align] -For `align`, if the specified alignment is less than the alignment of the type -without the `align` modifier, then the alignment is unaffected. +For `align`, if the specified alignment is less than the alignment of the type without the `align` modifier, then the alignment is unaffected. r[layout.repr.alignment.packed] -For `packed`, if the specified alignment is greater than the type's alignment -without the `packed` modifier, then the alignment and layout is unaffected. +For `packed`, if the specified alignment is greater than the type's alignment without the `packed` modifier, then the alignment and layout is unaffected. r[layout.repr.alignment.packed-fields] -The alignments of each field, for the purpose of positioning fields, is the -smaller of the specified alignment and the alignment of the field's type. +The alignments of each field, for the purpose of positioning fields, is the smaller of the specified alignment and the alignment of the field's type. r[layout.repr.alignment.packed-padding] -Inter-field padding is guaranteed to be the minimum required in order to -satisfy each field's (possibly altered) alignment (although note that, on its -own, `packed` does not provide any guarantee about field ordering). An -important consequence of these rules is that a type with `#[repr(packed(1))]` -(or `#[repr(packed)]`) will have no inter-field padding. +Inter-field padding is guaranteed to be the minimum required in order to satisfy each field's (possibly altered) alignment (although note that, on its own, `packed` does not provide any guarantee about field ordering). An important consequence of these rules is that a type with `#[repr(packed(1))]` (or `#[repr(packed)]`) will have no inter-field padding. r[layout.repr.alignment.constraint-exclusive] -The `align` and `packed` modifiers cannot be applied on the same type and a -`packed` type cannot transitively contain another `align`ed type. `align` and -`packed` may only be applied to the [`Rust`] and [`C`] representations. +The `align` and `packed` modifiers cannot be applied on the same type and a `packed` type cannot transitively contain another `align`ed type. `align` and `packed` may only be applied to the [`Rust`] and [`C`] representations. r[layout.repr.alignment.enum] -The `align` modifier can also be applied on an `enum`. -When it is, the effect on the `enum`'s alignment is the same as if the `enum` -was wrapped in a newtype `struct` with the same `align` modifier. +The `align` modifier can also be applied on an `enum`. When it is, the effect on the `enum`'s alignment is the same as if the `enum` was wrapped in a newtype `struct` with the same `align` modifier. > [!NOTE] > References to unaligned fields are not allowed because it is [undefined behavior]. When fields are unaligned due to an alignment modifier, consider the following options for using references and dereferences: @@ -632,23 +529,17 @@ r[layout.repr.transparent] ### The `transparent` representation r[layout.repr.transparent.constraint-field] -The `transparent` representation can only be used on a [`struct`][structs] -or an [`enum`][enumerations] with a single variant that has: +The `transparent` representation can only be used on a [`struct`][structs] or an [`enum`][enumerations] with a single variant that has: - any number of fields with size 0 and alignment 1 (e.g. [`PhantomData`]), and - at most one other field. r[layout.repr.transparent.layout-abi] -Structs and enums with this representation have the same layout and ABI -as the only non-size 0 non-alignment 1 field, if present, or unit otherwise. +Structs and enums with this representation have the same layout and ABI as the only non-size 0 non-alignment 1 field, if present, or unit otherwise. -This is different than the `C` representation because -a struct with the `C` representation will always have the ABI of a `C` `struct` -while, for example, a struct with the `transparent` representation with a -primitive field will have the ABI of the primitive field. +This is different than the `C` representation because a struct with the `C` representation will always have the ABI of a `C` `struct` while, for example, a struct with the `transparent` representation with a primitive field will have the ABI of the primitive field. r[layout.repr.transparent.constraint-exclusive] -Because this representation delegates type layout to another type, it cannot be -used with any other representation. +Because this representation delegates type layout to another type, it cannot be used with any other representation. [`align_of_val`]: std::mem::align_of_val [`size_of_val`]: std::mem::size_of_val diff --git a/src/types.md b/src/types.md index de67050ad0..c62419b7ba 100644 --- a/src/types.md +++ b/src/types.md @@ -2,13 +2,10 @@ r[type] # Types r[type.intro] -Every variable, item, and value in a Rust program has a type. The _type_ of a -*value* defines the interpretation of the memory holding it and the operations -that may be performed on the value. +Every variable, item, and value in a Rust program has a type. The _type_ of a *value* defines the interpretation of the memory holding it and the operations that may be performed on the value. r[type.builtin] -Built-in types are tightly integrated into the language, in nontrivial ways -that are not possible to emulate in user-defined types. +Built-in types are tightly integrated into the language, in nontrivial ways that are not possible to emulate in user-defined types. r[type.user-defined] User-defined types have limited capabilities. @@ -68,8 +65,7 @@ TypeNoBounds -> ``` r[type.name.intro] -A _type expression_ as defined in the [Type] grammar rule above is the syntax -for referring to a type. It may refer to: +A _type expression_ as defined in the [Type] grammar rule above is the syntax for referring to a type. It may refer to: r[type.name.sequence] * Sequence types ([tuple], [array], [slice]). @@ -108,12 +104,7 @@ ParenthesizedType -> `(` Type `)` ``` r[type.name.parenthesized.intro] -In some situations the combination of types may be ambiguous. Use parentheses -around a type to avoid ambiguity. For example, the `+` operator for [type -boundaries] within a [reference type] is unclear where the -boundary applies, so the use of parentheses is required. Grammar rules that -require this disambiguation use the [TypeNoBounds] rule instead of -[Type][grammar-Type]. +In some situations the combination of types may be ambiguous. Use parentheses around a type to avoid ambiguity. For example, the `+` operator for [type boundaries] within a [reference type] is unclear where the boundary applies, so the use of parentheses is required. Grammar rules that require this disambiguation use the [TypeNoBounds] rule instead of [Type][grammar-Type]. ```rust # use std::any::Any; @@ -124,19 +115,13 @@ r[type.recursive] ## Recursive types r[type.recursive.intro] -Nominal types — [structs], [enumerations], and [unions] — may be -recursive. That is, each `enum` variant or `struct` or `union` field may -refer, directly or indirectly, to the enclosing `enum` or `struct` type -itself. +Nominal types — [structs], [enumerations], and [unions] — may be recursive. That is, each `enum` variant or `struct` or `union` field may refer, directly or indirectly, to the enclosing `enum` or `struct` type itself. r[type.recursive.constraint] Such recursion has restrictions: -* Recursive types must include a nominal type in the recursion (not mere [type - aliases], or other structural types such as [arrays] or [tuples]). So `type - Rec = &'static [Rec]` is not allowed. -* The size of a recursive type must be finite; in other words the recursive - fields of the type must be [pointer types]. +* Recursive types must include a nominal type in the recursion (not mere [type aliases], or other structural types such as [arrays] or [tuples]). So `type Rec = &'static [Rec]` is not allowed. +* The size of a recursive type must be finite; in other words the recursive fields of the type must be [pointer types]. An example of a *recursive* type and its use: diff --git a/src/types/array.md b/src/types/array.md index e01a4e5ee4..8df7cb711d 100644 --- a/src/types/array.md +++ b/src/types/array.md @@ -7,8 +7,7 @@ ArrayType -> `[` Type `;` Expression `]` ``` r[type.array.intro] -An array is a fixed-size sequence of `N` elements of type `T`. The array type -is written as `[T; N]`. +An array is a fixed-size sequence of `N` elements of type `T`. The array type is written as `[T; N]`. r[type.array.constraint] The size is a [constant expression] that evaluates to a [`usize`]. @@ -24,8 +23,7 @@ let boxed_array: Box<[i32]> = Box::new([1, 2, 3]); ``` r[type.array.index] -All elements of arrays are always initialized, and access to an array is -always bounds-checked in safe methods and operators. +All elements of arrays are always initialized, and access to an array is always bounds-checked in safe methods and operators. > [!NOTE] > The [`Vec`] standard library type provides a heap-allocated resizable array type. diff --git a/src/types/boolean.md b/src/types/boolean.md index 27ec97cb81..1420d03002 100644 --- a/src/types/boolean.md +++ b/src/types/boolean.md @@ -6,12 +6,10 @@ let b: bool = true; ``` r[type.bool.intro] -The *boolean type* or *bool* is a primitive data type that can take on one of -two values, called *true* and *false*. +The *boolean type* or *bool* is a primitive data type that can take on one of two values, called *true* and *false*. r[type.bool.literal] -Values of this type may be created using a [literal expression] using the -keywords `true` and `false` corresponding to the value of the same name. +Values of this type may be created using a [literal expression] using the keywords `true` and `false` corresponding to the value of the same name. r[type.bool.namespace] This type is a part of the [language prelude] with the [name] `bool`. @@ -20,9 +18,7 @@ r[type.bool.layout] An object with the boolean type has a [size and alignment] of 1 each. r[type.bool.repr] -The value false has the bit pattern `0x00` and the value true has the bit pattern -`0x01`. It is [undefined behavior] for an object with the boolean type to have -any other bit pattern. +The value false has the bit pattern `0x00` and the value true has the bit pattern `0x01`. It is [undefined behavior] for an object with the boolean type to have any other bit pattern. r[type.bool.usage] The boolean type is the type of many operands in various [expressions]: @@ -37,9 +33,7 @@ r[type.bool.usage-lazy-operator] > The boolean type acts similarly to but is not an [enumerated type]. In practice, this mostly means that constructors are not associated to the type (e.g. `bool::true`). r[type.bool.traits] -Like all primitives, the boolean type [implements][p-impl] the -[traits][p-traits] [`Clone`][p-clone], [`Copy`][p-copy], [`Sized`][p-sized], -[`Send`][p-send], and [`Sync`][p-sync]. +Like all primitives, the boolean type [implements][p-impl] the [traits][p-traits] [`Clone`][p-clone], [`Copy`][p-copy], [`Sized`][p-sized], [`Send`][p-send], and [`Sync`][p-sync]. > [!NOTE] > See the [standard library docs](bool) for library operations. @@ -47,8 +41,7 @@ Like all primitives, the boolean type [implements][p-impl] the r[type.bool.expr] ## Operations on boolean values -When using certain operator expressions with a boolean type for its operands, -they evaluate using the rules of [boolean logic]. +When using certain operator expressions with a boolean type for its operands, they evaluate using the rules of [boolean logic]. r[type.bool.expr.not] ### Logical not @@ -122,9 +115,7 @@ r[type.bool.expr.cmp.less-eq] r[type.bool.validity] ## Bit validity -The single byte of a `bool` is guaranteed to be initialized (in other words, -`transmute::(...)` is always sound -- but since some bit patterns -are invalid `bool`s, the inverse is not always sound). +The single byte of a `bool` is guaranteed to be initialized (in other words, `transmute::(...)` is always sound -- but since some bit patterns are invalid `bool`s, the inverse is not always sound). [boolean logic]: https://en.wikipedia.org/wiki/Boolean_algebra [enumerated type]: enum.md diff --git a/src/types/closure.md b/src/types/closure.md index 33fb09e92b..84bc951ab9 100644 --- a/src/types/closure.md +++ b/src/types/closure.md @@ -2,9 +2,7 @@ r[type.closure] # Closure types r[type.closure.intro] -A [closure expression] produces a closure value with a unique, anonymous type that cannot be written out. -A closure type is approximately equivalent to a struct which contains the captured values. -For instance, the following closure: +A [closure expression] produces a closure value with a unique, anonymous type that cannot be written out. A closure type is approximately equivalent to a struct which contains the captured values. For instance, the following closure: ```rust #[derive(Debug)] @@ -61,8 +59,7 @@ r[type.closure.capture] ## Capture modes r[type.closure.capture.intro] -A *capture mode* determines how a [place expression] from the environment is borrowed or moved into the closure. -The capture modes are: +A *capture mode* determines how a [place expression] from the environment is borrowed or moved into the closure. The capture modes are: 1. Immutable borrow (`ImmBorrow`) --- The place expression is captured as a [shared reference]. 2. Unique immutable borrow (`UniqueImmBorrow`) --- This is similar to an immutable borrow, but must be unique as described [below](#unique-immutable-borrows-in-captures). @@ -70,8 +67,7 @@ The capture modes are: 4. Move (`ByValue`) --- The place expression is captured by [moving the value] into the closure. r[type.closure.capture.precedence] -Place expressions from the environment are captured from the first mode that is compatible with how the captured value is used inside the closure body. -The mode is not affected by the code surrounding the closure, such as the lifetimes of involved variables or fields, or of the closure itself. +Place expressions from the environment are captured from the first mode that is compatible with how the captured value is used inside the closure body. The mode is not affected by the code surrounding the closure, such as the lifetimes of involved variables or fields, or of the closure itself. [moving the value]: ../expressions.md#moved-and-copied-types [mutable reference]: pointer.md#mutable-references-mut @@ -123,8 +119,7 @@ let c = || { c(); ``` -Here the capture path is the local variable `s`, followed by a field access `.f1`, and then a tuple index `.1`. -This closure captures an immutable borrow of `s.f1.1`. +Here the capture path is the local variable `s`, followed by a field access `.f1`, and then a tuple index `.1`. This closure captures an immutable borrow of `s.f1.1`. [field access]: ../expressions/field-expr.md [pattern destructuring]: patterns.destructure @@ -163,11 +158,9 @@ r[type.closure.capture.precision.dereference-shared] The capture path is truncated at the rightmost dereference in the capture path if the dereference is applied to a shared reference. -This truncation is allowed because fields that are read through a shared reference will always be read via a shared reference or a copy. -This helps reduce the size of the capture when the extra precision does not yield any benefit from a borrow checking perspective. +This truncation is allowed because fields that are read through a shared reference will always be read via a shared reference or a copy. This helps reduce the size of the capture when the extra precision does not yield any benefit from a borrow checking perspective. -The reason it is the *rightmost* dereference is to help avoid a shorter lifetime than is necessary. -Consider the following example: +The reason it is the *rightmost* dereference is to help avoid a shorter lifetime than is necessary. Consider the following example: ```rust struct Int(i32); @@ -445,8 +438,7 @@ c(); r[type.closure.capture.precision.move-dereference] ### Capturing references in move contexts -Because it is not allowed to move fields out of a reference, `move` closures will only capture the prefix of a capture path that runs up to, but not including, the first dereference of a reference. -The reference itself will be moved into the closure. +Because it is not allowed to move fields out of a reference, `move` closures will only capture the prefix of a capture path that runs up to, but not including, the first dereference of a reference. The reference itself will be moved into the closure. ```rust struct T(String, String); @@ -505,9 +497,7 @@ c(); r[type.closure.capture.precision.unaligned] ### Reference into unaligned `struct`s -Because it is [undefined behavior] to create references to unaligned fields in a structure, -closures will only capture the prefix of the capture path that runs up to, but not including, the first field access into a structure that uses [the `packed` representation]. -This includes all fields, even those that are aligned, to protect against compatibility concerns should any of the fields in the structure change in the future. +Because it is [undefined behavior] to create references to unaligned fields in a structure, closures will only capture the prefix of the capture path that runs up to, but not including, the first field access into a structure that uses [the `packed` representation]. This includes all fields, even those that are aligned, to protect against compatibility concerns should any of the fields in the structure change in the future. ```rust #[repr(packed)] @@ -618,9 +608,7 @@ let c_box = move || { r[type.closure.unique-immutable] ## Unique immutable borrows in captures -Captures can occur by a special kind of borrow called a _unique immutable borrow_, -which cannot be used anywhere else in the language and cannot be written out explicitly. -It occurs when modifying the referent of a mutable reference, as in the following example: +Captures can occur by a special kind of borrow called a _unique immutable borrow_, which cannot be used anywhere else in the language and cannot be written out explicitly. It occurs when modifying the referent of a mutable reference, as in the following example: ```rust let mut b = false; @@ -637,10 +625,7 @@ c(); let z = &x; ``` -In this case, borrowing `x` mutably is not possible, because `x` is not `mut`. -But at the same time, borrowing `x` immutably would make the assignment illegal, -because a `& &mut` reference might not be unique, so it cannot safely be used to modify a value. -So a unique immutable borrow is used: it borrows `x` immutably, but like a mutable borrow, it must be unique. +In this case, borrowing `x` mutably is not possible, because `x` is not `mut`. But at the same time, borrowing `x` immutably would make the assignment illegal, because a `& &mut` reference might not be unique, so it cannot safely be used to modify a value. So a unique immutable borrow is used: it borrows `x` immutably, but like a mutable borrow, it must be unique. In the above example, uncommenting the declaration of `y` will produce an error because it would violate the uniqueness of the closure's borrow of `x`; the declaration of z is valid because the closure's lifetime has expired at the end of the block, releasing the borrow. @@ -648,25 +633,19 @@ r[type.closure.call] ## Call traits and coercions r[type.closure.call.intro] -Closure types all implement [`FnOnce`], indicating that they can be called once -by consuming ownership of the closure. Additionally, some closures implement -more specific call traits: +Closure types all implement [`FnOnce`], indicating that they can be called once by consuming ownership of the closure. Additionally, some closures implement more specific call traits: r[type.closure.call.fn-mut] -* A closure which does not move out of any captured variables implements - [`FnMut`], indicating that it can be called by mutable reference. +* A closure which does not move out of any captured variables implements [`FnMut`], indicating that it can be called by mutable reference. r[type.closure.call.fn] -* A closure which does not mutate or move out of any captured variables - implements [`Fn`], indicating that it can be called by shared reference. +* A closure which does not mutate or move out of any captured variables implements [`Fn`], indicating that it can be called by shared reference. > [!NOTE] > `move` closures may still implement [`Fn`] or [`FnMut`], even though they capture variables by move. This is because the traits implemented by a closure type are determined by what the closure does with captured values, not how it captures them. r[type.closure.non-capturing] -*Non-capturing closures* are closures that don't capture anything from their -environment. Non-async, non-capturing closures can be coerced to function pointers (e.g., `fn()`) -with the matching signature. +*Non-capturing closures* are closures that don't capture anything from their environment. Non-async, non-capturing closures can be coerced to function pointers (e.g., `fn()`) with the matching signature. ```rust let add = |x, y| x + y; @@ -740,8 +719,7 @@ r[type.closure.traits] ### Other traits r[type.closure.traits.intro] -All closure types implement [`Sized`]. Additionally, closure types implement the -following traits if allowed to do so by the types of the captures it stores: +All closure types implement [`Sized`]. Additionally, closure types implement the following traits if allowed to do so by the types of the captures it stores: * [`Clone`] * [`Copy`] @@ -749,19 +727,13 @@ following traits if allowed to do so by the types of the captures it stores: * [`Send`] r[type.closure.traits.behavior] -The rules for [`Send`] and [`Sync`] match those for normal struct types, while -[`Clone`] and [`Copy`] behave as if [derived]. For [`Clone`], the order of -cloning of the captured values is left unspecified. +The rules for [`Send`] and [`Sync`] match those for normal struct types, while [`Clone`] and [`Copy`] behave as if [derived]. For [`Clone`], the order of cloning of the captured values is left unspecified. Because captures are often by reference, the following general rules arise: * A closure is [`Sync`] if all captured values are [`Sync`]. -* A closure is [`Send`] if all values captured by non-unique immutable - reference are [`Sync`], and all values captured by unique immutable or mutable - reference, copy, or move are [`Send`]. -* A closure is [`Clone`] or [`Copy`] if it does not capture any values by - unique immutable or mutable reference, and if all values it captures by copy - or move are [`Clone`] or [`Copy`], respectively. +* A closure is [`Send`] if all values captured by non-unique immutable reference are [`Sync`], and all values captured by unique immutable or mutable reference, copy, or move are [`Send`]. +* A closure is [`Clone`] or [`Copy`] if it does not capture any values by unique immutable or mutable reference, and if all values it captures by copy or move are [`Clone`] or [`Copy`], respectively. [`Clone`]: ../special-types-and-traits.md#clone [`Copy`]: ../special-types-and-traits.md#copy @@ -822,8 +794,7 @@ f(Closure { rect: rect }); r[type.closure.capture.precision.edition2018.composite] ### Capture precision difference -Composite types such as structs, tuples, and enums are always captured in its entirety, -not by individual fields. As a result, it may be necessary to borrow into a local variable in order to capture a single field: +Composite types such as structs, tuples, and enums are always captured in its entirety, not by individual fields. As a result, it may be necessary to borrow into a local variable in order to capture a single field: ```rust # use std::collections::HashSet; diff --git a/src/types/enum.md b/src/types/enum.md index f434cfaebd..8fa2dfd96e 100644 --- a/src/types/enum.md +++ b/src/types/enum.md @@ -2,27 +2,21 @@ r[type.enum] # Enumerated types r[type.enum.intro] -An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted -by the name of an [`enum` item]. [^enumtype] +An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted by the name of an [`enum` item]. [^enumtype] r[type.enum.declaration] -An [`enum` item] declares both the type and a number of *variants*, each of -which is independently named and has the syntax of a struct, tuple struct or -unit-like struct. +An [`enum` item] declares both the type and a number of *variants*, each of which is independently named and has the syntax of a struct, tuple struct or unit-like struct. r[type.enum.constructor] New instances of an `enum` can be constructed with a [struct expression]. r[type.enum.value] -Any `enum` value consumes as much memory as the largest variant for its -corresponding `enum` type, as well as the size needed to store a discriminant. +Any `enum` value consumes as much memory as the largest variant for its corresponding `enum` type, as well as the size needed to store a discriminant. r[type.enum.name] -Enum types cannot be denoted *structurally* as types, but must be denoted by -named reference to an [`enum` item]. +Enum types cannot be denoted *structurally* as types, but must be denoted by named reference to an [`enum` item]. -[^enumtype]: The `enum` type is analogous to a `data` constructor declaration in - Haskell, or a *pick ADT* in Limbo. +[^enumtype]: The `enum` type is analogous to a `data` constructor declaration in Haskell, or a *pick ADT* in Limbo. [`enum` item]: ../items/enumerations.md [struct expression]: ../expressions/struct-expr.md diff --git a/src/types/function-item.md b/src/types/function-item.md index d9732f3e79..ca70d8f090 100644 --- a/src/types/function-item.md +++ b/src/types/function-item.md @@ -2,24 +2,15 @@ r[type.fn-item] # Function item types r[type.fn-item.intro] -When referred to, a function item, or the constructor of a tuple-like struct or -enum variant, yields a zero-sized value of its _function item type_. +When referred to, a function item, or the constructor of a tuple-like struct or enum variant, yields a zero-sized value of its _function item type_. r[type.fn-item.unique] -That type explicitly identifies the function - its name, its type arguments, and its -early-bound lifetime arguments (but not its late-bound lifetime arguments, -which are only assigned when the function is called) - so the value does not -need to contain an actual function pointer, and no indirection is needed when -the function is called. +That type explicitly identifies the function - its name, its type arguments, and its early-bound lifetime arguments (but not its late-bound lifetime arguments, which are only assigned when the function is called) - so the value does not need to contain an actual function pointer, and no indirection is needed when the function is called. r[type.fn-item.name] -There is no syntax that directly refers to a function item type, but the -compiler will display the type as something like `fn(u32) -> i32 {fn_name}` in -error messages. +There is no syntax that directly refers to a function item type, but the compiler will display the type as something like `fn(u32) -> i32 {fn_name}` in error messages. -Because the function item type explicitly identifies the function, the item -types of different functions - different items, or the same item with different -generics - are distinct, and mixing them will create a type error: +Because the function item type explicitly identifies the function, the item types of different functions - different items, or the same item with different generics - are distinct, and mixing them will create a type error: ```rust,compile_fail,E0308 fn foo() { } @@ -28,11 +19,7 @@ let x = &mut foo::; ``` r[type.fn-item.coercion] -However, there is a [coercion] from function items to [function pointers] with -the same signature, which is triggered not only when a function item is used -when a function pointer is directly expected, but also when different function -item types with the same signature meet in different arms of the same `if` or -`match`: +However, there is a [coercion] from function items to [function pointers] with the same signature, which is triggered not only when a function item is used when a function pointer is directly expected, but also when different function item types with the same signature meet in different arms of the same `if` or `match`: ```rust # let want_i32 = false; diff --git a/src/types/function-pointer.md b/src/types/function-pointer.md index e79b945314..08dfbbf235 100644 --- a/src/types/function-pointer.md +++ b/src/types/function-pointer.md @@ -45,8 +45,7 @@ r[type.fn-pointer.coercion] Function pointers can be created via a coercion from both [function items] and non-capturing, non-async [closures]. r[type.fn-pointer.qualifiers] -The `unsafe` qualifier indicates that the type's value is an [unsafe -function], and the `extern` qualifier indicates it is an [extern function]. +The `unsafe` qualifier indicates that the type's value is an [unsafe function], and the `extern` qualifier indicates it is an [extern function]. r[type.fn-pointer.constraint-variadic] For the function to be variadic, its `extern` ABI must be one of those listed in [items.extern.variadic.conventions]. @@ -54,8 +53,7 @@ For the function to be variadic, its `extern` ABI must be one of those listed in r[type.fn-pointer.attributes] ## Attributes on function pointer parameters -Attributes on function pointer parameters follow the same rules and -restrictions as [regular function parameters]. +Attributes on function pointer parameters follow the same rules and restrictions as [regular function parameters]. [`extern`]: ../items/external-blocks.md [closures]: closure.md diff --git a/src/types/impl-trait.md b/src/types/impl-trait.md index 543575ec1d..266d4018ba 100644 --- a/src/types/impl-trait.md +++ b/src/types/impl-trait.md @@ -9,9 +9,7 @@ ImplTraitTypeOneBound -> `impl` TraitBound ``` r[type.impl-trait.intro] -`impl Trait` provides ways to specify unnamed but concrete types that -implement a specific trait. -It can appear in two sorts of places: argument position (where it can act as an anonymous type parameter to functions), and return position (where it can act as an abstract return type). +`impl Trait` provides ways to specify unnamed but concrete types that implement a specific trait. It can appear in two sorts of places: argument position (where it can act as an anonymous type parameter to functions), and return position (where it can act as an abstract return type). ```rust trait Trait {} @@ -32,8 +30,7 @@ r[type.impl-trait.param] > This is often called "impl Trait in argument position". (The term "parameter" is more correct here, but "impl Trait in argument position" is the phrasing used during the development of this feature, and it remains in parts of the implementation.) r[type.impl-trait.param.intro] -Functions can use `impl` followed by a set of trait bounds to declare a parameter as having an anonymous type. -The caller must provide a type that satisfies the bounds declared by the anonymous type parameter, and the function can only use the methods available through the trait bounds of the anonymous type parameter. +Functions can use `impl` followed by a set of trait bounds to declare a parameter as having an anonymous type. The caller must provide a type that satisfies the bounds declared by the anonymous type parameter, and the function can only use the methods available through the trait bounds of the anonymous type parameter. For example, these two forms are almost equivalent: @@ -62,16 +59,12 @@ r[type.impl-trait.return] > This is often called "impl Trait in return position". r[type.impl-trait.return.intro] -Functions can use `impl Trait` to return an abstract return type. -These types stand in for another concrete type where the caller may only use the methods declared by the specified `Trait`. +Functions can use `impl Trait` to return an abstract return type. These types stand in for another concrete type where the caller may only use the methods declared by the specified `Trait`. r[type.impl-trait.return.constraint-body] Each possible return value from the function must resolve to the same concrete type. -`impl Trait` in return position allows a function to return an unboxed abstract type. -This is particularly useful with [closures] and iterators. -For example, closures have a unique, un-writable type. -Previously, the only way to return a closure from a function was to use a [trait object]: +`impl Trait` in return position allows a function to return an unboxed abstract type. This is particularly useful with [closures] and iterators. For example, closures have a unique, un-writable type. Previously, the only way to return a closure from a function was to use a [trait object]: ```rust fn returns_closure() -> Box i32> { @@ -79,10 +72,7 @@ fn returns_closure() -> Box i32> { } ``` -This could incur performance penalties from heap allocation and dynamic dispatch. -It wasn't possible to fully specify the type of the closure, only to use the `Fn` trait. -That means that the trait object is necessary. -However, with `impl Trait`, it is possible to write this more simply: +This could incur performance penalties from heap allocation and dynamic dispatch. It wasn't possible to fully specify the type of the closure, only to use the `Fn` trait. That means that the trait object is necessary. However, with `impl Trait`, it is possible to write this more simply: ```rust fn returns_closure() -> impl Fn(i32) -> i32 { @@ -92,8 +82,7 @@ fn returns_closure() -> impl Fn(i32) -> i32 { which also avoids the drawbacks of using a boxed trait object. -Similarly, the concrete types of iterators could become very complex, incorporating the types of all previous iterators in a chain. -Returning `impl Iterator` means that a function only exposes the `Iterator` trait as a bound on its return type, instead of explicitly specifying all of the other iterator types involved. +Similarly, the concrete types of iterators could become very complex, incorporating the types of all previous iterators in a chain. Returning `impl Iterator` means that a function only exposes the `Iterator` trait as a bound on its return type, instead of explicitly specifying all of the other iterator types involved. r[type.impl-trait.return-in-trait] ## Return-position `impl Trait` in traits and trait implementations @@ -147,9 +136,7 @@ Any `use<..>` bound that is present in an associated function in a trait definit ## Differences between generics and `impl Trait` in return position -In argument position, `impl Trait` is very similar in semantics to a generic type parameter. -However, there are significant differences between the two in return position. -With `impl Trait`, unlike with a generic type parameter, the function chooses the return type, and the caller cannot choose the return type. +In argument position, `impl Trait` is very similar in semantics to a generic type parameter. However, there are significant differences between the two in return position. With `impl Trait`, unlike with a generic type parameter, the function chooses the return type, and the caller cannot choose the return type. The function: @@ -173,14 +160,12 @@ fn foo() -> impl Trait { } ``` -doesn't allow the caller to determine the return type. -Instead, the function chooses the return type, but only promises that it will implement `Trait`. +doesn't allow the caller to determine the return type. Instead, the function chooses the return type, but only promises that it will implement `Trait`. r[type.impl-trait.constraint] ## Limitations -`impl Trait` can only appear as a parameter or return type of a non-`extern` function. -It cannot be the type of a `let` binding, field type, or appear inside a type alias. +`impl Trait` can only appear as a parameter or return type of a non-`extern` function. It cannot be the type of a `let` binding, field type, or appear inside a type alias. [`use<..>` bound]: ../trait-bounds.md#use-bounds [closures]: closure.md diff --git a/src/types/inferred.md b/src/types/inferred.md index f5736b6427..fcbb149e78 100644 --- a/src/types/inferred.md +++ b/src/types/inferred.md @@ -7,8 +7,7 @@ InferredType -> `_` ``` r[type.inferred.intro] -The inferred type asks the compiler to infer the type if possible based on the -surrounding information available. +The inferred type asks the compiler to infer the type if possible based on the surrounding information available. > [!EXAMPLE] > The inferred type is often used in generic arguments: diff --git a/src/types/never.md b/src/types/never.md index 04516182e1..fe30bce74d 100644 --- a/src/types/never.md +++ b/src/types/never.md @@ -7,15 +7,13 @@ NeverType -> `!` ``` r[type.never.intro] -The never type `!` is a type with no values, representing the result of -computations that never complete. +The never type `!` is a type with no values, representing the result of computations that never complete. r[type.never.coercion] Expressions of type `!` can be coerced into any other type. r[type.never.constraint] -The `!` type can **only** appear in function return types presently, -indicating it is a diverging function that never returns. +The `!` type can **only** appear in function return types presently, indicating it is a diverging function that never returns. ```rust fn foo() -> ! { diff --git a/src/types/numeric.md b/src/types/numeric.md index 5b796e4179..ec7309b707 100644 --- a/src/types/numeric.md +++ b/src/types/numeric.md @@ -29,26 +29,19 @@ Type | Minimum | Maximum r[type.numeric.float] ## Floating-point types -The IEEE 754-2008 "binary32" and "binary64" floating-point types are `f32` and -`f64`, respectively. +The IEEE 754-2008 "binary32" and "binary64" floating-point types are `f32` and `f64`, respectively. r[type.numeric.int.size] ## Machine-dependent integer types r[type.numeric.int.size.usize] -The `usize` type is an unsigned integer type with the same number of bits as the -platform's pointer type. It can represent every memory address in the process. +The `usize` type is an unsigned integer type with the same number of bits as the platform's pointer type. It can represent every memory address in the process. > [!NOTE] -> While a `usize` can represent every *address*, converting a *pointer* to a `usize` is not necessarily a reversible operation. -> For more information, see the documentation for [type cast expressions], [`std::ptr`], and [provenance][std::ptr#provenance] in particular. +> While a `usize` can represent every *address*, converting a *pointer* to a `usize` is not necessarily a reversible operation. For more information, see the documentation for [type cast expressions], [`std::ptr`], and [provenance][std::ptr#provenance] in particular. r[type.numeric.int.size.isize] -The `isize` type is a signed two's complement integer type with the same number of bits as the -platform's pointer type. The theoretical upper bound on object and array size -is the maximum `isize` value. This ensures that `isize` can be used to calculate -differences between pointers into an object or array and can address every byte -within an object along with one byte past the end. +The `isize` type is a signed two's complement integer type with the same number of bits as the platform's pointer type. The theoretical upper bound on object and array size is the maximum `isize` value. This ensures that `isize` can be used to calculate differences between pointers into an object or array and can address every byte within an object along with one byte past the end. r[type.numeric.int.size.minimum] `usize` and `isize` are at least 16-bits wide. @@ -59,7 +52,6 @@ r[type.numeric.int.size.minimum] r[type.numeric.validity] ## Bit validity -For every numeric type, `T`, the bit validity of `T` is equivalent to the bit -validity of `[u8; size_of::()]`. An uninitialized byte is not a valid `u8`. +For every numeric type, `T`, the bit validity of `T` is equivalent to the bit validity of `[u8; size_of::()]`. An uninitialized byte is not a valid `u8`. [type cast expressions]: ../expressions/operator-expr.md#type-cast-expressions diff --git a/src/types/parameters.md b/src/types/parameters.md index 1434789151..88932f8694 100644 --- a/src/types/parameters.md +++ b/src/types/parameters.md @@ -1,8 +1,7 @@ r[type.generic] # Type parameters -Within the body of an item that has type parameter declarations, the names of -its type parameters are types: +Within the body of an item that has type parameter declarations, the names of its type parameters are types: ```rust fn to_vec(xs: &[A]) -> Vec { @@ -16,5 +15,4 @@ fn to_vec(xs: &[A]) -> Vec { } ``` -Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and -`rest` has type `Vec`, a vector with element type `A`. +Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and `rest` has type `Vec`, a vector with element type `A`. diff --git a/src/types/pointer.md b/src/types/pointer.md index c33be4ee76..91a94c1e95 100644 --- a/src/types/pointer.md +++ b/src/types/pointer.md @@ -2,8 +2,7 @@ r[type.pointer] # Pointer types r[type.pointer.intro] -All pointers are explicit first-class values. -They can be moved or copied, stored into data structs, and returned from functions. +All pointers are explicit first-class values. They can be moved or copied, stored into data structs, and returned from functions. r[type.pointer.reference] ## References (`&` and `&mut`) @@ -20,22 +19,16 @@ r[type.pointer.reference.shared.intro] Shared references point to memory which is owned by some other value. r[type.pointer.reference.shared.constraint-mutation] -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. +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. r[type.pointer.reference.shared.copy] -Copying a reference is a "shallow" operation: -it involves only copying the pointer itself, that is, pointers are `Copy`. -Releasing a reference has no effect on the value it points to, but referencing of a [temporary value] will keep it alive during the scope of the reference itself. +Copying a reference is a "shallow" operation: it involves only copying the pointer itself, that is, pointers are `Copy`. Releasing a reference has no effect on the value it points to, but referencing of a [temporary value] will keep it alive during the scope of the reference itself. r[type.pointer.reference.mut] ### Mutable references (`&mut`) r[type.pointer.reference.mut.intro] -Mutable references point to memory which is owned by some other value. -A mutable reference type is written `&mut type` or `&'a mut type`. +Mutable references point to memory which is owned by some other value. A mutable reference type is written `&mut type` or `&'a mut type`. r[type.pointer.reference.mut.copy] A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`. @@ -49,9 +42,7 @@ RawPointerType -> `*` ( `mut` | `const` ) TypeNoBounds ``` r[type.pointer.raw.intro] -Raw pointers are pointers without safety or liveness guarantees. -Raw pointers are written as `*const T` or `*mut T`. -For example `*const i32` means a raw pointer to a 32-bit integer. +Raw pointers are pointers without safety or liveness guarantees. Raw pointers are written as `*const T` or `*mut T`. For example `*const i32` means a raw pointer to a 32-bit integer. r[type.pointer.raw.copy] Copying or dropping a raw pointer has no effect on the lifecycle of any other value. @@ -59,13 +50,10 @@ Copying or dropping a raw pointer has no effect on the lifecycle of any other va r[type.pointer.raw.safety] Dereferencing a raw pointer is an [`unsafe` operation]. -This can also be used to convert a raw pointer to a reference by reborrowing it (`&*` or `&mut *`). -Raw pointers are generally discouraged; -they exist to support interoperability with foreign code, and writing performance-critical or low-level functions. +This can also be used to convert a raw pointer to a reference by reborrowing it (`&*` or `&mut *`). Raw pointers are generally discouraged; they exist to support interoperability with foreign code, and writing performance-critical or low-level functions. r[type.pointer.raw.cmp] -When comparing raw pointers they are compared by their address, rather than by what they point to. -When comparing raw pointers to [dynamically sized types] they also have their additional data compared. +When comparing raw pointers they are compared by their address, rather than by what they point to. When comparing raw pointers to [dynamically sized types] they also have their additional data compared. r[type.pointer.raw.constructor] Raw pointers can be created directly using `&raw const` for `*const` pointers and `&raw mut` for `*mut` pointers. @@ -79,14 +67,10 @@ r[type.pointer.validity] ## Bit validity r[type.pointer.validity.pointer-fragment] -Despite pointers and references being similar to `usize`s in the machine code emitted on most platforms, -the semantics of transmuting a reference or pointer type to a non-pointer type is currently undecided. -Thus, it may not be valid to transmute a pointer or reference type, `P`, to a `[u8; size_of::

()]`. +Despite pointers and references being similar to `usize`s in the machine code emitted on most platforms, the semantics of transmuting a reference or pointer type to a non-pointer type is currently undecided. Thus, it may not be valid to transmute a pointer or reference type, `P`, to a `[u8; size_of::

()]`. r[type.pointer.validity.raw] -For thin raw pointers (i.e., for `P = *const T` or `P = *mut T` for `T: Sized`), -the inverse direction (transmuting from an integer or array of integers to `P`) is always valid. -However, the pointer produced via such a transmutation may not be dereferenced (not even if `T` has size zero). +For thin raw pointers (i.e., for `P = *const T` or `P = *mut T` for `T: Sized`), the inverse direction (transmuting from an integer or array of integers to `P`) is always valid. However, the pointer produced via such a transmutation may not be dereferenced (not even if `T` has size zero). [Interior mutability]: ../interior-mutability.md [`unsafe` operation]: ../unsafety.md diff --git a/src/types/slice.md b/src/types/slice.md index c76700258d..e8be3a9f1e 100644 --- a/src/types/slice.md +++ b/src/types/slice.md @@ -7,14 +7,12 @@ SliceType -> `[` Type `]` ``` r[type.slice.intro] -A slice is a [dynamically sized type] representing a 'view' into a sequence of -elements of type `T`. The slice type is written as `[T]`. +A slice is a [dynamically sized type] representing a 'view' into a sequence of elements of type `T`. The slice type is written as `[T]`. r[type.slice.unsized] Slice types are generally used through pointer types. For example: -* `&[T]`: a 'shared slice', often just called a 'slice'. It doesn't own the - data it points to; it borrows it. +* `&[T]`: a 'shared slice', often just called a 'slice'. It doesn't own the data it points to; it borrows it. * `&mut [T]`: a 'mutable slice'. It mutably borrows the data it points to. * `Box<[T]>`: a 'boxed slice' @@ -29,7 +27,6 @@ let slice: &[i32] = &boxed_array[..]; ``` r[type.slice.safe] -All elements of slices are always initialized, and access to a slice is always -bounds-checked in safe methods and operators. +All elements of slices are always initialized, and access to a slice is always bounds-checked in safe methods and operators. [dynamically sized type]: ../dynamically-sized-types.md diff --git a/src/types/struct.md b/src/types/struct.md index eda170e3e5..3e0cf383eb 100644 --- a/src/types/struct.md +++ b/src/types/struct.md @@ -2,34 +2,24 @@ r[type.struct] # Struct types r[type.struct.intro] -A `struct` *type* is a heterogeneous product of other types, called the -*fields* of the type.[^structtype] +A `struct` *type* is a heterogeneous product of other types, called the *fields* of the type.[^structtype] r[type.struct.constructor] New instances of a `struct` can be constructed with a [struct expression]. r[type.struct.layout] -The memory layout of a `struct` is undefined by default to allow for compiler -optimizations like field reordering, but it can be fixed with the -[`repr` attribute]. In either case, fields may be given in any order in a -corresponding struct *expression*; the resulting `struct` value will always -have the same memory layout. +The memory layout of a `struct` is undefined by default to allow for compiler optimizations like field reordering, but it can be fixed with the [`repr` attribute]. In either case, fields may be given in any order in a corresponding struct *expression*; the resulting `struct` value will always have the same memory layout. r[type.struct.field-visibility] -The fields of a `struct` may be qualified by [visibility modifiers], to allow -access to data in a struct outside a module. +The fields of a `struct` may be qualified by [visibility modifiers], to allow access to data in a struct outside a module. r[type.struct.tuple] -A _tuple struct_ type is just like a struct type, except that the fields are -anonymous. +A _tuple struct_ type is just like a struct type, except that the fields are anonymous. r[type.struct.unit] -A _unit-like struct_ type is like a struct type, except that it has no fields. -The one value constructed by the associated [struct expression] is the only -value that inhabits such a type. +A _unit-like struct_ type is like a struct type, except that it has no fields. The one value constructed by the associated [struct expression] is the only value that inhabits such a type. -[^structtype]: `struct` types are analogous to `struct` types in C, the - *record* types of the ML family, or the *struct* types of the Lisp family. +[^structtype]: `struct` types are analogous to `struct` types in C, the *record* types of the ML family, or the *struct* types of the Lisp family. [`repr` attribute]: ../type-layout.md#representations [struct expression]: ../expressions/struct-expr.md diff --git a/src/types/textual.md b/src/types/textual.md index 32722e7203..05068309a7 100644 --- a/src/types/textual.md +++ b/src/types/textual.md @@ -5,26 +5,16 @@ r[type.text.intro] The types `char` and `str` hold textual data. r[type.text.char-value] -A value of type `char` is a [Unicode scalar value] (i.e. a code point that is -not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to 0xD7FF -or 0xE000 to 0x10FFFF range. +A value of type `char` is a [Unicode scalar value] (i.e. a code point that is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to 0xD7FF or 0xE000 to 0x10FFFF range. r[type.text.char-precondition] -It is immediate [undefined behavior] to create a -`char` that falls outside this range. A `[char]` is effectively a UCS-4 / UTF-32 -string of length 1. +It is immediate [undefined behavior] to create a `char` that falls outside this range. A `[char]` is effectively a UCS-4 / UTF-32 string of length 1. r[type.text.str-value] -A value of type `str` is represented the same way as `[u8]`, a slice of -8-bit unsigned bytes. However, the Rust standard library makes extra assumptions -about `str`: methods working on `str` assume and ensure that the data in there -is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause -[undefined behavior] now or in the future. +A value of type `str` is represented the same way as `[u8]`, a slice of 8-bit unsigned bytes. However, the Rust standard library makes extra assumptions about `str`: methods working on `str` assume and ensure that the data in there is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause [undefined behavior] now or in the future. r[type.text.str-unsized] -Since `str` is a [dynamically sized type], it can only be instantiated through a -pointer type, such as `&str`. The layout of `&str` is the same as the layout of -`&[u8]`. +Since `str` is a [dynamically sized type], it can only be instantiated through a pointer type, such as `&str`. The layout of `&str` is the same as the layout of `&[u8]`. r[type.text.layout] ## Layout and bit validity @@ -33,9 +23,7 @@ r[type.layout.char-layout] `char` is guaranteed to have the same size and alignment as `u32` on all platforms. r[type.layout.char-validity] -Every byte of a `char` is guaranteed to be initialized (in other words, -`transmute::()]>(...)` is always sound -- but since -some bit patterns are invalid `char`s, the inverse is not always sound). +Every byte of a `char` is guaranteed to be initialized (in other words, `transmute::()]>(...)` is always sound -- but since some bit patterns are invalid `char`s, the inverse is not always sound). [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value [undefined behavior]: ../behavior-considered-undefined.md diff --git a/src/types/trait-object.md b/src/types/trait-object.md index 1c1eefd665..c0eb98b831 100644 --- a/src/types/trait-object.md +++ b/src/types/trait-object.md @@ -9,22 +9,16 @@ TraitObjectTypeOneBound -> `dyn`? TraitBound ``` r[type.trait-object.intro] -A *trait object* is an opaque value of another type that implements a set of -traits. The set of traits is made up of a [dyn compatible] *base trait* plus any -number of [auto traits]. +A *trait object* is an opaque value of another type that implements a set of traits. The set of traits is made up of a [dyn compatible] *base trait* plus any number of [auto traits]. r[type.trait-object.impls] -Trait objects implement the base trait, its auto traits, and any [supertraits] -of the base trait. +Trait objects implement the base trait, its auto traits, and any [supertraits] of the base trait. r[type.trait-object.name] -Trait objects are written as the keyword `dyn` followed by a set of trait -bounds, but with the following restrictions on the trait bounds. +Trait objects are written as the keyword `dyn` followed by a set of trait bounds, but with the following restrictions on the trait bounds. r[type.trait-object.constraint] -There may not be more than one non-auto trait, no more than one -lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore, -paths to traits may be parenthesized. +There may not be more than one non-auto trait, no more than one lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore, paths to traits may be parenthesized. For example, given a trait `Trait`, the following are all trait objects: @@ -48,28 +42,15 @@ r[type.trait-object.syntax-edition2018] > Beginning in the 2018 edition, `dyn` is a true keyword and is not allowed in paths, so the parentheses are not necessary. r[type.trait-object.alias] -Two trait object types alias each other if the base traits alias each other and -if the sets of auto traits are the same and the lifetime bounds are the same. -For example, `dyn Trait + Send + UnwindSafe` is the same as -`dyn Trait + UnwindSafe + Send`. +Two trait object types alias each other if the base traits alias each other and if the sets of auto traits are the same and the lifetime bounds are the same. For example, `dyn Trait + Send + UnwindSafe` is the same as `dyn Trait + UnwindSafe + Send`. r[type.trait-object.unsized] -Due to the opaqueness of which concrete type the value is of, trait objects are -[dynamically sized types]. Like all -DSTs, trait objects are used -behind some type of pointer; for example `&dyn SomeTrait` or -`Box`. Each instance of a pointer to a trait object includes: +Due to the opaqueness of which concrete type the value is of, trait objects are [dynamically sized types]. Like all DSTs, trait objects are used behind some type of pointer; for example `&dyn SomeTrait` or `Box`. Each instance of a pointer to a trait object includes: - a pointer to an instance of a type `T` that implements `SomeTrait` - - a _virtual method table_, often just called a _vtable_, which contains, for - each method of `SomeTrait` and its [supertraits] that `T` implements, a - pointer to `T`'s implementation (i.e. a function pointer). + - a _virtual method table_, often just called a _vtable_, which contains, for each method of `SomeTrait` and its [supertraits] that `T` implements, a pointer to `T`'s implementation (i.e. a function pointer). -The purpose of trait objects is to permit "late binding" of methods. Calling a -method on a trait object results in virtual dispatch at runtime: that is, a -function pointer is loaded from the trait object vtable and invoked indirectly. -The actual implementation for each vtable entry can vary on an object-by-object -basis. +The purpose of trait objects is to permit "late binding" of methods. Calling a method on a trait object results in virtual dispatch at runtime: that is, a function pointer is loaded from the trait object vtable and invoked indirectly. The actual implementation for each vtable entry can vary on an object-by-object basis. An example of a trait object: @@ -91,16 +72,12 @@ fn main() { } ``` -In this example, the trait `Printable` occurs as a trait object in both the -type signature of `print`, and the cast expression in `main`. +In this example, the trait `Printable` occurs as a trait object in both the type signature of `print`, and the cast expression in `main`. r[type.trait-object.lifetime-bounds] ## Trait object lifetime bounds -Since a trait object can contain references, the lifetimes of those references -need to be expressed as part of the trait object. This lifetime is written as -`Trait + 'a`. There are [defaults] that allow this lifetime to usually be -inferred with a sensible choice. +Since a trait object can contain references, the lifetimes of those references need to be expressed as part of the trait object. This lifetime is written as `Trait + 'a`. There are [defaults] that allow this lifetime to usually be inferred with a sensible choice. [auto traits]: ../special-types-and-traits.md#auto-traits [defaults]: ../lifetime-elision.md#default-trait-object-lifetimes diff --git a/src/types/tuple.md b/src/types/tuple.md index a686cfb8fc..9a190eafc8 100644 --- a/src/types/tuple.md +++ b/src/types/tuple.md @@ -17,21 +17,13 @@ r[type.tuple.restriction] 1-ary tuples require a comma after their element type to be disambiguated with a [parenthesized type]. r[type.tuple.field-number] -A tuple type has a number of fields equal to the length of the list of types. -This number of fields determines the *arity* of the tuple. -A tuple with `n` fields is called an *n-ary tuple*. -For example, a tuple with 2 fields is a 2-ary tuple. +A tuple type has a number of fields equal to the length of the list of types. This number of fields determines the *arity* of the tuple. A tuple with `n` fields is called an *n-ary tuple*. For example, a tuple with 2 fields is a 2-ary tuple. r[type.tuple.field-name] -Fields of tuples are named using increasing numeric names matching their position in the list of types. -The first field is `0`. -The second field is `1`. -And so on. -The type of each field is the type of the same position in the tuple's list of types. +Fields of tuples are named using increasing numeric names matching their position in the list of types. The first field is `0`. The second field is `1`. And so on. The type of each field is the type of the same position in the tuple's list of types. r[type.tuple.unit] -For convenience and historical reasons, the tuple type with no fields (`()`) is often called *unit* or *the unit type*. -Its one value is also called *unit* or *the unit value*. +For convenience and historical reasons, the tuple type with no fields (`()`) is often called *unit* or *the unit type*. Its one value is also called *unit* or *the unit value*. Some examples of tuple types: @@ -43,14 +35,12 @@ Some examples of tuple types: * `(i32, f64, Vec, Option)` r[type.tuple.constructor] -Values of this type are constructed using a [tuple expression]. -Furthermore, various expressions will produce the unit value if there is no other meaningful value for it to evaluate to. +Values of this type are constructed using a [tuple expression]. Furthermore, various expressions will produce the unit value if there is no other meaningful value for it to evaluate to. r[type.tuple.access] Tuple fields can be accessed by either a [tuple index expression] or [pattern matching]. -[^1]: Structural types are always equivalent if their internal types are equivalent. - For a nominal version of tuples, see [tuple structs]. +[^1]: Structural types are always equivalent if their internal types are equivalent. For a nominal version of tuples, see [tuple structs]. [parenthesized type]: ../types.md#parenthesized-types [pattern matching]: ../patterns.md#tuple-patterns diff --git a/src/types/union.md b/src/types/union.md index 6c3dbfcaf7..3ba187d5ad 100644 --- a/src/types/union.md +++ b/src/types/union.md @@ -2,26 +2,19 @@ r[type.union] # Union types r[type.union.intro] -A *union type* is a nominal, heterogeneous C-like union, denoted by the name of -a [`union` item][item]. +A *union type* is a nominal, heterogeneous C-like union, denoted by the name of a [`union` item][item]. r[type.union.access] -Unions have no notion of an "active field". Instead, every union access -transmutes parts of the content of the union to the type of the accessed field. +Unions have no notion of an "active field". Instead, every union access transmutes parts of the content of the union to the type of the accessed field. r[type.union.safety] -Since transmutes can cause unexpected or undefined behaviour, `unsafe` is -required to read from a union field. +Since transmutes can cause unexpected or undefined behaviour, `unsafe` is required to read from a union field. r[type.union.constraint] -Union field types are also restricted to a -subset of types which ensures that they never need dropping. See the [item] -documentation for further details. +Union field types are also restricted to a subset of types which ensures that they never need dropping. See the [item] documentation for further details. r[type.union.layout] -The memory layout of a `union` is undefined by default (in particular, fields do -*not* have to be at offset 0), but the `#[repr(...)]` attribute can be used to -fix a layout. +The memory layout of a `union` is undefined by default (in particular, fields do *not* have to be at offset 0), but the `#[repr(...)]` attribute can be used to fix a layout. [`Copy`]: ../special-types-and-traits.md#copy [item]: ../items/unions.md