From b615c2b9b65676f5a4c92f2500deef3ee9f8f808 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Fri, 4 Jun 2021 20:13:08 +0200 Subject: [PATCH 001/315] Clarify "string continue" for (byte) string literals The previous version just said "whitespace at the beginning of the next line is ignored", but that is not quite correct. Currently, exactly four characters are ignored in that position. This is different from the definition of `char::is_whitespace` and `char::is_ascii_whitespace`. Additionally "at the beginning of the next line" is confusing as additional \n are also ignored. https://github.com/rust-lang/rust/blob/595088d602049d821bf9a217f2d79aea40715208/compiler/rustc_lexer/src/unescape.rs#L281-L287 https://github.com/rust-lang/rust/blob/595088d602049d821bf9a217f2d79aea40715208/compiler/rustc_lexer/src/unescape.rs#L300-L307 --- src/tokens.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 15d8468a0..8f2063656 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -153,16 +153,21 @@ which must be _escaped_ by a preceding `U+005C` character (`\`). Line-breaks are allowed in string literals. A line-break is either a newline (`U+000A`) or a pair of carriage return and newline (`U+000D`, `U+000A`). Both byte sequences are normally translated to `U+000A`, but as a special exception, -when an unescaped `U+005C` character (`\`) occurs immediately before the -line-break, then the `U+005C` character, the line-break, and all whitespace at the -beginning of the next line are ignored. Thus `a` and `b` are equal: +when an unescaped `U+005C` character (`\`) occurs immediately before a line +break, then the line break character(s), and all immediately following +` ` (`U+0020`), `\t` (`U+0009`), `\n` (`U+000A`) and `\r` (`U+0000D`) characters +are ignored. Thus `a`, `b` and `c` are equal: ```rust let a = "foobar"; let b = "foo\ bar"; +let c = "foo\ -assert_eq!(a,b); + bar"; + +assert_eq!(a, b); +assert_eq!(b, c); ``` #### Character escapes From 5a8a664e423165e5eeae7b33bd259dab8f27f949 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 31 Jan 2022 14:05:27 +0100 Subject: [PATCH 002/315] Specify guarantees for repr(rust) structs --- src/type-layout.md | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index 22b5752bb..9b23b9e68 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -86,9 +86,10 @@ String slices are a UTF-8 representation of characters that have the same layout ## Tuple Layout -Tuples do not have any guarantees about their layout. +Tuples have the same layout guarantees a struct with the same fields laid out +according to the default struct representation. -The exception to this is the unit tuple (`()`) which is guaranteed as a +The exception to this is the unit tuple (`()`), which is guaranteed as a zero-sized type to have a size of 0 and an alignment of 1. ## Trait Object Layout @@ -162,7 +163,24 @@ representation will not change the layout of `Inner`. Nominal types without a `repr` attribute have the default representation. Informally, this representation is also called the `rust` representation. -There are no guarantees of data layout made by this representation. +There are very few data layout guarantees made by this representation. The only +guarantees are: + + 1. The fields of the struct are properly aligned. + 2. The fields do not overlap. + 3. The alignment of the struct is not less than the alignment of any of its + fields. + +Formally, the first guarantee means that the offset of any field in the struct +is divisible by that field's alignment. The second guarantee means that the +fields can be ordered such that the offset plus the size of any field is less +than or equal to the offset of the next field in the ordering. The ordering does +not have to be the same as the order in which the field are specified in the +declaration of the 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. ### The `C` Representation From e9a1ddf72d41083433ffd3e8f71902cebf1c1775 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sun, 6 Feb 2022 16:13:00 +0100 Subject: [PATCH 003/315] Address review --- src/type-layout.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index 9b23b9e68..915e9cbea 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -86,8 +86,8 @@ String slices are a UTF-8 representation of characters that have the same layout ## Tuple Layout -Tuples have the same layout guarantees a struct with the same fields laid out -according to the default struct representation. +Tuples have the same layout guarantees as a struct with the same fields when +laid out according to the default struct representation. 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. @@ -163,12 +163,12 @@ representation will not change the layout of `Inner`. Nominal types without a `repr` attribute have the default representation. Informally, this representation is also called the `rust` representation. -There are very few data layout guarantees made by this representation. The only -guarantees are: +The only data layout guarantees made by this representation are those required +for soundness. They are: 1. The fields of the struct are properly aligned. 2. The fields do not overlap. - 3. The alignment of the struct is not less than the alignment of any of its + 3. The minimum alignment of the struct is at least the maximum alignment of its fields. Formally, the first guarantee means that the offset of any field in the struct @@ -182,6 +182,8 @@ Be aware that the second guarantee does not imply that the fields have distinct addresses: zero-sized types may have the same address as other fields in the same struct. +There are no other guarantees of data layout made by this representation. + ### The `C` Representation The `C` representation is designed for dual purposes. One purpose is for From 377c524cf9d9a659eaa6d4c6ee2ee4d509f85118 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Tue, 22 Mar 2022 18:58:39 +0100 Subject: [PATCH 004/315] Fix typo Co-authored-by: Josh Triplett --- src/type-layout.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type-layout.md b/src/type-layout.md index 915e9cbea..c63371ff7 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -175,7 +175,7 @@ Formally, the first guarantee means that the offset of any field in the struct is divisible by that field's alignment. The second guarantee means that the fields can be ordered such that the offset plus the size of any field is less than or equal to the offset of the next field in the ordering. The ordering does -not have to be the same as the order in which the field are specified in the +not have to be the same as the order in which the fields are specified in the declaration of the struct. Be aware that the second guarantee does not imply that the fields have distinct From e72976a22b6e7e074a357a3a7a704bba6c5ec4e6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 26 Mar 2022 10:08:52 -0400 Subject: [PATCH 005/315] clarify that references size_of_val can never exceed isize::MAX --- src/behavior-considered-undefined.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index c4a998097..e5a0554ea 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -78,11 +78,12 @@ reading uninitialized memory is permitted are inside `union`s and in "padding" A reference/pointer is "dangling" if it is null or not all of the bytes it points to are part of the same allocation (so in particular they all have to be part of *some* allocation). The span of bytes it points to is determined by the -pointer value and the size of the pointee type (using `size_of_val`). As a -consequence, if the span is empty, "dangling" is the same as "non-null". Note -that slices and strings point to their entire range, so it is important that the length -metadata is never too large. In particular, allocations and therefore slices and strings -cannot be bigger than `isize::MAX` bytes. +pointer value and the size of the pointee type (using `size_of_val`). + +Note that dynamically sized types (such as slices and strings) point to their +entire range, so it is important that the length metadata is never too large. In +particular, the dynamic size of a Rust value (as determined by `size_of_val`) +must never exceed `isize::MAX`. [`bool`]: types/boolean.md [`const`]: items/constant-items.md From 5316050cc3783b3215ea71038dbb1d03cd63b9e5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 15 Feb 2022 21:50:35 -0500 Subject: [PATCH 006/315] Document target_has_atomic --- src/conditional-compilation.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 6966cec4f..a9a63daec 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -191,6 +191,28 @@ Example values: * `"pc"` * `"unknown"` +### `target_has_atomic` + +Key-value option set for each bit width that the target supports +atomic loads, stores, and compare-and-swap operations. + +When this cfg is present, all of the [`core::sync::atomic`] APIs are available for +the relevant atomic width with the exception of `from_mut` methods (currently +unstable), which additionally require that the primitive integer and atomic have +the same minimum alignment on the given target. No user-visible, stable cfg is +exposed for that method at this time. + +[`core::sync::atomic`]: https://doc.rust-lang.org/nightly/core/sync/atomic/index.html + +Possible values: + +* `"8"` +* `"16"` +* `"32"` +* `"64"` +* `"128"` +* `"ptr"` + ### `test` Enabled when compiling the test harness. Done with `rustc` by using the From 1ae3accbc7038fba2677a9b8cb95c85cf9ae9e58 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 20 Apr 2022 17:16:30 -0700 Subject: [PATCH 007/315] Use relative link for core::sync::atomic --- src/conditional-compilation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index a9a63daec..3f6173e67 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -202,7 +202,7 @@ unstable), which additionally require that the primitive integer and atomic have the same minimum alignment on the given target. No user-visible, stable cfg is exposed for that method at this time. -[`core::sync::atomic`]: https://doc.rust-lang.org/nightly/core/sync/atomic/index.html +[`core::sync::atomic`]: ../core/sync/atomic/index.html Possible values: From 1c78b7416d7fa40d740ec80333bd6f4743d000a4 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 8 May 2022 21:57:31 +0300 Subject: [PATCH 008/315] Document native library modifier `bundle` --- src/items/external-blocks.md | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 84f8046f2..dbe30ccc4 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -162,6 +162,29 @@ 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. +#### Linking modifiers: `bundle` + +This modifier is only compatible with the `static` linking kind. +Using any other kind will result in a compiler error. + +When building a rlib or staticlib `+bundle` means that all object files from the native static +library will be added to the rlib or staticlib archive, and then used from it 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. + +This modifier has no effect when building other targets like executables or dynamic libraries. + +The default for this modifier is `+bundle`. + +More implementation details about this modifier can be found in +[`bundle` documentation for rustc]. + #### Linking modifiers: `whole-archive` This modifier is only compatible with the `static` linking kind. @@ -170,7 +193,10 @@ Using any other kind will result in a compiler error. `+whole-archive` means that the static library is linked as a whole archive without throwing any object files away. -More implementation details about this modifier can be found in [documentation for rustc]. +The default for this modifier is `-whole-archive`. + +More implementation details about this modifier can be found in +[`whole-archive` documentation for rustc]. ### The `link_name` attribute @@ -205,4 +231,5 @@ restrictions as [regular function parameters]. [_Visibility_]: ../visibility-and-privacy.md [attributes]: ../attributes.md [regular function parameters]: functions.md#attributes-on-function-parameters -[documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive +[`bundle` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-bundle +[`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive From f758647f8ece7b93b841b4f3d89138d280a2835c Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 9 May 2022 12:24:33 +0100 Subject: [PATCH 009/315] Add a not to the turbofish section about impl Trait Signed-off-by: Nick Cameron --- src/paths.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/paths.md b/src/paths.md index 51bd8cad5..cb6b24aa0 100644 --- a/src/paths.md +++ b/src/paths.md @@ -81,6 +81,9 @@ arguments, then const arguments, then equality constraints. Const arguments must be surrounded by braces unless they are a [literal] or a single segment path. +The synthetic type parameters corresponding to `impl Trait` types are implicit, +and these cannot be explicitly specified. + ## Qualified paths > **Syntax**\ From f9ec1d2b90e80d7e7ae2f078a8888f29c7b7582e Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 9 May 2022 17:05:34 +0200 Subject: [PATCH 010/315] Be less struct-centric --- src/type-layout.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index c63371ff7..b2e80b599 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -166,17 +166,17 @@ Informally, this representation is also called the `rust` representation. The only data layout guarantees made by this representation are those required for soundness. They are: - 1. The fields of the struct are properly aligned. + 1. The fields are properly aligned. 2. The fields do not overlap. - 3. The minimum alignment of the struct is at least the maximum alignment of its + 3. The minimum alignment of the type is at least the maximum alignment of its fields. -Formally, the first guarantee means that the offset of any field in the struct -is divisible by that field's alignment. The second guarantee means that the -fields can be ordered such that the offset plus the size of any field is less -than or equal to the offset of the next field in the ordering. The ordering does -not have to be the same as the order in which the fields are specified in the -declaration of the struct. +Formally, the first guarantee means that the offset of any field is divisible by +that field's alignment. The second guarantee means that the fields can be +ordered such that the offset plus the size of any field is less than or equal to +the offset of the next field in the ordering. The ordering does not have to be +the same as the order in which the fields are specified in the declaration of +the type. Be aware that the second guarantee does not imply that the fields have distinct addresses: zero-sized types may have the same address as other fields in the From 1275bcc033be63bd4175d989b4a147a90b2a277a Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 9 May 2022 17:11:10 +0200 Subject: [PATCH 011/315] Rephrase layout of tuples --- src/type-layout.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index b2e80b599..c236addca 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -86,8 +86,7 @@ String slices are a UTF-8 representation of characters that have the same layout ## Tuple Layout -Tuples have the same layout guarantees as a struct with the same fields when -laid out according to the default struct representation. +Tuples are laid out according to the default representation. 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. From 3ecc681250d82aa401e1cc0049360af80769c6ad Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 9 May 2022 17:13:17 +0200 Subject: [PATCH 012/315] Remove stray 'minimum' --- src/type-layout.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index c236addca..467ad65d2 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -167,8 +167,7 @@ for soundness. They are: 1. The fields are properly aligned. 2. The fields do not overlap. - 3. The minimum alignment of the type is at least the maximum alignment of its - fields. + 3. The alignment of the type is at least the maximum alignment of its fields. Formally, the first guarantee means that the offset of any field is divisible by that field's alignment. The second guarantee means that the fields can be From db4124306287420c2b9d80a9687c86e2057be716 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 3 Jun 2022 16:49:45 +0200 Subject: [PATCH 013/315] modify variance section --- src/subtyping.md | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/subtyping.md b/src/subtyping.md index 15b0b206a..40f5a1544 100644 --- a/src/subtyping.md +++ b/src/subtyping.md @@ -61,25 +61,51 @@ Variance of types is automatically determined as follows | `[T]` and `[T; n]` | | covariant | | `fn() -> T` | | covariant | | `fn(T) -> ()` | | contravariant | -| `fn(T) -> T` | | invariant | | `std::cell::UnsafeCell` | | invariant | | `std::marker::PhantomData` | | covariant | | `dyn Trait + 'a` | covariant | invariant | -The variance of other `struct`, `enum`, `union`, and tuple types is decided by +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` +example the following struct is covariant in `'a` and `T` and invariant in `'b`, `'c`, and `U`. ```rust use std::cell::UnsafeCell; -struct Variance<'a, 'b, T, U: 'a> { +struct Variance<'a, 'b, 'c, T, U: 'a> { x: &'a U, // This makes `Variance` covariant in 'a, and would // make it covariant in U, but U is used later y: *const T, // Covariant in T z: UnsafeCell<&'b f64>, // Invariant in 'b w: *mut U, // Invariant in U, makes the whole struct invariant + + f: fn(&'c ()) -> &'c () // Both co- and contravariant, makes 'c invariant + // in the struct. +} +``` + +When used outside of an `struct`, `enum`, or `union`, the variance for parameters is checked at each location separately. + +```rust +# use std::cell::UnsafeCell; +fn generic_tuple<'short, 'long: 'short>( + // 'long is used inside of a tuple in both a co- and invariant position. + x: (&'long u32, UnsafeCell<&'long u32>), +) { + // As the variance at these positions is computed separately, + // we can freely shrink 'long in the covariant position. + let _: (&'short u32, UnsafeCell<&'long u32>) = x; +} + +fn takes_fn_ptr<'short, 'middle: 'short>( + // 'middle is used in both a co- and contravariant position. + f: fn(&'middle ()) -> &'middle (), +) { + // As the variance at these positions is computed separately, + // we can freely shrink 'middle in the covariant position + // and extend it in the contravariant position. + let _: fn(&'static ()) -> &'short () = f; } ``` From 77ab06c34e50e9cce04acf979a4402fa01ef48e9 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 4 Jun 2021 05:07:50 -0700 Subject: [PATCH 014/315] Add "scopes" chapter. --- src/expressions/block-expr.md | 2 + src/items.md | 18 +- src/items/generics.md | 3 + src/names.md | 2 +- src/names/scopes.md | 323 +++++++++++++++++++++++++++++++++- src/patterns.md | 3 +- src/statements.md | 3 +- src/trait-bounds.md | 3 +- 8 files changed, 343 insertions(+), 14 deletions(-) diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index a68b27e56..e3ab49663 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -15,6 +15,7 @@ A *block expression*, or *block*, is a control flow expression and anonymous namespace scope for items and variable declarations. As a control flow expression, a block sequentially executes its component non-item declaration statements and then its final optional expression. 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. 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 `}`. @@ -181,6 +182,7 @@ fn is_unix_platform() -> bool { [inner attributes]: ../attributes.md [method]: ../items/associated-items.md#methods [mutable reference]: ../types/pointer.md#mutables-references- +[scopes]: ../names/scopes.md [shared references]: ../types/pointer.md#shared-references- [statement]: ../statements.md [statements]: ../statements.md diff --git a/src/items.md b/src/items.md index addbe0efd..9bc07a62c 100644 --- a/src/items.md +++ b/src/items.md @@ -53,15 +53,10 @@ There are several kinds of items: * [implementations] * [`extern` blocks] -Some items form an implicit scope for the declaration of sub-items. In other -words, within a function or module, declarations of items can (in many cases) -be mixed with the statements, control blocks, and similar artifacts that -otherwise compose the item body. The meaning of these scoped items is the same -as if the item was declared outside the scope — it is still a static item -— except that the item's *path name* within the module namespace is -qualified by the name of the enclosing item, or is private to the enclosing -item (in the case of functions). The grammar specifies the exact locations in -which sub-item declarations may appear. +Items may be declared in the [root of the crate], a [module][modules], or a [statement]. +Additionally, a subset of items, called [associated items], may be declared in [traits] and [implementations]. + +See [item scopes] for information on the scoping rules of items. [_ConstantItem_]: items/constant-items.md [_Enumeration_]: items/enumerations.md @@ -83,14 +78,19 @@ which sub-item declarations may appear. [`extern crate` declarations]: items/extern-crates.md [`extern` blocks]: items/external-blocks.md [`use` declarations]: items/use-declarations.md +[associated items]: items/associated-items.md [constant items]: items/constant-items.md [enumeration definitions]: items/enumerations.md [function definitions]: items/functions.md [implementations]: items/implementations.md +[item scopes]: names/scopes.md#item-scopes [modules]: items/modules.md [paths]: paths.md +[root of the crate]: crates-and-source-files.md +[statement]: statements.md [static items]: items/static-items.md [struct definitions]: items/structs.md [trait definitions]: items/traits.md +[traits]: items/traits.md [type definitions]: items/type-aliases.md [union definitions]: items/unions.md diff --git a/src/items/generics.md b/src/items/generics.md index 5ffcd1580..adea3015a 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -23,6 +23,7 @@ parameters are listed in angle brackets (`<...>`)(U); 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. [References], [raw pointers], [arrays], [slices], [tuples], and [function pointers] have lifetime or type parameters as well, but are not @@ -286,6 +288,7 @@ struct Foo<#[my_flexible_clone(unbounded)] H> { [functions]: functions.md [function pointers]: ../types/function-pointer.md [generic implementations]: implementations.md#generic-implementations +[generic parameter scopes]: ../names/scopes.md#generic-parameter-scopes [higher-ranked lifetimes]: ../trait-bounds.md#higher-ranked-trait-bounds [implementations]: implementations.md [item declarations]: ../statements.md#item-declarations diff --git a/src/names.md b/src/names.md index fd8f50cd0..46d34459e 100644 --- a/src/names.md +++ b/src/names.md @@ -13,7 +13,7 @@ Some entities are [explicitly declared](#explicitly-declared-entities) in the source code, and some are [implicitly declared](#implicitly-declared-entities) as part of the language or compiler extensions. -[*Paths*] are used to refer to an entity, possibly in another scope. Lifetimes +[*Paths*] are used to refer to an entity, possibly in another module or type. Lifetimes and loop labels use a [dedicated syntax][lifetimes-and-loop-labels] using a leading quote. diff --git a/src/names/scopes.md b/src/names/scopes.md index 288781bd3..066faed51 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -1,3 +1,324 @@ # Scopes -> **Note**: This is a placeholder for future expansion. +A *scope* is the region of source text where a named [entity] may be referenced with that name. +The following sections provide details on the scoping rules and behavior, which depend on the kind of entity and where it is declared. +The process of how names are resolved to entities is described in the [name resolution] chapter. +More information on "drop scopes" used for the purpose of running destructors maybe be found in the [destructors] chapter. + +## Item scopes + +The name of an [item][items] declared directly in a [module] has a scope that extends from the start of the module to the end of the module. These items are also members of the module and can be referred to with a [path] leading from their module. + +The name of an item declared as a [statement] has a scope that extends from the start of the block the item statement is in until the end of the block. + +It is an error to introduce an item with a duplicate name of another item in the same [namespace] within the same module or block. +[Asterisk glob imports] have special behavior for dealing with duplicate names and shadowing, see the linked chapter for more details. +Items in a module may shadow items in a [prelude](#prelude-scopes). + +Item names from outer modules are not in scope within a nested module. +A [path] may be used to refer to an item in another module. + +### Associated item scopes + +[Associated items] are not scoped and can only be referred to by using a [path] leading from the type they are associated with. +[Methods] can also be referred to via [call expressions]. + +## Pattern binding scopes + +The scope of a local variable [pattern] binding depends on where it is used: + +* [`let` statement] bindings range from just after the `let` statement until the end of the block where it is declared. +* [Function parameter] bindings are within the body of the function. +* [Closure parameter] bindings are within the closure body. +* [`for`] and [`while let`] bindings are within the loop body. +* [`if let`] bindings are within the consequent block. +* [`match` arms] bindings are within the [match guard] and the match arm expression. + +Local variable scopes do not extend into item declarations. + + +### Pattern binding shadowing + +Pattern bindings are allowed to shadow any name in scope with the following exceptions which are an error: + +* [Const generic parameters] +* [Static items] +* [Const items] +* Constructors for [structs] and [enums] + +The following example illustrates how local bindings can shadow item declarations: + +```rust +fn shadow_example() { + // Since there are no local variables in scope yet, this resolves to the function. + foo(); // prints `function` + let foo = || println!("closure"); + fn foo() { println!("function"); } + // This resolves to the local closure since it shadows the item. + foo(); // prints `closure` +} +``` + +## Generic parameter scopes + +Generic parameters are declared in a [_GenericParams_] list. +The scope of a generic parameter is within the item it is declared on. + +All parameters are in scope within the generic parameter list regardless of the order they are declared. +The following shows some examples where a parameter may be referenced before it is declared: + +```rust +// The 'b bound is referenced before it is declared. +fn params_scope<'a: 'b, 'b>() {} + +# trait SomeTrait {} +// The const N is referenced in the trait bound before it is declared. +fn f, const N: usize>() {} +``` + +Generic parameters are also in scope for type bounds and where clauses, for example: + +```rust +# trait SomeTrait<'a, T> {} +// The <'a, U> for `SomeTrait` refer to the 'a and U parameters of `bounds_scope`. +fn bounds_scope<'a, T: SomeTrait<'a, U>, U>() {} + +fn where_scope<'a, T, U>() + where T: SomeTrait<'a, U> +{} +``` + +Generic scopes do not extend into [items] declared inside a function. + +### Generic parameter shadowing + +It is an error to shadow a generic parameter. +Items declared within functions are allowed to reuse generic parameter names from the function because generic scopes do not extend to inner items. + +```rust +fn example<'a>() { + // Items within functions are allowed to reuse generic parameter in scope + // because all generics are not in scope within inner items. + fn inner<'a>() {} // OK +} +``` + +```rust,compile_fail +trait SomeTrait<'a> { + fn example<'a>() {} // ERROR: 'a is already in scope +} +``` + +### Lifetime scopes + +Lifetime parameters are declared in a [_GenericParams_] list and [higher-ranked trait bounds][hrtb]. + +The `'static` lifetime and [placeholder lifetime] `'_` have a special meaning and cannot be declared as a parameter. + +#### Lifetime generic parameter scopes + +[Constant] and [static] items and [const contexts] only ever allow `'static` lifetime references, so no other lifetime may be in scope within them. +[Associated consts] do allow referring to lifetimes declared in their trait or implementation. + +#### Higher-ranked trait bound scopes + +The scope of a lifetime parameter declared as a [higher-ranked trait bound][hrtb] depends on the scenario where it is used. + +* As a [_TypeBoundWhereClauseItem_] the declared lifetimes are in scope in the type and the type bounds. +* As a [_TraitBound_] the declared lifetimes are in scope within the bound type path. +* As a [_BareFunctionType_] the declared lifetimes are in scope within the function parameters and return type. + +```rust +# trait Trait<'a>{} + +fn where_clause() + // 'a is in scope in both the type and the type bounds. + where for <'a> &'a T: Trait<'a> +{} + +fn bound() + // 'a is in scope within the bound. + where T: for <'a> Trait<'a> +{} + +# struct Example<'a> { +# field: &'a u32 +# } + +// 'a is in scope in both the parameters and return type. +type FnExample = for<'a> fn(x: Example<'a>) -> Example<'a>; +``` + +#### Impl trait restrictions + +[Impl trait] types can only reference lifetimes declared on a function or implementation. + + +```rust +# trait Trait1 { +# type Item; +# } +# trait Trait2<'a> {} +# +# struct Example; +# +# impl Trait1 for Example { +# type Item = Element; +# } +# +# struct Element; +# impl<'a> Trait2<'a> for Element {} +# +// The `impl Trait2` here is not allowed to refer to 'b but it is allowed to +// refer to 'a. +fn foo<'a>() -> impl for<'b> Trait1> { + // ... +# Example +} +``` + +## Loop label scopes + +[Loop labels] may be declared by a [loop expression]. +The scope of a loop label is from the point it is declared till the end of the loop expression. +The scope does not extend into [items], [closures], [async blocks], [const arguments], [const contexts], and the iterator expression of the defining [`for` loop]. + +```rust +'a: for n in 0..3 { + if n % 2 == 0 { + break 'a; + } + fn inner() { + // Using 'a here would be an error. + // break 'a; + } +} + +// The label is in scope for the expression of `while` loops. +'a: while break 'a {} // Loop does not run. +'a: while let _ = break 'a {} // Loop does not run. + +// The label is not in scope in the defining `for` loop: +'a: for outer in 0..5 { + // This will break the outer loop, skipping the inner loop and stopping + // the outer loop. + 'a: for inner in { break 'a; 0..1 } { + println!("{}", inner); // This does not run. + } + println!("{}", outer); // This does not run, either. +} + +``` + +Loop labels may shadow labels of the same name in outer scopes. +References to a label refer to the closest definition. + +```rust +// Loop label shadowing example. +'a: for outer in 0..5 { + 'a: for inner in 0..5 { + // This terminates the inner loop, but the outer loop continues to run. + break 'a; + } +} +``` + +> **Note**: `rustc` currently warns about defining the same loop label multiple times in the same function, or if the label has the same name as an in-scope lifetime. +> This is intended as a future-compatibility warning about a possible extension to the language. +> See [PR #24162](https://github.com/rust-lang/rust/pull/24162). + +## Prelude scopes + +[Preludes] bring entities into scope of every module. +The preludes are layered such that one shadows another if they contain entities of the same name. +The order that preludes may shadow other preludes is the following where earlier entries may shadow later ones: + +1. [Extern prelude] +2. [Tool prelude] +3. [`macro_use` prelude] +4. [Standard library prelude] +5. [Language prelude] + +## `macro_rules` scopes + +The scope of `macro_rules` macros is described in the [Macros By Example] chapter. +The behavior depends on the use of the [`macro_use`] and [`macro_export`] attributes. + +## Derive macro helper attributes + +[Derive macro helper attributes] are in scope in the item where their corresponding [`derive` attribute] is specified. +The scope extends from just after the `derive` attribute to the end of the item. +Helper attributes shadow other attributes of the same name in scope. + +## `Self` scope + +Although [`Self`] is a keyword with special meaning, it interacts with name resolution in a way similar to normal names. + +The implicit `Self` type in the definition of a [struct], [enum], [union], [trait], or [implementation] is treated similarly to a [generic parameter](#generic-parameter-scopes), and is in scope in the same way as a generic type parameter. +For struct, enum, and unions, it is in scope starting after the generic parameters. +For traits and implementations, it is in scope starting just before the generic parameters. + +The implicit `Self` constructor in the value [namespace] of an [implementation] is in scope within the body of the implementation (the implementation's [associated items]). + +[_BareFunctionType_]: ../types/function-pointer.md +[_GenericParams_]: ../items/generics.md +[_TraitBound_]: ../trait-bounds.md +[_TypeBoundWhereClauseItem_]: ../items/generics.md +[`derive` attribute]: ../attributes/derive.md +[`for` loop]: ../expressions/loop-expr.md#iterator-loops +[`for`]: ../expressions/loop-expr.md#iterator-loops +[`if let`]: ../expressions/if-expr.md#if-let-expressions +[`let` statement]: ../statements.md#let-statements +[`macro_export`]: ../macros-by-example.md#path-based-scope +[`macro_use` prelude]: preludes.md#macro_use-prelude +[`macro_use`]: ../macros-by-example.md#the-macro_use-attribute +[`match` arms]: ../expressions/match-expr.md +[`Self`]: ../paths.md#self-1 +[`while let`]: ../expressions/loop-expr.md#predicate-pattern-loops +[Associated consts]: ../items/associated-items.md#associated-constants +[associated items]: ../items/associated-items.md +[Asterisk glob imports]: ../items/use-declarations.md +[async blocks]: ../expressions/block-expr.md#async-blocks +[call expressions]: ../expressions/call-expr.md +[Closure parameter]: ../expressions/closure-expr.md +[closures]: ../expressions/closure-expr.md +[const arguments]: ../items/generics.md#const-generics +[const contexts]: ../const_eval.md#const-context +[Const generic parameters]: ../items/generics.md#const-generics +[Const items]: ../items/constant-items.md +[Constant]: ../items/constant-items.md +[Derive macro helper attributes]: ../procedural-macros.md#derive-macro-helper-attributes +[destructors]: ../destructors.md +[entity]: ../names.md +[enum]: ../items/enumerations.mdr +[enums]: ../items/enumerations.md +[Extern prelude]: preludes.md#extern-prelude +[Function parameter]: ../items/functions.md#function-parameters +[hrtb]: ../trait-bounds.md#higher-ranked-trait-bounds +[Impl trait]: ../types/impl-trait.md +[implementation]: ../items/implementations.md +[items]: ../items.md +[Language prelude]: preludes.md#language-prelude +[loop expression]: ../expressions/loop-expr.md +[Loop labels]: ../expressions/loop-expr.md#loop-labels +[Macros By Example]: ../macros-by-example.md +[match guard]: ../expressions/match-expr.md#match-guards +[methods]: ../items/associated-items.md#methods +[module]: ../items/modules.md +[name resolution]: name-resolution.md +[namespace]: namespaces.md +[path]: ../paths.md +[pattern]: ../patterns.md +[placeholder lifetime]: ../lifetime-elision.md +[preludes]: preludes.md +[Standard library prelude]: preludes.md#standard-library-prelude +[statement]: ../statements.md +[Static items]: ../items/static-items.md +[static]: ../items/static-items.md +[struct]: ../items/structs.md +[structs]: ../items/structs.md +[Tool prelude]: preludes.md#tool-prelude +[trait]: ../items/traits.md +[union]: ../items/unions.md diff --git a/src/patterns.md b/src/patterns.md index 5c81ecd87..5254a73da 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -177,7 +177,7 @@ for i in -2..5 { Identifier patterns bind the value they match to a variable. The identifier must be unique within the pattern. The variable will shadow any variables of -the same name in scope. The scope of the new binding depends on the context of +the same name in scope. The [scope] of the new binding depends on the context of where the pattern is used (such as a `let` binding or a `match` arm). Patterns that consist of only an identifier, possibly with a `mut`, match any value and @@ -867,6 +867,7 @@ result in a type mismatch between `x` in the different subpatterns. [IDENTIFIER]: identifiers.md [enums]: items/enumerations.md [literals]: expressions/literal-expr.md +[scope]: names/scopes.md [structs]: items/structs.md [tuples]: types/tuple.md [scrutinee]: glossary.md#scrutinee diff --git a/src/statements.md b/src/statements.md index 8d9c21d7d..753d01a9b 100644 --- a/src/statements.md +++ b/src/statements.md @@ -29,7 +29,7 @@ statements. An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module]. Declaring an item within a statement -block restricts its scope to the block containing the statement. The item is not +block restricts its [scope] to the block containing the statement. The item is not given a [canonical path] nor are any sub-items it may declare. The exception to this is that associated items defined by [implementations] are still accessible in outer scopes as long as the item and, if applicable, trait are accessible. @@ -128,6 +128,7 @@ statement are [`cfg`], and [the lint check attributes]. [`cfg`]: conditional-compilation.md [the lint check attributes]: attributes/diagnostics.md#lint-check-attributes [pattern]: patterns.md +[scope]: names/scopes.md [_ExpressionStatement_]: #expression-statements [_Expression_]: expressions.md [_Item_]: items.md diff --git a/src/trait-bounds.md b/src/trait-bounds.md index f284ca4eb..2aa41e5d6 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -145,7 +145,7 @@ fn call_on_ref_zero(f: F) where for<'a> F: Fn(&'a i32) { ``` Higher-ranked lifetimes may also be specified just before the trait: the only -difference is the scope of the lifetime parameter, which extends only to the +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. @@ -165,6 +165,7 @@ fn call_on_ref_zero(f: F) where F: for<'a> Fn(&'a i32) { [arrays]: types/array.md [associated types]: items/associated-items.md#associated-types +[hrtb-scopes]: names/scopes.md#higher-ranked-trait-bound-scopes [supertraits]: items/traits.md#supertraits [generic]: items/generics.md [higher-ranked lifetimes]: #higher-ranked-trait-bounds From c7b17a197e9ba9209246783c1a6cf8b95d3c5e69 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 21 Jun 2021 06:24:37 -0700 Subject: [PATCH 015/315] Grammar fix. --- src/names/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/names/scopes.md b/src/names/scopes.md index 066faed51..25c8a53f2 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -257,7 +257,7 @@ Helper attributes shadow other attributes of the same name in scope. Although [`Self`] is a keyword with special meaning, it interacts with name resolution in a way similar to normal names. The implicit `Self` type in the definition of a [struct], [enum], [union], [trait], or [implementation] is treated similarly to a [generic parameter](#generic-parameter-scopes), and is in scope in the same way as a generic type parameter. -For struct, enum, and unions, it is in scope starting after the generic parameters. +For structs, enums, and unions, it is in scope starting after the generic parameters. For traits and implementations, it is in scope starting just before the generic parameters. The implicit `Self` constructor in the value [namespace] of an [implementation] is in scope within the body of the implementation (the implementation's [associated items]). From df36b811bd830a14873bb383533d20f3426ffddd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 26 Jun 2021 18:42:08 -0700 Subject: [PATCH 016/315] Clarify shadowing of prelude names. --- src/names/scopes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/names/scopes.md b/src/names/scopes.md index 25c8a53f2..617c1aa4e 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -232,6 +232,9 @@ References to a label refer to the closest definition. ## Prelude scopes [Preludes] bring entities into scope of every module. +The entities are not members of the module, but are implicitly queried during [name resolution]. +The prelude names may be shadowed by declarations in a module. + The preludes are layered such that one shadows another if they contain entities of the same name. The order that preludes may shadow other preludes is the following where earlier entries may shadow later ones: From 57d286f1697a83b8790a59dddc7e53697a7a9b28 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 30 Jun 2021 17:40:51 -0700 Subject: [PATCH 017/315] Add some details on item definition order. --- src/items.md | 5 +++++ src/names/scopes.md | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/items.md b/src/items.md index 9bc07a62c..3d7f53242 100644 --- a/src/items.md +++ b/src/items.md @@ -56,6 +56,9 @@ There are several kinds of items: Items may be declared in the [root of the crate], a [module][modules], or a [statement]. Additionally, a subset of items, called [associated items], may be declared in [traits] and [implementations]. +Items may be defined in any order, with the exception of [`macro_rules`] which has its own scoping behavior. +[Name resolution] of item names allows items to be defined before or after where the item is referred to in the module or block. + See [item scopes] for information on the scoping rules of items. [_ConstantItem_]: items/constant-items.md @@ -77,6 +80,7 @@ See [item scopes] for information on the scoping rules of items. [_Visibility_]: visibility-and-privacy.md [`extern crate` declarations]: items/extern-crates.md [`extern` blocks]: items/external-blocks.md +[`macro_rules`]: macros-by-example.md [`use` declarations]: items/use-declarations.md [associated items]: items/associated-items.md [constant items]: items/constant-items.md @@ -85,6 +89,7 @@ See [item scopes] for information on the scoping rules of items. [implementations]: items/implementations.md [item scopes]: names/scopes.md#item-scopes [modules]: items/modules.md +[name resolution]: names/name-resolution.md [paths]: paths.md [root of the crate]: crates-and-source-files.md [statement]: statements.md diff --git a/src/names/scopes.md b/src/names/scopes.md index 617c1aa4e..035676a6a 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -23,6 +23,8 @@ A [path] may be used to refer to an item in another module. [Associated items] are not scoped and can only be referred to by using a [path] leading from the type they are associated with. [Methods] can also be referred to via [call expressions]. +Similar to items within a module or block, it is an error to introduce an item within a trait or implementation that is a duplicate of another item in the trait or impl in the same namespace. + ## Pattern binding scopes The scope of a local variable [pattern] binding depends on where it is used: From 524b9b1efdfdef603d9617d8e1476b66b99a6349 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 7 May 2022 12:24:17 -0700 Subject: [PATCH 018/315] Updates from review. --- src/items.md | 6 +++-- src/names/scopes.md | 53 +++++++++++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/items.md b/src/items.md index 3d7f53242..00639acf4 100644 --- a/src/items.md +++ b/src/items.md @@ -53,8 +53,9 @@ There are several kinds of items: * [implementations] * [`extern` blocks] -Items may be declared in the [root of the crate], a [module][modules], or a [statement]. -Additionally, a subset of items, called [associated items], may be declared in [traits] and [implementations]. +Items may be declared in the [root of the crate], a [module][modules], or a [block expression]. +A subset of items, called [associated items], may be declared in [traits] and [implementations]. +A subset of items, called external items, may be declared in [`extern` blocks]. Items may be defined in any order, with the exception of [`macro_rules`] which has its own scoping behavior. [Name resolution] of item names allows items to be defined before or after where the item is referred to in the module or block. @@ -83,6 +84,7 @@ See [item scopes] for information on the scoping rules of items. [`macro_rules`]: macros-by-example.md [`use` declarations]: items/use-declarations.md [associated items]: items/associated-items.md +[block expression]: expressions/block-expr.md [constant items]: items/constant-items.md [enumeration definitions]: items/enumerations.md [function definitions]: items/functions.md diff --git a/src/names/scopes.md b/src/names/scopes.md index 035676a6a..012bb25f5 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -3,7 +3,7 @@ A *scope* is the region of source text where a named [entity] may be referenced with that name. The following sections provide details on the scoping rules and behavior, which depend on the kind of entity and where it is declared. The process of how names are resolved to entities is described in the [name resolution] chapter. -More information on "drop scopes" used for the purpose of running destructors maybe be found in the [destructors] chapter. +More information on "drop scopes" used for the purpose of running destructors may be found in the [destructors] chapter. ## Item scopes @@ -20,10 +20,10 @@ A [path] may be used to refer to an item in another module. ### Associated item scopes -[Associated items] are not scoped and can only be referred to by using a [path] leading from the type they are associated with. +[Associated items] are not scoped and can only be referred to by using a [path] leading from the type or trait they are associated with. [Methods] can also be referred to via [call expressions]. -Similar to items within a module or block, it is an error to introduce an item within a trait or implementation that is a duplicate of another item in the trait or impl in the same namespace. +Similar to items within a module or block, it is an error to introduce an item within a trait or implementation that is a duplicate of another item in the trait or impl in the same namespace. ## Pattern binding scopes @@ -90,24 +90,33 @@ fn where_scope<'a, T, U>() {} ``` -Generic scopes do not extend into [items] declared inside a function. +It is an error for [items] declared inside a function to refer to a generic parameter from their outer scope. + +```rust,compile_fail +fn example() { + fn inner(x: T) {} // ERROR: can't use generic parameters from outer function +} +``` ### Generic parameter shadowing -It is an error to shadow a generic parameter. -Items declared within functions are allowed to reuse generic parameter names from the function because generic scopes do not extend to inner items. +It is an error to shadow a generic parameter with the exception that items declared within functions are allowed to shadow generic parameter names from the function. ```rust -fn example<'a>() { - // Items within functions are allowed to reuse generic parameter in scope - // because all generics are not in scope within inner items. - fn inner<'a>() {} // OK +fn example<'a, T, const N: usize>() { + // Items within functions are allowed to shadow generic parameter in scope. + fn inner_lifetime<'a>() {} // OK + fn inner_type() {} // OK + fn inner_const() {} // OK } ``` ```rust,compile_fail -trait SomeTrait<'a> { - fn example<'a>() {} // ERROR: 'a is already in scope +trait SomeTrait<'a, T, const N: usize> { + fn example_lifetime<'a>() {} // ERROR: 'a is already in use + fn example_type() {} // ERROR: T is already in use + fn example_const() {} // ERROR: N is already in use + fn example_mixed() {} // ERROR: T is already in use } ``` @@ -262,11 +271,27 @@ Helper attributes shadow other attributes of the same name in scope. Although [`Self`] is a keyword with special meaning, it interacts with name resolution in a way similar to normal names. The implicit `Self` type in the definition of a [struct], [enum], [union], [trait], or [implementation] is treated similarly to a [generic parameter](#generic-parameter-scopes), and is in scope in the same way as a generic type parameter. -For structs, enums, and unions, it is in scope starting after the generic parameters. -For traits and implementations, it is in scope starting just before the generic parameters. The implicit `Self` constructor in the value [namespace] of an [implementation] is in scope within the body of the implementation (the implementation's [associated items]). +```rust +// Self type within struct definition. +struct Recursive { + f1: Option> +} + +// Self type within generic parameters. +struct SelfGeneric>(T); + +// Self value constructor within an implementation. +struct ImplExample(); +impl ImplExample { + fn example() -> Self { // Self type + Self() // Self value constructor + } +} +``` + [_BareFunctionType_]: ../types/function-pointer.md [_GenericParams_]: ../items/generics.md [_TraitBound_]: ../trait-bounds.md From fe9eec6b3eb3dc4e42d83d40adc2c9a2660ea874 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 3 Jun 2022 15:00:29 -0700 Subject: [PATCH 019/315] Remove note about 24162 now that it has been resolved by https://github.com/rust-lang/rust/pull/96296. --- src/names/scopes.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/names/scopes.md b/src/names/scopes.md index 012bb25f5..58ee99b55 100644 --- a/src/names/scopes.md +++ b/src/names/scopes.md @@ -236,10 +236,6 @@ References to a label refer to the closest definition. } ``` -> **Note**: `rustc` currently warns about defining the same loop label multiple times in the same function, or if the label has the same name as an in-scope lifetime. -> This is intended as a future-compatibility warning about a possible extension to the language. -> See [PR #24162](https://github.com/rust-lang/rust/pull/24162). - ## Prelude scopes [Preludes] bring entities into scope of every module. From a00cc5d6cf6c97132902fce5fe1358a621318e01 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 11 Jun 2022 22:02:03 -0300 Subject: [PATCH 020/315] dollar-dollar --- src/macros-by-example.md | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 2c49300cd..17a68f8d8 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -193,6 +193,53 @@ compiler knows how to expand them properly: not have the same number. This requirement applies to every layer of nested repetitions. +## Dollar-dollar ($$) + +`$$` expands to a single `$`. + +Since metavariable expressions always apply during the expansion of a macro, they cannot be used in recursive macro definitions and this is where `$$` expressions comes into play, i.e., `$$` can be used to resolve ambiguities in nested macros. + +The following example illustrates a macro that fails to compile due to the ambiguity of the repetition in a nested macro: + +```rust,compile_fail +macro_rules! foo_error { + () => { + macro_rules! bar_error { + ( $( $any:tt )* ) => { $( $any )* }; + // ^^^^^^^^^^^ error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth + } + }; +} + +foo_error!(); +``` + +The following resolves the problem by escaping the `$` in the repetition with `$$`: + +```rust +macro_rules! foo_ok { + () => { + macro_rules! bar_ok { + ( $$( $any:tt )* ) => { $$( $any )* }; + } + }; +} + +foo_ok!(); +``` + +One consequence of such expansion is that deeper nested levels make dollar-dollar declarations grown linearly, starting at `$$`, then `$$$$`, then `$$$$$` and so on. This is also necessary to be fully featured so that it is possible to specify names of metavariables using other metavariables at each nesting level. + +``` +$foo => bar => bar // Evaluate foo at level 1 +$$foo => $foo => bar // Evaluate foo at level 2 +$$$foo => $bar => baz // Evaluate foo at level 1, and use that as a name at level 2 +$$$$foo => $$foo => $foo // Evaluate foo at level 3 +$$$$$foo => $$bar => $bar // Evaluate foo at level 1, and use that as a name at level 3 +$$$$$$foo => $$$foo => $bar // Evaluate foo at level 2, and use that as a name at level 3 +$$$$$$$foo => $$$bar => $baz // Evaluate foo at level 1, use that at level 2, and then use *that* at level 3 +``` + ## Scoping, Exporting, and Importing For historical reasons, the scoping of macros by example does not work entirely From 8d039bda5d4153ab99c368c4c159fd76471b01b8 Mon Sep 17 00:00:00 2001 From: Caio Date: Sat, 11 Jun 2022 22:41:39 -0300 Subject: [PATCH 021/315] Update macros-by-example.md --- src/macros-by-example.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 17a68f8d8..b70b94e96 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -230,7 +230,7 @@ foo_ok!(); One consequence of such expansion is that deeper nested levels make dollar-dollar declarations grown linearly, starting at `$$`, then `$$$$`, then `$$$$$` and so on. This is also necessary to be fully featured so that it is possible to specify names of metavariables using other metavariables at each nesting level. -``` +```ignore $foo => bar => bar // Evaluate foo at level 1 $$foo => $foo => bar // Evaluate foo at level 2 $$$foo => $bar => baz // Evaluate foo at level 1, and use that as a name at level 2 From efc277f7de99d232b33d279605a10eeecf928683 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Mon, 13 Jun 2022 08:14:31 +0200 Subject: [PATCH 022/315] Add note to line continuation section about confusing behavior --- src/tokens.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tokens.md b/src/tokens.md index 8f2063656..5e7a59157 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -170,6 +170,11 @@ assert_eq!(a, b); assert_eq!(b, c); ``` +> Note: Rust skipping additional newlines (like in example `c`) is potentially confusing and +> unexpected. This behavior may be adjusted in the future. Until a decision is made, it is +> recommended to avoid relying on this, i.e. skipping multiple newlines with line continuations. +> See [this issue](https://github.com/rust-lang/reference/pull/1042) for more information. + #### Character escapes Some additional _escapes_ are available in either character or non-raw string From b5596cb97e4c94237b54639579ad1853d64fe930 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 21 Jun 2022 13:54:21 +0200 Subject: [PATCH 023/315] Remove outdated restriction on recursive types --- src/types.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/types.md b/src/types.md index a7ce5bc82..aed10fd0f 100644 --- a/src/types.md +++ b/src/types.md @@ -104,9 +104,6 @@ itself. Such recursion has restrictions: 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 type definitions can cross module boundaries, but not module - *visibility* boundaries, or crate boundaries (in order to simplify the module - system and type checker). An example of a *recursive* type and its use: From 32fc50e5d211a6a02f874d7e6ae29b4a344f3bdb Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 24 Jun 2022 18:55:01 +0100 Subject: [PATCH 024/315] Describe what `windows_subsystem` does --- src/runtime.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/runtime.md b/src/runtime.md index 06966926d..a281d50fb 100644 --- a/src/runtime.md +++ b/src/runtime.md @@ -63,6 +63,13 @@ the [subsystem] when linking on a Windows target. It uses the `console` or `windows`. This attribute is ignored on non-Windows targets, and for non-`bin` [crate types]. +The "console" subsystem is the default. If a console process is run from an +existing console then it will be attached to that console, otherwise a new +console window will be created. + +The "windows" subsystem is commonly used by GUI applications that do not want to +display a console window on startup. It will run detached from any existing console. + ```rust #![windows_subsystem = "windows"] ``` From 43cdd4bcf25953cb86bccbd57df98c923e16804e Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts <2467194+yoshuawuyts@users.noreply.github.com> Date: Fri, 1 Jul 2022 13:00:09 +0200 Subject: [PATCH 025/315] Add `IntoFuture::into_future` desugaring --- src/expressions/await-expr.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/expressions/await-expr.md b/src/expressions/await-expr.md index e7fc45d27..84cae07a4 100644 --- a/src/expressions/await-expr.md +++ b/src/expressions/await-expr.md @@ -4,17 +4,20 @@ > _AwaitExpression_ :\ >    [_Expression_] `.` `await` -*Await expressions* suspend the current computation until the given future is ready to produce a value. -The syntax for an await expression is an expression with a type that implements the [Future] trait, called the *future operand*, then the token `.`, and then the `await` keyword. +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. +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. Await expressions are legal only within an [async context], like an [`async fn`] or an [`async` block]. More specifically, an await expression has the following effect. -1. Evaluate the future operand to a [future] `tmp`; -2. Pin `tmp` using [`Pin::new_unchecked`]; -3. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context); -3. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 2; -4. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself. +1. Create a future by calling [`IntoFuture::into_future`] on the future operand. +2. Evaluate the future to a [future] `tmp`; +3. Pin `tmp` using [`Pin::new_unchecked`]; +4. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context); +5. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 2; +6. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself. > **Edition differences**: Await expressions are only available beginning with Rust 2018. @@ -29,7 +32,7 @@ Effectively, an await expression is roughly equivalent to the following non-norm ```rust,ignore -match future_operand { +match operand.into_future() { mut pinned => loop { let mut pin = unsafe { Pin::new_unchecked(&mut pinned) }; match Pin::future::poll(Pin::borrow(&mut pin), &mut current_context) { @@ -53,3 +56,5 @@ The variable `current_context` refers to the context taken from the async enviro [`poll::Ready`]: ../../std/task/enum.Poll.html#variant.Ready [async context]: ../expressions/block-expr.md#async-context [future]: ../../std/future/trait.Future.html +[`IntoFuture`]: ../../std/future/trait.IntoFuture.html +[`IntoFuture::into_future`]: ../../std/future/trait.IntoFuture.html#tymethod.into_future From 88b6a426410aedd747c42fe26e34c84ab7629e3f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 11 Jul 2022 17:57:57 -0400 Subject: [PATCH 026/315] clarify the size=0 case --- src/behavior-considered-undefined.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index e5a0554ea..e810e8c0d 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -76,10 +76,14 @@ reading uninitialized memory is permitted are inside `union`s and in "padding" [dangling]: #dangling-pointers A reference/pointer is "dangling" if it is null or not all of the bytes it -points to are part of the same allocation (so in particular they all have to be +points to are part of the same live allocation (so in particular they all have to be part of *some* allocation). The span of bytes it points to is determined by the pointer value and the size of the pointee type (using `size_of_val`). +If the size is 0, then the pointer must either point inside of a live allocation +(including pointing just after the last byte of the allocation), or it must be +directly constructed from a non-zero integer literal. + Note that dynamically sized types (such as slices and strings) point to their entire range, so it is important that the length metadata is never too large. In particular, the dynamic size of a Rust value (as determined by `size_of_val`) From 969e45e09c68a167ecf456901f490cd6a21a70a2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 Jul 2022 08:45:34 -0400 Subject: [PATCH 027/315] update union field type rules --- src/items/unions.md | 37 ++++++++++++++----------------------- src/types/union.md | 15 ++++++++------- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/src/items/unions.md b/src/items/unions.md index 7ad5da71e..325b22717 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -20,6 +20,16 @@ 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. +Union field types are restricted to the following subset of types: +- `Copy` types +- References (`&T` and `&mut T` for arbitrary `T`) +- `ManuallyDrop` (for arbitrary `T`) +- Tuples and arrays containing only allowed union field types + +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. + ## Initialization of a union A value of a union type can be created using the same syntax that is used for @@ -67,32 +77,13 @@ unsafe { } ``` -Writes to [`Copy`] or [`ManuallyDrop`][ManuallyDrop] union fields do not -require reads for running destructors, so these writes don't have to be placed -in `unsafe` blocks - -```rust -# use std::mem::ManuallyDrop; -union MyUnion { f1: u32, f2: ManuallyDrop } -let mut u = MyUnion { f1: 1 }; - -// These do not require `unsafe`. -u.f1 = 2; -u.f2 = ManuallyDrop::new(String::from("example")); -``` - Commonly, code using unions will provide safe wrappers around unsafe union field accesses. -## Unions and `Drop` - -When a union is dropped, it cannot know which of its fields needs to be dropped. -For this reason, all union fields must either be of a [`Copy`] type or of the -shape [`ManuallyDrop<_>`][ManuallyDrop]. This ensures that a union does not -need to drop anything when it goes out of scope. - -Like for structs and enums, it is possible to `impl Drop` for a union to -manually define what happens when it gets dropped. +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.) ## Pattern matching on unions diff --git a/src/types/union.md b/src/types/union.md index 3f96cc96d..326e720c6 100644 --- a/src/types/union.md +++ b/src/types/union.md @@ -4,14 +4,15 @@ A *union type* is a nominal, heterogeneous C-like union, denoted by the name of a [`union` item][item]. 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. Since transmutes can cause unexpected or undefined behaviour, `unsafe` -is required to read from a union field, or to write to a field that doesn't -implement [`Copy`] or has a [`ManuallyDrop`] type. See the [item] documentation -for further details. +transmutes parts of the content of the union to the type of the accessed field. +Since transmutes can cause unexpected or undefined behaviour, `unsafe` is +required to read from a union field. 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. -The memory layout of a `union` is undefined by default, 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 [`ManuallyDrop`]: ../../std/mem/struct.ManuallyDrop.html From 797bb9fc17a2e6b818dac3a810ffbc343bd9eddd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Apr 2021 19:12:08 +0200 Subject: [PATCH 028/315] document raw-addr-of operators --- src/expressions/operator-expr.md | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 83e0e0aaa..5a4508029 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -79,6 +79,50 @@ let a = && && mut 10; let a = & & & & mut 10; ``` +### Raw address-of operators + +Related to the borrow operators are the raw address-of operators, which do not have first-class syntax, but are exposed via the macros `ptr::addr_of!(expr)` and `ptr::addr_of_mut!(expr)`. +Like with `&`/`&mut`, the expression is evaluated in place expression context. +The difference is that `&`/`&mut` create *references* of type `&T`/`&mut T`, while `ptr::addr_of!(expr)` creates a (const) raw pointer of type `*const T` and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`. + +The raw address-of operators must be used whenever the place expression denotes a place that is not properly aligned or does not store a valid value as determined by its type. +In those situations, using a borrow operator would cause [undefined behavior] by creating an invalid reference, but a raw pointer may still be constructed using an address-of operator. + +**Example of creating a raw pointer to an unaligned place (through a `packed` struct):** + +```rust +use std::ptr; + +#[repr(packed)] +struct Packed { + f1: u8, + f2: u16, +} + +let packed = Packed { f1: 1, f2: 2 }; +// `&packed.f2` would create an unaligned reference, and thus be Undefined Behavior! +let raw_f2 = ptr::addr_of!(packed.f2); +assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); +``` + +**Example of creating a raw pointer to a place that does not contain a valid value:** + +```rust +use std::{ptr, mem::MaybeUninit}; + +struct Demo { + field: bool, +} + +let mut uninit = MaybeUninit::::uninit(); +// `&uninit.as_mut().field` would create a reference to an uninitialized `bool`, +// and thus be Undefined Behavior! +let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) }; +unsafe { f1_ptr.write(true); } +let init = unsafe { uninit.assume_init() }; +``` + + ## The dereference operator > **Syntax**\ @@ -605,6 +649,7 @@ See [this test] for an example of using this dependency. [float-float]: https://github.com/rust-lang/rust/issues/15536 [Function pointer]: ../types/function-pointer.md [Function item]: ../types/function-item.md +[undefined behavior]: ../behavior-considered-undefined.md [_BorrowExpression_]: #borrow-operators [_DereferenceExpression_]: #the-dereference-operator From 39b8157d587a27cc3792416264fe218bb85c412f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 6 Apr 2021 14:22:25 +0200 Subject: [PATCH 029/315] Apply suggestions from code review Co-authored-by: Ryan Scheel --- src/expressions/operator-expr.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 5a4508029..410aa96fb 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -81,14 +81,14 @@ let a = & & & & mut 10; ### Raw address-of operators -Related to the borrow operators are the raw address-of operators, which do not have first-class syntax, but are exposed via the macros `ptr::addr_of!(expr)` and `ptr::addr_of_mut!(expr)`. +Related to the borrow operators are the *raw address-of operators*, which do not have first-class syntax, but are exposed via the macros `ptr::addr_of!(expr)` and `ptr::addr_of_mut!(expr)`. Like with `&`/`&mut`, the expression is evaluated in place expression context. The difference is that `&`/`&mut` create *references* of type `&T`/`&mut T`, while `ptr::addr_of!(expr)` creates a (const) raw pointer of type `*const T` and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`. -The raw address-of operators must be used whenever the place expression denotes a place that is not properly aligned or does not store a valid value as determined by its type. +The raw address-of operators must be used 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. In those situations, using a borrow operator would cause [undefined behavior] by creating an invalid reference, but a raw pointer may still be constructed using an address-of operator. -**Example of creating a raw pointer to an unaligned place (through a `packed` struct):** +The following is an example of creating a raw pointer to an unaligned place through a `packed` struct: ```rust use std::ptr; @@ -105,7 +105,7 @@ let raw_f2 = ptr::addr_of!(packed.f2); assert_eq!(unsafe { raw_f2.read_unaligned() }, 2); ``` -**Example of creating a raw pointer to a place that does not contain a valid value:** +The following is an example of creating a raw pointer to a place that does not contain a valid value: ```rust use std::{ptr, mem::MaybeUninit}; From 3501d8599fa349d833524b399c36b14e0a984e85 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 6 Apr 2021 14:26:46 +0200 Subject: [PATCH 030/315] edits --- src/expressions.md | 3 ++- src/expressions/operator-expr.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 5b4092984..32ee658ff 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -157,7 +157,7 @@ A *value expression* is an expression that represents an actual value. The following contexts are *place expression* contexts: * The left operand of a [compound assignment] expression. -* The operand of a unary [borrow] or [dereference][deref] operator. +* The operand of a unary [borrow], [address-of][addr-of] or [dereference][deref] operator. * The operand of a field expression. * The indexed operand of an array indexing expression. * The operand of any [implicit borrow]. @@ -308,6 +308,7 @@ They are never allowed before: [assign]: expressions/operator-expr.md#assignment-expressions [borrow]: expressions/operator-expr.md#borrow-operators +[addr-of]: expressions/operator-expr.md#raw-address-of-operators [comparison]: expressions/operator-expr.md#comparison-operators [compound assignment]: expressions/operator-expr.md#compound-assignment-expressions [deref]: expressions/operator-expr.md#the-dereference-operator diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 410aa96fb..e3225dc99 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -82,7 +82,7 @@ let a = & & & & mut 10; ### Raw address-of operators Related to the borrow operators are the *raw address-of operators*, which do not have first-class syntax, but are exposed via the macros `ptr::addr_of!(expr)` and `ptr::addr_of_mut!(expr)`. -Like with `&`/`&mut`, the expression is evaluated in place expression context. +Like with `&`/`&mut`, the expression `expr` is evaluated in place expression context. The difference is that `&`/`&mut` create *references* of type `&T`/`&mut T`, while `ptr::addr_of!(expr)` creates a (const) raw pointer of type `*const T` and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`. The raw address-of operators must be used 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. From 9b5148c9989c2ea2b403d8f038cd9e093203e620 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 7 Apr 2021 14:50:14 +0200 Subject: [PATCH 031/315] further tweak addr_of exposition --- src/expressions/operator-expr.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index e3225dc99..b2b603206 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -82,10 +82,10 @@ let a = & & & & mut 10; ### Raw address-of operators Related to the borrow operators are the *raw address-of operators*, which do not have first-class syntax, but are exposed via the macros `ptr::addr_of!(expr)` and `ptr::addr_of_mut!(expr)`. -Like with `&`/`&mut`, the expression `expr` is evaluated in place expression context. -The difference is that `&`/`&mut` create *references* of type `&T`/`&mut T`, while `ptr::addr_of!(expr)` creates a (const) raw pointer of type `*const T` and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`. +The expression `expr` is evaluated in place expression context. +`ptr::addr_of!(expr)` then creates a (const) raw pointer of type `*const T` to the given place, and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`. -The raw address-of operators must be used 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. +The raw address-of 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 using an address-of operator. The following is an example of creating a raw pointer to an unaligned place through a `packed` struct: From 5c4a7a617c596b78593cabdf72e522ac2b8d1fba Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 27 Feb 2022 21:52:12 -0500 Subject: [PATCH 032/315] tweaks --- src/expressions/operator-expr.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index b2b603206..d8658d647 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -81,9 +81,9 @@ let a = & & & & mut 10; ### Raw address-of operators -Related to the borrow operators are the *raw address-of operators*, which do not have first-class syntax, but are exposed via the macros `ptr::addr_of!(expr)` and `ptr::addr_of_mut!(expr)`. +Related to the borrow operators are the *raw address-of operators*, which do not have first-class syntax, but are exposed via the macros [`ptr::addr_of!(expr)`][addr_of] and [`ptr::addr_of_mut!(expr)`][addr_of_mut]. The expression `expr` is evaluated in place expression context. -`ptr::addr_of!(expr)` then creates a (const) raw pointer of type `*const T` to the given place, and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`. +`ptr::addr_of!(expr)` then creates a const raw pointer of type `*const T` to the given place, and `ptr::addr_of_mut!(expr)` creates a mutable raw pointer of type `*mut T`. The raw address-of 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 using an address-of operator. @@ -650,6 +650,8 @@ See [this test] for an example of using this dependency. [Function pointer]: ../types/function-pointer.md [Function item]: ../types/function-item.md [undefined behavior]: ../behavior-considered-undefined.md +[addr_of]: ../../std/ptr/macro.addr_of.html +[addr_of_mut]: ../../std/ptr/macro.addr_of_mut.html [_BorrowExpression_]: #borrow-operators [_DereferenceExpression_]: #the-dereference-operator From 72fea089185bc823685373b79dd85aecd07ae050 Mon Sep 17 00:00:00 2001 From: pierwill <19642016+pierwill@users.noreply.github.com> Date: Thu, 21 Jul 2022 09:22:11 -0500 Subject: [PATCH 033/315] Update subtyping.md Remove "in Rust" per style guidelines, and edit sentence for clarity. --- src/subtyping.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/subtyping.md b/src/subtyping.md index 40f5a1544..7bca6c979 100644 --- a/src/subtyping.md +++ b/src/subtyping.md @@ -1,8 +1,8 @@ # Subtyping and Variance Subtyping is implicit and can occur at any stage in type checking or -inference. Subtyping in Rust is very restricted and occurs only due to -variance with respect to lifetimes and between types with higher ranked +inference. 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. From ece3e184c0beeadba97c78eed9005533c3874e43 Mon Sep 17 00:00:00 2001 From: pierwill Date: Thu, 21 Jul 2022 09:26:07 -0500 Subject: [PATCH 034/315] Remove uses of the phrase "in Rust" This is mentioned specifically in the style guide. --- src/comments.md | 2 +- src/interior-mutability.md | 2 +- src/items/functions.md | 2 +- src/statements-and-expressions.md | 2 +- src/types/pointer.md | 4 ++-- src/visibility-and-privacy.md | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/comments.md b/src/comments.md index ff1595064..46074b45c 100644 --- a/src/comments.md +++ b/src/comments.md @@ -34,7 +34,7 @@ ## Non-doc comments -Comments in Rust code follow the general C++ style of line (`//`) and +Comments follow the general C++ style of line (`//`) and block (`/* ... */`) comment forms. Nested block comments are supported. Non-doc comments are interpreted as a form of whitespace. diff --git a/src/interior-mutability.md b/src/interior-mutability.md index e786d5649..914600776 100644 --- a/src/interior-mutability.md +++ b/src/interior-mutability.md @@ -6,7 +6,7 @@ mutability if its internal state can be changed through a [shared reference] to it. This goes against the usual [requirement][ub] that the value pointed to by a shared reference is not mutated. -[`std::cell::UnsafeCell`] type is the only allowed way in Rust to disable +[`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. As with all other types, it is undefined behavior to have multiple `&mut UnsafeCell` diff --git a/src/items/functions.md b/src/items/functions.md index 6a2ab4e16..325588a53 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -175,7 +175,7 @@ is equivalent to: extern "Rust" fn foo() {} ``` -Functions in Rust can be called by foreign code, and using an ABI that +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: diff --git a/src/statements-and-expressions.md b/src/statements-and-expressions.md index bb59108f1..b093972a9 100644 --- a/src/statements-and-expressions.md +++ b/src/statements-and-expressions.md @@ -7,5 +7,5 @@ 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 in Rust serve _mostly_ to contain and explicitly +In contrast, statements serve _mostly_ to contain and explicitly sequence expression evaluation. diff --git a/src/types/pointer.md b/src/types/pointer.md index 47bda4f82..9c8d80f39 100644 --- a/src/types/pointer.md +++ b/src/types/pointer.md @@ -1,6 +1,6 @@ # Pointer types -All pointers in Rust are explicit first-class values. +All pointers are explicit first-class values. They can be moved or copied, stored into data structs, and returned from functions. ## References (`&` and `&mut`) @@ -38,7 +38,7 @@ For example `*const i32` means a raw pointer to a 32-bit integer. Copying or dropping a raw pointer has no effect on the lifecycle of any other value. 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 in Rust code; +Raw pointers are generally discouraged; they exist to support interoperability with foreign code, and writing performance-critical or low-level functions. When comparing raw pointers they are compared by their address, rather than by what they point to. diff --git a/src/visibility-and-privacy.md b/src/visibility-and-privacy.md index 209b9bcf6..df9f05ad8 100644 --- a/src/visibility-and-privacy.md +++ b/src/visibility-and-privacy.md @@ -22,7 +22,7 @@ of an item to see whether it should be allowed or not. This is where privacy warnings are generated, or otherwise "you used a private item of another module and weren't allowed to." -By default, everything in Rust is *private*, with two exceptions: Associated +By default, everything is *private*, with two exceptions: Associated items in a `pub` Trait are public by default; Enum variants in a `pub` enum are also public by default. When an item is declared as `pub`, it can be thought of as being accessible to the outside world. For example: From 314d63a53825a9d51830bdef2fc6f9643f91e038 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 22 Jul 2022 02:21:29 +0200 Subject: [PATCH 035/315] Revert "Add stable references of `macro_metavar_expr`" --- src/macros-by-example.md | 47 ---------------------------------------- 1 file changed, 47 deletions(-) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index b70b94e96..2c49300cd 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -193,53 +193,6 @@ compiler knows how to expand them properly: not have the same number. This requirement applies to every layer of nested repetitions. -## Dollar-dollar ($$) - -`$$` expands to a single `$`. - -Since metavariable expressions always apply during the expansion of a macro, they cannot be used in recursive macro definitions and this is where `$$` expressions comes into play, i.e., `$$` can be used to resolve ambiguities in nested macros. - -The following example illustrates a macro that fails to compile due to the ambiguity of the repetition in a nested macro: - -```rust,compile_fail -macro_rules! foo_error { - () => { - macro_rules! bar_error { - ( $( $any:tt )* ) => { $( $any )* }; - // ^^^^^^^^^^^ error: attempted to repeat an expression containing no syntax variables matched as repeating at this depth - } - }; -} - -foo_error!(); -``` - -The following resolves the problem by escaping the `$` in the repetition with `$$`: - -```rust -macro_rules! foo_ok { - () => { - macro_rules! bar_ok { - ( $$( $any:tt )* ) => { $$( $any )* }; - } - }; -} - -foo_ok!(); -``` - -One consequence of such expansion is that deeper nested levels make dollar-dollar declarations grown linearly, starting at `$$`, then `$$$$`, then `$$$$$` and so on. This is also necessary to be fully featured so that it is possible to specify names of metavariables using other metavariables at each nesting level. - -```ignore -$foo => bar => bar // Evaluate foo at level 1 -$$foo => $foo => bar // Evaluate foo at level 2 -$$$foo => $bar => baz // Evaluate foo at level 1, and use that as a name at level 2 -$$$$foo => $$foo => $foo // Evaluate foo at level 3 -$$$$$foo => $$bar => $bar // Evaluate foo at level 1, and use that as a name at level 3 -$$$$$$foo => $$$foo => $bar // Evaluate foo at level 2, and use that as a name at level 3 -$$$$$$$foo => $$$bar => $baz // Evaluate foo at level 1, use that at level 2, and then use *that* at level 3 -``` - ## Scoping, Exporting, and Importing For historical reasons, the scoping of macros by example does not work entirely From be45f8f36860378109dfa1f6a6beedd39e420a9e Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 21 Jul 2022 18:58:23 -0700 Subject: [PATCH 036/315] Fix `IntoFuture` link --- src/expressions/await-expr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expressions/await-expr.md b/src/expressions/await-expr.md index 84cae07a4..b52cda1b9 100644 --- a/src/expressions/await-expr.md +++ b/src/expressions/await-expr.md @@ -7,7 +7,7 @@ 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. -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. +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. Await expressions are legal only within an [async context], like an [`async fn`] or an [`async` block]. More specifically, an await expression has the following effect. From 15049771545fb6cebec0753fe72d761ede2d0e57 Mon Sep 17 00:00:00 2001 From: Chris de Claverie Date: Sun, 24 Jul 2022 10:21:19 +0200 Subject: [PATCH 037/315] Remove outdated warning --- src/expressions/array-expr.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/expressions/array-expr.md b/src/expressions/array-expr.md index 432a45ad8..fd7e2d378 100644 --- a/src/expressions/array-expr.md +++ b/src/expressions/array-expr.md @@ -29,13 +29,6 @@ When the repeat operand is a constant item, it is evaluated the length operand's If that value is `0`, then the constant item is not evaluated at all. For expressions that are not a constant item, it is evaluated exactly once, and then the result is copied the length operand's value times. -
- -Warning: In the case where the length operand is 0, and the repeat operand is a non-constant item, there is currently a bug in `rustc` where the value `a` is evaluated but not dropped, thus causing a leak. -See [issue #74836](https://github.com/rust-lang/rust/issues/74836). - -
- ```rust [1, 2, 3, 4]; ["a", "b", "c", "d"]; From 4662059acd4ab5dffe888a31256320347b0692a5 Mon Sep 17 00:00:00 2001 From: Caio Date: Mon, 25 Jul 2022 08:14:36 -0300 Subject: [PATCH 038/315] Add let_chains references --- src/expressions/if-expr.md | 122 ++++++++++++++++++++--------------- src/expressions/loop-expr.md | 48 ++++++++++---- 2 files changed, 108 insertions(+), 62 deletions(-) diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index 591437fc9..c82cad3d1 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -1,14 +1,22 @@ -# `if` and `if let` expressions +# `if` expressions -## `if` expressions +## Syntax + +The same syntax is used by `if`, `if let` and chains of expressions. > **Syntax**\ > _IfExpression_ :\ ->    `if` [_Expression_]_except struct expression_ [_BlockExpression_]\ ->    (`else` ( -> [_BlockExpression_] -> | _IfExpression_ -> | _IfLetExpression_ ) )\? +>    `if` _IfLetList_ [_BlockExpression_]\ +>    ( `else` _IfLetList_ [_BlockExpression_] )\? +> +> _IfLet_ :\ +>    [_Expression_]_except struct expression_ +> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ +> +> _IfLetList_ :\ +>    _IfLet_ ( && _IfLet_ )* + +## `if` An `if` expression is a conditional branch in program control. The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. @@ -37,16 +45,7 @@ let y = if 12 * 15 > 150 { assert_eq!(y, "Bigger"); ``` -## `if let` expressions - -> **Syntax**\ -> _IfLetExpression_ :\ ->    `if` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_ -> [_BlockExpression_]\ ->    (`else` ( -> [_BlockExpression_] -> | _IfExpression_ -> | _IfLetExpression_ ) )\? +## `if let` An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand. If the value of the scrutinee matches the pattern, the corresponding block will execute. @@ -90,27 +89,6 @@ let a = if let Some(1) = x { assert_eq!(a, 3); ``` -An `if let` expression is equivalent to a [`match` expression] as follows: - - -```rust,ignore -if let PATS = EXPR { - /* body */ -} else { - /*else */ -} -``` - -is equivalent to - - -```rust,ignore -match EXPR { - PATS => { /* body */ }, - _ => { /* else */ }, // () if there is no else -} -``` - Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions: ```rust @@ -126,30 +104,72 @@ if let E::X(n) | E::Y(n) = v { ``` The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. -Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]). -When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below: +Scrutinee expressions also cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_] due to ambiguity and precedence with [chains of expressions][_ChainsOfExpressions_]. - -```rust,ignore -// Before... -if let PAT = EXPR && EXPR { .. } +## Chains of expressions + +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: -// After... -if let PAT = ( EXPR && EXPR ) { .. } +```rust +fn single() { + let outer_opt = Some(Some(1i32)); + + if let Some(inner_opt) = outer_opt + && let Some(number) = inner_opt + && number == 1 + { + println!("Peek a boo"); + } +} + +The above is equivalent to the following without using expression chains: + +fn nested() { + let outer_opt = Some(Some(1i32)); + + if let Some(inner_opt) = outer_opt { + if let Some(number) = inner_opt { + if number == 1 { + println!("Peek a boo"); + } + } + } +} +``` + +In other words, chains are equivalent to nested [`if let` expressions]: + + +```rust,ignore +if let PAT0 = EXPR0 && let PAT1 = EXPR1 { + /* body */ +} else { + /* else */ +} +``` -// Before... -if let PAT = EXPR || EXPR { .. } +is equivalent to -// After... -if let PAT = ( EXPR || EXPR ) { .. } + +```rust,ignore +if let PAT0 = EXPR0 { + if let PAT1 = EXPR1 { + /* body */ + } + else { + /* else */ + } +} else { + /* else */ +} ``` [_BlockExpression_]: block-expr.md +[_ChainsOfExpressions_]: #chains-of-expressions [_Expression_]: ../expressions.md [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators [_Pattern_]: ../patterns.md [_Scrutinee_]: match-expr.md -[_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018 [`match` expression]: match-expr.md [boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 308f3e346..5033a1ce8 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -5,14 +5,12 @@ >    [_LoopLabel_]? (\ >          [_InfiniteLoopExpression_]\ >       | [_PredicateLoopExpression_]\ ->       | [_PredicatePatternLoopExpression_]\ >       | [_IteratorLoopExpression_]\ >    ) [_LoopLabel_]: #loop-labels [_InfiniteLoopExpression_]: #infinite-loops [_PredicateLoopExpression_]: #predicate-loops -[_PredicatePatternLoopExpression_]: #predicate-pattern-loops [_IteratorLoopExpression_]: #iterator-loops Rust supports four loop expressions: @@ -39,9 +37,23 @@ A `loop` expression containing associated [`break` expression(s)](#break-express ## Predicate loops +### Syntax + +The same syntax is used by `while`, `while let` and chains of expressions. + > **Syntax**\ -> _PredicateLoopExpression_ :\ ->    `while` [_Expression_]_except struct expression_ [_BlockExpression_] +> [_PredicateLoopExpression_] :\ +> _WhileExpression_ :\ +>    `while` _WhileLetList_ [_BlockExpression_] +> +> _WhileLet_ :\ +>    ( [_Expression_]_except struct expression_ +> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ ) +> +> _WhileLetList_ :\ +>    _WhileLet_ ( && _WhileLet_ )* + +### `while` A `while` loop begins by evaluating the [boolean] loop conditional operand. If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand. @@ -58,13 +70,7 @@ while i < 10 { } ``` -## Predicate pattern loops - -> **Syntax**\ -> [_PredicatePatternLoopExpression_] :\ ->    `while` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_ -> [_BlockExpression_] - +### `while let` A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression. If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement. @@ -117,6 +123,26 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() { As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. +### Chains of expressions + +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: + +```rust +fn main() { + let outer_opt = Some(Some(1i32)); + + while let Some(inner_opt) = outer_opt + && let Some(number) = inner_opt + && number == 1 + { + println!("Peek a boo"); + break; + } +} +``` + +The only remark is the fact that parenthesis (`while (let Some(a) = opt && (let Some(b) = a)) && b == 1`) and `||` operators (`while let A(x) = e1 || let B(x) = e2`) are not currently supported. + ## Iterator loops > **Syntax**\ From b83d8e616c47e11cfc152618e1b633311ffa29ad Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 25 Jul 2022 15:40:07 -0700 Subject: [PATCH 039/315] Unify while/while let and if/if let expressions. This updates the `if` and `while` expressions so that they each are presented as a single expression kind with multiple condition operators instead of being logically separated from their `let` counterparts. This also includes various fixes and additions. --- src/SUMMARY.md | 2 +- src/attributes/type_system.md | 1 - src/const_eval.md | 6 +- src/destructors.md | 4 +- src/expressions.md | 6 +- src/expressions/block-expr.md | 3 +- src/expressions/if-expr.md | 112 +++++++++++++-------------------- src/expressions/loop-expr.md | 62 +++++++++--------- src/expressions/struct-expr.md | 2 +- src/names.md | 4 +- src/names/namespaces.md | 4 +- src/patterns.md | 2 +- src/tokens.md | 4 +- 13 files changed, 91 insertions(+), 121 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 82d70d043..6a8f72475 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -62,7 +62,7 @@ - [Closure expressions](expressions/closure-expr.md) - [Loop expressions](expressions/loop-expr.md) - [Range expressions](expressions/range-expr.md) - - [If and if let expressions](expressions/if-expr.md) + - [If expressions](expressions/if-expr.md) - [Match expressions](expressions/match-expr.md) - [Return expressions](expressions/return-expr.md) - [Await expressions](expressions/await-expr.md) diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index 729069d26..d15836fb0 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -133,7 +133,6 @@ Non-exhaustive types are always considered inhabited in downstream crates. [_StructExpression_]: ../expressions/struct-expr.md [_StructPattern_]: ../patterns.md#struct-patterns [_TupleStructPattern_]: ../patterns.md#tuple-struct-patterns -[`if let`]: ../expressions/if-expr.md#if-let-expressions [`match`]: ../expressions/match-expr.md [attributes]: ../attributes.md [enum]: ../items/enumerations.md diff --git a/src/const_eval.md b/src/const_eval.md index c0560376c..d735a20ec 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -45,8 +45,8 @@ to be run. * pointer to address casts and * function pointer to address casts. * Calls of [const functions] and const methods. -* [loop], [while] and [`while let`] expressions. -* [if], [`if let`] and [match] expressions. +* [loop] and [while] expressions. +* [if] and [match] expressions. ## Const context @@ -121,7 +121,6 @@ Conversely, the following are possible in a const function, but not in a const c [grouped]: expressions/grouped-expr.md [interior mutability]: interior-mutability.md [if]: expressions/if-expr.md#if-expressions -[`if let`]: expressions/if-expr.md#if-let-expressions [lazy boolean]: expressions/operator-expr.md#lazy-boolean-operators [let statements]: statements.md#let-statements [literals]: expressions/literal-expr.md @@ -138,4 +137,3 @@ Conversely, the following are possible in a const function, but not in a const c [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md [while]: expressions/loop-expr.md#predicate-loops -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops diff --git a/src/destructors.md b/src/destructors.md index 6d616b3e7..083ed86eb 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -388,12 +388,12 @@ variable or field from being dropped automatically. [tuple expression]: expressions/tuple-expr.md#tuple-expressions [`for`]: expressions/loop-expr.md#iterator-loops -[`if let`]: expressions/if-expr.md#if-let-expressions +[`if let`]: expressions/if-expr.md#if-let-patterns [`if`]: expressions/if-expr.md#if-expressions [`let` statement]: statements.md#let-statements [`loop`]: expressions/loop-expr.md#infinite-loops [`match`]: expressions/match-expr.md -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: expressions/loop-expr.md#while-let-patterns [`while`]: expressions/loop-expr.md#predicate-loops [`::drop`]: ../std/ops/trait.Drop.html#tymethod.drop diff --git a/src/expressions.md b/src/expressions.md index 32ee658ff..5b6525fec 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -38,7 +38,6 @@ >       | [_UnsafeBlockExpression_]\ >       | [_LoopExpression_]\ >       | [_IfExpression_]\ ->       | [_IfLetExpression_]\ >       | [_MatchExpression_]\ >    ) @@ -295,13 +294,13 @@ They are never allowed before: [call expressions]: expressions/call-expr.md [field]: expressions/field-expr.md [functional update]: expressions/struct-expr.md#functional-update-syntax -[`if let`]: expressions/if-expr.md#if-let-expressions +[`if let`]: expressions/if-expr.md#if-let-patterns [match]: expressions/match-expr.md [method-call]: expressions/method-call-expr.md [paths]: expressions/path-expr.md [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: expressions/loop-expr.md#while-let-patterns [array expressions]: expressions/array-expr.md [array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions @@ -348,7 +347,6 @@ They are never allowed before: [_FieldExpression_]: expressions/field-expr.md [_GroupedExpression_]: expressions/grouped-expr.md [_IfExpression_]: expressions/if-expr.md#if-expressions -[_IfLetExpression_]: expressions/if-expr.md#if-let-expressions [_IndexExpression_]: expressions/array-expr.md#array-and-slice-indexing-expressions [_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators [_LiteralExpression_]: expressions/literal-expr.md diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index a68b27e56..01e6ef95c 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -145,7 +145,7 @@ let a = unsafe { an_unsafe_fn() }; [Inner attributes] are allowed directly after the opening brace of a block expression in the following situations: * [Function] and [method] bodies. -* Loop bodies ([`loop`], [`while`], [`while let`], and [`for`]). +* 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. @@ -172,7 +172,6 @@ fn is_unix_platform() -> bool { [`loop`]: loop-expr.md#infinite-loops [`std::ops::Fn`]: ../../std/ops/trait.Fn.html [`std::future::Future`]: ../../std/future/trait.Future.html -[`while let`]: loop-expr.md#predicate-pattern-loops [`while`]: loop-expr.md#predicate-loops [array expressions]: array-expr.md [call expressions]: call-expr.md diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index c82cad3d1..9de65df87 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -2,29 +2,30 @@ ## Syntax -The same syntax is used by `if`, `if let` and chains of expressions. - > **Syntax**\ > _IfExpression_ :\ ->    `if` _IfLetList_ [_BlockExpression_]\ ->    ( `else` _IfLetList_ [_BlockExpression_] )\? +>    `if` _IfConditions_ [_BlockExpression_]\ +>    (`else` ( [_BlockExpression_] | _IfExpression_ ) )\? > -> _IfLet_ :\ ->    [_Expression_]_except struct expression_ -> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ +> _IfConditions_ :\ +>    _IfCondition_ ( && _IfCondition_ )* > -> _IfLetList_ :\ ->    _IfLet_ ( && _IfLet_ )* - -## `if` +> _IfCondition_ :\ +>       [_Expression_]_except struct expression_\ +>    | `let` [_Pattern_] `=` [_Scrutinee_] An `if` expression is a conditional branch in program control. -The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. -The condition operands must have the [boolean type]. -If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped. -If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated. +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. + +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, +the consequent block is executed and any subsequent `else if` or `else` block is skipped. +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 all `if` and `else if` conditions evaluate to `false` then any `else` block is executed. -An if expression evaluates to the same value as the executed block, or `()` if no block is evaluated. + +An `if` expression evaluates to the same value as the executed block, or `()` if no block is evaluated. An `if` expression must have the same type in all situations. ```rust @@ -37,6 +38,7 @@ if x == 4 { println!("x is something else"); } +// `if` can be used as an expression. let y = if 12 * 15 > 150 { "Bigger" } else { @@ -45,17 +47,15 @@ let y = if 12 * 15 > 150 { assert_eq!(y, "Bigger"); ``` -## `if let` +## `if let` patterns -An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand. -If the value of the scrutinee matches the pattern, the corresponding block will execute. -Otherwise, flow proceeds to the following `else` block if it exists. -Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated. +`let` patterns in an `if` condition allow binding new variables into scope when the pattern matches successfully. +The following examples illustrate bindings using `let` patterns: ```rust let dish = ("Ham", "Eggs"); -// this body will be skipped because the pattern is refuted +// This body will be skipped because the pattern is refuted. if let ("Bacon", b) = dish { println!("Bacon is served with {}", b); } else { @@ -63,7 +63,7 @@ if let ("Bacon", b) = dish { println!("No bacon will be served"); } -// this body will execute +// This body will execute. if let ("Ham", b) = dish { println!("Ham is served with {}", b); } @@ -73,23 +73,8 @@ if let _ = 5 { } ``` -`if` and `if let` expressions can be intermixed: - -```rust -let x = Some(3); -let a = if let Some(1) = x { - 1 -} else if x == Some(2) { - 2 -} else if let Some(y) = x { - y -} else { - -1 -}; -assert_eq!(a, 3); -``` - -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 { @@ -103,10 +88,13 @@ if let E::X(n) | E::Y(n) = v { } ``` -The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. -Scrutinee expressions also cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_] due to ambiguity and precedence with [chains of expressions][_ChainsOfExpressions_]. +## Chains of conditions -## Chains of expressions +Multiple condition operands can be separated with `&&`. +Similar to a `&&` [_LazyBooleanOperatorExpression_], 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. + +The bindings of each pattern are put into scope to be available for the next condition operand and the consequent block. 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: @@ -121,9 +109,11 @@ fn single() { println!("Peek a boo"); } } +``` -The above is equivalent to the following without using expression chains: +The above is equivalent to the following without using chains of conditions: +```rust fn nested() { let outer_opt = Some(Some(1i32)); @@ -137,39 +127,23 @@ fn nested() { } ``` -In other words, chains are equivalent to nested [`if let` expressions]: +If any condition operand is a `let` pattern, then none of the condition operands can be a `||` [lazy boolean operator expression][_LazyBooleanOperatorExpression_] due to ambiguity and precedence with the `let` scrutinee. +If a `||` expression is needed, then parentheses can be used. For example: - -```rust,ignore -if let PAT0 = EXPR0 && let PAT1 = EXPR1 { - /* body */ -} else { - /* else */ -} +```rust +# let foo = Some(123); +# let condition1 = true; +# let condition2 = false; +// Parentheses are required here. +if let Some(x) = foo && (condition1 || condition2) { /*...*/ } ``` -is equivalent to - - -```rust,ignore -if let PAT0 = EXPR0 { - if let PAT1 = EXPR1 { - /* body */ - } - else { - /* else */ - } -} else { - /* else */ -} -``` [_BlockExpression_]: block-expr.md -[_ChainsOfExpressions_]: #chains-of-expressions [_Expression_]: ../expressions.md [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators [_Pattern_]: ../patterns.md [_Scrutinee_]: match-expr.md -[`match` expression]: match-expr.md +[`match` expressions]: match-expr.md [boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 5033a1ce8..d9458d56f 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -13,14 +13,13 @@ [_PredicateLoopExpression_]: #predicate-loops [_IteratorLoopExpression_]: #iterator-loops -Rust supports four loop expressions: +Rust supports three loop expressions: * A [`loop` expression](#infinite-loops) denotes an infinite loop. * A [`while` expression](#predicate-loops) loops until a predicate is false. -* A [`while let` expression](#predicate-pattern-loops) tests a pattern. * A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty. -All four types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels). +All three types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels). Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). ## Infinite loops @@ -37,27 +36,29 @@ A `loop` expression containing associated [`break` expression(s)](#break-express ## Predicate loops -### Syntax - -The same syntax is used by `while`, `while let` and chains of expressions. - > **Syntax**\ > [_PredicateLoopExpression_] :\ -> _WhileExpression_ :\ ->    `while` _WhileLetList_ [_BlockExpression_] +>    `while` _WhileConditions_ [_BlockExpression_] > -> _WhileLet_ :\ ->    ( [_Expression_]_except struct expression_ -> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ ) +> _WhileConditions_ :\ +>    _WhileCondition_ ( && _WhileCondition_ )* > -> _WhileLetList_ :\ ->    _WhileLet_ ( && _WhileLet_ )* +> _WhileCondition_ :\ +>       [_Expression_]_except struct expression_\ +>    | `let` [_Pattern_] `=` [_Scrutinee_] -### `while` +A `while` loop expression allows repeating the evaluation of a block while a set of conditions remain true. +The syntax of a `while` expression is a sequence of one or more condition operands separated by `&&`, +followed by a [_BlockExpression_]. -A `while` loop begins by evaluating the [boolean] loop conditional operand. -If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand. -If the loop conditional expression evaluates to `false`, the `while` expression completes. +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. +After the loop body successfully executes, the condition operands are re-evaluated to determine if the body should be executed again. +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. + +A `while` expression evaluates to `()`. An example: @@ -70,11 +71,10 @@ while i < 10 { } ``` -### `while let` +### `while let` patterns -A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression. -If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement. -Otherwise, the while expression completes. +`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]; @@ -121,9 +121,12 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() { } ``` -As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. +As is the case in [`if` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. + +### `while` condition chains -### Chains of expressions +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: @@ -141,8 +144,6 @@ fn main() { } ``` -The only remark is the fact that parenthesis (`while (let Some(a) = opt && (let Some(b) = a)) && b == 1`) and `||` operators (`while let A(x) = e1 || let B(x) = e2`) are not currently supported. - ## Iterator loops > **Syntax**\ @@ -259,7 +260,7 @@ A `break` expression is only permitted in the body of a loop, and has one of the >    `continue` [LIFETIME_OR_LABEL]? When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop *head*. -In the case of a `while` loop, the head is the conditional expression controlling the loop. +In the case of a `while` loop, the head is the conditional operands controlling the loop. In the case of a `for` loop, the head is the call-expression controlling the loop. Like `break`, `continue` is normally associated with the innermost enclosing loop, but `continue 'label` may be used to specify the loop affected. @@ -290,11 +291,12 @@ In the case a `loop` has an associated `break`, it is not considered diverging, [LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels [_BlockExpression_]: block-expr.md [_Expression_]: ../expressions.md +[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators [_Pattern_]: ../patterns.md [_Scrutinee_]: match-expr.md +[`if` condition chains]: if-expr.md#chains-of-conditions +[`if` expressions]: if-expr.md [`match` expression]: match-expr.md -[boolean]: ../types/boolean.md +[boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee [temporary values]: ../expressions.md#temporaries -[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators -[`if let` expressions]: if-expr.md#if-let-expressions diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md index 8caeff200..e0643fe2a 100644 --- a/src/expressions/struct-expr.md +++ b/src/expressions/struct-expr.md @@ -131,7 +131,7 @@ let b = Gamma{}; // Exact same value as `a`. [_PathInExpression_]: ../paths.md#paths-in-expressions [call expression]: call-expr.md [enum variant]: ../items/enumerations.md -[if let]: if-expr.md#if-let-expressions +[if let]: if-expr.md#if-let-patterns [if]: if-expr.md#if-expressions [loop]: loop-expr.md [match]: match-expr.md diff --git a/src/names.md b/src/names.md index fd8f50cd0..26bce0bd1 100644 --- a/src/names.md +++ b/src/names.md @@ -90,13 +90,13 @@ to with certain [path qualifiers] or aliases. [*visibility*]: visibility-and-privacy.md [`'static`]: keywords.md#weak-keywords [`for`]: expressions/loop-expr.md#iterator-loops -[`if let`]: expressions/if-expr.md#if-let-expressions +[`if let`]: expressions/if-expr.md#if-let-patterns [`let` statement]: statements.md#let-statements [`macro_export` attribute]: macros-by-example.md#path-based-scope [`macro_rules` declarations]: macros-by-example.md [`macro_use` attribute]: macros-by-example.md#the-macro_use-attribute [`match`]: expressions/match-expr.md -[`while let`]: expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: expressions/loop-expr.md#while-let-patterns [associated items]: items/associated-items.md [attributes]: attributes.md [Boolean type]: types/boolean.md diff --git a/src/names/namespaces.md b/src/names/namespaces.md index 14811697c..1c94745d8 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -118,14 +118,14 @@ It is still an error for a [`use` import] to shadow another macro, regardless of [`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute [`cfg` macro]: ../conditional-compilation.md#the-cfg-macro [`for`]: ../expressions/loop-expr.md#iterator-loops -[`if let`]: ../expressions/if-expr.md#if-let-expressions +[`if let`]: ../expressions/if-expr.md#if-let-patterns [`let`]: ../statements.md#let-statements [`macro_rules` declarations]: ../macros-by-example.md [`match`]: ../expressions/match-expr.md [`Self` constructors]: ../paths.md#self-1 [`Self` type]: ../paths.md#self-1 [`use` import]: ../items/use-declarations.md -[`while let`]: ../expressions/loop-expr.md#predicate-pattern-loops +[`while let`]: ../expressions/loop-expr.md#while-let-patterns [Associated const declarations]: ../items/associated-items.md#associated-constants [Associated function declarations]: ../items/associated-items.md#associated-functions-and-methods [Associated type declarations]: ../items/associated-items.md#associated-types diff --git a/src/patterns.md b/src/patterns.md index 5c81ecd87..3a1c609bf 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -69,7 +69,7 @@ Patterns are used in: parameters * [`match` expressions](expressions/match-expr.md) * [`if let` expressions](expressions/if-expr.md) -* [`while let` expressions](expressions/loop-expr.md#predicate-pattern-loops) +* [`while let` expressions](expressions/loop-expr.md#while-let-patterns) * [`for` expressions](expressions/loop-expr.md#iterator-loops) ## Destructuring diff --git a/src/tokens.md b/src/tokens.md index 197c20147..71a3527fd 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -710,7 +710,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [functions]: items/functions.md [generics]: items/generics.md [identifier]: identifiers.md -[if let]: expressions/if-expr.md#if-let-expressions +[if let]: expressions/if-expr.md#if-let-patterns [keywords]: keywords.md [lazy-bool]: expressions/operator-expr.md#lazy-boolean-operators [literal expressions]: expressions/literal-expr.md @@ -738,4 +738,4 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [unary minus operator]: expressions/operator-expr.md#negation-operators [use declarations]: items/use-declarations.md [use wildcards]: items/use-declarations.md -[while let]: expressions/loop-expr.md#predicate-pattern-loops +[while let]: expressions/loop-expr.md#while-let-patterns From 36a66c0ccf9f8a5b941b0df9923ece80d8714c83 Mon Sep 17 00:00:00 2001 From: pierwill <19642016+pierwill@users.noreply.github.com> Date: Wed, 27 Jul 2022 09:22:18 -0500 Subject: [PATCH 040/315] Update src/subtyping.md Co-authored-by: Ryan Scheel --- src/subtyping.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/subtyping.md b/src/subtyping.md index 7bca6c979..b31e25d8a 100644 --- a/src/subtyping.md +++ b/src/subtyping.md @@ -2,7 +2,7 @@ Subtyping is implicit and can occur at any stage in type checking or inference. Subtyping is restricted to two cases: -variance with respect to lifetimes, and between types with higher ranked +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. From bdaa92848c77f4eaadbab5dc753e0ec0b84c5221 Mon Sep 17 00:00:00 2001 From: Liigo Zhuang Date: Mon, 8 Aug 2022 14:49:20 +0800 Subject: [PATCH 041/315] a fix about .await --- src/expressions/await-expr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expressions/await-expr.md b/src/expressions/await-expr.md index b52cda1b9..feea1a368 100644 --- a/src/expressions/await-expr.md +++ b/src/expressions/await-expr.md @@ -16,7 +16,7 @@ More specifically, an await expression has the following effect. 2. Evaluate the future to a [future] `tmp`; 3. Pin `tmp` using [`Pin::new_unchecked`]; 4. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context); -5. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 2; +5. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 3; 6. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself. > **Edition differences**: Await expressions are only available beginning with Rust 2018. From 1efe76d2f4fd3ba5cf320c81777cbad80e691633 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 8 Aug 2022 18:11:13 +0300 Subject: [PATCH 042/315] Be less specific about the representation of `+bundle` --- src/items/external-blocks.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index dbe30ccc4..e768a1502 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -167,9 +167,9 @@ block. This modifier is only compatible with the `static` linking kind. Using any other kind will result in a compiler error. -When building a rlib or staticlib `+bundle` means that all object files from the native static -library will be added to the rlib or staticlib archive, and then used from it 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. 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 From 3036b18c92b0ed77a36ae29d556efc57f2a37b47 Mon Sep 17 00:00:00 2001 From: Lamb Date: Sun, 14 Aug 2022 14:15:35 +0200 Subject: [PATCH 043/315] cannot cast non-exhaustive enum from foreign crate --- src/attributes/type_system.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index d15836fb0..7f08557ca 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -127,6 +127,14 @@ match message { } ``` +It's also impossible to cast non-exhaustive types from foreign crates. +```rust, ignore +use othercrate::NonExhaustiveEnum; + +// Cannot cast a non-exhaustive enum outside of its defining crate. +let _ = NonExhaustiveEnum::default() as u8; +``` + Non-exhaustive types are always considered inhabited in downstream crates. [_MetaWord_]: ../attributes.md#meta-item-attribute-syntax From 4aff5bed5eb04411174a7bd7e86975d3eb7b62d5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Aug 2022 21:00:49 +0000 Subject: [PATCH 044/315] Revert "Unify while/while let and if/if let expressions." This reverts commit b83d8e616c47e11cfc152618e1b633311ffa29ad. --- src/SUMMARY.md | 2 +- src/attributes/type_system.md | 1 + src/const_eval.md | 6 +- src/destructors.md | 4 +- src/expressions.md | 6 +- src/expressions/block-expr.md | 3 +- src/expressions/if-expr.md | 112 ++++++++++++++++++++------------- src/expressions/loop-expr.md | 62 +++++++++--------- src/expressions/struct-expr.md | 2 +- src/names.md | 4 +- src/names/namespaces.md | 4 +- src/patterns.md | 2 +- src/tokens.md | 4 +- 13 files changed, 121 insertions(+), 91 deletions(-) diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 6a8f72475..82d70d043 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -62,7 +62,7 @@ - [Closure expressions](expressions/closure-expr.md) - [Loop expressions](expressions/loop-expr.md) - [Range expressions](expressions/range-expr.md) - - [If expressions](expressions/if-expr.md) + - [If and if let expressions](expressions/if-expr.md) - [Match expressions](expressions/match-expr.md) - [Return expressions](expressions/return-expr.md) - [Await expressions](expressions/await-expr.md) diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index d15836fb0..729069d26 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -133,6 +133,7 @@ Non-exhaustive types are always considered inhabited in downstream crates. [_StructExpression_]: ../expressions/struct-expr.md [_StructPattern_]: ../patterns.md#struct-patterns [_TupleStructPattern_]: ../patterns.md#tuple-struct-patterns +[`if let`]: ../expressions/if-expr.md#if-let-expressions [`match`]: ../expressions/match-expr.md [attributes]: ../attributes.md [enum]: ../items/enumerations.md diff --git a/src/const_eval.md b/src/const_eval.md index d735a20ec..c0560376c 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -45,8 +45,8 @@ to be run. * pointer to address casts and * function pointer to address casts. * Calls of [const functions] and const methods. -* [loop] and [while] expressions. -* [if] and [match] expressions. +* [loop], [while] and [`while let`] expressions. +* [if], [`if let`] and [match] expressions. ## Const context @@ -121,6 +121,7 @@ Conversely, the following are possible in a const function, but not in a const c [grouped]: expressions/grouped-expr.md [interior mutability]: interior-mutability.md [if]: expressions/if-expr.md#if-expressions +[`if let`]: expressions/if-expr.md#if-let-expressions [lazy boolean]: expressions/operator-expr.md#lazy-boolean-operators [let statements]: statements.md#let-statements [literals]: expressions/literal-expr.md @@ -137,3 +138,4 @@ Conversely, the following are possible in a const function, but not in a const c [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md [while]: expressions/loop-expr.md#predicate-loops +[`while let`]: expressions/loop-expr.md#predicate-pattern-loops diff --git a/src/destructors.md b/src/destructors.md index 083ed86eb..6d616b3e7 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -388,12 +388,12 @@ variable or field from being dropped automatically. [tuple expression]: expressions/tuple-expr.md#tuple-expressions [`for`]: expressions/loop-expr.md#iterator-loops -[`if let`]: expressions/if-expr.md#if-let-patterns +[`if let`]: expressions/if-expr.md#if-let-expressions [`if`]: expressions/if-expr.md#if-expressions [`let` statement]: statements.md#let-statements [`loop`]: expressions/loop-expr.md#infinite-loops [`match`]: expressions/match-expr.md -[`while let`]: expressions/loop-expr.md#while-let-patterns +[`while let`]: expressions/loop-expr.md#predicate-pattern-loops [`while`]: expressions/loop-expr.md#predicate-loops [`::drop`]: ../std/ops/trait.Drop.html#tymethod.drop diff --git a/src/expressions.md b/src/expressions.md index 5b6525fec..32ee658ff 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -38,6 +38,7 @@ >       | [_UnsafeBlockExpression_]\ >       | [_LoopExpression_]\ >       | [_IfExpression_]\ +>       | [_IfLetExpression_]\ >       | [_MatchExpression_]\ >    ) @@ -294,13 +295,13 @@ They are never allowed before: [call expressions]: expressions/call-expr.md [field]: expressions/field-expr.md [functional update]: expressions/struct-expr.md#functional-update-syntax -[`if let`]: expressions/if-expr.md#if-let-patterns +[`if let`]: expressions/if-expr.md#if-let-expressions [match]: expressions/match-expr.md [method-call]: expressions/method-call-expr.md [paths]: expressions/path-expr.md [struct]: expressions/struct-expr.md [tuple expressions]: expressions/tuple-expr.md -[`while let`]: expressions/loop-expr.md#while-let-patterns +[`while let`]: expressions/loop-expr.md#predicate-pattern-loops [array expressions]: expressions/array-expr.md [array indexing]: expressions/array-expr.md#array-and-slice-indexing-expressions @@ -347,6 +348,7 @@ They are never allowed before: [_FieldExpression_]: expressions/field-expr.md [_GroupedExpression_]: expressions/grouped-expr.md [_IfExpression_]: expressions/if-expr.md#if-expressions +[_IfLetExpression_]: expressions/if-expr.md#if-let-expressions [_IndexExpression_]: expressions/array-expr.md#array-and-slice-indexing-expressions [_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators [_LiteralExpression_]: expressions/literal-expr.md diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index 01e6ef95c..a68b27e56 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -145,7 +145,7 @@ let a = unsafe { an_unsafe_fn() }; [Inner attributes] are allowed directly after the opening brace of a block expression in the following situations: * [Function] and [method] bodies. -* Loop bodies ([`loop`], [`while`], and [`for`]). +* Loop bodies ([`loop`], [`while`], [`while let`], and [`for`]). * Block expressions used as a [statement]. * Block expressions as elements of [array expressions], [tuple expressions], [call expressions], and tuple-style [struct] expressions. @@ -172,6 +172,7 @@ fn is_unix_platform() -> bool { [`loop`]: loop-expr.md#infinite-loops [`std::ops::Fn`]: ../../std/ops/trait.Fn.html [`std::future::Future`]: ../../std/future/trait.Future.html +[`while let`]: loop-expr.md#predicate-pattern-loops [`while`]: loop-expr.md#predicate-loops [array expressions]: array-expr.md [call expressions]: call-expr.md diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index 9de65df87..c82cad3d1 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -2,30 +2,29 @@ ## Syntax +The same syntax is used by `if`, `if let` and chains of expressions. + > **Syntax**\ > _IfExpression_ :\ ->    `if` _IfConditions_ [_BlockExpression_]\ ->    (`else` ( [_BlockExpression_] | _IfExpression_ ) )\? +>    `if` _IfLetList_ [_BlockExpression_]\ +>    ( `else` _IfLetList_ [_BlockExpression_] )\? > -> _IfConditions_ :\ ->    _IfCondition_ ( && _IfCondition_ )* +> _IfLet_ :\ +>    [_Expression_]_except struct expression_ +> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ > -> _IfCondition_ :\ ->       [_Expression_]_except struct expression_\ ->    | `let` [_Pattern_] `=` [_Scrutinee_] +> _IfLetList_ :\ +>    _IfLet_ ( && _IfLet_ )* + +## `if` An `if` expression is a conditional branch in program control. -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. - -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, -the consequent block is executed and any subsequent `else if` or `else` block is skipped. -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. +The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. +The condition operands must have the [boolean type]. +If a condition operand evaluates to `true`, the consequent block is executed and any subsequent `else if` or `else` block is skipped. +If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated. If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed. - -An `if` expression evaluates to the same value as the executed block, or `()` if no block is evaluated. +An if expression evaluates to the same value as the executed block, or `()` if no block is evaluated. An `if` expression must have the same type in all situations. ```rust @@ -38,7 +37,6 @@ if x == 4 { println!("x is something else"); } -// `if` can be used as an expression. let y = if 12 * 15 > 150 { "Bigger" } else { @@ -47,15 +45,17 @@ let y = if 12 * 15 > 150 { assert_eq!(y, "Bigger"); ``` -## `if let` patterns +## `if let` -`let` patterns in an `if` condition allow binding new variables into scope when the pattern matches successfully. -The following examples illustrate bindings using `let` patterns: +An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand. +If the value of the scrutinee matches the pattern, the corresponding block will execute. +Otherwise, flow proceeds to the following `else` block if it exists. +Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated. ```rust let dish = ("Ham", "Eggs"); -// This body will be skipped because the pattern is refuted. +// this body will be skipped because the pattern is refuted if let ("Bacon", b) = dish { println!("Bacon is served with {}", b); } else { @@ -63,7 +63,7 @@ if let ("Bacon", b) = dish { println!("No bacon will be served"); } -// This body will execute. +// this body will execute if let ("Ham", b) = dish { println!("Ham is served with {}", b); } @@ -73,8 +73,23 @@ if let _ = 5 { } ``` -Multiple patterns may be specified with the `|` operator. -This has the same semantics as with `|` in [`match` expressions]: +`if` and `if let` expressions can be intermixed: + +```rust +let x = Some(3); +let a = if let Some(1) = x { + 1 +} else if x == Some(2) { + 2 +} else if let Some(y) = x { + y +} else { + -1 +}; +assert_eq!(a, 3); +``` + +Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions: ```rust enum E { @@ -88,13 +103,10 @@ if let E::X(n) | E::Y(n) = v { } ``` -## Chains of conditions +The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. +Scrutinee expressions also cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_] due to ambiguity and precedence with [chains of expressions][_ChainsOfExpressions_]. -Multiple condition operands can be separated with `&&`. -Similar to a `&&` [_LazyBooleanOperatorExpression_], 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. - -The bindings of each pattern are put into scope to be available for the next condition operand and the consequent block. +## Chains of expressions 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: @@ -109,11 +121,9 @@ fn single() { println!("Peek a boo"); } } -``` -The above is equivalent to the following without using chains of conditions: +The above is equivalent to the following without using expression chains: -```rust fn nested() { let outer_opt = Some(Some(1i32)); @@ -127,23 +137,39 @@ fn nested() { } ``` -If any condition operand is a `let` pattern, then none of the condition operands can be a `||` [lazy boolean operator expression][_LazyBooleanOperatorExpression_] due to ambiguity and precedence with the `let` scrutinee. -If a `||` expression is needed, then parentheses can be used. For example: +In other words, chains are equivalent to nested [`if let` expressions]: -```rust -# let foo = Some(123); -# let condition1 = true; -# let condition2 = false; -// Parentheses are required here. -if let Some(x) = foo && (condition1 || condition2) { /*...*/ } + +```rust,ignore +if let PAT0 = EXPR0 && let PAT1 = EXPR1 { + /* body */ +} else { + /* else */ +} ``` +is equivalent to + + +```rust,ignore +if let PAT0 = EXPR0 { + if let PAT1 = EXPR1 { + /* body */ + } + else { + /* else */ + } +} else { + /* else */ +} +``` [_BlockExpression_]: block-expr.md +[_ChainsOfExpressions_]: #chains-of-expressions [_Expression_]: ../expressions.md [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators [_Pattern_]: ../patterns.md [_Scrutinee_]: match-expr.md -[`match` expressions]: match-expr.md +[`match` expression]: match-expr.md [boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index d9458d56f..5033a1ce8 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -13,13 +13,14 @@ [_PredicateLoopExpression_]: #predicate-loops [_IteratorLoopExpression_]: #iterator-loops -Rust supports three loop expressions: +Rust supports four loop expressions: * A [`loop` expression](#infinite-loops) denotes an infinite loop. * A [`while` expression](#predicate-loops) loops until a predicate is false. +* A [`while let` expression](#predicate-pattern-loops) tests a pattern. * A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty. -All three types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels). +All four types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels). Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). ## Infinite loops @@ -36,29 +37,27 @@ A `loop` expression containing associated [`break` expression(s)](#break-express ## Predicate loops +### Syntax + +The same syntax is used by `while`, `while let` and chains of expressions. + > **Syntax**\ > [_PredicateLoopExpression_] :\ ->    `while` _WhileConditions_ [_BlockExpression_] +> _WhileExpression_ :\ +>    `while` _WhileLetList_ [_BlockExpression_] > -> _WhileConditions_ :\ ->    _WhileCondition_ ( && _WhileCondition_ )* +> _WhileLet_ :\ +>    ( [_Expression_]_except struct expression_ +> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ ) > -> _WhileCondition_ :\ ->       [_Expression_]_except struct expression_\ ->    | `let` [_Pattern_] `=` [_Scrutinee_] +> _WhileLetList_ :\ +>    _WhileLet_ ( && _WhileLet_ )* -A `while` loop expression allows repeating the evaluation of a block while a set of conditions remain true. -The syntax of a `while` expression is a sequence of one or more condition operands separated by `&&`, -followed by a [_BlockExpression_]. +### `while` -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. -After the loop body successfully executes, the condition operands are re-evaluated to determine if the body should be executed again. -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. - -A `while` expression evaluates to `()`. +A `while` loop begins by evaluating the [boolean] loop conditional operand. +If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand. +If the loop conditional expression evaluates to `false`, the `while` expression completes. An example: @@ -71,10 +70,11 @@ while i < 10 { } ``` -### `while let` patterns +### `while let` -`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: +A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression. +If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement. +Otherwise, the while expression completes. ```rust let mut x = vec![1, 2, 3]; @@ -121,12 +121,9 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() { } ``` -As is the case in [`if` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. - -### `while` condition chains +As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. -Multiple condition operands can be separated with `&&`. -These have the same semantics and restrictions as [`if` condition chains]. +### Chains of expressions 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: @@ -144,6 +141,8 @@ fn main() { } ``` +The only remark is the fact that parenthesis (`while (let Some(a) = opt && (let Some(b) = a)) && b == 1`) and `||` operators (`while let A(x) = e1 || let B(x) = e2`) are not currently supported. + ## Iterator loops > **Syntax**\ @@ -260,7 +259,7 @@ A `break` expression is only permitted in the body of a loop, and has one of the >    `continue` [LIFETIME_OR_LABEL]? When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop *head*. -In the case of a `while` loop, the head is the conditional operands controlling the loop. +In the case of a `while` loop, the head is the conditional expression controlling the loop. In the case of a `for` loop, the head is the call-expression controlling the loop. Like `break`, `continue` is normally associated with the innermost enclosing loop, but `continue 'label` may be used to specify the loop affected. @@ -291,12 +290,11 @@ In the case a `loop` has an associated `break`, it is not considered diverging, [LIFETIME_OR_LABEL]: ../tokens.md#lifetimes-and-loop-labels [_BlockExpression_]: block-expr.md [_Expression_]: ../expressions.md -[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators [_Pattern_]: ../patterns.md [_Scrutinee_]: match-expr.md -[`if` condition chains]: if-expr.md#chains-of-conditions -[`if` expressions]: if-expr.md [`match` expression]: match-expr.md -[boolean type]: ../types/boolean.md +[boolean]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee [temporary values]: ../expressions.md#temporaries +[_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators +[`if let` expressions]: if-expr.md#if-let-expressions diff --git a/src/expressions/struct-expr.md b/src/expressions/struct-expr.md index e0643fe2a..8caeff200 100644 --- a/src/expressions/struct-expr.md +++ b/src/expressions/struct-expr.md @@ -131,7 +131,7 @@ let b = Gamma{}; // Exact same value as `a`. [_PathInExpression_]: ../paths.md#paths-in-expressions [call expression]: call-expr.md [enum variant]: ../items/enumerations.md -[if let]: if-expr.md#if-let-patterns +[if let]: if-expr.md#if-let-expressions [if]: if-expr.md#if-expressions [loop]: loop-expr.md [match]: match-expr.md diff --git a/src/names.md b/src/names.md index 26bce0bd1..fd8f50cd0 100644 --- a/src/names.md +++ b/src/names.md @@ -90,13 +90,13 @@ to with certain [path qualifiers] or aliases. [*visibility*]: visibility-and-privacy.md [`'static`]: keywords.md#weak-keywords [`for`]: expressions/loop-expr.md#iterator-loops -[`if let`]: expressions/if-expr.md#if-let-patterns +[`if let`]: expressions/if-expr.md#if-let-expressions [`let` statement]: statements.md#let-statements [`macro_export` attribute]: macros-by-example.md#path-based-scope [`macro_rules` declarations]: macros-by-example.md [`macro_use` attribute]: macros-by-example.md#the-macro_use-attribute [`match`]: expressions/match-expr.md -[`while let`]: expressions/loop-expr.md#while-let-patterns +[`while let`]: expressions/loop-expr.md#predicate-pattern-loops [associated items]: items/associated-items.md [attributes]: attributes.md [Boolean type]: types/boolean.md diff --git a/src/names/namespaces.md b/src/names/namespaces.md index 1c94745d8..14811697c 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -118,14 +118,14 @@ It is still an error for a [`use` import] to shadow another macro, regardless of [`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute [`cfg` macro]: ../conditional-compilation.md#the-cfg-macro [`for`]: ../expressions/loop-expr.md#iterator-loops -[`if let`]: ../expressions/if-expr.md#if-let-patterns +[`if let`]: ../expressions/if-expr.md#if-let-expressions [`let`]: ../statements.md#let-statements [`macro_rules` declarations]: ../macros-by-example.md [`match`]: ../expressions/match-expr.md [`Self` constructors]: ../paths.md#self-1 [`Self` type]: ../paths.md#self-1 [`use` import]: ../items/use-declarations.md -[`while let`]: ../expressions/loop-expr.md#while-let-patterns +[`while let`]: ../expressions/loop-expr.md#predicate-pattern-loops [Associated const declarations]: ../items/associated-items.md#associated-constants [Associated function declarations]: ../items/associated-items.md#associated-functions-and-methods [Associated type declarations]: ../items/associated-items.md#associated-types diff --git a/src/patterns.md b/src/patterns.md index 3a1c609bf..5c81ecd87 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -69,7 +69,7 @@ Patterns are used in: parameters * [`match` expressions](expressions/match-expr.md) * [`if let` expressions](expressions/if-expr.md) -* [`while let` expressions](expressions/loop-expr.md#while-let-patterns) +* [`while let` expressions](expressions/loop-expr.md#predicate-pattern-loops) * [`for` expressions](expressions/loop-expr.md#iterator-loops) ## Destructuring diff --git a/src/tokens.md b/src/tokens.md index 71a3527fd..197c20147 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -710,7 +710,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [functions]: items/functions.md [generics]: items/generics.md [identifier]: identifiers.md -[if let]: expressions/if-expr.md#if-let-patterns +[if let]: expressions/if-expr.md#if-let-expressions [keywords]: keywords.md [lazy-bool]: expressions/operator-expr.md#lazy-boolean-operators [literal expressions]: expressions/literal-expr.md @@ -738,4 +738,4 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [unary minus operator]: expressions/operator-expr.md#negation-operators [use declarations]: items/use-declarations.md [use wildcards]: items/use-declarations.md -[while let]: expressions/loop-expr.md#while-let-patterns +[while let]: expressions/loop-expr.md#predicate-pattern-loops From db6fc4e9d4737af84ca2e5137df3dcf3485e5e54 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 14 Aug 2022 21:00:55 +0000 Subject: [PATCH 045/315] Revert "Add let_chains references" This reverts commit 4662059acd4ab5dffe888a31256320347b0692a5. --- src/expressions/if-expr.md | 122 +++++++++++++++-------------------- src/expressions/loop-expr.md | 48 ++++---------- 2 files changed, 62 insertions(+), 108 deletions(-) diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index c82cad3d1..591437fc9 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -1,22 +1,14 @@ -# `if` expressions +# `if` and `if let` expressions -## Syntax - -The same syntax is used by `if`, `if let` and chains of expressions. +## `if` expressions > **Syntax**\ > _IfExpression_ :\ ->    `if` _IfLetList_ [_BlockExpression_]\ ->    ( `else` _IfLetList_ [_BlockExpression_] )\? -> -> _IfLet_ :\ ->    [_Expression_]_except struct expression_ -> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ -> -> _IfLetList_ :\ ->    _IfLet_ ( && _IfLet_ )* - -## `if` +>    `if` [_Expression_]_except struct expression_ [_BlockExpression_]\ +>    (`else` ( +> [_BlockExpression_] +> | _IfExpression_ +> | _IfLetExpression_ ) )\? An `if` expression is a conditional branch in program control. The syntax of an `if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` block. @@ -45,7 +37,16 @@ let y = if 12 * 15 > 150 { assert_eq!(y, "Bigger"); ``` -## `if let` +## `if let` expressions + +> **Syntax**\ +> _IfLetExpression_ :\ +>    `if` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_ +> [_BlockExpression_]\ +>    (`else` ( +> [_BlockExpression_] +> | _IfExpression_ +> | _IfLetExpression_ ) )\? An `if let` expression is semantically similar to an `if` expression but in place of a condition operand it expects the keyword `let` followed by a pattern, an `=` and a [scrutinee] operand. If the value of the scrutinee matches the pattern, the corresponding block will execute. @@ -89,6 +90,27 @@ let a = if let Some(1) = x { assert_eq!(a, 3); ``` +An `if let` expression is equivalent to a [`match` expression] as follows: + + +```rust,ignore +if let PATS = EXPR { + /* body */ +} else { + /*else */ +} +``` + +is equivalent to + + +```rust,ignore +match EXPR { + PATS => { /* body */ }, + _ => { /* else */ }, // () if there is no else +} +``` + Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions: ```rust @@ -104,72 +126,30 @@ if let E::X(n) | E::Y(n) = v { ``` The expression cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. -Scrutinee expressions also cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_] due to ambiguity and precedence with [chains of expressions][_ChainsOfExpressions_]. - -## Chains of expressions - -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: +Use of a lazy boolean operator is ambiguous with a planned feature change of the language (the implementation of if-let chains - see [eRFC 2947][_eRFCIfLetChain_]). +When lazy boolean operator expression is desired, this can be achieved by using parenthesis as below: -```rust -fn single() { - let outer_opt = Some(Some(1i32)); - - if let Some(inner_opt) = outer_opt - && let Some(number) = inner_opt - && number == 1 - { - println!("Peek a boo"); - } -} - -The above is equivalent to the following without using expression chains: - -fn nested() { - let outer_opt = Some(Some(1i32)); - - if let Some(inner_opt) = outer_opt { - if let Some(number) = inner_opt { - if number == 1 { - println!("Peek a boo"); - } - } - } -} -``` - -In other words, chains are equivalent to nested [`if let` expressions]: - - + ```rust,ignore -if let PAT0 = EXPR0 && let PAT1 = EXPR1 { - /* body */ -} else { - /* else */ -} -``` +// Before... +if let PAT = EXPR && EXPR { .. } -is equivalent to +// After... +if let PAT = ( EXPR && EXPR ) { .. } - -```rust,ignore -if let PAT0 = EXPR0 { - if let PAT1 = EXPR1 { - /* body */ - } - else { - /* else */ - } -} else { - /* else */ -} +// Before... +if let PAT = EXPR || EXPR { .. } + +// After... +if let PAT = ( EXPR || EXPR ) { .. } ``` [_BlockExpression_]: block-expr.md -[_ChainsOfExpressions_]: #chains-of-expressions [_Expression_]: ../expressions.md [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators [_Pattern_]: ../patterns.md [_Scrutinee_]: match-expr.md +[_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018 [`match` expression]: match-expr.md [boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 5033a1ce8..308f3e346 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -5,12 +5,14 @@ >    [_LoopLabel_]? (\ >          [_InfiniteLoopExpression_]\ >       | [_PredicateLoopExpression_]\ +>       | [_PredicatePatternLoopExpression_]\ >       | [_IteratorLoopExpression_]\ >    ) [_LoopLabel_]: #loop-labels [_InfiniteLoopExpression_]: #infinite-loops [_PredicateLoopExpression_]: #predicate-loops +[_PredicatePatternLoopExpression_]: #predicate-pattern-loops [_IteratorLoopExpression_]: #iterator-loops Rust supports four loop expressions: @@ -37,23 +39,9 @@ A `loop` expression containing associated [`break` expression(s)](#break-express ## Predicate loops -### Syntax - -The same syntax is used by `while`, `while let` and chains of expressions. - > **Syntax**\ -> [_PredicateLoopExpression_] :\ -> _WhileExpression_ :\ ->    `while` _WhileLetList_ [_BlockExpression_] -> -> _WhileLet_ :\ ->    ( [_Expression_]_except struct expression_ -> | `let` [_Pattern_] `=` [_Expression_]_except struct expression_ ) -> -> _WhileLetList_ :\ ->    _WhileLet_ ( && _WhileLet_ )* - -### `while` +> _PredicateLoopExpression_ :\ +>    `while` [_Expression_]_except struct expression_ [_BlockExpression_] A `while` loop begins by evaluating the [boolean] loop conditional operand. If the loop conditional operand evaluates to `true`, the loop body block executes, then control returns to the loop conditional operand. @@ -70,7 +58,13 @@ while i < 10 { } ``` -### `while let` +## Predicate pattern loops + +> **Syntax**\ +> [_PredicatePatternLoopExpression_] :\ +>    `while` `let` [_Pattern_] `=` [_Scrutinee_]_except lazy boolean operator expression_ +> [_BlockExpression_] + A `while let` loop is semantically similar to a `while` loop but in place of a condition expression it expects the keyword `let` followed by a pattern, an `=`, a [scrutinee] expression and a block expression. If the value of the scrutinee matches the pattern, the loop body block executes then control returns to the pattern matching statement. @@ -123,26 +117,6 @@ while let Some(v @ 1) | Some(v @ 2) = vals.pop() { As is the case in [`if let` expressions], the scrutinee cannot be a [lazy boolean operator expression][_LazyBooleanOperatorExpression_]. -### Chains of expressions - -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: - -```rust -fn main() { - let outer_opt = Some(Some(1i32)); - - while let Some(inner_opt) = outer_opt - && let Some(number) = inner_opt - && number == 1 - { - println!("Peek a boo"); - break; - } -} -``` - -The only remark is the fact that parenthesis (`while (let Some(a) = opt && (let Some(b) = a)) && b == 1`) and `||` operators (`while let A(x) = e1 || let B(x) = e2`) are not currently supported. - ## Iterator loops > **Syntax**\ From bce9bb30bae071776a22ccdb09af1a78bb3aeb63 Mon Sep 17 00:00:00 2001 From: "Farya L. M" <57440804+lambinoo@users.noreply.github.com> Date: Tue, 16 Aug 2022 19:54:12 +0200 Subject: [PATCH 046/315] Update type_system.md --- src/attributes/type_system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index 7f08557ca..f378c4d1d 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -127,7 +127,7 @@ match message { } ``` -It's also impossible to cast non-exhaustive types from foreign crates. +It's also not allowed to cast non-exhaustive types from foreign crates. ```rust, ignore use othercrate::NonExhaustiveEnum; From 8fda26b2aa4c24d6902d283badd0a75ae51d487e Mon Sep 17 00:00:00 2001 From: xd009642 Date: Tue, 16 Aug 2022 21:47:56 +0100 Subject: [PATCH 047/315] Initial stab at docs for RFC2867 --- src/attributes/codegen.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 4ebabaccf..e18c8679d 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -352,3 +352,18 @@ trait object whose methods are attributed. [`core::intrinsics::caller_location`]: ../../core/intrinsics/fn.caller_location.html [`core::panic::Location::caller`]: ../../core/panic/struct.Location.html#method.caller [`Location`]: ../../core/panic/struct.Location.html + +## The `instruction_set` attribute + +The `instruction_set` attribute may be applied to a function to enable code generation for a specific +instruction set supported by the target architecture. Currently, this is only available for `ARMv4T` +devices where the architecture has "ARM code" and "Thumb code" available and a single program may +utilise both of these. If not specified the default instruction set for the target will be used. + +```rust +#[instruction_set(arm::a32)] +fn foo_arm_code() {} + +#[instruction_set(arm::t32)] +fn bar_thumb_code() {} +``` From ef7036576c03bf56748892a0ebd151946f6dfc9f Mon Sep 17 00:00:00 2001 From: xd009642 Date: Tue, 16 Aug 2022 21:50:47 +0100 Subject: [PATCH 048/315] Move to US spelling --- src/attributes/codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index e18c8679d..ff38f3d98 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -358,7 +358,7 @@ trait object whose methods are attributed. The `instruction_set` attribute may be applied to a function to enable code generation for a specific instruction set supported by the target architecture. Currently, this is only available for `ARMv4T` devices where the architecture has "ARM code" and "Thumb code" available and a single program may -utilise both of these. If not specified the default instruction set for the target will be used. +utilize both of these. If not specified the default instruction set for the target will be used. ```rust #[instruction_set(arm::a32)] From e389abd88300e4ac3131e8761779e20c45b8b665 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Tue, 16 Aug 2022 23:13:41 +0100 Subject: [PATCH 049/315] Apply feedback --- src/attributes.md | 1 + src/attributes/codegen.md | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index 857cd7d72..194261c6f 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -246,6 +246,7 @@ The following is an index of all built-in attributes. - [`no_builtins`] — Disables use of certain built-in functions. - [`target_feature`] — Configure platform-specific code generation. - [`track_caller`] - Pass the parent call location to `std::panic::Location::caller()`. + - [`instruction_set`] - Specify the instruction set used to generate a functions code - Documentation - `doc` — Specifies documentation. See [The Rustdoc Book] for more information. [Doc comments] are transformed into `doc` attributes. diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index ff38f3d98..f75129dda 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -355,11 +355,17 @@ trait object whose methods are attributed. ## The `instruction_set` attribute -The `instruction_set` attribute may be applied to a function to enable code generation for a specific -instruction set supported by the target architecture. Currently, this is only available for `ARMv4T` -devices where the architecture has "ARM code" and "Thumb code" available and a single program may -utilize both of these. If not specified the default instruction set for the target will be used. +The *`instruction_set` attribute* may be applied to a function to enable code generation for a specific +instruction set supported by the target architecture. It uses the [_MetaListPath_] syntax and a path +comprised of the architecture and instruction set to specify how to generate the code for +architectures where a single program may utilize multiple instruction sets. +The following values are available on targets for the `ARMv4` architecture: + +* `arm::a32` - Uses ARM code. +* `arm::t32` - Uses Thumb code. + + ```rust #[instruction_set(arm::a32)] fn foo_arm_code() {} @@ -367,3 +373,5 @@ fn foo_arm_code() {} #[instruction_set(arm::t32)] fn bar_thumb_code() {} ``` + +[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax From 8919fc1bddcb09ddd06253b12c8495207e892e38 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Wed, 17 Aug 2022 08:16:50 +0100 Subject: [PATCH 050/315] Mention ARMv5te --- src/attributes/codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index f75129dda..925b9ded2 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -360,7 +360,7 @@ instruction set supported by the target architecture. It uses the [_MetaListPath comprised of the architecture and instruction set to specify how to generate the code for architectures where a single program may utilize multiple instruction sets. -The following values are available on targets for the `ARMv4` architecture: +The following values are available on targets for the `ARMv4` and ARMv5te` architectures: * `arm::a32` - Uses ARM code. * `arm::t32` - Uses Thumb code. From 3315bbc80f763e087aeb196da8a7c616b6116ed9 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Fri, 19 Aug 2022 08:48:36 +0100 Subject: [PATCH 051/315] Add link reference --- src/attributes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/attributes.md b/src/attributes.md index 194261c6f..7da42388d 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -297,6 +297,7 @@ The following is an index of all built-in attributes. [`global_allocator`]: runtime.md#the-global_allocator-attribute [`ignore`]: attributes/testing.md#the-ignore-attribute [`inline`]: attributes/codegen.md#the-inline-attribute +[`instruction_set`]: attributes/codegen.md#the-instruction-set-attribute [`link_name`]: items/external-blocks.md#the-link_name-attribute [`link_section`]: abi.md#the-link_section-attribute [`link`]: items/external-blocks.md#the-link-attribute From 33e327187495101b120b300fa55b8939c97eb250 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Fri, 19 Aug 2022 08:49:34 +0100 Subject: [PATCH 052/315] Apply ignore --- src/attributes/codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 925b9ded2..60f924d60 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -366,7 +366,7 @@ The following values are available on targets for the `ARMv4` and ARMv5te` archi * `arm::t32` - Uses Thumb code. -```rust +```rust,ignore #[instruction_set(arm::a32)] fn foo_arm_code() {} From d27f43f4e235e03394c6999566026ce9bc2d3e9e Mon Sep 17 00:00:00 2001 From: xd009642 Date: Fri, 19 Aug 2022 09:01:48 +0100 Subject: [PATCH 053/315] Remove spaces at end of lines --- src/attributes/codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 60f924d60..57c1d5a18 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -358,7 +358,7 @@ trait object whose methods are attributed. The *`instruction_set` attribute* may be applied to a function to enable code generation for a specific instruction set supported by the target architecture. It uses the [_MetaListPath_] syntax and a path comprised of the architecture and instruction set to specify how to generate the code for -architectures where a single program may utilize multiple instruction sets. +architectures where a single program may utilize multiple instruction sets. The following values are available on targets for the `ARMv4` and ARMv5te` architectures: From dbb8e2a834fc0f1e16ed08128f24595af7e243b7 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Fri, 19 Aug 2022 09:26:53 +0100 Subject: [PATCH 054/315] hopefully fix link --- src/attributes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes.md b/src/attributes.md index 7da42388d..7da406bb3 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -297,7 +297,7 @@ The following is an index of all built-in attributes. [`global_allocator`]: runtime.md#the-global_allocator-attribute [`ignore`]: attributes/testing.md#the-ignore-attribute [`inline`]: attributes/codegen.md#the-inline-attribute -[`instruction_set`]: attributes/codegen.md#the-instruction-set-attribute +[`instruction_set`]: attributes/codegen.md#the-instruction_set-attribute [`link_name`]: items/external-blocks.md#the-link_name-attribute [`link_section`]: abi.md#the-link_section-attribute [`link`]: items/external-blocks.md#the-link-attribute From d5d9829cc0468b001c19365b2959f9d21171a9ab Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 22 Aug 2022 18:04:32 +0200 Subject: [PATCH 055/315] allow to quickly edit a page directly on github --- book.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/book.toml b/book.toml index 2bc218fe4..19b9afc79 100644 --- a/book.toml +++ b/book.toml @@ -6,6 +6,7 @@ author = "The Rust Project Developers" [output.html] additional-css = ["theme/reference.css"] git-repository-url = "https://github.com/rust-lang/reference/" +edit-url-template = "https://github.com/rust-lang/reference/edit/master/{path}" [output.html.redirect] "/expressions/enum-variant-expr.html" = "struct-expr.html" From c126440392be42d9dd3906478111cc7b52473d89 Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Sat, 27 Aug 2022 13:39:39 +0100 Subject: [PATCH 056/315] Update examples of what implements `Termination` --- src/attributes/testing.md | 3 +-- src/crates-and-source-files.md | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/attributes/testing.md b/src/attributes/testing.md index 63df999ad..2c3b29286 100644 --- a/src/attributes/testing.md +++ b/src/attributes/testing.md @@ -12,9 +12,8 @@ functions are only compiled when in test mode. Test functions must be free, monomorphic functions that take no arguments, and the return type must implement the [`Termination`] trait, for example: * `()` -* `Result<(), E> where E: Debug` +* `Result where T: Termination, E: Debug` * `!` - diff --git a/src/crates-and-source-files.md b/src/crates-and-source-files.md index 6922b0ee3..8d54c3f6b 100644 --- a/src/crates-and-source-files.md +++ b/src/crates-and-source-files.md @@ -123,10 +123,9 @@ fn main() -> impl std::process::Termination { > > * `()` > * [`!`] +> * [`Infallible`] > * [`ExitCode`] -> * `Result<(), E> where E: Debug` -> * `Result where E: Debug` - +> * `Result where T: Termination, E: Debug` @@ -165,6 +164,7 @@ or `_` (U+005F) characters. [_shebang_]: https://en.wikipedia.org/wiki/Shebang_(Unix) [_utf8 byte order mark_]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 [`ExitCode`]: ../std/process/struct.ExitCode.html +[`Infallible`]: ../std/convert/enum.Infallible.html [`Termination`]: ../std/process/trait.Termination.html [attribute]: attributes.md [attributes]: attributes.md From 33cc59a684310570456ae7bc61f5bdc9400b59a2 Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sat, 3 Sep 2022 17:41:29 -0700 Subject: [PATCH 057/315] Clarify that 0 is a valid multiple of a type's alignment The reference currently states that "[t]he size of a value is always a multiple of its alignment." This might be taken to imply that a type's size is greater than or equal to its alignment. This commit clarifies that 0 is a valid multiple; zero-sized types have 0 size and nonzero alignment. --- src/type-layout.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index ce9296662..dc9bed92c 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -20,8 +20,10 @@ The alignment of a value can be checked with the [`align_of_val`] function. The *size* of a value is the offset in bytes between successive elements in an array with that item type including alignment padding. The size of a value is -always a multiple of its alignment. The size of a value can be checked with the -[`size_of_val`] function. +always a multiple of its alignment. Note that some types are zero-sized; 0 is +considered a multiple of any alignment (for example, on some platforms, the type +`[u16; 0]` has size 0 and alignment 2). The size of a value can be checked with +the [`size_of_val`] function. Types where all values have the same size and alignment, and both are known at compile time, implement the [`Sized`] trait and can be checked with the From 4c94e39b77c3fc738d3881e88d087e6137c2e938 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 5 Sep 2022 11:26:17 +0100 Subject: [PATCH 058/315] Clarify reference on async blocks * fix "typo" when declaring semantics of `return` from within async block * remove confusing false comment from the example --- src/expressions/block-expr.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index a68b27e56..3f18e6791 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -103,7 +103,7 @@ Async contexts are established by async blocks as well as the bodies of async fu Async blocks act like a function boundary, much like closures. Therefore, the `?` operator and `return` expressions both affect the output of the future, not the enclosing function or other context. -That is, `return ` from within a closure will return the result of `` as the output of the future. +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. Finally, the `break` and `continue` keywords cannot be used to branch out from an async block. @@ -112,7 +112,7 @@ Therefore the following is illegal: ```rust,compile_fail loop { async move { - break; // This would break out of the loop. + break; // error[E0267]: `break` inside of an `async` block } } ``` From e93265ab4e964a56b665db968b02a511cb59e08f Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Tue, 6 Sep 2022 14:18:22 -0400 Subject: [PATCH 059/315] feat: use default not-equal method --- src/attributes/derive.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/derive.md b/src/attributes/derive.md index b8909ac71..4916b6f44 100644 --- a/src/attributes/derive.md +++ b/src/attributes/derive.md @@ -26,7 +26,7 @@ impl PartialEq for Foo { } fn ne(&self, other: &Foo) -> bool { - self.a != other.a || self.b != other.b + !self.eq(other) } } ``` From 7b1240b2451be16ccfc9bd695e6ebb95f80b11c6 Mon Sep 17 00:00:00 2001 From: "Ryan Scheel (isHavvy)" Date: Thu, 8 Sep 2022 15:18:03 -0700 Subject: [PATCH 060/315] One sentence, one line Patterns chapter This was mostly mechanical. There are only two things of note: 1. A couple sentences ended with commas instead of periods. I changed them to periods. They were both in the Binding Modes section, so I assume they were added together. 2. In the static/dynamic behavior for or patterns, for two sections, I separated lines based on commas instead of the one really large sentence they are. --- src/patterns.md | 278 +++++++++++++++++++----------------------------- 1 file changed, 111 insertions(+), 167 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index 5c81ecd87..ea7beb30f 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -22,18 +22,16 @@ >    | [_PathPattern_]\ >    | [_MacroInvocation_] -Patterns are used to match values against structures and to, -optionally, bind variables to values inside these structures. They are also -used in variable declarations and parameters for functions and closures. +Patterns are used to match values against structures and to, optionally, bind variables to values inside these structures. +They are also used in variable declarations and parameters for functions and closures. The pattern in the following example does four things: * Tests if `person` has the `car` field filled with something. -* Tests if the person's `age` field is between 13 and 19, and binds its value to - the `person_age` variable. +* Tests if the person's `age` field is between 13 and 19, and binds its value to the `person_age` variable. * Binds a reference to the `name` field to the variable `person_name`. -* Ignores the rest of the fields of `person`. The remaining fields can have any value and - are not bound to any variables. +* Ignores the rest of the fields of `person`. + The remaining fields can have any value and are not bound to any variables. ```rust # struct Car; @@ -65,8 +63,7 @@ if let Patterns are used in: * [`let` declarations](statements.md#let-statements) -* [Function](items/functions.md) and [closure](expressions/closure-expr.md) - parameters +* [Function](items/functions.md) and [closure](expressions/closure-expr.md) parameters * [`match` expressions](expressions/match-expr.md) * [`if let` expressions](expressions/if-expr.md) * [`while let` expressions](expressions/loop-expr.md#predicate-pattern-loops) @@ -75,13 +72,10 @@ Patterns are used in: ## Destructuring Patterns can be used to *destructure* [structs], [enums], and [tuples]. -Destructuring breaks up a value into its component pieces. The syntax used is -almost the same as when creating such values. In a pattern whose [scrutinee] -expression has a `struct`, `enum` or `tuple` type, a placeholder (`_`) stands -in for a *single* data field, whereas a wildcard `..` stands in for *all* the -remaining fields of a particular variant. When destructuring a data structure -with named (but not numbered) fields, it is allowed to write `fieldname` as a -shorthand for `fieldname: fieldname`. +Destructuring breaks up a value into its component pieces. +The syntax used is almost the same as when creating such values. +In a pattern whose [scrutinee] expression has a `struct`, `enum` or `tuple` type, a placeholder (`_`) stands in for a *single* data field, whereas a wildcard `..` stands in for *all* the remaining fields of a particular variant. +When destructuring a data structure with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. ```rust # enum Message { @@ -104,9 +98,9 @@ match message { ## Refutability -A pattern is said to be *refutable* when it has the possibility of not being matched -by the value it is being matched against. *Irrefutable* patterns, on the other hand, -always match the value they are being matched against. Examples: +A pattern is said to be *refutable* when it has the possibility of not being matched by the value it is being matched against. +*Irrefutable* patterns, on the other hand, always match the value they are being matched against. +Examples: ```rust let (x, y) = (1, 2); // "(x, y)" is an irrefutable pattern @@ -141,16 +135,12 @@ if let (a, 3) = (1, 2) { // "(a, 3)" is refutable, and will not match [INTEGER_LITERAL]: tokens.md#integer-literals [FLOAT_LITERAL]: tokens.md#floating-point-literals -_Literal patterns_ match exactly the same value as what is created by the -literal. Since negative numbers are not [literals], literal patterns also -accept an optional minus sign before the literal, which acts like the negation -operator. +_Literal patterns_ match exactly the same value as what is created by the literal. +Since negative numbers are not [literals], literal patterns also accept an optional minus sign before the literal, which acts like the negation operator.
-Floating-point literals are currently accepted, but due to the complexity of comparing -them, they are going to be forbidden on literal patterns in a future version of Rust (see -[issue #41620](https://github.com/rust-lang/rust/issues/41620)). +Floating-point literals are currently accepted, but due to the complexity of comparing them, they are going to be forbidden on literal patterns in a future version of Rust (see [issue #41620](https://github.com/rust-lang/rust/issues/41620)).
@@ -175,14 +165,13 @@ for i in -2..5 { > _IdentifierPattern_ :\ >       `ref`? `mut`? [IDENTIFIER] (`@` [_PatternNoTopAlt_] ) ? -Identifier patterns bind the value they match to a variable. The identifier -must be unique within the pattern. The variable will shadow any variables of -the same name in scope. The scope of the new binding depends on the context of -where the pattern is used (such as a `let` binding or a `match` arm). +Identifier patterns bind the value they match to a variable. +The identifier must be unique within the pattern. +The variable will shadow any variables of the same name in scope. +The scope of the new binding depends on the context of where the pattern is used (such as a `let` binding or a `match` arm). -Patterns that consist of only an identifier, possibly with a `mut`, match any value and -bind it to that identifier. This is the most commonly used pattern in variable -declarations and parameters for functions and closures. +Patterns that consist of only an identifier, possibly with a `mut`, match any value and bind it to that identifier. +This is the most commonly used pattern in variable declarations and parameters for functions and closures. ```rust let mut variable = 10; @@ -191,9 +180,8 @@ fn sum(x: i32, y: i32) -> i32 { # } ``` -To bind the matched value of a pattern to a variable, use the syntax `variable @ -subpattern`. For example, the following binds the value 2 to `e` (not the -entire range: the range here is a range subpattern). +To bind the matched value of a pattern to a variable, use the syntax `variable @ subpattern`. +For example, the following binds the value 2 to `e` (not the entire range: the range here is a range subpattern). ```rust let x = 2; @@ -204,10 +192,8 @@ match x { } ``` -By default, identifier patterns bind a variable to a copy of or move from the -matched value depending on whether the matched value implements [`Copy`]. -This can be changed to bind to a reference by using the `ref` keyword, -or to a mutable reference using `ref mut`. For example: +By default, identifier patterns bind a variable to a copy of or move from the matched value depending on whether the matched value implements [`Copy`]. +This can be changed to bind to a reference by using the `ref` keyword, or to a mutable reference using `ref mut`. For example: ```rust # let a = Some(10); @@ -222,10 +208,10 @@ match a { } ``` -In the first match expression, the value is copied (or moved). In the second match, -a reference to the same memory location is bound to the variable value. This syntax is -needed because in destructuring subpatterns the `&` operator can't be applied to -the value's fields. For example, the following is not valid: +In the first match expression, the value is copied (or moved). +In the second match, a reference to the same memory location is bound to the variable value. +This syntax is needed because in destructuring subpatterns the `&` operator can't be applied to the value's fields. +For example, the following is not valid: ```rust,compile_fail # struct Person { @@ -247,21 +233,18 @@ To make it valid, write the following: if let Person {name: ref person_name, age: 18..=150 } = value { } ``` -Thus, `ref` is not something that is being matched against. Its objective is -exclusively to make the matched binding a reference, instead of potentially -copying or moving what was matched. +Thus, `ref` is not something that is being matched against. +Its objective is exclusively to make the matched binding a reference, instead of potentially copying or moving what was matched. -[Path patterns](#path-patterns) take precedence over identifier patterns. It is an error -if `ref` or `ref mut` is specified and the identifier shadows a constant. +[Path patterns](#path-patterns) take precedence over identifier patterns. +It is an error if `ref` or `ref mut` is specified and the identifier shadows a constant. -Identifier patterns are irrefutable if the `@` subpattern is irrefutable or -the subpattern is not specified. +Identifier patterns are irrefutable if the `@` subpattern is irrefutable or the subpattern is not specified. ### Binding modes -To service better ergonomics, patterns operate in different *binding modes* in -order to make it easier to bind references to values. When a reference value is matched by -a non-reference pattern, it will be automatically treated as a `ref` or `ref mut` binding. +To service better ergonomics, patterns operate in different *binding modes* in order to make it easier to bind references to values. +When a reference value is matched by a non-reference pattern, it will be automatically treated as a `ref` or `ref mut` binding. Example: ```rust @@ -271,26 +254,22 @@ if let Some(y) = x { } ``` -*Non-reference patterns* include all patterns except bindings, [wildcard -patterns](#wildcard-pattern) (`_`), [`const` patterns](#path-patterns) of reference types, -and [reference patterns](#reference-patterns). - -If a binding pattern does not explicitly have `ref`, `ref mut`, or `mut`, then it uses the -*default binding mode* to determine how the variable is bound. The default binding -mode starts in "move" mode which uses move semantics. When matching a pattern, the -compiler starts from the outside of the pattern and works inwards. Each time a reference -is matched using a non-reference pattern, it will automatically dereference the value and -update the default binding mode. References will set the default binding mode to `ref`. -Mutable references will set the mode to `ref mut` unless the mode is already `ref` in -which case it remains `ref`. If the automatically dereferenced value is still a reference, -it is dereferenced and this process repeats. - -Move bindings and reference bindings can be mixed together in the same pattern, doing so will -result in partial move of the object bound to and the object cannot be used afterwards. +*Non-reference patterns* include all patterns except bindings, [wildcard patterns](#wildcard-pattern) (`_`), [`const` patterns](#path-patterns) of reference types, and [reference patterns](#reference-patterns). + +If a binding pattern does not explicitly have `ref`, `ref mut`, or `mut`, then it uses the *default binding mode* to determine how the variable is bound. +The default binding mode starts in "move" mode which uses move semantics. +When matching a pattern, the compiler starts from the outside of the pattern and works inwards. +Each time a reference is matched using a non-reference pattern, it will automatically dereference the value and update the default binding mode. +References will set the default binding mode to `ref`. +Mutable references will set the mode to `ref mut` unless the mode is already `ref` in which case it remains `ref`. +If the automatically dereferenced value is still a reference, it is dereferenced and this process repeats. + +Move bindings and reference bindings can be mixed together in the same pattern. +Doing so will result in partial move of the object bound to and the object cannot be used afterwards. This applies only if the type cannot be copied. -In the example below, `name` is moved out of `person`, trying to use `person` as a whole or -`person.name` would result in an error because of *partial move*. +In the example below, `name` is moved out of `person`. +Trying to use `person` as a whole or `person.name` would result in an error because of *partial move*. Example: @@ -310,10 +289,10 @@ let Person { name, ref age } = person; > _WildcardPattern_ :\ >    `_` -The _wildcard pattern_ (an underscore symbol) matches any value. It is used to ignore values when they don't -matter. Inside other patterns it matches a single data field (as opposed to the `..` -which matches the remaining fields). Unlike identifier patterns, it does not copy, move -or borrow the value it matches. +The _wildcard pattern_ (an underscore symbol) matches any value. +It is used to ignore values when they don't matter. +Inside other patterns it matches a single data field (as opposed to the `..` which matches the remaining fields). +Unlike identifier patterns, it does not copy, move or borrow the value it matches. Examples: @@ -351,13 +330,9 @@ The wildcard pattern is always irrefutable. > _RestPattern_ :\ >    `..` -The _rest pattern_ (the `..` token) acts as a variable-length pattern which -matches zero or more elements that haven't been matched already before and -after. It may only be used in [tuple](#tuple-patterns), [tuple -struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and -may only appear once as one of the elements in those patterns. It is also -allowed in an [identifier pattern](#identifier-patterns) for [slice -patterns](#slice-patterns) only. +The _rest pattern_ (the `..` token) acts as a variable-length pattern which matches zero or more elements that haven't been matched already before and after. +It may only be used in [tuple](#tuple-patterns), [tuple struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and may only appear once as one of the elements in those patterns. +It is also allowed in an [identifier pattern](#identifier-patterns) for [slice patterns](#slice-patterns) only. The rest pattern is always irrefutable. @@ -425,29 +400,26 @@ match tuple { >    | `-`? [FLOAT_LITERAL]\ >    | [_PathExpression_] -Range patterns match values within the range defined by their bounds. A range pattern may be -closed or half-open. A range pattern is closed if it has both a lower and an upper bound, and -it matches all the values between and including both of its bounds. A range pattern that is -half-open is written with a lower bound but not an upper bound, and matches any value equal to -or greater than the specified lower bound. +Range patterns match values within the range defined by their bounds. +A range pattern may be closed or half-open. +A range pattern is closed if it has both a lower and an upper bound, and it matches all the values between and including both of its bounds. +A range pattern that is half-open is written with a lower bound but not an upper bound, and matches any value equal to or greater than the specified lower bound. -For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. For an integer the -pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but -not 0, and not negative numbers for signed integers. The bounds can be literals or paths that point -to constant values. +For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. +For an integer the pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers. +The bounds can be literals or paths that point to constant values. A half-open range pattern in the style `a..` cannot be used to match within the context of a slice. -A pattern `a..=b` must always have a ≤ b. It is an error to have a range pattern -`10..=0`, for example. +A pattern `a..=b` must always have a ≤ b. +It is an error to have a range pattern `10..=0`, for example. Range patterns only work on scalar types. The accepted types are: * Integer types (u8, i8, u16, i16, usize, isize, etc.). * Character types (char). -* Floating point types (f32 and f64). This is being deprecated and will not be available - in a future version of Rust (see - [issue #41620](https://github.com/rust-lang/rust/issues/41620)). +* Floating point types (f32 and f64). + This is being deprecated and will not be available in a future version of Rust (see [issue #41620](https://github.com/rust-lang/rust/issues/41620)). Examples: @@ -524,12 +496,10 @@ println!("{}", match 0xfacade { }); ``` -Range patterns for (non-`usize` and -`isize`) integer and `char` types are irrefutable -when they span the entire set of possible values of a type. For example, `0u8..=255u8` -is irrefutable. The range of values for an integer type is the closed range from its -minimum to maximum value. The range of values for a `char` type are precisely those -ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and -`'\u{E000}'..='\u{10FFFF}'`. +Range patterns for (non-`usize` and -`isize`) integer and `char` types are irrefutable when they span the entire set of possible values of a type. +For example, `0u8..=255u8` is irrefutable. +The range of values for an integer type is the closed range from its minimum to maximum value. +The range of values for a `char` type are precisely those ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and `'\u{E000}'..='\u{10FFFF}'`. > **Edition Differences**: Before the 2021 edition, closed range patterns may also be written using `...` as an alternative to `..=`, with the same meaning. @@ -539,8 +509,7 @@ ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and > _ReferencePattern_ :\ >    (`&`|`&&`) `mut`? [_PatternWithoutRange_] -Reference patterns dereference the pointers that are being matched -and, thus, borrow them. +Reference patterns dereference the pointers that are being matched and, thus, borrow them. For example, these two matches on `x: &i32` are equivalent: @@ -553,11 +522,9 @@ let b = match int_reference { &0 => "zero", _ => "some" }; assert_eq!(a, b); ``` -The grammar production for reference patterns has to match the token `&&` to match a -reference to a reference because it is a token by itself, not two `&` tokens. +The grammar production for reference patterns has to match the token `&&` to match a reference to a reference because it is a token by itself, not two `&` tokens. -Adding the `mut` keyword dereferences a mutable reference. The mutability must match the -mutability of the reference. +Adding the `mut` keyword dereferences a mutable reference. The mutability must match the mutability of the reference. Reference patterns are always irrefutable. @@ -594,8 +561,7 @@ Reference patterns are always irrefutable. Struct patterns match struct values that match all criteria defined by its subpatterns. They are also used to [destructure](#destructuring) a struct. -On a struct pattern, the fields are referenced by name, index (in the case of tuple -structs) or ignored by use of `..`: +On a struct pattern, the fields are referenced by name, index (in the case of tuple structs) or ignored by use of `..`: ```rust # struct Point { @@ -644,8 +610,7 @@ match struct_value { } ``` -The `ref` and/or `mut` _IDENTIFIER_ syntax matches any value and binds it to -a variable with the same name as the given field. +The `ref` and/or `mut` _IDENTIFIER_ syntax matches any value and binds it to a variable with the same name as the given field. ```rust # struct Struct { @@ -669,9 +634,8 @@ A struct pattern is refutable when one of its subpatterns is refutable. > _TupleStructItems_ :\ >    [_Pattern_] ( `,` [_Pattern_] )\* `,`? -Tuple struct patterns match tuple struct and enum values that match all criteria defined -by its subpatterns. They are also used to [destructure](#destructuring) a tuple struct or -enum value. +Tuple struct patterns match tuple struct and enum values that match all criteria defined by its subpatterns. +They are also used to [destructure](#destructuring) a tuple struct or enum value. A tuple struct pattern is refutable when one of its subpatterns is refutable. @@ -689,8 +653,7 @@ A tuple struct pattern is refutable when one of its subpatterns is refutable. Tuple patterns match tuple values that match all criteria defined by its subpatterns. They are also used to [destructure](#destructuring) a tuple. -The form `(..)` with a single [_RestPattern_] is a special form that does not -require a comma, and matches a tuple of any size. +The form `(..)` with a single [_RestPattern_] is a special form that does not require a comma, and matches a tuple of any size. The tuple pattern is refutable when one of its subpatterns is refutable. @@ -710,10 +673,8 @@ assert_eq!(b, "ten"); > _GroupedPattern_ :\ >    `(` [_Pattern_] `)` -Enclosing a pattern in parentheses can be used to explicitly control the -precedence of compound patterns. For example, a reference pattern next to a -range pattern such as `&0..=5` is ambiguous and is not allowed, but can be -expressed with parentheses. +Enclosing a pattern in parentheses can be used to explicitly control the precedence of compound patterns. +For example, a reference pattern next to a range pattern such as `&0..=5` is ambiguous and is not allowed, but can be expressed with parentheses. ```rust let int_reference = &3; @@ -733,6 +694,7 @@ match int_reference { >    [_Pattern_] \(`,` [_Pattern_])\* `,`? Slice patterns can match both arrays of fixed size and slices of dynamic size. + ```rust // Fixed size let arr = [1, 2, 3]; @@ -751,14 +713,10 @@ match v[..] { }; ``` -Slice patterns are irrefutable when matching an array as long as each element -is irrefutable. When matching a slice, it is irrefutable only in the form with -a single `..` [rest pattern](#rest-patterns) or [identifier -pattern](#identifier-patterns) with the `..` rest pattern as a subpattern. +Slice patterns are irrefutable when matching an array as long as each element is irrefutable. +When matching a slice, it is irrefutable only in the form with a single `..` [rest pattern](#rest-patterns) or [identifier pattern](#identifier-patterns) with the `..` rest pattern as a subpattern. -Within a slice, a half-open range pattern like `a..` must be enclosed in parentheses, -as in `(a..)`, to clarify it is intended to match a single value. -A future version of Rust may give the non-parenthesized version an alternate meaning. +Within a slice, a half-open range pattern like `a..` must be enclosed in parentheses, as in `(a..)`, to clarify it is intended to match a single value. ## Path patterns @@ -778,33 +736,27 @@ Unqualified path patterns can refer to: Qualified path patterns can only refer to associated constants. -Constants cannot be a union type. Struct and enum constants must have -`#[derive(PartialEq, Eq)]` (not merely implemented). +Constants cannot be a union type. +Struct and enum constants must have `#[derive(PartialEq, Eq)]` (not merely implemented). -Path patterns are irrefutable when they refer to structs or an enum variant when the enum -has only one variant or a constant whose type is irrefutable. They are refutable when they -refer to refutable constants or enum variants for enums with multiple variants. +Path patterns are irrefutable when they refer to structs or an enum variant when the enum has only one variant or a constant whose type is irrefutable. +They are refutable when they refer to refutable constants or enum variants for enums with multiple variants. ## Or-patterns -_Or-patterns_ are patterns that match on one of two or more sub-patterns (e.g. -`A | B | C`). They can nest arbitrarily. Syntactically, or-patterns are allowed -in any of the places where other patterns are allowed (represented by the -_Pattern_ production), with the exceptions of `let`-bindings and function and -closure arguments (represented by the _PatternNoTopAlt_ production). +_Or-patterns_ are patterns that match on one of two or more sub-patterns (for example `A | B | C`). +They can nest arbitrarily. +Syntactically, or-patterns are allowed in any of the places where other patterns are allowed (represented by the _Pattern_ production), with the exceptions of `let`-bindings and function and closure arguments (represented by the _PatternNoTopAlt_ production). ### Static semantics -1. Given a pattern `p | q` at some depth for some arbitrary patterns `p` and `q`, - the pattern is considered ill-formed if: +1. Given a pattern `p | q` at some depth for some arbitrary patterns `p` and `q`, the pattern is considered ill-formed if: + the type inferred for `p` does not unify with the type inferred for `q`, or + the same set of bindings are not introduced in `p` and `q`, or - + the type of any two bindings with the same name in `p` and `q` do not unify - with respect to types or binding modes. + + the type of any two bindings with the same name in `p` and `q` do not unify with respect to types or binding modes. - Unification of types is in all instances aforementioned exact and - implicit [type coercions] do not apply. + Unification of types is in all instances aforementioned exact and implicit [type coercions] do not apply. 2. When type checking an expression `match e_s { a_1 => e_1, ... a_n => e_n }`, for each match arm `a_i` which contains a pattern of form `p_i | q_i`, @@ -812,35 +764,27 @@ closure arguments (represented by the _PatternNoTopAlt_ production). at the depth `d` where it exists the fragment of `e_s` at depth `d`, the type of the expression fragment does not unify with `p_i | q_i`. -3. With respect to exhaustiveness checking, a pattern `p | q` is - considered to cover `p` as well as `q`. For some constructor `c(x, ..)` - the distributive law applies such that `c(p | q, ..rest)` covers the same - set of value as `c(p, ..rest) | c(q, ..rest)` does. This can be applied - recursively until there are no more nested patterns of form `p | q` other - than those that exist at the top level. +3. With respect to exhaustiveness checking, a pattern `p | q` is considered to cover `p` as well as `q`. + For some constructor `c(x, ..)` the distributive law applies such that `c(p | q, ..rest)` covers the same set of value as `c(p, ..rest) | c(q, ..rest)` does. + This can be applied recursively until there are no more nested patterns of form `p | q` other than those that exist at the top level. - Note that by *"constructor"* we do not refer to tuple struct patterns, - but rather we refer to a pattern for any product type. - This includes enum variants, tuple structs, structs with named fields, - arrays, tuples, and slices. + Note that by *"constructor"* we do not refer to tuple struct patterns, but rather we refer to a pattern for any product type. + This includes enum variants, tuple structs, structs with named fields, arrays, tuples, and slices. ### Dynamic semantics -1. The dynamic semantics of pattern matching a scrutinee expression `e_s` - against a pattern `c(p | q, ..rest)` at depth `d` where `c` is some constructor, - `p` and `q` are arbitrary patterns, and `rest` is optionally any remaining - potential factors in `c`, is defined as being the same as that of - `c(p, ..rest) | c(q, ..rest)`. +1. The dynamic semantics of pattern matching a scrutinee expression `e_s` against a pattern `c(p | q, ..rest)` at depth `d` where `c` is some constructor, + `p` and `q` are arbitrary patterns, + and `rest` is optionally any remaining potential factors in `c`, + is defined as being the same as that of `c(p, ..rest) | c(q, ..rest)`. ### Precedence with other undelimited patterns -As shown elsewhere in this chapter, there are several types of patterns that -are syntactically undelimited, including identifier patterns, reference -patterns, and or-patterns. Or-patterns always have the lowest-precedence. This -allows us to reserve syntactic space for a possible future type ascription -feature and also to reduce ambiguity. For example, `x @ A(..) | B(..)` will -result in an error that `x` is not bound in all patterns, `&A(x) | B(x)` will -result in a type mismatch between `x` in the different subpatterns. +As shown elsewhere in this chapter, there are several types of patterns that are syntactically undelimited, including identifier patterns, reference patterns, and or-patterns. +Or-patterns always have the lowest-precedence. +This allows us to reserve syntactic space for a possible future type ascription feature and also to reduce ambiguity. +For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound in all patterns. +`&A(x) | B(x)` will result in a type mismatch between `x` in the different subpatterns. [_GroupedPattern_]: #grouped-patterns [_IdentifierPattern_]: #identifier-patterns From ea7ba21c879c5cf58d7a2dffcf74f93a6c0933c4 Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Thu, 8 Sep 2022 20:22:14 -0400 Subject: [PATCH 061/315] feat: do not specify not-equal at all See https://github.com/rust-lang/reference/pull/1264#issuecomment-1239719515 --- src/attributes/derive.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/attributes/derive.md b/src/attributes/derive.md index 4916b6f44..bb5631f7a 100644 --- a/src/attributes/derive.md +++ b/src/attributes/derive.md @@ -24,10 +24,6 @@ impl PartialEq for Foo { fn eq(&self, other: &Foo) -> bool { self.a == other.a && self.b == other.b } - - fn ne(&self, other: &Foo) -> bool { - !self.eq(other) - } } ``` From 60cd80a6732f8375e8f5303290f27b97e33a0263 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Thu, 8 Sep 2022 20:45:12 -0400 Subject: [PATCH 062/315] Add basic GATs info --- src/items/associated-items.md | 38 ++++++++++++++++++++++++++++++++++- src/items/type-aliases.md | 6 +++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index f5dc31aae..66db45b54 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -220,7 +220,12 @@ If a type `Item` has an associated type `Assoc` from a trait `Trait`, then associated type definition. Furthermore, if `Item` is a type parameter, then `Item::Assoc` can be used in type parameters. -Associated types must not include [generic parameters] or [where clauses]. +Associated types may include [generic parameters] or [where clauses]; these may +be referred to 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 { @@ -249,6 +254,37 @@ fn main() { } ``` +An example of associated types with generics and where clauses: + +```rust +struct ArrayLender<'a, T>(&'a mut [T; 16]); + +trait Lend { + // Generic associated type declaration + type Lender<'a> where Self: 'a; + fn lend<'a>(&'a mut self) -> Self::Lender<'a>; +} + +impl Lend for [T; 16] { + // Generic associated type definition + type Lender<'a> = ArrayLender<'a, T> where Self: 'a; + + fn lend<'a>(&'a mut self) -> Self::Lender<'a> { + ArrayLender(self) + } +} + +fn borrow<'a, T: Lend>(array: &'a mut T) -> ::Lender<'a> { + array.lend() +} + + +fn main() { + let mut array = [0usize; 16]; + let lender = borrow(&mut array); +} +``` + ### Associated Types Container Example Consider the following example of a `Container` trait. Notice that the type is diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md index ff0cc75f7..2b5307600 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -4,7 +4,7 @@ > _TypeAlias_ :\ >    `type` [IDENTIFIER] [_GenericParams_]? > ( `:` [_TypeParamBounds_] )? -> [_WhereClause_]? ( `=` [_Type_] )? `;` +> [_WhereClause_]? ( `=` [_Type_] )? [_WhereClause_]? `;` A _type alias_ defines a new name for an existing [type]. Type aliases are declared with the keyword `type`. Every value has a single, specific type, but @@ -37,6 +37,9 @@ A type alias without the [_Type_] specification may only appear as an A type alias with [_TypeParamBounds_] may only specified when used as an [associated type] in a [trait]. +A type alias with where clauses after the equals sign may only appear as an +[associated type] in a [trait] or a [trait impl]. + [IDENTIFIER]: ../identifiers.md [_GenericParams_]: generics.md [_TypeParamBounds_]: ../trait-bounds.md @@ -45,3 +48,4 @@ an [associated type] in a [trait]. [associated type]: associated-items.md#associated-types [trait]: traits.md [type]: ../types.md +[trait impl]: implementations.md#trait-implementations From 5e8efd6fdaa4914d482c81226ee8e7f6f2b194ca Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Thu, 8 Sep 2022 21:47:36 -0400 Subject: [PATCH 063/315] Fix typo --- src/items/associated-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 66db45b54..48f0eca5b 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -221,7 +221,7 @@ associated type definition. Furthermore, if `Item` is a type parameter, then `Item::Assoc` can be used in type parameters. Associated types may include [generic parameters] or [where clauses]; these may -be referred to generic associated types, or GATs. If the type `Thing` has an +be 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 From 1ef107a457a2d2945887fc026a28ee557710918b Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 9 Sep 2022 19:57:12 -0400 Subject: [PATCH 064/315] Review comments --- src/items/associated-items.md | 38 ++++++++++++++++++++++++++--------- src/items/traits.md | 1 + src/items/type-aliases.md | 10 ++++++--- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 48f0eca5b..009ccd0ba 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -205,26 +205,46 @@ types cannot be defined in [inherent implementations] nor can they be given a default implementation in traits. An *associated type declaration* declares a signature for associated type -definitions. It is written as `type`, then an [identifier], and -finally an optional list of trait bounds. +definitions. It is written in one of the following forms, where `Assoc` is the +name of the associated type, `Params` is a comma-separated list of type, +lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds +on the associated type, and `WhereBounds` is a comma-separated list of bounds on +parameters: + +```rust,ignore +type Assoc; +type Assoc: Bounds; +type Assoc; +type Assoc: Bounds; +type Assoc where WhereBounds; +type Assoc: Bounds where WhereBounds; +``` The identifier is the name of the declared type alias. The optional trait bounds must be fulfilled by the implementations of the type alias. There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound. -An *associated type definition* defines a type alias on another type. It is -written as `type`, then an [identifier], then an `=`, and finally a [type]. +An *associated type definition* defines a type alias on for the implementation +of a trait on a type. They are written similarly to an *associated type declaration*, +but cannot contain `Bounds`, but instead must contain a `Type`: + +```rust,ignore +type Assoc = Type; +type Assoc = Type; +type Assoc where WhereBounds = Type; +type Assoc = Type where WhereBounds; +``` 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. Furthermore, if `Item` is a type parameter, then `Item::Assoc` can be used in type parameters. -Associated types may include [generic parameters] or [where clauses]; these may -be 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 +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 diff --git a/src/items/traits.md b/src/items/traits.md index 26870a0fc..3c5d31d5c 100644 --- a/src/items/traits.md +++ b/src/items/traits.md @@ -70,6 +70,7 @@ Object safe traits can be the base trait of a [trait object]. A trait is * All [supertraits] must also be object safe. * `Sized` must not be a [supertrait][supertraits]. In other words, it must not require `Self: Sized`. * It must not have any associated constants. +* It must not have any associated types with generics. * All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable: * Dispatchable functions require: * Not have any type parameters (although lifetime parameters are allowed), diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md index 2b5307600..74463ea78 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -4,7 +4,7 @@ > _TypeAlias_ :\ >    `type` [IDENTIFIER] [_GenericParams_]? > ( `:` [_TypeParamBounds_] )? -> [_WhereClause_]? ( `=` [_Type_] )? [_WhereClause_]? `;` +> [_WhereClause_]? ( `=` [_Type_] [_WhereClause_]?)? `;` A _type alias_ defines a new name for an existing [type]. Type aliases are declared with the keyword `type`. Every value has a single, specific type, but @@ -34,11 +34,15 @@ let _ = TypeAlias(5); // Doesn't work A type alias without the [_Type_] specification may only appear as an [associated type] in a [trait]. +A type alias with the [_Type_] specification may only appear as an +[associated type] in a [trait impl]. + A type alias with [_TypeParamBounds_] may only specified when used as an [associated type] in a [trait]. -A type alias with where clauses after the equals sign may only appear as an -[associated type] in a [trait] or a [trait impl]. +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 where T: Foo = Bar`) are preferred. [IDENTIFIER]: ../identifiers.md [_GenericParams_]: generics.md From a7a54f5ee340db8477cff9f17cbaea5d78e42ad3 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 9 Sep 2022 20:21:18 -0400 Subject: [PATCH 065/315] Add explanation for required clauses on GATs --- src/items/associated-items.md | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 009ccd0ba..33eb4a7a9 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -335,6 +335,68 @@ impl Container for Vec { } ``` +### Required where clauses on generic associated types + +Generic associated type declarations on traits currently may require a list of +where clauses, dependent on functions in the trait and how the GAT is used. + +In a few words, these where clauses are required in order to maximize the allowed +definitions of the associated type in impls. To do this, any clauses that *can be +proven to hold* on functions (using the parameters of the function or trait) +where a GAT appears as an input or output must also be written on the GAT itself. + +```rust +trait LendingIterator { + type Item<'x> where Self: 'x; + fn next<'a>(&'a mut self) -> Self::Item<'a>; +} +``` + +In the above, on the `next` function, we can prove that `Self: 'a`, because of +the implied bounds from `&'a mut self`; therefore, we must write the equivalent +bound on the GAT itself: `where Self: 'x`. + +When there are multiple functions in a trait that use the GAT, then the +*intersection* of the bounds from the different functions are used, rather than +the union. + +```rust +trait Check { + type Checker<'x>; + fn create_checker<'a>(item: &'a T) -> Self::Checker<'a>; + fn do_check(checker: Self::Checker<'a>); +} +``` + +In this example, no bounds are required on the `type Checker<'a>;`. While we +know that `T: 'a` on `create_checker`, we do not know that on `do_check`. However, +if `do_check` was commented out, then the `where T: 'x` bound would be required +on `Checker`. + +The bounds on associated types also propagate required where clauses. + +```rust +trait Iterable { + type Item<'a> where Self: 'a; + type Iterator<'a>: Iterator> where Self: 'a; + fn iter<'a>(&'a self) -> Self::Iterator<'a>; +} +``` + +Here, `where Self: 'a` is required on `Item` because of `iter`. However, `Item` +is used in the bounds of `Iterator`, the `where Self: 'a` clause is also required +there. + +Finally, any explicit uses of `'static` on GATs in the trait do not count towards +the required bounds. + +```rust +trait StaticReturn { + type Y<'a>; + fn foo(&self) -> Self::Y<'static>; +} +``` + ## Associated Constants *Associated constants* are [constants] associated with a type. From dd84a6268eaade7e59460fac51d885685825c777 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 9 Sep 2022 20:26:02 -0400 Subject: [PATCH 066/315] Fixed second where clause location --- src/items/type-aliases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md index 74463ea78..dd0efee04 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -42,7 +42,7 @@ an [associated type] in a [trait]. 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 where T: Foo = Bar`) are preferred. +the equals sign (like `type TypeAlias = Bar where T: Foo`) are preferred. [IDENTIFIER]: ../identifiers.md [_GenericParams_]: generics.md From d32ca057e7e65768e70a428956b1bbf03002a74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 11 Sep 2022 17:11:16 +0200 Subject: [PATCH 067/315] Classify AsyncBlockExpression as ExpressionWithoutBlock --- src/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expressions.md b/src/expressions.md index 32ee658ff..0c01238c3 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -22,6 +22,7 @@ >       | [_MethodCallExpression_]\ >       | [_FieldExpression_]\ >       | [_ClosureExpression_]\ +>       | [_AsyncBlockExpression_]\ >       | [_ContinueExpression_]\ >       | [_BreakExpression_]\ >       | [_RangeExpression_]\ @@ -34,7 +35,6 @@ >    [_OuterAttribute_]\*[†](#expression-attributes)\ >    (\ >          [_BlockExpression_]\ ->       | [_AsyncBlockExpression_]\ >       | [_UnsafeBlockExpression_]\ >       | [_LoopExpression_]\ >       | [_IfExpression_]\ From dc1eeb4cbb64c3f8fdc17635330bb533992d2bef Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Sun, 11 Sep 2022 21:55:36 -0400 Subject: [PATCH 068/315] Fix lifetime --- src/items/associated-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 33eb4a7a9..d28ab6b13 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -364,7 +364,7 @@ the union. trait Check { type Checker<'x>; fn create_checker<'a>(item: &'a T) -> Self::Checker<'a>; - fn do_check(checker: Self::Checker<'a>); + fn do_check(checker: Self::Checker<'_>); } ``` From d6cd338e3a9c0c7f33c8f0e65105dca6c1911bc5 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Fri, 29 Jul 2022 10:26:06 -0700 Subject: [PATCH 069/315] Add documentation for raw-dylib and link_ordinal --- src/attributes.md | 3 ++ src/items/external-blocks.md | 59 +++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/attributes.md b/src/attributes.md index 857cd7d72..b7c1ef609 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -228,6 +228,8 @@ The following is an index of all built-in attributes. - [`link`] — Specifies a native library to link with an `extern` block. - [`link_name`] — Specifies the name of the symbol for functions or statics in an `extern` block. + - [`link_ordinal`] — Specifies the ordinal of the symbol for functions or + statics in an `extern` block. - [`no_link`] — Prevents linking an extern crate. - [`repr`] — Controls type layout. - [`crate_type`] — Specifies the type of crate (library, executable, etc.). @@ -297,6 +299,7 @@ The following is an index of all built-in attributes. [`ignore`]: attributes/testing.md#the-ignore-attribute [`inline`]: attributes/codegen.md#the-inline-attribute [`link_name`]: items/external-blocks.md#the-link_name-attribute +[`link_ordinal`]: items/external-blocks.md#the-link_ordinal-attribute [`link_section`]: abi.md#the-link_section-attribute [`link`]: items/external-blocks.md#the-link-attribute [`macro_export`]: macros-by-example.md#path-based-scope diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index e768a1502..e13ca5438 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -122,6 +122,9 @@ specifies the kind of library with the following possible values: - `static` — Indicates a static library. - `framework` — Indicates a macOS framework. This is only valid for macOS targets. +- `raw-dylib` - Indicates a dynamic library where the compiler will generate + an import library to link against (see [`dylib` versus `raw-dylib`] below + for details). This is only valid for Windows targets. The `name` key must be included if `kind` is specified. @@ -198,9 +201,26 @@ The default for this modifier is `-whole-archive`. More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. +#### `dylib` versus `raw-dylib` + +On Windows, linking against a dynamic library requires that an import library +is provided to the linker: this is a special static library that declares all +of the symbols exported by the dynamic library in such a way that the linker +knows that they have to be dynamically loaded at runtime. + +Specifying `kind = "dylib"` instructs the Rust compiler to link an import +library based on the `name` key, the linker will then use its normal library +resolution logic to find that import library. Alternatively, specifying +`kind = "raw-dylib"` instructs the compiler to generate an import library +during compilation and provide that to the linker instead. + +`raw-dylib` is only supported on Windows and not supported on x86 +(`target_arch="x86"`), see [58713]. Using it when targeting other platforms or +x86 on Windows will result in a compiler error. + ### The `link_name` attribute -The `link_name` attribute may be specified on declarations inside an `extern` +The *`link_name` attribute* may be specified on declarations inside an `extern` block to indicate the symbol to import for the given function or static. It uses the [_MetaNameValueStr_] syntax to specify the name of the symbol. @@ -211,6 +231,41 @@ extern { } ``` +Using this attribute with the `link_ordinal` attribute will result in a +compiler error. + +### The `link_ordinal` attribute + +The *`link_ordinal` attribute* can be applied on declarations inside an `extern` +block to indicate the numeric ordinal to use when generating the import library +to link against. An ordinal is a unique number per symbol exported by a dynamic +library on Windows and can be used when the library is being loaded to find +that symbol rather than having to look it up by name. + +
+ +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. + +
+ + +```rust,ignore +#[link(name = "exporter", kind = "raw-dylib")] +extern "stdcall" { + #[link_ordinal(15)] + fn imported_function_stdcall(i: i32); +} +``` + +This attribute is only used with the `raw-dylib` linking kind. +Using any other kind will result in a compiler error. + +Using this attribute with the `link_name` attribute will result in a +compiler error. + ### Attributes on function parameters Attributes on extern function parameters follow the same rules and @@ -233,3 +288,5 @@ restrictions as [regular function parameters]. [regular function parameters]: functions.md#attributes-on-function-parameters [`bundle` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-bundle [`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive +[`dylib` versus `raw-dylib`]: #dylib-versus-raw-dylib +[58713]: https://github.com/rust-lang/rust/issues/58713 From 04ce4c4e508797abb7534053c1e8420ce5873c27 Mon Sep 17 00:00:00 2001 From: Guo Ci Date: Tue, 13 Sep 2022 14:59:49 -0400 Subject: [PATCH 070/315] Update closure-expr.md --- src/expressions/closure-expr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/expressions/closure-expr.md b/src/expressions/closure-expr.md index bdc177bb5..103f74795 100644 --- a/src/expressions/closure-expr.md +++ b/src/expressions/closure-expr.md @@ -12,7 +12,7 @@ > _ClosureParam_ :\ >    [_OuterAttribute_]\* [_PatternNoTopAlt_] ( `:` [_Type_] )? -A *closure expression*, also know as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type. +A *closure expression*, also known as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type. The syntax for a closure expression is an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], called the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, called the *return type*, and then an expression, called the *closure body operand*. The optional type after each pattern is a type annotation for the pattern. If there is a return type, the closure body must be a [block]. From bf51d22ce086e5e7210a080a8218b12223c1a6c5 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 14 Jul 2022 08:49:47 -0500 Subject: [PATCH 071/315] Document `label_break_value` in the reference --- src/expressions/block-expr.md | 5 +++++ src/expressions/loop-expr.md | 32 +++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index 3f18e6791..e46f2e83d 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -140,6 +140,10 @@ unsafe { let a = unsafe { an_unsafe_fn() }; ``` +## Labelled block expressions + +Labelled block expressions are documented in the [Loop expressions] section. + ## Attributes on block expressions [Inner attributes] are allowed directly after the opening brace of a block expression in the following situations: @@ -189,3 +193,4 @@ fn is_unix_platform() -> bool { [tuple expressions]: tuple-expr.md [unsafe operations]: ../unsafety.md [value expressions]: ../expressions.md#place-expressions-and-value-expressions +[Loop expressions]: loop-expr.md#labelled-block-expressions diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 308f3e346..d3c4d38d1 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -7,6 +7,7 @@ >       | [_PredicateLoopExpression_]\ >       | [_PredicatePatternLoopExpression_]\ >       | [_IteratorLoopExpression_]\ +>       | [_LabelBlockExpression_]\ >    ) [_LoopLabel_]: #loop-labels @@ -14,16 +15,19 @@ [_PredicateLoopExpression_]: #predicate-loops [_PredicatePatternLoopExpression_]: #predicate-pattern-loops [_IteratorLoopExpression_]: #iterator-loops +[_LabelBlockExpression_]: #labelled-block-expressions -Rust supports four loop expressions: +Rust supports five loop expressions: * A [`loop` expression](#infinite-loops) denotes an infinite loop. * A [`while` expression](#predicate-loops) loops until a predicate is false. * A [`while let` expression](#predicate-pattern-loops) tests a pattern. * A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty. +* A [labelled block expression](#labelled-block-expressions) runs a loop exactly once, but allows exiting the loop early with `break`. -All four types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels). -Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). +All five types of loop support [`break` expressions](#break-expressions), and [labels](#loop-labels). +All except labelled block expressions support [`continue` expressions](#continue-expressions). +Only `loop` and labelled block expressions support [evaluation to non-trivial values](#break-and-loop-values). ## Infinite loops @@ -193,6 +197,18 @@ A loop expression may optionally have a _label_. The label is written as a lifet If a label is present, then labeled `break` and `continue` expressions nested within this loop may exit out of this loop or return control to its head. See [break expressions](#break-expressions) and [continue expressions](#continue-expressions). +Labels follow the hygiene and shadowing rules of local variables. For example, this code will print "outer loop": + +```rust +'a: loop { + 'a: loop { + break 'a; + } + print!("outer loop"); + break 'a; +} +``` + ## `break` expressions > **Syntax**\ @@ -226,6 +242,16 @@ Example: A `break` expression is only permitted in the body of a loop, and has one of the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) `break EXPR` or `break 'label EXPR`. +## Labelled block expressions + +> **Syntax**\ +> _LabelBlockExpression_ :\ +>    [_BlockExpression_] + +Labelled block expressions are exactly like block expressions, except that they allow using `break` expressions within the block. +Unlike other loops, `break` expressions within a label expression *must* have a label (i.e. the label is not optional). +Unlike other loops, labelled block expressions *must* begin with a label. + ## `continue` expressions > **Syntax**\ From b00444a90f2fb381b4e3bdc66c19b47cfc4b5450 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 16 Sep 2022 18:52:29 +0800 Subject: [PATCH 072/315] Add `sym` operands for inline assembly --- src/inline-assembly.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index 6233475a3..996b157da 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -123,12 +123,17 @@ Several types of operands are supported: * `inlateout() ` / `inlateout() => ` - Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`). - You should only write to the register after all inputs are read, otherwise you may clobber an input. +* `sym ` + - `` must refer to a `fn` or `static`. + - A mangled symbol name referring to the item is substituted into the asm template string. + - The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc). + - `` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data. Operand expressions are evaluated from left to right, just like function call arguments. After the `asm!` has executed, outputs are written to in left to right order. This is significant if two outputs point to the same place: that place will contain the value of the rightmost output. -Since `global_asm!` exists outside a function, it cannot use input/output operands. +Since `global_asm!` exists outside a function, it can only use `sym` operands. ## Register operands From 0763b2ebb6c8d4c8057f1a498438d791840495f7 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 16 Sep 2022 10:10:46 -0400 Subject: [PATCH 073/315] Nikos review --- src/items/associated-items.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index d28ab6b13..97b2c2087 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -230,7 +230,7 @@ but cannot contain `Bounds`, but instead must contain a `Type`: ```rust,ignore type Assoc = Type; -type Assoc = Type; +type Assoc = Type; // the type `Type` here may reference `Params` type Assoc where WhereBounds = Type; type Assoc = Type where WhereBounds; ``` @@ -338,7 +338,9 @@ impl Container for Vec { ### Required where clauses on generic associated types Generic associated type declarations on traits currently may require a list of -where clauses, dependent on functions in the trait and how the GAT is used. +where clauses, dependent on functions in the trait and how the GAT is used. These +rules may be loosened in the future; updates can be found [on the generic +associated types initiative repository](https://rust-lang.github.io/generic-associated-types-initiative/explainer/required_bounds.html). In a few words, these where clauses are required in order to maximize the allowed definitions of the associated type in impls. To do this, any clauses that *can be From 3970ed35ebbb91083dfadceea35ae4c982969a83 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Fri, 16 Sep 2022 10:20:59 -0400 Subject: [PATCH 074/315] Remove space --- src/items/type-aliases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md index dd0efee04..5ab885af8 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -40,7 +40,7 @@ A type alias with the [_Type_] specification may only appear as an A type alias with [_TypeParamBounds_] may only specified when used as an [associated type] in a [trait]. -Where clauses before the equals sign on a type alias in a [trait impl] (like +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. From 37881f526811bdf0d27a47da19bb725fb671128b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 18 Sep 2022 06:20:15 -0400 Subject: [PATCH 075/315] Update src/items/associated-items.md --- src/items/associated-items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 97b2c2087..4996ff719 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -224,7 +224,7 @@ The identifier is the name of the declared type alias. The optional trait bounds must be fulfilled by the implementations of the type alias. There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound. -An *associated type definition* defines a type alias on for the implementation +An *associated type definition* defines a type alias for the implementation of a trait on a type. They are written similarly to an *associated type declaration*, but cannot contain `Bounds`, but instead must contain a `Type`: From 1ae7c2d5c6f56df070002788d355cd6c927c465d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 19 Sep 2022 14:32:31 -0700 Subject: [PATCH 076/315] Link to default representation. --- src/type-layout.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type-layout.md b/src/type-layout.md index 467ad65d2..6154fe16a 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -86,7 +86,7 @@ String slices are a UTF-8 representation of characters that have the same layout ## Tuple Layout -Tuples are laid out according to the default representation. +Tuples are laid out according to the [default representation][Default]. 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. From 300ac4bdb40b91945a8e774f534a2902564d41ec Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 19 Sep 2022 16:18:44 -0700 Subject: [PATCH 077/315] Editorial changes for raw-dylib. --- src/items/external-blocks.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index e13ca5438..c91e1d10c 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -122,7 +122,7 @@ specifies the kind of library with the following possible values: - `static` — Indicates a static library. - `framework` — Indicates a macOS framework. This is only valid for macOS targets. -- `raw-dylib` - Indicates a dynamic library where the compiler will generate +- `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. @@ -209,13 +209,13 @@ of the symbols exported by the dynamic library in such a way that the linker knows that they have to be dynamically loaded at runtime. Specifying `kind = "dylib"` instructs the Rust compiler to link an import -library based on the `name` key, the linker will then use its normal library +library based on the `name` key. The linker will then use its normal library resolution logic to find that import library. Alternatively, specifying `kind = "raw-dylib"` instructs the compiler to generate an import library during compilation and provide that to the linker instead. -`raw-dylib` is only supported on Windows and not supported on x86 -(`target_arch="x86"`), see [58713]. Using it when targeting other platforms or +`raw-dylib` is only supported on Windows and not supported on 32-bit x86 +(`target_arch="x86"`). Using it when targeting other platforms or x86 on Windows will result in a compiler error. ### The `link_name` attribute @@ -289,4 +289,3 @@ restrictions as [regular function parameters]. [`bundle` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-bundle [`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive [`dylib` versus `raw-dylib`]: #dylib-versus-raw-dylib -[58713]: https://github.com/rust-lang/rust/issues/58713 From 1f9de62e04e6c79922ab78062407a658f4c3fa6a Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Tue, 20 Sep 2022 08:24:17 +0800 Subject: [PATCH 078/315] Update Unicode reference to match rustc implementation. --- src/identifiers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/identifiers.md b/src/identifiers.md index a4e972cd3..c760f6826 100644 --- a/src/identifiers.md +++ b/src/identifiers.md @@ -13,7 +13,7 @@ > NON_KEYWORD_IDENTIFIER | RAW_IDENTIFIER -Identifiers follow the specification in [Unicode Standard Annex #31][UAX31] for Unicode version 13.0, with the additions described below. Some examples of identifiers: +Identifiers follow the specification in [Unicode Standard Annex #31][UAX31] for Unicode version 15.0, with the additions described below. Some examples of identifiers: * `foo` * `_identifier` @@ -68,5 +68,5 @@ keyword except the ones listed above for `RAW_IDENTIFIER`. [proc-macro]: procedural-macros.md [reserved]: keywords.md#reserved-keywords [strict]: keywords.md#strict-keywords -[UAX15]: https://www.unicode.org/reports/tr15/tr15-50.html -[UAX31]: https://www.unicode.org/reports/tr31/tr31-33.html +[UAX15]: https://www.unicode.org/reports/tr15/tr15-53.html +[UAX31]: https://www.unicode.org/reports/tr31/tr31-37.html From e2ac66c1898a64628923ec4487088dc45d1dfd4a Mon Sep 17 00:00:00 2001 From: Ceyhun ERTURK Date: Thu, 26 May 2022 02:00:53 +0300 Subject: [PATCH 079/315] Clarify wording for references. --- src/types/pointer.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types/pointer.md b/src/types/pointer.md index 47bda4f82..f627cdc7c 100644 --- a/src/types/pointer.md +++ b/src/types/pointer.md @@ -11,8 +11,8 @@ They can be moved or copied, stored into data structs, and returned from functio ### Shared references (`&`) -These point to memory _owned by some other value_. -When a shared reference to a value is created it prevents direct mutation of the value. +Shared references point to memory which is owned by some other value. +When a shared reference to a value is created, it prevents direct mutation of the value. [Interior mutability] provides an exception for this in certain circumstances. As the name suggests, any number of shared references to a value may exist. A shared reference type is written `&type`, or `&'a type` when you need to specify an explicit lifetime. @@ -22,7 +22,7 @@ Releasing a reference has no effect on the value it points to, but referencing o ### Mutable references (`&mut`) -These also point to memory owned by some other value. +Mutable references point to memory which is owned by some other value. A mutable reference type is written `&mut type` or `&'a mut type`. A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`. From 328e227ea01617f3d42cb8fe981031bd08863e72 Mon Sep 17 00:00:00 2001 From: Smittyvb Date: Sat, 24 Sep 2022 08:25:06 -0400 Subject: [PATCH 080/315] Use semver-compliant example version Clippy warns if this version isn't semver-compliant. --- src/attributes/diagnostics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 1dd9363d8..45f9cc440 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -184,7 +184,7 @@ Tuple struct fields are ignored. Here is an example: ```rust -#[deprecated(since = "5.2", note = "foo was rarely used. Users should instead use bar")] +#[deprecated(since = "5.2.0", note = "foo was rarely used. Users should instead use bar")] pub fn foo() {} pub fn bar() {} From a87587e8d7dbccf80db60f0ec2df381ff7733405 Mon Sep 17 00:00:00 2001 From: "Ryan Scheel (isHavvy)" Date: Sun, 11 Sep 2022 02:09:51 -0700 Subject: [PATCH 081/315] Rewrite Range Patterns with Half Open ranges This rewrite not only adds half-open ranges to the documentation for stabilizing the feature, it also rewrites the entire section to answer more questions about how they work, like what types the range patterns actually match against. --- src/patterns.md | 61 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index ea7beb30f..987a90d74 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -389,6 +389,7 @@ match tuple { > > _HalfOpenRangePattern_ :\ >    | _RangePatternBound_ `..` +>    | `..=` _RangePatternBound_ > > _ObsoleteRangePattern_ :\ >    _RangePatternBound_ `...` _RangePatternBound_ @@ -400,26 +401,51 @@ match tuple { >    | `-`? [FLOAT_LITERAL]\ >    | [_PathExpression_] -Range patterns match values within the range defined by their bounds. +*Range patterns* match scalar values within the range defined by their bounds. +A bound on the left of its sigils is a *lower bound*. +A bound on the right is an *upper bound*. A range pattern may be closed or half-open. -A range pattern is closed if it has both a lower and an upper bound, and it matches all the values between and including both of its bounds. -A range pattern that is half-open is written with a lower bound but not an upper bound, and matches any value equal to or greater than the specified lower bound. + +A range pattern is *closed* if it has both a lower and an upper bound. +The only closed ranged pattern is the inclusive range pattern. + +*Inclusive range patterns* match all the values between and including both of its bounds. +It is written as its lower bounds, followed by `..=`, followed by its upper bounds. +The type of it is the type unification of its upper and lower bounds. For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. + +The lower bound cannot be greater than the upper bound. +That is, in `a..=b`, a ≤ b must be the case. +For example, it is an error to have a range pattern `10..=0`. + +Range patterns are *half-open* if they have only an upper or lower bound. +They have the same type as their upper or lower bound. + +A half open range with only a lower bound is written as its lower bound followed by `..`. +These range patterns will match on any value greater than or equal to the lower bound. +For example, `1..` will match 1, 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers. For an integer the pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers. The bounds can be literals or paths that point to constant values. -A half-open range pattern in the style `a..` cannot be used to match within the context of a slice. +A half open range with only an upper bound is written as `..=` followed by its upper bound. +These range patterns will match on any value less than or equal to the upper bound. +For example, `..=10` will match 10, 1, 0, and for signed interger types, all negative values. -A pattern `a..=b` must always have a ≤ b. -It is an error to have a range pattern `10..=0`, for example. +Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns). -Range patterns only work on scalar types. The accepted types are: +The bounds is written as one of: -* Integer types (u8, i8, u16, i16, usize, isize, etc.). -* Character types (char). -* Floating point types (f32 and f64). - This is being deprecated and will not be available in a future version of Rust (see [issue #41620](https://github.com/rust-lang/rust/issues/41620)). +* A character, byte, integer, or float literal. +* A `-` followed by an integer or float literal. +* A [path] + +If the bounds is written as a path, after macro resolution, the path must resolve to a constant item of the type `char`, an integer type, or a float type. + +The type and value of the bounds is dependent upon how it is written out. +If the bounds is a [path], the pattern has the type and value of the [constant] the path resolves to. +If it is a literal, it has the type and value of the corresponding [literal expression]. +If is a literal preceded by a `-`, it has the same type as the corresponding [literal expression] and the value of [negating] the value of the corresponding literal expression. Examples: @@ -496,13 +522,19 @@ println!("{}", match 0xfacade { }); ``` -Range patterns for (non-`usize` and -`isize`) integer and `char` types are irrefutable when they span the entire set of possible values of a type. +Range patterns for fix-width integer and `char` types are irrefutable when they span the entire set of possible values of a type. For example, `0u8..=255u8` is irrefutable. The range of values for an integer type is the closed range from its minimum to maximum value. The range of values for a `char` type are precisely those ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and `'\u{E000}'..='\u{10FFFF}'`. +Floating point range patterns are deprecated and may be removed in a future Rust release. +See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more information. + > **Edition Differences**: Before the 2021 edition, closed range patterns may also be written using `...` as an alternative to `..=`, with the same meaning. +> **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns. +> That is, neither `x .. y` nor `.. x` are valid range patterns. + ## Reference patterns > **Syntax**\ @@ -809,8 +841,13 @@ For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound i [`Copy`]: special-types-and-traits.md#copy [IDENTIFIER]: identifiers.md +[constant]: items/constant-items.md [enums]: items/enumerations.md [literals]: expressions/literal-expr.md +[literal expression]: expressions/literal-expr.md +[negating]: expressions/operator-expr.md#negation-operators +[path]: expressions/path-expr.md +[range expressions]: expressions/range-expr.md [structs]: items/structs.md [tuples]: types/tuple.md [scrutinee]: glossary.md#scrutinee From 32caa7d1ad18984ebf7ee44f78b11f4515fd6909 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Sep 2022 22:04:33 +0200 Subject: [PATCH 082/315] mention the extra const UB --- src/behavior-considered-undefined.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index e810e8c0d..10954a072 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -60,6 +60,11 @@ code. > `rustc_layout_scalar_valid_range_*` attributes. * Incorrect use of inline assembly. For more details, refer to the [rules] to follow when writing code that uses inline assembly. +* **In [const context](const_eval.md#const-context)**: transmuting or otherwise + reinterpreting a pointer (reference, raw pointer, or function pointer) into + some allocated object as a non-pointer type (such as integers). + 'Reinterpreting' refers to loading the pointer value at integer type without a + cast, e.g. by doing raw pointer casts or using a union. **Note:** Uninitialized memory is also implicitly invalid for any type that has a restricted set of valid values. In other words, the only cases in which From 6c8431ff420371d78f3a6ed29018dc28d116f257 Mon Sep 17 00:00:00 2001 From: "Ryan Scheel (isHavvy)" Date: Mon, 26 Sep 2022 22:43:23 -0700 Subject: [PATCH 083/315] Address review comments on Range Pattern commit. --- src/patterns.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index 987a90d74..14bbac155 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -388,7 +388,7 @@ match tuple { >       _RangePatternBound_ `..=` _RangePatternBound_ > > _HalfOpenRangePattern_ :\ ->    | _RangePatternBound_ `..` +>       _RangePatternBound_ `..` >    | `..=` _RangePatternBound_ > > _ObsoleteRangePattern_ :\ @@ -425,7 +425,6 @@ They have the same type as their upper or lower bound. A half open range with only a lower bound is written as its lower bound followed by `..`. These range patterns will match on any value greater than or equal to the lower bound. For example, `1..` will match 1, 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers. -For an integer the pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but not 0, and not negative numbers for signed integers. The bounds can be literals or paths that point to constant values. A half open range with only an upper bound is written as `..=` followed by its upper bound. From da28385057ca850ba7019f956589aa0807ade571 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Tue, 27 Sep 2022 14:13:36 +0200 Subject: [PATCH 084/315] Update tokens.md Fix singular/plural issue. --- src/tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens.md b/src/tokens.md index 197c20147..8f9bcb1f7 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -667,7 +667,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite > **Edition Differences**: Starting with the 2021 edition, reserved prefixes are reported as an error by the lexer (in particular, they cannot be passed to macros). > -> Before the 2021 edition, a reserved prefixes are accepted by the lexer and interpreted as multiple tokens (for example, one token for the identifier or keyword, followed by a `#` token). +> Before the 2021 edition, reserved prefixes are accepted by the lexer and interpreted as multiple tokens (for example, one token for the identifier or keyword, followed by a `#` token). > > Examples accepted in all editions: > ```rust From 575d859aa0f97f66a587b47c47bf03243765fd5a Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 27 Sep 2022 15:19:39 -0400 Subject: [PATCH 085/315] Alpha-rename "Loop expressions" chapter to "Loops and other breakable expressions" instead. --- src/expressions/block-expr.md | 4 ++-- src/expressions/loop-expr.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index e46f2e83d..bd9c0a623 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -142,7 +142,7 @@ let a = unsafe { an_unsafe_fn() }; ## Labelled block expressions -Labelled block expressions are documented in the [Loop expressions] section. +Labelled block expressions are documented in the [Loops and other breakable expressions] section. ## Attributes on block expressions @@ -193,4 +193,4 @@ fn is_unix_platform() -> bool { [tuple expressions]: tuple-expr.md [unsafe operations]: ../unsafety.md [value expressions]: ../expressions.md#place-expressions-and-value-expressions -[Loop expressions]: loop-expr.md#labelled-block-expressions +[Loops and other breakable expressions]: loop-expr.md#labelled-block-expressions diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index d3c4d38d1..204207ee0 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -1,4 +1,4 @@ -# Loops +# Loops and other breakable expressions > **Syntax**\ > _LoopExpression_ :\ From f24b8d4ca7aeb5340db673c7364b19e056b4de48 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Sep 2022 17:31:50 +0200 Subject: [PATCH 086/315] merge unsafe-block and unsafe-function into one page --- book.toml | 2 ++ src/SUMMARY.md | 3 +-- src/attributes/codegen.md | 2 +- src/types/function-pointer.md | 2 +- src/unsafe-functions.md | 5 ----- src/{unsafe-blocks.md => unsafe-keyword.md} | 10 +++++++++- 6 files changed, 14 insertions(+), 10 deletions(-) delete mode 100644 src/unsafe-functions.md rename src/{unsafe-blocks.md => unsafe-keyword.md} (79%) diff --git a/book.toml b/book.toml index 19b9afc79..9fb3730c8 100644 --- a/book.toml +++ b/book.toml @@ -10,6 +10,8 @@ edit-url-template = "https://github.com/rust-lang/reference/edit/master/{path}" [output.html.redirect] "/expressions/enum-variant-expr.html" = "struct-expr.html" +"/unsafe-blocks.html" = "unsafe-keyword.html" +"/unsafe-functions.html" = "unsafe-keyword.html" [rust] edition = "2021" diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 82d70d043..4d9cc1d76 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -118,8 +118,7 @@ - [Inline assembly](inline-assembly.md) - [Unsafety](unsafety.md) - - [Unsafe functions](unsafe-functions.md) - - [Unsafe blocks](unsafe-blocks.md) + - [The `unsafe` keyword](unsafe-keyword.md) - [Behavior considered undefined](behavior-considered-undefined.md) - [Behavior not considered unsafe](behavior-not-considered-unsafe.md) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 4ebabaccf..3a36a10ca 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -347,7 +347,7 @@ trait object whose methods are attributed. [target architecture]: ../conditional-compilation.md#target_arch [trait]: ../items/traits.md [undefined behavior]: ../behavior-considered-undefined.md -[unsafe function]: ../unsafe-functions.md +[unsafe function]: ../unsafe-keyword.md [rust-abi]: ../items/external-blocks.md#abi [`core::intrinsics::caller_location`]: ../../core/intrinsics/fn.caller_location.html [`core::panic::Location::caller`]: ../../core/panic/struct.Location.html#method.caller diff --git a/src/types/function-pointer.md b/src/types/function-pointer.md index a51f76135..82103beaa 100644 --- a/src/types/function-pointer.md +++ b/src/types/function-pointer.md @@ -62,5 +62,5 @@ restrictions as [regular function parameters]. [closures]: closure.md [extern function]: ../items/functions.md#extern-function-qualifier [function items]: function-item.md -[unsafe function]: ../unsafe-functions.md +[unsafe function]: ../unsafe-keyword.md [regular function parameters]: ../items/functions.md#attributes-on-function-parameters diff --git a/src/unsafe-functions.md b/src/unsafe-functions.md deleted file mode 100644 index 7a5064c08..000000000 --- a/src/unsafe-functions.md +++ /dev/null @@ -1,5 +0,0 @@ -# Unsafe functions - -Unsafe functions are functions that are not safe in all contexts and/or for all -possible inputs. Such a function must be prefixed with the keyword `unsafe` and -can only be called from an `unsafe` block or another `unsafe` function. diff --git a/src/unsafe-blocks.md b/src/unsafe-keyword.md similarity index 79% rename from src/unsafe-blocks.md rename to src/unsafe-keyword.md index 754278445..1c7b4c848 100644 --- a/src/unsafe-blocks.md +++ b/src/unsafe-keyword.md @@ -1,4 +1,12 @@ -# Unsafe blocks +# The `unsafe` keyword + +## Unsafe functions + +Unsafe functions are functions that are not safe in all contexts and/or for all +possible inputs. Such a function must be prefixed with the keyword `unsafe` and +can only be called from an `unsafe` block or another `unsafe` function. + +## Unsafe blocks A block of code can be prefixed with the `unsafe` keyword, to permit calling `unsafe` functions or dereferencing raw pointers within a safe function. From 3c8acda52ffcf5f7ca410c76f4fddf0e129592e2 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Wed, 28 Sep 2022 18:11:43 -0400 Subject: [PATCH 087/315] Review comments --- src/items/associated-items.md | 4 +++- src/items/type-aliases.md | 12 ++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 4996ff719..0bc1a2b8c 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -211,6 +211,7 @@ lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds on the associated type, and `WhereBounds` is a comma-separated list of bounds on parameters: + ```rust,ignore type Assoc; type Assoc: Bounds; @@ -228,11 +229,12 @@ An *associated type definition* defines a type alias for the implementation of a trait on a type. They are written similarly to an *associated type declaration*, but cannot contain `Bounds`, but instead must contain a `Type`: + ```rust,ignore type Assoc = Type; type Assoc = Type; // the type `Type` here may reference `Params` -type Assoc where WhereBounds = Type; type Assoc = Type where WhereBounds; +type Assoc where WhereBounds = Type; // deprecated, prefer the form above ``` If a type `Item` has an associated type `Assoc` from a trait `Trait`, then diff --git a/src/items/type-aliases.md b/src/items/type-aliases.md index 5ab885af8..d2e14b903 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -31,14 +31,14 @@ let _ = UseAlias(5); // OK let _ = TypeAlias(5); // Doesn't work ``` -A type alias without the [_Type_] specification may only appear as an -[associated type] in a [trait]. +A type alias, when not used as an associated type, must include a [_Type_] and +may not include [_TypeParamBounds_]. -A type alias with the [_Type_] specification may only appear as an -[associated type] in a [trait impl]. +A type alias, when used as an [associated type] in a [trait], must not include a +[_Type_] specification but may include [_TypeParamBounds_]. -A type alias with [_TypeParamBounds_] may only specified when used as -an [associated type] in a [trait]. +A type alias, when used as an [associated type] in a [trait impl], must include +a [_Type_] specification and may not include [_TypeParamBounds_]. Where clauses before the equals sign on a type alias in a [trait impl] (like `type TypeAlias where T: Foo = Bar`) are deprecated. Where clauses after From 1423936cc4a847e2e5fa0b49d08b39a80f90e872 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Sep 2022 15:45:27 +0200 Subject: [PATCH 088/315] update unsafe docs --- src/unsafe-keyword.md | 81 ++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/src/unsafe-keyword.md b/src/unsafe-keyword.md index 1c7b4c848..71e055ca0 100644 --- a/src/unsafe-keyword.md +++ b/src/unsafe-keyword.md @@ -1,30 +1,55 @@ # The `unsafe` keyword -## Unsafe functions - -Unsafe functions are functions that are not safe in all contexts and/or for all -possible inputs. Such a function must be prefixed with the keyword `unsafe` and -can only be called from an `unsafe` block or another `unsafe` function. - -## Unsafe blocks - -A block of code can be prefixed with the `unsafe` keyword, to permit calling -`unsafe` functions or dereferencing raw pointers within a safe function. - -When a programmer has sufficient conviction that a sequence of potentially -unsafe operations is actually safe, they can encapsulate that sequence (taken -as a whole) within an `unsafe` block. The compiler will consider uses of such -code safe, in the surrounding context. - -Unsafe blocks are used to wrap foreign libraries, make direct use of hardware -or implement features not directly present in the language. For example, Rust -provides the language features necessary to implement memory-safe concurrency -in the language but the implementation of threads and message passing is in the -standard library. - -Rust's type system is a conservative approximation of the dynamic safety -requirements, so in some cases there is a performance cost to using safe code. -For example, a doubly-linked list is not a tree structure and can only be -represented with reference-counted pointers in safe code. By using `unsafe` -blocks to represent the reverse links as raw pointers, it can be implemented -with only boxes. +The `unsafe` keyword can occur in several different contexts: +unsafe functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe trait`), and unsafe trait implementations (`unsafe impl`). +It plays several different roles, depending on where it is used and whether the `unsafe_op_in_unsafe_fn` lint is enabled: +- it is used to mark code that *defines* extra safety conditions (`unsafe fn`, `unsafe trait`) +- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without `unsafe_op_in_unsafe_fn`) + +The following discusses each of these cases. +See the [keyword documentation][keyword] for some illustrative examples. + +[keyword]: ../std/keyword.unsafe.html + +## Unsafe functions (`unsafe fn`) + +Unsafe functions are functions that are not safe in all contexts and/or for all possible inputs. +We say they have *extra safety conditions*, which are requirements that must be upheld by all callers and that the compiler does not check. +For example, `get_unchecked` has the extra safety condition that the index must be in-bounds. +The module defining an unsafe function is responsible for documenting what those extra safety conditions are. + +Such a function must be prefixed with the keyword `unsafe` and can only be called from inside an `unsafe` block. + +## Unsafe blocks (`unsafe {}`) + +A block of code can be prefixed with the `unsafe` keyword, to permit calling `unsafe` functions or dereferencing raw pointers. +By default, the body of an unsafe function is also considered to be an unsafe block; +this can be changed by enabling the `unsafe_op_in_unsafe_fn` lint. + +By putting operations into an unsafe block, the programmer states that they have taken care of satisfying the extra safety conditions of all operations inside that block. + +Unsafe blocks are the logical dual to unsafe functions: +where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations have been discharged. +There are many ways to discharge proof obligations; +for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn` and use its own proof obligations to discharge the proof obligations of its callees. + +Unsafe blocks are used to wrap foreign libraries, make direct use of hardware or implement features not directly present in the language. +For example, Rust provides the language features necessary to implement memory-safe concurrency in the language but the implementation of threads and message passing in the standard library uses unsafe blocks. + +Rust's type system is a conservative approximation of the dynamic safety requirements, so in some cases there is a performance cost to using safe code. +For example, a doubly-linked list is not a tree structure and can only be represented with reference-counted pointers in safe code. +By using `unsafe` blocks to represent the reverse links as raw pointers, it can be implemented without reference counting. + +## Unsafe traits (`unsafe trait`) + +An unsafe trait is a trait that comes with extra safety conditions that must be upheld by *implementations* of the trait. +The module defining an unsafe trait is responsible for documenting what those extra safety conditions are. + +Such a trait must be prefixed with the keyword `unsafe` and can only be implemented by `unsafe impl` blocks. + +## Unsafe trait implementations (`unsafe impl`) + +When implementing an unsafe trait, the implementation needs to be prefixed with the `unsafe` keyword. +By writing `unsafe impl`, the programmer states that they have taken care of satisfying the extra safety conditions required by the trait. + +Unsafe trait implementations are the logical dual to unsafe traits: where unsafe traits define a proof obligation that implementations must uphold, unsafe implementations state that all relevant proof obligations have been discharged. From d1e4ea12affb7f0b5abf733d5150bc62905a9c94 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 30 Sep 2022 11:09:25 +0200 Subject: [PATCH 089/315] apply feedback --- src/unsafe-keyword.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/unsafe-keyword.md b/src/unsafe-keyword.md index 71e055ca0..5fa5deea6 100644 --- a/src/unsafe-keyword.md +++ b/src/unsafe-keyword.md @@ -4,27 +4,25 @@ The `unsafe` keyword can occur in several different contexts: unsafe functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe trait`), and unsafe trait implementations (`unsafe impl`). It plays several different roles, depending on where it is used and whether the `unsafe_op_in_unsafe_fn` lint is enabled: - it is used to mark code that *defines* extra safety conditions (`unsafe fn`, `unsafe trait`) -- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without `unsafe_op_in_unsafe_fn`) +- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without [`unsafe_op_in_unsafe_fn`]) The following discusses each of these cases. See the [keyword documentation][keyword] for some illustrative examples. -[keyword]: ../std/keyword.unsafe.html - ## Unsafe functions (`unsafe fn`) Unsafe functions are functions that are not safe in all contexts and/or for all possible inputs. We say they have *extra safety conditions*, which are requirements that must be upheld by all callers and that the compiler does not check. -For example, `get_unchecked` has the extra safety condition that the index must be in-bounds. -The module defining an unsafe function is responsible for documenting what those extra safety conditions are. +For example, [`get_unchecked`] has the extra safety condition that the index must be in-bounds. +The unsafe function should come with documentation explaining what those extra safety conditions are. -Such a function must be prefixed with the keyword `unsafe` and can only be called from inside an `unsafe` block. +Such a function must be prefixed with the keyword `unsafe` and can only be called from inside an `unsafe` block, or inside `unsafe fn` without the [`unsafe_op_in_unsafe_fn`] lint. ## Unsafe blocks (`unsafe {}`) A block of code can be prefixed with the `unsafe` keyword, to permit calling `unsafe` functions or dereferencing raw pointers. By default, the body of an unsafe function is also considered to be an unsafe block; -this can be changed by enabling the `unsafe_op_in_unsafe_fn` lint. +this can be changed by enabling the [`unsafe_op_in_unsafe_fn`] lint. By putting operations into an unsafe block, the programmer states that they have taken care of satisfying the extra safety conditions of all operations inside that block. @@ -39,11 +37,12 @@ For example, Rust provides the language features necessary to implement memory-s Rust's type system is a conservative approximation of the dynamic safety requirements, so in some cases there is a performance cost to using safe code. For example, a doubly-linked list is not a tree structure and can only be represented with reference-counted pointers in safe code. By using `unsafe` blocks to represent the reverse links as raw pointers, it can be implemented without reference counting. +(See ["Learn Rust With Entirely Too Many Linked Lists"](https://rust-unofficial.github.io/too-many-lists/) for a more in-depth exploration of this particular example.) ## Unsafe traits (`unsafe trait`) An unsafe trait is a trait that comes with extra safety conditions that must be upheld by *implementations* of the trait. -The module defining an unsafe trait is responsible for documenting what those extra safety conditions are. +The unsafe trait should come with documentation explaining what those extra safety conditions are. Such a trait must be prefixed with the keyword `unsafe` and can only be implemented by `unsafe impl` blocks. @@ -53,3 +52,7 @@ When implementing an unsafe trait, the implementation needs to be prefixed with By writing `unsafe impl`, the programmer states that they have taken care of satisfying the extra safety conditions required by the trait. Unsafe trait implementations are the logical dual to unsafe traits: where unsafe traits define a proof obligation that implementations must uphold, unsafe implementations state that all relevant proof obligations have been discharged. + +[keyword]: ../std/keyword.unsafe.html +[`get_unchecked`]: ../std/primitive.slice.html#method.get_unchecked +[`unsafe_op_in_unsafe_fn`]: ../rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn From 2325d952d11ff817ce50c0c1a96b81517f566c51 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 3 Oct 2022 18:57:35 -0400 Subject: [PATCH 090/315] Remove unstable API mention --- src/conditional-compilation.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 3f6173e67..97840e4f6 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -196,11 +196,8 @@ Example values: Key-value option set for each bit width that the target supports atomic loads, stores, and compare-and-swap operations. -When this cfg is present, all of the [`core::sync::atomic`] APIs are available for -the relevant atomic width with the exception of `from_mut` methods (currently -unstable), which additionally require that the primitive integer and atomic have -the same minimum alignment on the given target. No user-visible, stable cfg is -exposed for that method at this time. +When this cfg is present, all of the stable [`core::sync::atomic`] APIs are available for +the relevant atomic width. [`core::sync::atomic`]: ../core/sync/atomic/index.html From 3e10ae3bbb46a9070b4232d3fe64ff5f1a22c438 Mon Sep 17 00:00:00 2001 From: est31 Date: Thu, 3 Feb 2022 19:31:43 +0100 Subject: [PATCH 091/315] Document let else statements --- src/statements.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/statements.md b/src/statements.md index 8d9c21d7d..67e77efaa 100644 --- a/src/statements.md +++ b/src/statements.md @@ -54,17 +54,27 @@ fn outer() { > **Syntax**\ > _LetStatement_ :\ >    [_OuterAttribute_]\* `let` [_PatternNoTopAlt_] -> ( `:` [_Type_] )? (`=` [_Expression_] )? `;` - -A *`let` statement* introduces a new set of [variables], given by an -irrefutable [pattern]. The pattern is followed optionally by a type -annotation and then optionally by an initializer expression. When no -type annotation is given, the compiler will infer the type, or signal +> ( `:` [_Type_] )? (`=` [_Expression_] [†](#let-else-restriction) +> ( `else` [_BlockExpression_]) ? ) ? `;` +> +> † When an `else` block is specified, the +> _Expression_ must not be a [_LazyBooleanExpression_], or end with a `}`. + +A *`let` statement* introduces a new set of [variables], given by a [pattern]. +The pattern is followed optionally by a type annotation and then either ends, +or is followed by an initializer expression plus an optional `else` block. +When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference. Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope, except when they are shadowed by another variable declaration. +If an `else` block is not present, the pattern must be irrefutable. +If an `else` block is present, the pattern may be refutable. +If the pattern does not match (this requires it to be refutable), the `else` +block is executed. +The `else` block must always diverge (evaluate to the [never type]). + ## Expression statements > **Syntax**\ @@ -121,6 +131,7 @@ statement are [`cfg`], and [the lint check attributes]. [function]: items/functions.md [item]: items.md [module]: items/modules.md +[never type]: types/never.md [canonical path]: paths.md#canonical-paths [implementations]: items/implementations.md [variables]: variables.md @@ -128,9 +139,11 @@ statement are [`cfg`], and [the lint check attributes]. [`cfg`]: conditional-compilation.md [the lint check attributes]: attributes/diagnostics.md#lint-check-attributes [pattern]: patterns.md +[_BlockExpression_]: expressions/block-expr.md [_ExpressionStatement_]: #expression-statements [_Expression_]: expressions.md [_Item_]: items.md +[_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators [_LetStatement_]: #let-statements [_MacroInvocationSemi_]: macros.md#macro-invocation [_OuterAttribute_]: attributes.md From a50e43ee796f0cc8266701736af0a287f6bc54c7 Mon Sep 17 00:00:00 2001 From: est31 Date: Tue, 20 Sep 2022 04:28:31 +0200 Subject: [PATCH 092/315] Add example --- src/statements.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/statements.md b/src/statements.md index 67e77efaa..7acb0dc25 100644 --- a/src/statements.md +++ b/src/statements.md @@ -75,6 +75,17 @@ 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 +let Some(t) = v.pop() else { // Refutable patterns require an else block + panic!(); // The else block must diverge +}; +let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler + // will lint as the else block is redundant. + panic!(); +}; +``` + ## Expression statements > **Syntax**\ From 9e6a8c029e142810b0f1dd7421c8aacab399aec6 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 26 Sep 2022 09:26:12 +0200 Subject: [PATCH 093/315] let bindings can now be refutable too --- src/items/functions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/items/functions.md b/src/items/functions.md index 325588a53..5b4ac7af6 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -59,8 +59,8 @@ fn answer_to_life_the_universe_and_everything() -> i32 { ## Function parameters -As with `let` bindings, function parameters are irrefutable [patterns], so any -pattern that is valid in a let binding is also valid as a parameter: +Function parameters are irrefutable [patterns], so any pattern that is valid in +an else-less `let` binding is also valid as a parameter: ```rust fn first((value, _): (i32, i32)) -> i32 { value } From cadf497c73fd8a745d2cbbcdd5539003f48f3c1b Mon Sep 17 00:00:00 2001 From: "Ryan Scheel (isHavvy)" Date: Wed, 28 Sep 2022 16:51:48 -0700 Subject: [PATCH 094/315] One line one sentence for main Expressions chapter. --- src/expressions.md | 137 +++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 85 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 0c01238c3..b2411cd8e 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -42,28 +42,24 @@ >       | [_MatchExpression_]\ >    ) -An expression may have two roles: it always produces a *value*, and it may have -*effects* (otherwise known as "side effects"). An expression *evaluates to* a -value, and has effects during *evaluation*. Many expressions contain -sub-expressions, called the *operands* of the expression. The meaning of each -kind of expression dictates several things: +An expression may have two roles: it always produces a *value*, and it may have *effects* (otherwise known as "side effects"). +An expression *evaluates to* a value, and has effects during *evaluation*. +Many expressions contain sub-expressions, called the *operands* of the expression. +The meaning of each kind of expression dictates several things: * Whether or not to evaluate the operands when evaluating the expression * The order in which to evaluate the operands * How to combine the operands' values to obtain the value of the expression In this way, the structure of expressions dictates the structure of execution. -Blocks are just another kind of expression, so blocks, statements, expressions, -and blocks again can recursively nest inside each other to an arbitrary depth. +Blocks are just another kind of expression, so blocks, statements, expressions, and blocks again can recursively nest inside each other to an arbitrary depth. -> **Note**: We give names to the operands of expressions so that we may discuss -> them, but these names are not stable and may be changed. +> **Note**: We give names to the operands of expressions so that we may discuss them, but these names are not stable and may be changed. ## Expression precedence -The precedence of Rust operators and expressions is ordered as follows, going -from strong to weak. Binary Operators at the same precedence level are grouped -in the order given by their associativity. +The precedence of Rust operators and expressions is ordered as follows, going from strong to weak. +Binary Operators at the same precedence level are grouped in the order given by their associativity. | Operator/Expression | Associativity | |-----------------------------|---------------------| @@ -89,9 +85,8 @@ in the order given by their associativity. ## Evaluation order of operands -The following list of expressions all evaluate their operands the same way, as -described after the list. Other expressions either don't take operands or -evaluate them conditionally as described on their respective pages. +The following list of expressions all evaluate their operands the same way, as described after the list. +Other expressions either don't take operands or evaluate them conditionally as described on their respective pages. * Dereference expression * Error propagation expression @@ -113,15 +108,13 @@ evaluate them conditionally as described on their respective pages. * Range expression * Return expression -The operands of these expressions are evaluated prior to applying the effects of -the expression. Expressions taking multiple operands are evaluated left to right -as written in the source code. +The operands of these expressions are evaluated prior to applying the effects of the expression. +Expressions taking multiple operands are evaluated left to right as written in the source code. > **Note**: Which subexpressions are the operands of an expression is > determined by expression precedence as per the previous section. -For example, the two `next` method calls will always be called in the same -order: +For example, the two `next` method calls will always be called in the same order: ```rust # // Using vec instead of array to avoid references @@ -134,23 +127,18 @@ assert_eq!( ); ``` -> **Note**: Since this is applied recursively, these expressions are also -> evaluated from innermost to outermost, ignoring siblings until there are no -> inner subexpressions. +> **Note**: Since this is applied recursively, these expressions are also evaluated from innermost to outermost, ignoring siblings until there are no inner subexpressions. ## Place Expressions and Value Expressions -Expressions are divided into two main categories: place expressions and value -expressions; there is also a third, minor category of expressions called -assignee expressions. Within each expression, operands may likewise occur in -either place context or value context. The evaluation of an expression depends -both on its own category and the context it occurs within. +Expressions are divided into two main categories: place expressions and value expressions; +there is also a third, minor category of expressions called assignee expressions. +Within each expression, operands may likewise occur in either place context or value context. +The evaluation of an expression depends both on its own category and the context it occurs within. -A *place expression* is an expression that represents a memory location. These -expressions are [paths] which refer to local variables, [static variables], -[dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), -[field] references (`expr.f`) and parenthesized place expressions. All other -expressions are value expressions. +A *place expression* is an expression that represents a memory location. +These expressions are [paths] which refer to local variables, [static variables], [dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized place expressions. +All other expressions are value expressions. A *value expression* is an expression that represents an actual value. @@ -166,11 +154,10 @@ The following contexts are *place expression* contexts: expression. * The base of a [functional update] struct expression. -> Note: Historically, place expressions were called *lvalues* and value -> expressions were called *rvalues*. +> Note: Historically, place expressions were called *lvalues* and value expressions were called *rvalues*. -An *assignee expression* is an expression that appears in the left operand of an -[assignment][assign] expression. Explicitly, the assignee expressions are: +An *assignee expression* is an expression that appears in the left operand of an [assignment][assign] expression. +Explicitly, the assignee expressions are: - Place expressions. - [Underscores][_UnderscoreExpression_]. @@ -185,59 +172,49 @@ Arbitrary parenthesisation is permitted inside assignee expressions. ### Moved and copied types -When a place expression is evaluated in a value expression context, or is bound -by value in a pattern, it denotes the value held _in_ that memory location. If -the type of that value implements [`Copy`], then the value will be copied. In -the remaining situations, if that type is [`Sized`], then it may be possible to -move the value. Only the following place expressions may be moved out of: +When a place expression is evaluated in a value expression context, or is bound by value in a pattern, it denotes the value held _in_ that memory location. +If the type of that value implements [`Copy`], then the value will be copied. +In the remaining situations, if that type is [`Sized`], then it may be possible to move the value. +Only the following place expressions may be moved out of: * [Variables] which are not currently borrowed. * [Temporary values](#temporaries). -* [Fields][field] of a place expression which can be moved out of and - don't implement [`Drop`]. -* The result of [dereferencing][deref] an expression with type [`Box`] and - that can also be moved out of. +* [Fields][field] of a place expression which can be moved out of and don't implement [`Drop`]. +* The result of [dereferencing][deref] an expression with type [`Box`] and that can also be moved out of. -After moving out of a place expression that evaluates to a local variable, the -location is deinitialized and cannot be read from again until it is -reinitialized. In all other cases, trying to use a place expression in a value -expression context is an error. +After moving out of a place expression that evaluates to a local variable, the location is deinitialized and cannot be read from again until it is reinitialized. +In all other cases, trying to use a place expression in a value expression context is an error. ### Mutability -For a place expression to be [assigned][assign] to, mutably [borrowed][borrow], -[implicitly mutably borrowed], or bound to a pattern containing `ref mut`, it -must be _mutable_. We call these *mutable place expressions*. In contrast, -other place expressions are called *immutable place expressions*. +For a place expression to be [assigned][assign] to, mutably [borrowed][borrow], [implicitly mutably borrowed], or bound to a pattern containing `ref mut`, it must be _mutable_. +We call these *mutable place expressions*. +In contrast, other place expressions are called *immutable place expressions*. The following expressions can be mutable place expression contexts: * Mutable [variables] which are not currently borrowed. * [Mutable `static` items]. * [Temporary values]. -* [Fields][field]: this evaluates the subexpression in a mutable place - expression context. +* [Fields][field]: this evaluates the subexpression in a mutable place expression context. * [Dereferences][deref] of a `*mut T` pointer. -* Dereference of a variable, or field of a variable, with type `&mut T`. Note: - This is an exception to the requirement of the next rule. -* Dereferences of a type that implements `DerefMut`: this then requires that - the value being dereferenced is evaluated in a mutable place expression context. -* [Array indexing] of a type that implements `IndexMut`: this - then evaluates the value being indexed, but not the index, in mutable place - expression context. +* Dereference of a variable, or field of a variable, with type `&mut T`. + Note: This is an exception to the requirement of the next rule. +* Dereferences of a type that implements `DerefMut`: + this then requires that the value being dereferenced is evaluated in a mutable place expression context. +* [Array indexing] of a type that implements `IndexMut`: + this then evaluates the value being indexed, but not the index, in mutable place expression context. ### Temporaries -When using a value expression in most place expression contexts, a temporary -unnamed memory location is created and initialized to that value. The expression -evaluates to that location instead, except if [promoted] to a `static`. The -[drop scope] of the temporary is usually the end of the enclosing statement. +When using a value expression in most place expression contexts, a temporary unnamed memory location is created and initialized to that value. +The expression evaluates to that location instead, except if [promoted] to a `static`. +The [drop scope] of the temporary is usually the end of the enclosing statement. ### Implicit Borrows -Certain expressions will treat an expression as a place expression by implicitly -borrowing it. For example, it is possible to compare two unsized [slices][slice] for -equality directly, because the `==` operator implicitly borrows its operands: +Certain expressions will treat an expression as a place expression by implicitly borrowing it. +For example, it is possible to compare two unsized [slices][slice] for equality directly, because the `==` operator implicitly borrows its operands: ```rust # let c = [1, 2, 3]; @@ -264,31 +241,21 @@ Implicit borrows may be taken in the following expressions: ## Overloading Traits -Many of the following operators and expressions can also be overloaded for -other types using traits in `std::ops` or `std::cmp`. These traits also -exist in `core::ops` and `core::cmp` with the same names. +Many of the following operators and expressions can also be overloaded for other types using traits in `std::ops` or `std::cmp`. +These traits also exist in `core::ops` and `core::cmp` with the same names. ## Expression Attributes -[Outer attributes][_OuterAttribute_] before an expression are allowed only in -a few specific cases: +[Outer attributes][_OuterAttribute_] before an expression are allowed only in a few specific cases: * Before an expression used as a [statement]. -* Elements of [array expressions], [tuple expressions], [call expressions], - and tuple-style [struct] expressions. - +* Elements of [array expressions], [tuple expressions], [call expressions], and tuple-style [struct] expressions. * The tail expression of [block expressions]. They are never allowed before: * [Range][_RangeExpression_] expressions. -* Binary operator expressions ([_ArithmeticOrLogicalExpression_], - [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_], - [_AssignmentExpression_], [_CompoundAssignmentExpression_]). +* Binary operator expressions ([_ArithmeticOrLogicalExpression_], [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_], [_AssignmentExpression_], [_CompoundAssignmentExpression_]). [block expressions]: expressions/block-expr.md From e076c6ed0caa11c33842dc0d22961947c8bf236a Mon Sep 17 00:00:00 2001 From: "Ryan Scheel (isHavvy)" Date: Wed, 28 Sep 2022 17:20:41 -0700 Subject: [PATCH 095/315] One line one sentence for the Statements chapter. --- src/expressions.md | 9 +++++++ src/statements.md | 62 +++++++++++++++++----------------------------- 2 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index b2411cd8e..0b446af2b 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -129,6 +129,15 @@ assert_eq!( > **Note**: Since this is applied recursively, these expressions are also evaluated from innermost to outermost, ignoring siblings until there are no inner subexpressions. +## Early Termination + +Expressions may be *terminated* early, whether by a jump expression or unwinding. +When terminated, evaluation of the expression stops. +If the expression is the target of termination by a jump expression, then it evaluates to the value specified by the jump expression. +Otherwise, it evaluates to the never type. + +**Note**: Destructors are still executed for the expression after being terminated. + ## Place Expressions and Value Expressions Expressions are divided into two main categories: place expressions and value expressions; diff --git a/src/statements.md b/src/statements.md index 7acb0dc25..c2ae585a0 100644 --- a/src/statements.md +++ b/src/statements.md @@ -9,35 +9,27 @@ >    | [_MacroInvocationSemi_] -A *statement* is a component of a [block], which is in turn a component of an -outer [expression] or [function]. +A *statement* is a component of a [block], which is in turn a component of an outer [expression] or [function]. -Rust has two kinds of statement: [declaration -statements](#declaration-statements) and [expression -statements](#expression-statements). +Rust has two kinds of statement: [declaration statements](#declaration-statements) and [expression statements](#expression-statements). ## Declaration statements -A *declaration statement* is one that introduces one or more *names* into the -enclosing statement block. The declared names may denote new variables or new -[items][item]. +A *declaration statement* is one that introduces one or more *names* into the enclosing statement block. +The declared names may denote new variables or new [items][item]. -The two kinds of declaration statements are item declarations and `let` -statements. +The two kinds of declaration statements are item declarations and `let` statements. ### Item declarations -An *item declaration statement* has a syntactic form identical to an -[item declaration][item] within a [module]. Declaring an item within a statement -block restricts its scope to the block containing the statement. The item is not -given a [canonical path] nor are any sub-items it may declare. The exception to -this is that associated items defined by [implementations] are still accessible -in outer scopes as long as the item and, if applicable, trait are accessible. +An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module]. +Declaring an item within a statement block restricts its scope to the block containing the statement. +The item is not given a [canonical path] nor are any sub-items it may declare. +The exception to this is that associated items defined by [implementations] are still accessible in outer scopes as long as the item and, if applicable, trait are accessible. It is otherwise identical in meaning to declaring the item inside a module. -There is no implicit capture of the containing function's generic parameters, -parameters, and local variables. For example, `inner` may not access -`outer_var`. +There is no implicit capture of the containing function's generic parameters, parameters, and local variables. +For example, `inner` may not access `outer_var`. ```rust fn outer() { @@ -61,18 +53,13 @@ fn outer() { > _Expression_ must not be a [_LazyBooleanExpression_], or end with a `}`.
A *`let` statement* introduces a new set of [variables], given by a [pattern]. -The pattern is followed optionally by a type annotation and then either ends, -or is followed by an initializer expression plus an optional `else` block. -When no type annotation is given, the compiler will infer the type, or signal -an error if insufficient type information is available for definite -inference. Any variables introduced by a variable declaration are visible -from the point of declaration until the end of the enclosing block scope, -except when they are shadowed by another variable declaration. +The pattern is followed optionally by a type annotation and then either ends, or is followed by an initializer expression plus an optional `else` block. +When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference. +Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope, except when they are shadowed by another variable declaration. If an `else` block is not present, the pattern must be irrefutable. If an `else` block is present, the pattern may be refutable. -If the pattern does not match (this requires it to be refutable), the `else` -block is executed. +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 @@ -93,16 +80,13 @@ let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler >       [_ExpressionWithoutBlock_][expression] `;`\ >    | [_ExpressionWithBlock_][expression] `;`? -An *expression statement* is one that evaluates an [expression] and ignores its -result. As a rule, an expression statement's purpose is to trigger the effects -of evaluating its expression. +An *expression statement* is one that evaluates an [expression] and ignores its result. +As a rule, an expression statement's purpose is to trigger the effects of evaluating its expression. -An expression that consists of only a [block expression][block] or control flow -expression, if used in a context where a statement is permitted, can omit the -trailing semicolon. This can cause an ambiguity between it being parsed as a -standalone statement and as a part of another expression; in this case, it is -parsed as a statement. The type of [_ExpressionWithBlock_][expression] -expressions when used as statements must be the unit type. +An expression that consists of only a [block expression][block] or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon. +This can cause an ambiguity between it being parsed as a standalone statement and as a part of another expression; +in this case, it is parsed as a statement. +The type of [_ExpressionWithBlock_][expression] expressions when used as statements must be the unit type. ```rust # let mut v = vec![1, 2, 3]; @@ -134,8 +118,8 @@ if true { ## Attributes on Statements -Statements accept [outer attributes]. The attributes that have meaning on a -statement are [`cfg`], and [the lint check attributes]. +Statements accept [outer attributes]. +The attributes that have meaning on a statement are [`cfg`], and [the lint check attributes]. [block]: expressions/block-expr.md [expression]: expressions.md From 45c47cd38654388910a8a92f5435570355ea2762 Mon Sep 17 00:00:00 2001 From: "Ryan Scheel (isHavvy)" Date: Wed, 28 Sep 2022 17:21:45 -0700 Subject: [PATCH 096/315] One line one sentence the statements and expressions chapter. --- src/expressions.md | 9 --------- src/statements-and-expressions.md | 12 ++++-------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/expressions.md b/src/expressions.md index 0b446af2b..b2411cd8e 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -129,15 +129,6 @@ assert_eq!( > **Note**: Since this is applied recursively, these expressions are also evaluated from innermost to outermost, ignoring siblings until there are no inner subexpressions. -## Early Termination - -Expressions may be *terminated* early, whether by a jump expression or unwinding. -When terminated, evaluation of the expression stops. -If the expression is the target of termination by a jump expression, then it evaluates to the value specified by the jump expression. -Otherwise, it evaluates to the never type. - -**Note**: Destructors are still executed for the expression after being terminated. - ## Place Expressions and Value Expressions Expressions are divided into two main categories: place expressions and value expressions; diff --git a/src/statements-and-expressions.md b/src/statements-and-expressions.md index b093972a9..fede41196 100644 --- a/src/statements-and-expressions.md +++ b/src/statements-and-expressions.md @@ -1,11 +1,7 @@ # Statements and expressions -Rust is _primarily_ an expression language. This means that most forms of -value-producing or effect-causing evaluation are directed by the uniform syntax -category of _expressions_. Each kind of expression can typically _nest_ within -each other kind of expression, and rules for evaluation of expressions involve -specifying both the value produced by the expression and the order in which its -sub-expressions are themselves evaluated. +Rust is _primarily_ an expression language. +This means that most forms of value-producing or effect-causing evaluation are directed by the uniform syntax category of _expressions_. +Each kind of expression can typically _nest_ within each other kind of expression, and rules for evaluation of expressions involve specifying both the value produced by the expression and the order in which its sub-expressions are themselves evaluated. -In contrast, statements serve _mostly_ to contain and explicitly -sequence expression evaluation. +In contrast, statements serve _mostly_ to contain and explicitly sequence expression evaluation. From 3c9516b800901a0bc323df0ebb6e34adf2d2f5e8 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Sat, 8 Oct 2022 11:43:07 +0900 Subject: [PATCH 097/315] Typo 'a' -> 'an' --- src/destructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/destructors.md b/src/destructors.md index 6d616b3e7..242d9b2db 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -158,7 +158,7 @@ smallest scope that contains the expression and is one of the following: * The entire function body. * A statement. -* The body of a [`if`], [`while`] or [`loop`] expression. +* The body of an [`if`], [`while`] or [`loop`] expression. * The `else` block of an `if` expression. * The condition expression of an `if` or `while` expression, or a `match` guard. From 6b9e4ffd539af7db5e27b6c829f120f827ef69a4 Mon Sep 17 00:00:00 2001 From: Jack Huey <31162821+jackh726@users.noreply.github.com> Date: Tue, 18 Oct 2022 20:14:44 -0400 Subject: [PATCH 098/315] Add a section on relationship between bounds and wherebounds --- src/items/associated-items.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 0bc1a2b8c..2401127b5 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -208,8 +208,8 @@ 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 -on the associated type, and `WhereBounds` is a comma-separated list of bounds on -parameters: +that the associated type must meet, and `WhereBounds` is a comma-separated list +of bounds that the parameters must meet: ```rust,ignore @@ -337,6 +337,19 @@ impl Container for Vec { } ``` +### Relationship between `Bounds` and `WhereBounds` + +In this example: + +```rust +# use std::fmt::Debug; +trait Example { + type Output: Ord where T: Debug; +} +``` + +Given a reference to the associated type like `::Output`, the associated type itself must be `Ord`, and the type `Y` must be `Debug`. + ### Required where clauses on generic associated types Generic associated type declarations on traits currently may require a list of From 50a597cc56af8d9d93e7071a4099480648eb9672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 19 Oct 2022 11:46:48 +0200 Subject: [PATCH 099/315] type parameter `Self` is unsized by default --- src/special-types-and-traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/special-types-and-traits.md b/src/special-types-and-traits.md index ca53b3c9a..6355f3fb2 100644 --- a/src/special-types-and-traits.md +++ b/src/special-types-and-traits.md @@ -135,7 +135,7 @@ UnwindSafe>` is a valid type. ## `Sized` The [`Sized`] trait indicates that the size of this type is known at compile-time; that is, it's not a [dynamically sized type]. -[Type parameters] are `Sized` by default, as are [associated types]. +[Type parameters] (except `Self` in traits) are `Sized` by default, as are [associated types]. `Sized` is always implemented automatically by the compiler, not by [implementation items]. These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound. From 7c5b80d96da3ba16848d6aba6a99aa06efe0bc31 Mon Sep 17 00:00:00 2001 From: amab8901 <83634595+amab8901@users.noreply.github.com> Date: Fri, 21 Oct 2022 04:57:01 +0200 Subject: [PATCH 100/315] clarifying which row contains the example --- src/expressions/grouped-expr.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/expressions/grouped-expr.md b/src/expressions/grouped-expr.md index 0ff7e2c90..1ae2209c5 100644 --- a/src/expressions/grouped-expr.md +++ b/src/expressions/grouped-expr.md @@ -16,8 +16,8 @@ Parentheses can be used to explicitly modify the precedence order of subexpressi An example of a parenthesized expression: ```rust -let x: i32 = 2 + 3 * 4; -let y: i32 = (2 + 3) * 4; +let x: i32 = 2 + 3 * 4; // not parenthesized +let y: i32 = (2 + 3) * 4; // parenthesized assert_eq!(x, 14); assert_eq!(y, 20); ``` From 4e0edd1428d3bdf680198a52e83ac400a1ba7c04 Mon Sep 17 00:00:00 2001 From: Yutaro Ohno Date: Wed, 26 Oct 2022 20:17:48 +0900 Subject: [PATCH 101/315] Fix a minor typo in the "Higher-ranked trait bounds" section --- src/trait-bounds.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trait-bounds.md b/src/trait-bounds.md index f284ca4eb..c8dab3f1c 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -121,7 +121,7 @@ For example, if `'a` is an unconstrained lifetime parameter, then `i32: 'static` > _ForLifetimes_ :\ >    `for` [_GenericParams_] -Type bounds may be *higher ranked* over lifetimes. These bounds specify a bound +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 From 45f85e1c2995e96ba0d907f4ea1572983647f124 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Sun, 14 Jul 2019 16:25:25 -0400 Subject: [PATCH 102/315] Update enum documentation for arbitrary_enum_discriminant feature. --- src/expressions/operator-expr.md | 2 +- src/items/enumerations.md | 128 ++++++++++++++++++++++++++----- 2 files changed, 110 insertions(+), 20 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index d8658d647..21621638f 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -368,7 +368,7 @@ reference types and `mut` or `const` in pointer types. | Type of `e` | `U` | Cast performed by `e as U` | |-----------------------|-----------------------|----------------------------------| | Integer or Float type | Integer or Float type | Numeric cast | -| C-like enum | Integer type | Enum cast | +| Field-less enum | Integer type | Enum cast | | `bool` or `char` | Integer type | Primitive to integer cast | | `u8` | `char` | `u8` to `char` cast | | `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast | diff --git a/src/items/enumerations.md b/src/items/enumerations.md index 28d3ba873..3b30cd469 100644 --- a/src/items/enumerations.md +++ b/src/items/enumerations.md @@ -13,8 +13,8 @@ > > _EnumItem_ :\ >    _OuterAttribute_\* [_Visibility_]?\ ->    [IDENTIFIER] ( _EnumItemTuple_ | _EnumItemStruct_ -> | _EnumItemDiscriminant_ )? +>    [IDENTIFIER] ( _EnumItemTuple_ | _EnumItemStruct_ )? +> _EnumItemDiscriminant_? > > _EnumItemTuple_ :\ >    `(` [_TupleFields_]? `)` @@ -56,22 +56,68 @@ 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. Each enum instance has a _discriminant_ which is an -integer associated to it that is used to determine which variant it holds. An -opaque reference to this discriminant can be obtained with the -[`mem::discriminant`] function. +called an enum variant. -## Custom Discriminant Values for Fieldless Enumerations +## Discriminants -If there is no data attached to *any* of the variants of an enumeration, -then the discriminant can be directly chosen and accessed. +Each enum instance has a _discriminant_: an integer logically associated to it +that is used to determine which variant it holds. An opaque reference to this +discriminant can be obtained with the [`mem::discriminant`] function. -These enumerations can be cast to integer types with the `as` operator by a -[numeric cast]. The enumeration can optionally specify which integer each -discriminant gets by following the variant name with `=` followed by a [constant -expression]. If the first variant in the declaration is unspecified, then it is -set to zero. For every other unspecified discriminant, it is set to one higher -than the previous variant in the declaration. +Under the [default 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. + +If the [primitive representation] or the [`C` representation] is used, the +leading bytes of a variant (e.g., two bytes if `#[repr(u16)]` is used), will +correspond exactly to the discriminant. + +### Assigning Discriminant Values + +#### Explicit Discriminants + +In two circumstances, the discriminant of a variant may be explicitly set by +following the variant name with `=` and a [constant expression]: + +
    +
  1. + +if the enumeration is "C-like" (i.e., it has no tuple or struct variants); e.g.: + +```rust +# #![feature(arbitrary_enum_discriminant)] +enum Enum { + Foo = 3, + Bar = 2, + Baz = 1, +} +``` +
  2. +
  3. + +if a [primitive representation] is used; e.g.: + +```rust +# #![feature(arbitrary_enum_discriminant)] +#[repr(u8)] +enum Enum { + Unit = 3, + Tuple(u16), + Struct { + a: u8, + b: u16, + } = 1, +} +``` +
  4. +
+ +#### 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. ```rust enum Foo { @@ -84,10 +130,7 @@ let baz_discriminant = Foo::Baz as u32; assert_eq!(baz_discriminant, 123); ``` -Under the [default representation], the specified discriminant is interpreted as -an `isize` value although the compiler is allowed to use a smaller type in the -actual memory layout. The size and thus acceptable values can be changed by -using a [primitive representation] or the [`C` representation]. +#### Restrictions It is an error when two variants share the same discriminant. @@ -122,6 +165,53 @@ enum OverflowingDiscriminantError2 { } ``` +### Accessing Discriminant Values + +#### Casting + +If there is no data attached to *any* of the variants of an enumeration, then +the discriminant can be directly accessed with a [numeric cast]; e.g.: + +```rust +enum Enum { + Unit, + Tuple(), + Struct{}, +} + +assert_eq!(0, Enum::Unit as isize); +assert_eq!(1, Enum::Tuple() as isize); +assert_eq!(2, Enum::Struct{} as isize); +``` + +#### Pointer Casting + +If the enumeration specifies a [primitive representation], then the +discriminant may be reliably accessed via unsafe pointer casting: + +```rust +#[repr(u8)] +enum Enum { + Unit, + Tuple(bool), + Struct{a: bool}, +} + +impl Enum { + fn discriminant(&self) -> u8 { + unsafe { *(self as *const Self as *const u8) } + } +} + +let unit_like = Enum::Unit; +let tuple_like = Enum::Tuple(true); +let struct_like = Enum::Struct{a: false}; + +assert_eq!(0, unit_like.discriminant()); +assert_eq!(1, tuple_like.discriminant()); +assert_eq!(2, struct_like.discriminant()); +``` + ## Zero-variant Enums Enums with zero variants are known as *zero-variant enums*. As they have From 3b5ac6c1cf13005a4a5be541b8d9b3fa8524f559 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Mon, 15 Jul 2019 13:27:25 -0400 Subject: [PATCH 103/315] "e.g." -> "for example" Co-Authored-By: Ryan Scheel --- src/items/enumerations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/items/enumerations.md b/src/items/enumerations.md index 3b30cd469..72c7820a5 100644 --- a/src/items/enumerations.md +++ b/src/items/enumerations.md @@ -69,7 +69,7 @@ an `isize` value. However, the compiler is allowed to use a smaller type (or another means of distinguishing variants) in its actual memory layout. If the [primitive representation] or the [`C` representation] is used, the -leading bytes of a variant (e.g., two bytes if `#[repr(u16)]` is used), will +leading bytes of a variant (for example, two bytes if `#[repr(u16)]` is used), will correspond exactly to the discriminant. ### Assigning Discriminant Values @@ -95,7 +95,7 @@ enum Enum {
  • -if a [primitive representation] is used; e.g.: +if a [primitive representation] is used. For example: ```rust # #![feature(arbitrary_enum_discriminant)] From f8ac109624aad26711824fc9e9e0780a1c52f34a Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sun, 4 Jul 2021 14:14:32 +0800 Subject: [PATCH 104/315] Applied suggestions from Havvy --- src/items/enumerations.md | 24 +++++++++++++----------- src/type-layout.md | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/items/enumerations.md b/src/items/enumerations.md index 72c7820a5..08c06cfcb 100644 --- a/src/items/enumerations.md +++ b/src/items/enumerations.md @@ -58,20 +58,18 @@ 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. +An enum where no constructors contain fields are called a +*field-less enum*. + ## Discriminants Each enum instance has a _discriminant_: an integer logically associated to it -that is used to determine which variant it holds. An opaque reference to this -discriminant can be obtained with the [`mem::discriminant`] function. +that is used to determine which variant it holds. Under the [default 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. -If the [primitive representation] or the [`C` representation] is used, the -leading bytes of a variant (for example, two bytes if `#[repr(u16)]` is used), will -correspond exactly to the discriminant. - ### Assigning Discriminant Values #### Explicit Discriminants @@ -85,7 +83,6 @@ following the variant name with `=` and a [constant expression]: if the enumeration is "C-like" (i.e., it has no tuple or struct variants); e.g.: ```rust -# #![feature(arbitrary_enum_discriminant)] enum Enum { Foo = 3, Bar = 2, @@ -98,7 +95,6 @@ enum Enum { if a [primitive representation] is used. For example: ```rust -# #![feature(arbitrary_enum_discriminant)] #[repr(u8)] enum Enum { Unit = 3, @@ -165,12 +161,18 @@ enum OverflowingDiscriminantError2 { } ``` -### Accessing Discriminant Values +### Accessing Discriminant + +#### Via `mem::discriminant` + +[`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. #### Casting -If there is no data attached to *any* of the variants of an enumeration, then -the discriminant can be directly accessed with a [numeric cast]; e.g.: +If an enumeration is fieldless, then its discriminant can be directly +accessed with a [numeric cast]; e.g.: ```rust enum Enum { diff --git a/src/type-layout.md b/src/type-layout.md index 80a36abb8..191567a42 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -583,7 +583,7 @@ used with any other representation. [`Sized`]: ../std/marker/trait.Sized.html [`Copy`]: ../std/marker/trait.Copy.html [dynamically sized types]: dynamically-sized-types.md -[field-less enums]: items/enumerations.md#custom-discriminant-values-for-fieldless-enumerations +[field-less enums]: items/enumerations.md#field-less-enum [enumerations]: items/enumerations.md [zero-variant enums]: items/enumerations.md#zero-variant-enums [undefined behavior]: behavior-considered-undefined.md From 3d4745b3480bfe80cd4320aeaf8b84394ae49fe0 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 19 Aug 2021 04:39:07 +0000 Subject: [PATCH 105/315] Apply Suggestions --- src/const_eval.md | 2 +- src/items/enumerations.md | 54 +++++++++++++++++---------------------- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/const_eval.md b/src/const_eval.md index c0560376c..34e34d703 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -113,7 +113,7 @@ Conversely, the following are possible in a const function, but not in a const c [Const parameters]: items/generics.md [dereference operator]: expressions/operator-expr.md#the-dereference-operator [destructors]: destructors.md -[enum discriminants]: items/enumerations.md#custom-discriminant-values-for-fieldless-enumerations +[enum discriminants]: items/enumerations.md#discriminants [expression statements]: statements.md#expression-statements [expressions]: expressions.md [field]: expressions/field-expr.md diff --git a/src/items/enumerations.md b/src/items/enumerations.md index 08c06cfcb..b023991e4 100644 --- a/src/items/enumerations.md +++ b/src/items/enumerations.md @@ -59,7 +59,7 @@ In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply called an enum variant. An enum where no constructors contain fields are called a -*field-less enum*. +*field-less enum*. ## Discriminants @@ -77,36 +77,30 @@ another means of distinguishing variants) in its actual memory layout. In two circumstances, the discriminant of a variant may be explicitly set by following the variant name with `=` and a [constant expression]: -
      -
    1. -if the enumeration is "C-like" (i.e., it has no tuple or struct variants); e.g.: - -```rust -enum Enum { - Foo = 3, - Bar = 2, - Baz = 1, -} -``` -
    2. -
    3. - -if a [primitive representation] is used. For example: - -```rust -#[repr(u8)] -enum Enum { - Unit = 3, - Tuple(u16), - Struct { - a: u8, - b: u16, - } = 1, -} -``` -
    4. -
    +1. if the enumeration is fieldless; e.g.: + + ```rust + enum Enum { + Foo = 3, + Bar() = 2, + Baz {} = 1, + } + ``` + +2. if a [primitive representation] is used. For example: + + ```rust + #[repr(u8)] + enum Enum { + Unit = 3, + Tuple(u16), + Struct { + a: u8, + b: u16, + } = 1, + } + ``` #### Implicit Discriminants From 5d9300ce4271e612fc8d7454a28c185692efb245 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 28 Oct 2022 14:59:51 +0800 Subject: [PATCH 106/315] Update terminology from fieldless to unit-only --- src/expressions/operator-expr.md | 3 +- src/items/enumerations.md | 49 ++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 21621638f..99d815d0f 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -368,7 +368,7 @@ reference types and `mut` or `const` in pointer types. | Type of `e` | `U` | Cast performed by `e as U` | |-----------------------|-----------------------|----------------------------------| | Integer or Float type | Integer or Float type | Numeric cast | -| Field-less enum | Integer type | Enum cast | +| [Unit-only enum] | Integer type | Enum cast | | `bool` or `char` | Integer type | Primitive to integer cast | | `u8` | `char` | `u8` to `char` cast | | `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast | @@ -643,6 +643,7 @@ See [this test] for an example of using this dependency. [assignee expression]: ../expressions.md#place-expressions-and-value-expressions [undefined behavior]: ../behavior-considered-undefined.md [unit]: ../types/tuple.md +[Unit-only enum]: ../items/enumerations.md#unit-only-enum [value expression]: ../expressions.md#place-expressions-and-value-expressions [temporary value]: ../expressions.md#temporaries [this test]: https://github.com/rust-lang/rust/blob/1.58.0/src/test/ui/expr/compound-assignment/eval-order.rs diff --git a/src/items/enumerations.md b/src/items/enumerations.md index b023991e4..ff0a3479d 100644 --- a/src/items/enumerations.md +++ b/src/items/enumerations.md @@ -59,7 +59,26 @@ In this example, `Cat` is a _struct-like enum variant_, whereas `Dog` is simply called an enum variant. An enum where no constructors contain fields are called a -*field-less enum*. +*field-less enum*. For example, this is a fieldless enum: + +```rust +enum Fieldless { + Tuple(), + Struct{}, + Unit, +} +``` + +If a field-less enum only contains unit variants, the enum is called an +*unit-only enum*. For example: + +```rust +enum Enum { + Foo = 3, + Bar = 2, + Baz = 1, +} +``` ## Discriminants @@ -78,15 +97,8 @@ In two circumstances, the discriminant of a variant may be explicitly set by following the variant name with `=` and a [constant expression]: -1. if the enumeration is fieldless; e.g.: +1. if the enumeration is "[unit-only]". - ```rust - enum Enum { - Foo = 3, - Bar() = 2, - Baz {} = 1, - } - ``` 2. if a [primitive representation] is used. For example: @@ -161,23 +173,23 @@ enum OverflowingDiscriminantError2 { [`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. +of the discriminant. #### Casting -If an enumeration is fieldless, 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 { - Unit, - Tuple(), - Struct{}, + Foo, + Bar, + Baz, } -assert_eq!(0, Enum::Unit as isize); -assert_eq!(1, Enum::Tuple() as isize); -assert_eq!(2, Enum::Struct{} as isize); +assert_eq!(0, Enum::Foo as isize); +assert_eq!(1, Enum::Bar as isize); +assert_eq!(2, Enum::Baz as isize); ``` #### Pointer Casting @@ -267,6 +279,7 @@ enum E { [enumerated type]: ../types/enum.md [`mem::discriminant`]: ../../std/mem/fn.discriminant.html [never type]: ../types/never.md +[unit-only]: #unit-only-enum [numeric cast]: ../expressions/operator-expr.md#semantics [constant expression]: ../const_eval.md#constant-expressions [default representation]: ../type-layout.md#the-default-representation From 8a86959fe961c09f201f1116bcbacf759e0604d4 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Mon, 31 Oct 2022 16:09:58 +0800 Subject: [PATCH 107/315] Add a comma --- src/items/generics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/generics.md b/src/items/generics.md index 5ffcd1580..5b7170726 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -51,7 +51,7 @@ instances of the item must be instantiated with a value of the given type. -The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`, `usize` +The only allowed types of const parameters are `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128`, `isize`, `char` and `bool`. Const parameters can be used anywhere a [const item] can be used, with the From 66754d60ef7eedb7c04e83024a1576a40ce4372b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Oct 2022 11:24:39 +0100 Subject: [PATCH 108/315] update aliasing rules section of the reference --- src/behavior-considered-undefined.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index e810e8c0d..baa064562 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -26,8 +26,15 @@ code. * Evaluating a [dereference expression] (`*expr`) on a raw pointer that is [dangling] or unaligned, even in [place expression context] (e.g. `addr_of!(&*expr)`). -* Breaking the [pointer aliasing rules]. `&mut T` and `&T` follow LLVM’s scoped - [noalias] model, except if the `&T` contains an [`UnsafeCell`]. +* Breaking the [pointer aliasing rules]. `Box`, `&mut T` and `&T` follow LLVM’s + scoped noalias model, except if the `&T` contains an [`UnsafeCell`]. + References must not be dangling while they are live. (The exact liveness + duration is not specified, but it is certainly upper-bounded by the syntactic + lifetime assigned by the borrow checker. When a reference is passed to a + function, it is live at least as long as that function call, again except if + the `&T` contains an [`UnsafeCell`].) All this also applies when values of + these types are passed in a (nested) field of a compound type, but not behind + pointer indirections. * Mutating immutable data. All data inside a [`const`] item is immutable. Moreover, all data reached through a shared reference or data owned by an immutable binding is immutable, unless that data is contained within an [`UnsafeCell`]. From 7110c8eb3bbc5ea92f03240aa5a271eec0037bb0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Oct 2022 19:19:09 +0100 Subject: [PATCH 109/315] add back link --- src/behavior-considered-undefined.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index baa064562..3f4e7d880 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -27,7 +27,7 @@ code. [dangling] or unaligned, even in [place expression context] (e.g. `addr_of!(&*expr)`). * Breaking the [pointer aliasing rules]. `Box`, `&mut T` and `&T` follow LLVM’s - scoped noalias model, except if the `&T` contains an [`UnsafeCell`]. + scoped [noalias] model, except if the `&T` contains an [`UnsafeCell`]. References must not be dangling while they are live. (The exact liveness duration is not specified, but it is certainly upper-bounded by the syntactic lifetime assigned by the borrow checker. When a reference is passed to a From 36579679fe9e959b0f3022c9fb35c9fadfb8df57 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 31 Oct 2022 20:51:54 +0100 Subject: [PATCH 110/315] clarify liveness --- src/behavior-considered-undefined.md | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 3f4e7d880..12cbc43bb 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -26,14 +26,20 @@ code. * Evaluating a [dereference expression] (`*expr`) on a raw pointer that is [dangling] or unaligned, even in [place expression context] (e.g. `addr_of!(&*expr)`). -* Breaking the [pointer aliasing rules]. `Box`, `&mut T` and `&T` follow LLVM’s - scoped [noalias] model, except if the `&T` contains an [`UnsafeCell`]. - References must not be dangling while they are live. (The exact liveness - duration is not specified, but it is certainly upper-bounded by the syntactic - lifetime assigned by the borrow checker. When a reference is passed to a - function, it is live at least as long as that function call, again except if - the `&T` contains an [`UnsafeCell`].) All this also applies when values of - these types are passed in a (nested) field of a compound type, but not behind +* Breaking the [pointer aliasing rules]. `Box`, `&mut T` and `&T` follow + LLVM’s scoped [noalias] model, except if the `&T` contains an + [`UnsafeCell`]. References and boxes must not be dangling while they are + live. The exact liveness duration is not specified, but some bounds exist: + * For references, the liveness duration is upper-bounded by the syntactic + lifetime assigned by the borrow checker. + * Each time a reference or box is passed to or returned from a function, it is + considered live. + * When a reference (but not a `Box`!) is passed to a function, it is live at + least as long as that function call, again except if the `&T` contains an + [`UnsafeCell`]. + + All this also applies when values of these + types are passed in a (nested) field of a compound type, but not behind pointer indirections. * Mutating immutable data. All data inside a [`const`] item is immutable. Moreover, all data reached through a shared reference or data owned by an immutable binding From e05229ddadbe233fc9fd1f1e4a32397793243d4e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Nov 2022 19:52:37 +0100 Subject: [PATCH 111/315] clarify "upper bound" Co-authored-by: Josh Triplett --- src/behavior-considered-undefined.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 12cbc43bb..6fc96a9e8 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -31,7 +31,8 @@ code. [`UnsafeCell`]. References and boxes must not be dangling while they are live. The exact liveness duration is not specified, but some bounds exist: * For references, the liveness duration is upper-bounded by the syntactic - lifetime assigned by the borrow checker. + lifetime assigned by the borrow checker; it cannot be live any *longer* than + that lifetime. * Each time a reference or box is passed to or returned from a function, it is considered live. * When a reference (but not a `Box`!) is passed to a function, it is live at From 2af818d235b6c39cb76a099b859a84438e3409f2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 1 Nov 2022 20:06:30 +0100 Subject: [PATCH 112/315] forward reference to 'dangling' --- src/behavior-considered-undefined.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 6fc96a9e8..f8bffd13e 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -28,7 +28,7 @@ code. (e.g. `addr_of!(&*expr)`). * Breaking the [pointer aliasing rules]. `Box`, `&mut T` and `&T` follow LLVM’s scoped [noalias] model, except if the `&T` contains an - [`UnsafeCell`]. References and boxes must not be dangling while they are + [`UnsafeCell`]. References and boxes must not be [dangling] while they are live. The exact liveness duration is not specified, but some bounds exist: * For references, the liveness duration is upper-bounded by the syntactic lifetime assigned by the borrow checker; it cannot be live any *longer* than From 219e33667d63dfa2069c6296d75d56e34fa5b8f8 Mon Sep 17 00:00:00 2001 From: Autumn! <86073772+autumnull@users.noreply.github.com> Date: Fri, 4 Nov 2022 02:17:41 +0000 Subject: [PATCH 113/315] Disallow newline directly following `//` --- src/comments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comments.md b/src/comments.md index 46074b45c..ad29c58e5 100644 --- a/src/comments.md +++ b/src/comments.md @@ -2,7 +2,7 @@ > **Lexer**\ > LINE_COMMENT :\ ->       `//` (~\[`/` `!`] | `//`) ~`\n`\*\ +>       `//` (~\[`/` `!` `\n`] | `//`) ~`\n`\*\ >    | `//` > > BLOCK_COMMENT :\ From 0ec6d52723c74542437d03092307cf2bf315629c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Nov 2022 15:43:18 +0300 Subject: [PATCH 114/315] Document native library modifier `verbatim` --- src/items/external-blocks.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index c91e1d10c..d89536968 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -201,6 +201,22 @@ The default for this modifier is `-whole-archive`. More implementation details about this modifier can be found in [`whole-archive` documentation for rustc]. +### Linking modifiers: `verbatim` + +This modifier is compatible with all linking kinds. + +`+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 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. + +The default for this modifier is `-verbatim`. + +More implementation details about this modifier can be found in +[`verbatim` documentation for rustc]. + #### `dylib` versus `raw-dylib` On Windows, linking against a dynamic library requires that an import library @@ -288,4 +304,5 @@ restrictions as [regular function parameters]. [regular function parameters]: functions.md#attributes-on-function-parameters [`bundle` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-bundle [`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive +[`verbatim` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-verbatim [`dylib` versus `raw-dylib`]: #dylib-versus-raw-dylib From 87f527b36e1e7195337b596e838a2e5d5cac88a8 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 15 Nov 2022 12:32:20 +0100 Subject: [PATCH 115/315] Add an anchor to the "forwarding macro fragments" paragraph Since this is a subtle idiosyncracy into which macro users sometimes bump, it can be incredibly help ful to give them a pin-pointed link to the exact paragraph talking about this. Hence the idea of adding some kind of header, and thus an anchor, to it. Since it's just a paragraph, I've gone for a very low header, such as h4. cc @nilstrieb --- src/macros-by-example.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 2c49300cd..861779156 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -76,6 +76,8 @@ delimiters for the matcher will match any pair of delimiters. Thus, for instance, the matcher `(())` will match `{()}` but not `{{}}`. The character `$` cannot be matched or transcribed literally. +#### Forwarding a matched fragment + When forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type. The second macro can't use literal tokens to match the fragments in the matcher, only a From 04f289ad17a9b86f9cde026d046072a5b3827486 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Tue, 15 Nov 2022 21:25:08 +0100 Subject: [PATCH 116/315] Fix header hierarchy Co-authored-by: Eric Huss --- src/macros-by-example.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 861779156..cd9dc3402 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -76,7 +76,7 @@ delimiters for the matcher will match any pair of delimiters. Thus, for instance, the matcher `(())` will match `{()}` but not `{{}}`. The character `$` cannot be matched or transcribed literally. -#### Forwarding a matched fragment +### Forwarding a matched fragment When forwarding a matched fragment to another macro-by-example, matchers in the second macro will see an opaque AST of the fragment type. The second macro From c47e316d9647d54540f046aa458ad0a902c6f171 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 16 Nov 2022 17:44:56 -0800 Subject: [PATCH 117/315] Fix backtick --- src/attributes/codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 57c1d5a18..56840c439 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -360,7 +360,7 @@ instruction set supported by the target architecture. It uses the [_MetaListPath comprised of the architecture and instruction set to specify how to generate the code for architectures where a single program may utilize multiple instruction sets. -The following values are available on targets for the `ARMv4` and ARMv5te` architectures: +The following values are available on targets for the `ARMv4` and `ARMv5te` architectures: * `arm::a32` - Uses ARM code. * `arm::t32` - Uses Thumb code. From 1c70ae7a5edca3cf21b0a0e637160bc5af323c9a Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 118/315] literal-expr.md: say that suffixes are removed before interpreting numbers --- src/expressions/literal-expr.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 4eec37dcb..ac42dabd4 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -96,6 +96,8 @@ The value of the expression is determined from the string representation of the * If the radix is not 10, the first two characters are removed from the string. +* Any suffix is removed from the string. + * Any underscores are removed from the string. * The string is converted to a `u128` value as if by [`u128::from_str_radix`] with the chosen radix. @@ -136,6 +138,8 @@ let x: f64 = 2.; // type f64 The value of the expression is determined from the string representation of the token as follows: +* Any suffix is removed from the string. + * Any underscores are removed from the string. * The string is converted to the expression's type as if by [`f32::from_str`] or [`f64::from_str`]. From c36b3c27ac305483d8ea261cded87980e392e9ba Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 119/315] tokens.md: add one more case to the "Reserved forms" lexer block --- src/tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 8f9bcb1f7..39b95cd40 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -536,7 +536,7 @@ Examples of such tokens: >    | OCT_LITERAL \[`8`-`9`​]\ >    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) `.` \ >          _(not immediately followed by `.`, `_` or an XID_Start character)_\ ->    | ( BIN_LITERAL | OCT_LITERAL ) `e`\ +>    | ( BIN_LITERAL | OCT_LITERAL ) (`e`|`E`)\ >    | `0b` `_`\* _end of input or not BIN_DIGIT_\ >    | `0o` `_`\* _end of input or not OCT_DIGIT_\ >    | `0x` `_`\* _end of input or not HEX_DIGIT_\ @@ -549,7 +549,7 @@ Due to the possible ambiguity these raise, they are rejected by the tokenizer in * An unsuffixed binary, octal, or hexadecimal literal followed, without intervening whitespace, by a period character (with the same restrictions on what follows the period as for floating-point literals). -* An unsuffixed binary or octal literal followed, without intervening whitespace, by the character `e`. +* An unsuffixed binary or octal literal followed, without intervening whitespace, by the character `e` or `E`. * Input which begins with one of the radix prefixes but is not a valid binary, octal, or hexadecimal literal (because it contains no digits). From b333c25a43fcb1964aa1e688e168c0f713865706 Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 120/315] tokens.md: remove the "examples of invalid integer literals" These are covered under "Reserved forms similar to number literals" --- src/tokens.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 39b95cd40..ef1f07c58 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -405,20 +405,6 @@ Examples of integer literals of various forms: Note that `-1i8`, for example, is analyzed as two tokens: `-` followed by `1i8`. -Examples of invalid integer literals: - -```rust,compile_fail -// uses numbers of the wrong base - -0b0102; -0o0581; - -// bin, hex, and octal literals must have at least one digit - -0b_; -0b____; -``` - #### Tuple index > **Lexer**\ From ccde77edcb4d4607f212bfd9fa65a913defb5055 Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 121/315] Numeric literals: say that the parser is now more lenient This reflects the changes made in in rust-lang/rust#102944 . Previously, unknown suffixes were rejected by the parser. Now they are accepted by the parser and rejected at a later stage. Similarly, integer literals too large to fit in u128 are now accepted by the parser. Forms like 5f32 are now INTEGER_LITERAL rather than FLOAT_LITERAL. The notion of a 'pseudoliteral' is no longer required. --- src/expressions/literal-expr.md | 14 ++-- src/tokens.md | 125 +++++++++++++++----------------- 2 files changed, 64 insertions(+), 75 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index ac42dabd4..e5bc2dff4 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -8,11 +8,9 @@ >    | [BYTE_LITERAL]\ >    | [BYTE_STRING_LITERAL]\ >    | [RAW_BYTE_STRING_LITERAL]\ ->    | [INTEGER_LITERAL][^out-of-range]\ +>    | [INTEGER_LITERAL]\ >    | [FLOAT_LITERAL]\ >    | `true` | `false` -> -> [^out-of-range]: A value ≥ 2128 is not allowed. A _literal expression_ is an expression consisting of a single token, rather than a sequence of tokens, that immediately and directly denotes the value it evaluates to, rather than referring to it by name or some other evaluation rule. @@ -54,7 +52,7 @@ A string literal expression consists of a single [BYTE_STRING_LITERAL] or [RAW_B An integer literal expression consists of a single [INTEGER_LITERAL] token. -If the token has a [suffix], the suffix will be the name of one of the [primitive integer types][numeric types]: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `usize`, or `isize`, and the expression has that type. +If the token has a [suffix], the suffix must be the name of one of the [primitive integer types][numeric types]: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `usize`, or `isize`, and the expression has that type. If the token has no suffix, the expression's type is determined by type inference: @@ -101,7 +99,7 @@ The value of the expression is determined from the string representation of the * Any underscores are removed from the string. * 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`, the expression is rejected by the parser. +If the value does not fit in `u128`, it is a compiler error. * The `u128` value is converted to the expression's type via a [numeric cast]. @@ -113,9 +111,11 @@ If the value does not fit in `u128`, the expression is rejected by the parser. ## Floating-point literal expressions -A floating-point literal expression consists of a single [FLOAT_LITERAL] token. +A floating-point literal expression has one of two forms: + * a single [FLOAT_LITERAL] token + * a single [INTEGER_LITERAL] token which has a suffix and no radix indicator -If the token has a [suffix], the suffix will be the name of one of the [primitive floating-point types][floating-point types]: `f32` or `f64`, and the expression has that type. +If the token has a [suffix], the suffix must be the name of one of the [primitive floating-point types][floating-point types]: `f32` or `f64`, and the expression has that type. If the token has no suffix, the expression's type is determined by type inference: diff --git a/src/tokens.md b/src/tokens.md index ef1f07c58..721c4add6 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -72,13 +72,13 @@ Literals are tokens used in [literal expressions]. #### Numbers -| [Number literals](#number-literals)`*` | Example | Exponentiation | Suffixes | -|----------------------------------------|---------|----------------|----------| -| Decimal integer | `98_222` | `N/A` | Integer suffixes | -| Hex integer | `0xff` | `N/A` | Integer suffixes | -| Octal integer | `0o77` | `N/A` | Integer suffixes | -| Binary integer | `0b1111_0000` | `N/A` | Integer suffixes | -| Floating-point | `123.0E+77` | `Optional` | Floating-point suffixes | +| [Number literals](#number-literals)`*` | Example | Exponentiation | +|----------------------------------------|---------|----------------| +| Decimal integer | `98_222` | `N/A` | +| Hex integer | `0xff` | `N/A` | +| Octal integer | `0o77` | `N/A` | +| Binary integer | `0b1111_0000` | `N/A` | +| Floating-point | `123.0E+77` | `Optional` | `*` All number literals allow `_` as a visual separator: `1_234.0E+18f64` @@ -86,17 +86,26 @@ Literals are tokens used in [literal expressions]. A suffix is a sequence of characters following the primary part of a literal (without intervening whitespace), of the same form as a non-raw identifier or keyword. -Any kind of literal (string, integer, etc) with any suffix is valid as a token, -and can be passed to a macro without producing an error. + +> **Lexer**\ +> SUFFIX : IDENTIFIER_OR_KEYWORD\ +> SUFFIX_NO_E : SUFFIX _not beginning with `e` or `E`_ + +Any kind of literal (string, integer, etc) with any suffix is valid as a token. + +A literal token with any suffix can be passed to a macro without producing an error. The macro itself will decide how to interpret such a token and whether to produce an error or not. +In particular, the `literal` fragment specifier for by-example macros matches literal tokens with arbitrary suffixes. ```rust macro_rules! blackhole { ($tt:tt) => () } +macro_rules! blackhole_lit { ($l:literal) => () } blackhole!("string"suffix); // OK +blackhole_lit!(1suffix); // OK ``` -However, suffixes on literal tokens parsed as Rust code are restricted. +However, suffixes on literal tokens which are interpreted as literal expressions or patterns are restricted. Any suffixes are rejected on non-numeric literal tokens, and numeric literal tokens are accepted only with suffixes from the list below. @@ -329,7 +338,7 @@ literal_. The grammar for recognizing the two kinds of literals is mixed. > **Lexer**\ > INTEGER_LITERAL :\ >    ( DEC_LITERAL | BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) -> INTEGER_SUFFIX? +> SUFFIX_NO_E? > > DEC_LITERAL :\ >    DEC_DIGIT (DEC_DIGIT|`_`)\* @@ -350,10 +359,6 @@ literal_. The grammar for recognizing the two kinds of literals is mixed. > DEC_DIGIT : \[`0`-`9`] > > HEX_DIGIT : \[`0`-`9` `a`-`f` `A`-`F`] -> -> INTEGER_SUFFIX :\ ->       `u8` | `u16` | `u32` | `u64` | `u128` | `usize`\ ->    | `i8` | `i16` | `i32` | `i64` | `i128` | `isize` An _integer literal_ has one of four forms: @@ -369,11 +374,11 @@ An _integer literal_ has one of four forms: (`0b`) and continues as any mixture (with at least one digit) of binary digits and underscores. -Like any literal, an integer literal may be followed (immediately, without any spaces) by an _integer suffix_, which must be the name of one of the [primitive integer types][numeric types]: -`u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `u128`, `i128`, `usize`, or `isize`. +Like any literal, an integer literal may be followed (immediately, without any spaces) by a suffix as described above. +The suffix may not begin with `e` or `E`, as that would be interpreted as the exponent of a floating-point literal. See [literal expressions] for the effect of these suffixes. -Examples of integer literals of various forms: +Examples of integer literals which are accepted as literal expressions: ```rust # #![allow(overflowing_literals)] @@ -396,15 +401,29 @@ Examples of integer literals of various forms: 0usize; -// These are too big for their type, but are still valid tokens - +// These are too big for their type, but are accepted as literal expressions. 128_i8; 256_u8; +// This is an integer literal, accepted as a floating-point literal expression. +5f32; ``` Note that `-1i8`, for example, is analyzed as two tokens: `-` followed by `1i8`. + +Examples of integer literals which are not accepted as literal expressions: + +```rust +# #[cfg(FALSE)] { +0invalidSuffix; +123AFB43; +0b010a; +0xAB_CD_EF_GH; +0b1111_f32; +# } +``` + #### Tuple index > **Lexer**\ @@ -428,9 +447,8 @@ let cat = example.01; // ERROR no field named `01` let horse = example.0b10; // ERROR no field named `0b10` ``` -> **Note**: The tuple index may include an `INTEGER_SUFFIX`, but this is not -> intended to be valid, and may be removed in a future version. See -> for more information. +> **Note**: Tuple indices may include certain suffixes, but this is not intended to be valid, and may be removed in a future version. +> See for more information. #### Floating-point literals @@ -438,38 +456,32 @@ let horse = example.0b10; // ERROR no field named `0b10` > FLOAT_LITERAL :\ >       DEC_LITERAL `.` > _(not immediately followed by `.`, `_` or an XID_Start character)_\ ->    | DEC_LITERAL FLOAT_EXPONENT\ ->    | DEC_LITERAL `.` DEC_LITERAL FLOAT_EXPONENT?\ ->    | DEC_LITERAL (`.` DEC_LITERAL)? -> FLOAT_EXPONENT? FLOAT_SUFFIX +>    | DEC_LITERAL `.` DEC_LITERAL SUFFIX_NO_E?\ +>    | DEC_LITERAL (`.` DEC_LITERAL)? FLOAT_EXPONENT SUFFIX?\ > > FLOAT_EXPONENT :\ >    (`e`|`E`) (`+`|`-`)? > (DEC_DIGIT|`_`)\* DEC_DIGIT (DEC_DIGIT|`_`)\* > -> FLOAT_SUFFIX :\ ->    `f32` | `f64` -A _floating-point literal_ has one of three forms: +A _floating-point literal_ has one of two forms: * A _decimal literal_ followed by a period character `U+002E` (`.`). This is optionally followed by another decimal literal, with an optional _exponent_. * A single _decimal literal_ followed by an _exponent_. -* A single _decimal literal_ (in which case a suffix is required). Like integer literals, a floating-point literal may be followed by a suffix, so long as the pre-suffix part does not end with `U+002E` (`.`). -There are two valid _floating-point suffixes_: `f32` and `f64` (the names of the 32-bit and 64-bit [primitive floating-point types][floating-point types]). +The suffix may not begin with `e` or `E` if the literal does not include an exponent. See [literal expressions] for the effect of these suffixes. -Examples of floating-point literals of various forms: +Examples of floating-point literals which are accepted as literal expressions: ```rust 123.0f64; 0.1f64; 0.1f32; 12E+99_f64; -5f32; let x: f64 = 2.; ``` @@ -479,39 +491,16 @@ to call a method named `f64` on `2`. Note that `-1.0`, for example, is analyzed as two tokens: `-` followed by `1.0`. -#### Number pseudoliterals - -> **Lexer**\ -> NUMBER_PSEUDOLITERAL :\ ->       DEC_LITERAL ( . DEC_LITERAL )? FLOAT_EXPONENT\ ->          ( NUMBER_PSEUDOLITERAL_SUFFIX | INTEGER_SUFFIX )\ ->    | DEC_LITERAL . DEC_LITERAL\ ->          ( NUMBER_PSEUDOLITERAL_SUFFIX_NO_E | INTEGER SUFFIX )\ ->    | DEC_LITERAL NUMBER_PSEUDOLITERAL_SUFFIX_NO_E\ ->    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL )\ ->          ( NUMBER_PSEUDOLITERAL_SUFFIX_NO_E | FLOAT_SUFFIX ) -> -> NUMBER_PSEUDOLITERAL_SUFFIX :\ ->    IDENTIFIER_OR_KEYWORD _not matching INTEGER_SUFFIX or FLOAT_SUFFIX_ -> -> NUMBER_PSEUDOLITERAL_SUFFIX_NO_E :\ ->    NUMBER_PSEUDOLITERAL_SUFFIX _not beginning with `e` or `E`_ - -Tokenization of numeric literals allows arbitrary suffixes as described in the grammar above. -These values generate valid tokens, but are not valid [literal expressions], so are usually an error except as macro arguments. +Examples of floating-point literals which are not accepted as literal expressions: -Examples of such tokens: -```rust,compile_fail -0invalidSuffix; -123AFB43; -0b010a; -0xAB_CD_EF_GH; +```rust +# #[cfg(FALSE)] { 2.0f80; 2e5f80; 2e5e6; 2.0e5e6; 1.3e10u64; -0b1111_f32; +# } ``` #### Reserved forms similar to number literals @@ -547,13 +536,13 @@ Examples of reserved forms: 0b0102; // this is not `0b010` followed by `2` 0o1279; // this is not `0o127` followed by `9` 0x80.0; // this is not `0x80` followed by `.` and `0` -0b101e; // this is not a pseudoliteral, or `0b101` followed by `e` -0b; // this is not a pseudoliteral, or `0` followed by `b` -0b_; // this is not a pseudoliteral, or `0` followed by `b_` -2e; // this is not a pseudoliteral, or `2` followed by `e` -2.0e; // this is not a pseudoliteral, or `2.0` followed by `e` -2em; // this is not a pseudoliteral, or `2` followed by `em` -2.0em; // this is not a pseudoliteral, or `2.0` followed by `em` +0b101e; // this is not a suffixed literal, or `0b101` followed by `e` +0b; // this is not an integer literal, or `0` followed by `b` +0b_; // this is not an integer literal, or `0` followed by `b_` +2e; // this is not a floating-point literal, or `2` followed by `e` +2.0e; // this is not a floating-point literal, or `2.0` followed by `e` +2em; // this is not a suffixed literal, or `2` followed by `em` +2.0em; // this is not a suffixed literal, or `2.0` followed by `em` ``` ## Lifetimes and loop labels From 018b14be9ded4e5890813dcf1209961298b0873e Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 122/315] tokens.md: add optional SUFFIX to the Lexer blocks for non-numeric literals --- src/tokens.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 721c4add6..0067b647d 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -119,7 +119,7 @@ and numeric literal tokens are accepted only with suffixes from the list below. > **Lexer**\ > CHAR_LITERAL :\ ->    `'` ( ~\[`'` `\` \\n \\r \\t] | QUOTE_ESCAPE | ASCII_ESCAPE | UNICODE_ESCAPE ) `'` +>    `'` ( ~\[`'` `\` \\n \\r \\t] | QUOTE_ESCAPE | ASCII_ESCAPE | UNICODE_ESCAPE ) `'` SUFFIX? > > QUOTE_ESCAPE :\ >    `\'` | `\"` @@ -145,7 +145,7 @@ which must be _escaped_ by a preceding `U+005C` character (`\`). >       | ASCII_ESCAPE\ >       | UNICODE_ESCAPE\ >       | STRING_CONTINUE\ ->    )\* `"` +>    )\* `"` SUFFIX? > > STRING_CONTINUE :\ >    `\` _followed by_ \\n @@ -205,7 +205,7 @@ following forms: > **Lexer**\ > RAW_STRING_LITERAL :\ ->    `r` RAW_STRING_CONTENT +>    `r` RAW_STRING_CONTENT SUFFIX? > > RAW_STRING_CONTENT :\ >       `"` ( ~ _IsolatedCR_ )* (non-greedy) `"`\ @@ -242,7 +242,7 @@ r##"foo #"# bar"##; // foo #"# bar > **Lexer**\ > BYTE_LITERAL :\ ->    `b'` ( ASCII_FOR_CHAR | BYTE_ESCAPE ) `'` +>    `b'` ( ASCII_FOR_CHAR | BYTE_ESCAPE ) `'` SUFFIX? > > ASCII_FOR_CHAR :\ >    _any ASCII (i.e. 0x00 to 0x7F), except_ `'`, `\`, \\n, \\r or \\t @@ -262,7 +262,7 @@ _number literal_. > **Lexer**\ > BYTE_STRING_LITERAL :\ ->    `b"` ( ASCII_FOR_STRING | BYTE_ESCAPE | STRING_CONTINUE )\* `"` +>    `b"` ( ASCII_FOR_STRING | BYTE_ESCAPE | STRING_CONTINUE )\* `"` SUFFIX? > > ASCII_FOR_STRING :\ >    _any ASCII (i.e 0x00 to 0x7F), except_ `"`, `\` _and IsolatedCR_ @@ -293,7 +293,7 @@ following forms: > **Lexer**\ > RAW_BYTE_STRING_LITERAL :\ ->    `br` RAW_BYTE_STRING_CONTENT +>    `br` RAW_BYTE_STRING_CONTENT SUFFIX? > > RAW_BYTE_STRING_CONTENT :\ >       `"` ASCII* (non-greedy) `"`\ From 3d45616386fb0d06d2b81660d339803849ecc62e Mon Sep 17 00:00:00 2001 From: Lokathor Date: Wed, 23 Nov 2022 09:43:02 -0700 Subject: [PATCH 123/315] Clearly specify the instruction_set inlining restrictions --- src/attributes/codegen.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 69ad341d1..27230e426 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -355,15 +355,16 @@ trait object whose methods are attributed. ## The `instruction_set` attribute -The *`instruction_set` attribute* may be applied to a function to enable code generation for a specific -instruction set supported by the target architecture. It uses the [_MetaListPath_] syntax and a path -comprised of the architecture and instruction set to specify how to generate the code for -architectures where a single program may utilize multiple instruction sets. +On some CPU architectures it is possible to mix more than one instruction set into a single program. +The `instruction_set` attribute lets you control which instruction set a particular function will be generated for. +It uses the [_MetaListPath_] syntax, and a path comprised of the architecture family name and instruction set name. -The following values are available on targets for the `ARMv4` and `ARMv5te` architectures: +[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax + +For the `ARMv4T` and `ARMv5te` architectures, the following are supported: -* `arm::a32` - Uses ARM code. -* `arm::t32` - Uses Thumb code. +* `arm::a32` - Generate the function as A32 "ARM" code. +* `arm::t32` - Generate the function as T32 "Thumb" code. ```rust,ignore @@ -374,4 +375,8 @@ fn foo_arm_code() {} fn bar_thumb_code() {} ``` -[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax +The rules for inlining functions using the `instruction_set` attribute are slightly more strict than normal: + +* If a function has an `instruction_set` attribute, then the function is assumed to require the given instruction set and it won't inline into a function of another instruction set. +* If a function does not have an `instruction_set` attribute but *does* contain inline assembly, then the inline assembly is assumed to require the default instruction set of the build target and so inlining between instruction sets won't happen. +* Otherwise, a function is assumed to not rely on a particular instruction set and the function *may* be inlined into any calling function (all other restrictions on inlining still apply). From 7ab06192d619402311790ebe09d209450bf3da59 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 27 Nov 2022 18:46:08 -0500 Subject: [PATCH 124/315] Document the efiapi ABI --- src/items/external-blocks.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index c91e1d10c..5454f8e77 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -90,6 +90,7 @@ There are also some platform-specific ABI strings: `__fastcall` and GCC and clang's `__attribute__((fastcall))` * `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's `__vectorcall` and clang's `__attribute__((vectorcall))` +* `extern "efiapi"` -- The ABI used for [UEFI] functions. ## Variadic functions @@ -272,6 +273,7 @@ Attributes on extern function parameters follow the same rules and restrictions as [regular function parameters]. [IDENTIFIER]: ../identifiers.md +[UEFI]: https://uefi.org/specifications [WebAssembly module]: https://webassembly.github.io/spec/core/syntax/modules.html [functions]: functions.md [statics]: static-items.md From 8ca80a14d359cc21b0e9c10dde7d45fe1fcb9af8 Mon Sep 17 00:00:00 2001 From: Eugene Date: Wed, 30 Nov 2022 21:27:06 +0800 Subject: [PATCH 125/315] repalce `crateid` term with `crate_name` The `crateid` term or attribute is replaced with `crate_name` in [chapter crates and source files](https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute). It was original proposed in [RFC0109] (https://rust-lang.github.io/rfcs/0109-remove-crate-id.html) and merged in [PR109](https://github.com/rust-lang/rfcs/pull/109) --- src/items/extern-crates.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/items/extern-crates.md b/src/items/extern-crates.md index f4dc735b0..d6b3a9aae 100644 --- a/src/items/extern-crates.md +++ b/src/items/extern-crates.md @@ -20,9 +20,9 @@ clause can be used to bind the imported crate to a different name. 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 `crateid` provided against -the `crateid` attributes that were declared on the external crate when it was -compiled. If no `crateid` is provided, a default `name` attribute is assumed, +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 `self` crate may be imported which creates a binding to the current crate. @@ -78,6 +78,7 @@ crate to access only its macros. [`macro_use` attribute]: ../macros-by-example.md#the-macro_use-attribute [extern prelude]: ../names/preludes.md#extern-prelude [`macro_use` prelude]: ../names/preludes.md#macro_use-prelude +[`crate_name` attributes]: ../crates-and-source-files.md#the-crate_name-attribute From 97c9ad16e565f2d47593a1ac56c806b2892e4223 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 21 Feb 2024 13:20:15 -0800 Subject: [PATCH 289/315] Semantic line wrapping. --- src/expressions/operator-expr.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index d5af503c7..d3fa33b81 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -483,18 +483,15 @@ assert_eq!(values[1], 3); `*const T` / `*mut T` can be cast to `*const U` / `*mut U` with the following behavior: - If `T` and `U` are both sized, the pointer is returned unchanged. -- 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)`. -- 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. +- 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)`. +- 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. ## Assignment expressions From 08e5cd4e3c8f6d56d793ac89eb8b9a0841d22f7a Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Tue, 27 Feb 2024 21:52:50 +0000 Subject: [PATCH 290/315] Say that struct patterns can match union values --- src/patterns.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index c4811a693..c92e2dcda 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -597,8 +597,8 @@ Reference patterns are always irrefutable. [_OuterAttribute_]: attributes.md [TUPLE_INDEX]: tokens.md#tuple-index -Struct patterns match struct and enum values that match all criteria defined by its subpatterns. -They are also used to [destructure](#destructuring) a struct or enum 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. On a struct pattern, the fields are referenced by name, index (in the case of tuple structs) or ignored by use of `..`: @@ -642,7 +642,7 @@ match m { } ``` -If `..` is not used, it is required to match all fields: +If `..` is not used, a struct pattern used to match a struct is required to specify all fields: ```rust # struct Struct { @@ -661,6 +661,8 @@ match struct_value { } ``` +A struct pattern used to match a union must specify exactly one field (see [Pattern matching on unions]). + The `ref` and/or `mut` _IDENTIFIER_ syntax matches any value and binds it to a variable with the same name as the given field. ```rust @@ -867,6 +869,7 @@ For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound i [literal expression]: expressions/literal-expr.md [negating]: expressions/operator-expr.md#negation-operators [path]: expressions/path-expr.md +[pattern matching on unions]: items/unions.md#pattern-matching-on-unions [range expressions]: expressions/range-expr.md [structs]: items/structs.md [tuples]: types/tuple.md From 7bd81a6a03a659ee46eb79533b6d37549dc9ecdd Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Mon, 4 Mar 2024 21:32:01 +0000 Subject: [PATCH 291/315] tokens.md: say that lifetime-like tokens can't be immediately followed by ' Forms like 'ab'c are rejected, so we need some way to explain why they don't tokenise as two consecutive LIFETIME_OR_LABEL tokens. Address this by adding "not immediately followed by `'`" to each of the lexer rules for the lifetime-like tokens. This also means there can be no ambiguity between CHAR_LITERAL and these tokens (at present we don't say how such ambiguities are resolved). --- src/tokens.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tokens.md b/src/tokens.md index cf76e729f..eded55ec3 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -630,11 +630,14 @@ Examples of reserved forms: > **Lexer**\ > LIFETIME_TOKEN :\ ->       `'` [IDENTIFIER_OR_KEYWORD][identifier]\ +>       `'` [IDENTIFIER_OR_KEYWORD][identifier] +> _(not immediately followed by `'`)_\ >    | `'_` +> _(not immediately followed by `'`)_ > > LIFETIME_OR_LABEL :\ >       `'` [NON_KEYWORD_IDENTIFIER][identifier] +> _(not immediately followed by `'`)_ Lifetime parameters and [loop labels] use LIFETIME_OR_LABEL tokens. Any LIFETIME_TOKEN will be accepted by the lexer, and for example, can be used in From 684b549fc74563fd7df3350f050010f4fce1a9ca Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 7 Mar 2024 19:36:58 +0000 Subject: [PATCH 292/315] add support for ATB in reference --- src/paths.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/paths.md b/src/paths.md index 828758cb9..39b94450c 100644 --- a/src/paths.md +++ b/src/paths.md @@ -53,7 +53,7 @@ mod m { >    | `<` ( _GenericArg_ `,` )\* _GenericArg_ `,`? `>` > > _GenericArg_ :\ ->    [_Lifetime_] | [_Type_] | _GenericArgsConst_ | _GenericArgsBinding_ +>    [_Lifetime_] | [_Type_] | _GenericArgsConst_ | _GenericArgsBinding_ | _GenericArgsBounds_ > > _GenericArgsConst_ :\ >       [_BlockExpression_]\ @@ -62,7 +62,10 @@ mod m { >    | [_SimplePathSegment_] > > _GenericArgsBinding_ :\ ->    [IDENTIFIER] `=` [_Type_] +>    [IDENTIFIER] _GenericArgs_? `=` [_TypeParamBounds_] +> +> _GenericArgsBounds_ :\ +>    [IDENTIFIER] _GenericArgs_? `:` [_TypeParamBounds_] Paths in expressions allow for paths with generic arguments to be specified. They are used in various places in [expressions] and [patterns]. @@ -396,6 +399,7 @@ mod without { // crate::without [_SimplePathSegment_]: #simple-paths [_Type_]: types.md#type-expressions [_TypeNoBounds_]: types.md#type-expressions +[_TypeParamBounds_]: trait-bounds.md [literal]: expressions/literal-expr.md [item]: items.md [variable]: variables.md From 9ad55f00b1a37ef21e53af5a9e22b4f8e443d878 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Mar 2024 11:42:32 -0500 Subject: [PATCH 293/315] Fix copy/paste error --- src/paths.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paths.md b/src/paths.md index 39b94450c..7a851f30a 100644 --- a/src/paths.md +++ b/src/paths.md @@ -62,7 +62,7 @@ mod m { >    | [_SimplePathSegment_] > > _GenericArgsBinding_ :\ ->    [IDENTIFIER] _GenericArgs_? `=` [_TypeParamBounds_] +>    [IDENTIFIER] _GenericArgs_? `=` [_TYPE_] > > _GenericArgsBounds_ :\ >    [IDENTIFIER] _GenericArgs_? `:` [_TypeParamBounds_] From 6c77f499eaf64bd89c29a8932e63a9343ee73663 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Mar 2024 11:42:50 -0500 Subject: [PATCH 294/315] Update src/paths.md --- src/paths.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paths.md b/src/paths.md index 7a851f30a..dbc73c4fa 100644 --- a/src/paths.md +++ b/src/paths.md @@ -62,7 +62,7 @@ mod m { >    | [_SimplePathSegment_] > > _GenericArgsBinding_ :\ ->    [IDENTIFIER] _GenericArgs_? `=` [_TYPE_] +>    [IDENTIFIER] _GenericArgs_? `=` [_Type_] > > _GenericArgsBounds_ :\ >    [IDENTIFIER] _GenericArgs_? `:` [_TypeParamBounds_] From 81fe01a11108a5e50bd51b7d22d638435ad687fd Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Thu, 18 Jan 2024 08:08:27 +0100 Subject: [PATCH 295/315] Add the `#[diagnostic]` attribute namespace and the `#[diagnostic::on_unimplemented]` feature to the reference --- src/attributes.md | 5 +++- src/attributes/diagnostics.md | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/attributes.md b/src/attributes.md index a1ad5c60c..3b26a319a 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -196,7 +196,7 @@ struct S { pub fn f() {} ``` -> Note: `rustc` currently recognizes the tools "clippy" and "rustfmt". +> Note: `rustc` currently recognizes the tools "clippy", "rustfmt" and "diagnostics". ## Built-in attributes index @@ -224,6 +224,8 @@ The following is an index of all built-in attributes. - [`allow`], [`warn`], [`deny`], [`forbid`] — Alters the default lint level. - [`deprecated`] — Generates deprecation notices. - [`must_use`] — Generates a lint for unused values. + - [`diagnostic::on_unimplemented`] - Hints the compiler to emit a certain error + message if a trait is not implemented. - ABI, linking, symbols, and FFI - [`link`] — Specifies a native library to link with an `extern` block. - [`link_name`] — Specifies the name of the symbol for functions or statics @@ -352,3 +354,4 @@ The following is an index of all built-in attributes. [closure]: expressions/closure-expr.md [function pointer]: types/function-pointer.md [variadic functions]: items/external-blocks.html#variadic-functions +[`diagnostic::on_unimplemented`]: attributes/diagnostics.md#the-diagnosticon_unimplemented-attribute diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 506e2848b..142b78f0f 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -301,6 +301,60 @@ When used on a function in a trait implementation, the attribute does nothing. > let _ = five(); > ``` +## The `diagnostic` tool attribute namespace + +The `#[diagnostic]` attribute namespace is meant to provide a home for attribute that allow users to influence error messages emitted by the compiler. The compiler is not guaranteed to use any of this hints, however it should accept any (non-)existing attribute in this namespace and potentially emit lint-warnings for unused attributes and options. This is meant to allow discarding certain attributes/options in the future to allow fundamental changes to the compiler without the need to keep then non-meaningful options working. + +### The `diagnostic::on_unimplemented` attribute + +The `#[diagnostic::on_unimplemented]` attribute is allowed to appear on trait definitions. This allows crate authors to hint the compiler to emit a specific worded error message if a certain trait is not implemented. The hinted message is supposed to replace the otherwise emitted error message. For the `#[diagnostic::on_unimplemented]` attribute the following options are implemented: + +* `message` which provides the text for the top level error message +* `label` which provides the text for the label shown inline in the broken code in the error message +* `note` which provides additional notes. + +The `note` option can appear several times, which results in several note messages being emitted. If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. Any other occurrence generates an lint warning. For any other non-existing option a lint-warning is generated. + +All three options accept a text as argument. This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax. For any non-existing argument a lint warning is generated. + +This allows to have a trait definition like: + +```rust +#[diagnostic::on_unimplemented( + message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`", + label = "My Label", + note = "Note 1", + note = "Note 2" +)] +trait ImportantTrait {} +``` + +which then generates the for the following code + +```rust +fn use_my_trait(_: impl ImportantTrait) {} + +fn main() { + use_my_trait(String::new()); +} +``` + +this error message: + +``` +error[E0277]: My Message for `ImportantTrait` implemented for `String` + --> src/main.rs:14:18 + | +14 | use_my_trait(String::new()); + | ------------ ^^^^^^^^^^^^^ My Label + | | + | required by a bound introduced by this call + | + = help: the trait `ImportantTrait` is not implemented for `String` + = note: Note 1 + = note: Note 2 +``` + [Clippy]: https://github.com/rust-lang/rust-clippy [_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax [_MetaListPaths_]: ../attributes.md#meta-item-attribute-syntax From 5baf87cdd925f4ca569570658d7fe55e783942ce Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 19 Jan 2024 08:11:40 +0000 Subject: [PATCH 296/315] Apply suggestions from code review Co-authored-by: Eric Huss --- src/attributes.md | 4 ++-- src/attributes/diagnostics.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index 3b26a319a..1218fcbd0 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -196,7 +196,7 @@ struct S { pub fn f() {} ``` -> Note: `rustc` currently recognizes the tools "clippy", "rustfmt" and "diagnostics". +> Note: `rustc` currently recognizes the tools "clippy", "rustfmt" and "diagnostic". ## Built-in attributes index @@ -224,7 +224,7 @@ The following is an index of all built-in attributes. - [`allow`], [`warn`], [`deny`], [`forbid`] — Alters the default lint level. - [`deprecated`] — Generates deprecation notices. - [`must_use`] — Generates a lint for unused values. - - [`diagnostic::on_unimplemented`] - Hints the compiler to emit a certain error + - [`diagnostic::on_unimplemented`] — Hints the compiler to emit a certain error message if a trait is not implemented. - ABI, linking, symbols, and FFI - [`link`] — Specifies a native library to link with an `extern` block. diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 142b78f0f..a70436876 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -315,7 +315,7 @@ The `#[diagnostic::on_unimplemented]` attribute is allowed to appear on trait de The `note` option can appear several times, which results in several note messages being emitted. If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. Any other occurrence generates an lint warning. For any other non-existing option a lint-warning is generated. -All three options accept a text as argument. This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax. For any non-existing argument a lint warning is generated. +All three options accept a text as argument. This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax. Any other format parameter will generate a warning, but will otherwise be included in the string as-is. This allows to have a trait definition like: From 99b19d92c138d633c6ae9c41d863112def6c377a Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Fri, 19 Jan 2024 09:43:09 +0100 Subject: [PATCH 297/315] Apply more review suggestions manually Co-authored-by: Eric Huss --- src/attributes/diagnostics.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index a70436876..c0c5c82f8 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -303,19 +303,29 @@ When used on a function in a trait implementation, the attribute does nothing. ## The `diagnostic` tool attribute namespace -The `#[diagnostic]` attribute namespace is meant to provide a home for attribute that allow users to influence error messages emitted by the compiler. The compiler is not guaranteed to use any of this hints, however it should accept any (non-)existing attribute in this namespace and potentially emit lint-warnings for unused attributes and options. This is meant to allow discarding certain attributes/options in the future to allow fundamental changes to the compiler without the need to keep then non-meaningful options working. +The `#[diagnostic]` attribute namespace is meant to provide a home for attributes to influence compile-time error messages. +The hints provides by these attributes are not guaranteed to be used. +Unknown attributes in this namespace are accepted, though tey may emit warings for unused attributes. +Additionally, invalid input to known attributes will typically be a warning (see the attribute definitions for details). +This is meant to allow adding or discarding attributes and changing inputs in the future to allow changes without the need to keep the non-meaningful attributes or options working. ### The `diagnostic::on_unimplemented` attribute -The `#[diagnostic::on_unimplemented]` attribute is allowed to appear on trait definitions. This allows crate authors to hint the compiler to emit a specific worded error message if a certain trait is not implemented. The hinted message is supposed to replace the otherwise emitted error message. For the `#[diagnostic::on_unimplemented]` attribute the following options are implemented: +The `#[diagnostic::on_unimplemented]` attribute is designed to appear on trait definitions. +This attribute hints to hint the compiler to supplement a specific worded error message that would normally be generated in scenarios where the trait is required but not implemented on a type +The attribute uses the [_MetaListNameValueStr_] syntax to specify its inputs, though any malformed input to the attribute is not considered as an error to provide both forwards and backwards compatibility. The following keys have the given meaning: * `message` which provides the text for the top level error message * `label` which provides the text for the label shown inline in the broken code in the error message * `note` which provides additional notes. -The `note` option can appear several times, which results in several note messages being emitted. If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. Any other occurrence generates an lint warning. For any other non-existing option a lint-warning is generated. +The `note` option can appear several times, which results in several note messages being emitted. +If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. Any other occurrence generates an lint warning. +For any other non-existing option a lint-warning is generated. -All three options accept a text as argument. This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax. Any other format parameter will generate a warning, but will otherwise be included in the string as-is. +All three options accept a text as argument. +This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax, where `{Self}` is resolved to the name of the type implementing the trait and `{NameOfGenericArgument}` is resolved to the relevant type name that replaces the `{NameOfGenericArgument}` argument if the error message is emitted. +Any other format parameter will generate a warning, but will otherwise be included in the string as-is. This allows to have a trait definition like: @@ -327,11 +337,7 @@ This allows to have a trait definition like: note = "Note 2" )] trait ImportantTrait {} -``` - -which then generates the for the following code -```rust fn use_my_trait(_: impl ImportantTrait) {} fn main() { @@ -339,7 +345,7 @@ fn main() { } ``` -this error message: +which might generate this error message: ``` error[E0277]: My Message for `ImportantTrait` implemented for `String` From 5e29b0135ed0353d7d9f4c2db9feba82f580cf50 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 12 Mar 2024 09:21:17 -0700 Subject: [PATCH 298/315] Various fixes and editing. --- src/attributes/diagnostics.md | 42 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index c0c5c82f8..45ed64534 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -303,33 +303,39 @@ When used on a function in a trait implementation, the attribute does nothing. ## The `diagnostic` tool attribute namespace -The `#[diagnostic]` attribute namespace is meant to provide a home for attributes to influence compile-time error messages. -The hints provides by these attributes are not guaranteed to be used. -Unknown attributes in this namespace are accepted, though tey may emit warings for unused attributes. -Additionally, invalid input to known attributes will typically be a warning (see the attribute definitions for details). +The `#[diagnostic]` attribute namespace is a home for attributes to influence compile-time error messages. +The hints provided by these attributes are not guaranteed to be used. +Unknown attributes in this namespace are accepted, though they may emit warnings for unused attributes. +Additionally, invalid inputs to known attributes will typically be a warning (see the attribute definitions for details). This is meant to allow adding or discarding attributes and changing inputs in the future to allow changes without the need to keep the non-meaningful attributes or options working. ### The `diagnostic::on_unimplemented` attribute -The `#[diagnostic::on_unimplemented]` attribute is designed to appear on trait definitions. -This attribute hints to hint the compiler to supplement a specific worded error message that would normally be generated in scenarios where the trait is required but not implemented on a type -The attribute uses the [_MetaListNameValueStr_] syntax to specify its inputs, though any malformed input to the attribute is not considered as an error to provide both forwards and backwards compatibility. The following keys have the given meaning: +The `#[diagnostic::on_unimplemented]` attribute is a hint to the compiler to supplement the error message that would normally be generated in scenarios where a trait is required but not implemented on a type. +The attribute should be placed on a [trait declaration], though it is not an error to be located in other positions. +The attribute uses the [_MetaListNameValueStr_] syntax to specify its inputs, though any malformed input to the attribute is not considered as an error to provide both forwards and backwards compatibility. +The following keys have the given meaning: -* `message` which provides the text for the top level error message -* `label` which provides the text for the label shown inline in the broken code in the error message -* `note` which provides additional notes. +* `message` — The text for the top level error message. +* `label` — The text for the label shown inline in the broken code in the error message. +* `note` — Provides additional notes. -The `note` option can appear several times, which results in several note messages being emitted. -If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. Any other occurrence generates an lint warning. +The `note` option can appear several times, which results in several note messages being emitted. +If any of the other options appears several times the first occurrence of the relevant option specifies the actually used value. +Any other occurrence generates an lint warning. For any other non-existing option a lint-warning is generated. -All three options accept a text as argument. -This text is allowed to contain format parameters referring to generic argument or `Self` by name via the `{Self}` or `{NameOfGenericArgument}` syntax, where `{Self}` is resolved to the name of the type implementing the trait and `{NameOfGenericArgument}` is resolved to the relevant type name that replaces the `{NameOfGenericArgument}` argument if the error message is emitted. +All three options accept a string as an argument. +The text in the string may contain the following format parameters which provide substitutions in the generated message: + +* `{Self}` — The name of the type implementing the trait. +* `{` *GenericParameterName* `}` — The name of the generic argument's type for the given generic parameter. + Any other format parameter will generate a warning, but will otherwise be included in the string as-is. -This allows to have a trait definition like: +In this example: -```rust +```rust,compile_fail,E0277 #[diagnostic::on_unimplemented( message = "My Message for `ImportantTrait<{A}>` implemented for `{Self}`", label = "My Label", @@ -345,9 +351,9 @@ fn main() { } ``` -which might generate this error message: +the compiler may generate an error message which looks like this: -``` +```text error[E0277]: My Message for `ImportantTrait` implemented for `String` --> src/main.rs:14:18 | From 659915cc1169e13329186748e26ec1e5c6a92d4d Mon Sep 17 00:00:00 2001 From: Matthew Woodcraft Date: Tue, 19 Mar 2024 19:36:32 +0000 Subject: [PATCH 299/315] Literal expressions: fix mistake in the definition of unicode escapes --- src/expressions/literal-expr.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 5a74425b2..2d8d5f9b7 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -76,7 +76,7 @@ The escaped value is the character whose [Unicode scalar value] is the result of The escape sequence consists of `\u{`, followed by a sequence of characters each of which is a hexadecimal digit or `_`, followed by `}`. -The escaped value is the character whose [Unicode scalar value] is the result of interpreting the hexadecimal digits contained in the escape sequence as a hexadecimal integer, as if by [`u8::from_str_radix`] with radix 16. +The escaped value is the character whose [Unicode scalar value] is the result of interpreting the hexadecimal digits contained in the escape sequence as a hexadecimal integer, as if by [`u32::from_str_radix`] with radix 16. > **Note**: the permitted forms of a [CHAR_LITERAL] or [STRING_LITERAL] token ensure that there is such a character. @@ -438,6 +438,7 @@ The expression's type is the primitive [boolean type], and its value is: [`f64::INFINITY`]: ../../core/primitive.f64.md#associatedconstant.INFINITY [`f64::NAN`]: ../../core/primitive.f64.md#associatedconstant.NAN [`u8::from_str_radix`]: ../../core/primitive.u8.md#method.from_str_radix +[`u32::from_str_radix`]: ../../core/primitive.u32.md#method.from_str_radix [`u128::from_str_radix`]: ../../core/primitive.u128.md#method.from_str_radix [CHAR_LITERAL]: ../tokens.md#character-literals [STRING_LITERAL]: ../tokens.md#string-literals From 0b153cb607e981bfa64ec6fcbfc92cefc891d4ed Mon Sep 17 00:00:00 2001 From: Shotaro Aoyama Date: Sun, 24 Mar 2024 14:02:49 +0900 Subject: [PATCH 300/315] fix typo of shebang --- src/input-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input-format.md b/src/input-format.md index 946e6782c..8d921bf8c 100644 --- a/src/input-format.md +++ b/src/input-format.md @@ -21,7 +21,7 @@ Other occurrences of the character `U+000D` (CR) are left in place (they are tre ## Shebang removal -If the remaining sequence begins with the characters `!#`, the characters up to and including the first `U+000A` (LF) are removed from the sequence. +If the remaining sequence begins with the characters `#!`, the characters up to and including the first `U+000A` (LF) are removed from the sequence. For example, the first line of the following file would be ignored: From a7a86824fa90172340e20053be5e6f217cc466fe Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 30 Mar 2024 23:14:03 +0300 Subject: [PATCH 301/315] Fix clippy warning in procedural macro example I copy+pasted this example into my code and the `clippy::to_string_in_format_args` lint fired. --- src/procedural-macros.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index 7d69ab72d..32b847c0f 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -234,8 +234,8 @@ shown in the comments after the function prefixed with "out:". #[proc_macro_attribute] pub fn show_streams(attr: TokenStream, item: TokenStream) -> TokenStream { - println!("attr: \"{}\"", attr.to_string()); - println!("item: \"{}\"", item.to_string()); + println!("attr: \"{attr}\""); + println!("item: \"{item}\""); item } ``` From 52874b8312ccbc28710a2532f82032876a08911b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 3 Apr 2024 14:29:34 -0700 Subject: [PATCH 302/315] Update on_unimplemented for format string changes. Updated in https://github.com/rust-lang/rust/pull/122402 --- src/attributes/diagnostics.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 45ed64534..c636a96cc 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -325,14 +325,17 @@ If any of the other options appears several times the first occurrence of the re Any other occurrence generates an lint warning. For any other non-existing option a lint-warning is generated. -All three options accept a string as an argument. -The text in the string may contain the following format parameters which provide substitutions in the generated message: +All three options accept a string as an argument, interpreted using the same formatting as a [`std::fmt`] string. +Format parameters with the given named parameter will be replaced with the following text: * `{Self}` — The name of the type implementing the trait. * `{` *GenericParameterName* `}` — The name of the generic argument's type for the given generic parameter. Any other format parameter will generate a warning, but will otherwise be included in the string as-is. +Invalid format strings may generate a warning, but are otherwise allowed, but may not display as intended. +Format specifiers may generate a warning, but are otherwise ignored. + In this example: ```rust,compile_fail,E0277 @@ -367,6 +370,7 @@ error[E0277]: My Message for `ImportantTrait` implemented for `String` = note: Note 2 ``` +[`std::fmt`]: ../../std/fmt/index.html [Clippy]: https://github.com/rust-lang/rust-clippy [_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax [_MetaListPaths_]: ../attributes.md#meta-item-attribute-syntax From b4311de6918170a2606bdd6e6cb4bf086badb0ef Mon Sep 17 00:00:00 2001 From: Jamie Lokier Date: Sun, 14 Apr 2024 14:07:07 +0100 Subject: [PATCH 303/315] Fix link to RISC-V Zkt spec; it was pointing to Zkr --- src/attributes/codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 348f92f37..76ec6fd2a 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -262,7 +262,7 @@ Feature | Implicitly Enables | Description [rv-zks]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zks.adoc [rv-zksed]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksed.adoc [rv-zksh]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zksh.adoc -[rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkr.adoc +[rv-zkt]: https://github.com/riscv/riscv-crypto/blob/e2dd7d98b7f34d477e38cb5fd7a3af4379525189/doc/scalar/riscv-crypto-scalar-zkt.adoc #### `wasm32` or `wasm64` From ec0065fd92cae8c0de7a604b6880b7738fbed196 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sun, 14 Apr 2024 08:45:19 -0700 Subject: [PATCH 304/315] Document how `non_exhaustive` interacts with tuple and unit-like structs. --- src/attributes/type_system.md | 60 +++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index 71b0243a6..6ff83d05c 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -20,6 +20,12 @@ pub struct Config { pub window_height: u16, } +#[non_exhaustive] +pub struct Token; + +#[non_exhaustive] +pub struct Id(pub u64); + #[non_exhaustive] pub enum Error { Message(String), @@ -34,11 +40,13 @@ pub enum Message { // Non-exhaustive structs can be constructed as normal within the defining crate. let config = Config { window_width: 640, window_height: 480 }; +let token = Token; +let id = Id(4); // Non-exhaustive structs can be matched on exhaustively within the defining crate. -if let Config { window_width, window_height } = config { - // ... -} +let Config { window_width, window_height } = config; +let Token = token; +let Id(id_number) = id; let error = Error::Other; let message = Message::Reaction(3); @@ -64,30 +72,47 @@ Non-exhaustive types cannot be constructed outside of the defining crate: - Non-exhaustive variants ([`struct`][struct] or [`enum` variant][enum]) cannot be constructed with a [_StructExpression_] \(including with [functional update syntax]). +- The visibility of the same-named constant of a [unit-like struct][struct] + is lowered to `min($vis, pub(crate))`. +- The visibility of the same-named constructor function of a [tuple struct][struct] + is lowered to `min($vis, pub(crate))`. - [`enum`][enum] instances can be constructed. +The following examples of construction do not compile when outside the defining crate: + ```rust,ignore -// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been -// annotated as `#[non_exhaustive]`. -use upstream::{Config, Error, Message}; +// These are types defined in an upstream crate that have been annotated as +// `#[non_exhaustive]`. +use upstream::{Config, Token, Id, Error, Message}; -// Cannot construct an instance of `Config`, if new fields were added in +// Cannot construct an instance of `Config`; if new fields were added in // a new version of `upstream` then this would fail to compile, so it is // disallowed. let config = Config { window_width: 640, window_height: 480 }; -// Can construct an instance of `Error`, new variants being introduced would +// Cannot construct an instance of `Token`; if new fields were added, then +// it would not be a unit-like struct any more, so the same-named constant +// created by it being a unit-like struct is not public outside the crate; +// this code fails to compile. +let token = Token; + +// Cannot construct an instance of `Id`; if new fields were added, then +// its constructor function signature would change, so its constructor +// function is not public outside the crate; this code fails to compile. +let id = Id(5); + +// Can construct an instance of `Error`; new variants being introduced would // not result in this failing to compile. let error = Error::Message("foo".to_string()); -// Cannot construct an instance of `Message::Send` or `Message::Reaction`, +// Cannot construct an instance of `Message::Send` or `Message::Reaction`; // if new fields were added in a new version of `upstream` then this would // fail to compile, so it is disallowed. let message = Message::Send { from: 0, to: 1, contents: "foo".to_string(), }; let message = Message::Reaction(0); -// Cannot construct an instance of `Message::Quit`, if this were converted to +// Cannot construct an instance of `Message::Quit`; if this were converted to // a tuple-variant `upstream` then this would fail to compile. let message = Message::Quit; ``` @@ -100,11 +125,13 @@ There are limitations when matching on non-exhaustive types outside of the defin - When pattern matching on a non-exhaustive [`enum`][enum], matching on a variant does not contribute towards the exhaustiveness of the arms. +The following examples of matching do not compile when outside the defining crate: + ```rust, ignore -// `Config`, `Error`, and `Message` are types defined in an upstream crate that have been -// annotated as `#[non_exhaustive]`. -use upstream::{Config, Error, Message}; +// These are types defined in an upstream crate that have been annotated as +// `#[non_exhaustive]`. +use upstream::{Config, Token, Id, Error, Message}; // Cannot match on a non-exhaustive enum without including a wildcard arm. match error { @@ -118,6 +145,13 @@ if let Ok(Config { window_width, window_height }) = config { // would compile with: `..` } +// Cannot match a non-exhaustive unit-like or tuple struct except by using +// braced struct syntax with a wildcard. +// This would compile as `let Token { .. } = token;` +let Token = token; +// This would compile as `let Id { 0: id_number, .. } = id;` +let Id(id_number) = id; + match message { // Cannot match on a non-exhaustive struct enum variant without including a wildcard. Message::Send { from, to, contents } => { }, From 076a798583ecb450dbb27d46c2e1558228d0fcf1 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 15 Apr 2024 11:13:52 -0700 Subject: [PATCH 305/315] =?UTF-8?q?Replace=20=E2=80=9Cmin()=E2=80=9D=20vis?= =?UTF-8?q?ibility=20notation=20with=20English.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/attributes/type_system.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/attributes/type_system.md b/src/attributes/type_system.md index 6ff83d05c..dd3ea9874 100644 --- a/src/attributes/type_system.md +++ b/src/attributes/type_system.md @@ -72,10 +72,12 @@ Non-exhaustive types cannot be constructed outside of the defining crate: - Non-exhaustive variants ([`struct`][struct] or [`enum` variant][enum]) cannot be constructed with a [_StructExpression_] \(including with [functional update syntax]). -- The visibility of the same-named constant of a [unit-like struct][struct] - is lowered to `min($vis, pub(crate))`. -- The visibility of the same-named constructor function of a [tuple struct][struct] - is lowered to `min($vis, pub(crate))`. +- The implicitly defined same-named constant of a [unit-like struct][struct], + or the same-named constructor function of a [tuple struct][struct], + has a [visibility] no greater than `pub(crate)`. + That is, if the struct’s visibility is `pub`, then the constant or constructor’s visibility + is `pub(crate)`, and otherwise the visibility of the two items is the same + (as is the case without `#[non_exhaustive]`). - [`enum`][enum] instances can be constructed. The following examples of construction do not compile when outside the defining crate: @@ -120,8 +122,8 @@ let message = Message::Quit; There are limitations when matching on non-exhaustive types outside of the defining crate: - When pattern matching on a non-exhaustive variant ([`struct`][struct] or [`enum` variant][enum]), - a [_StructPattern_] must be used which must include a `..`. Tuple variant constructor visibility - is lowered to `min($vis, pub(crate))`. + a [_StructPattern_] must be used which must include a `..`. A tuple variant's constructor's + [visibility] is reduced to be no greater than `pub(crate)`. - When pattern matching on a non-exhaustive [`enum`][enum], matching on a variant does not contribute towards the exhaustiveness of the arms. @@ -181,3 +183,4 @@ Non-exhaustive types are always considered inhabited in downstream crates. [enum]: ../items/enumerations.md [functional update syntax]: ../expressions/struct-expr.md#functional-update-syntax [struct]: ../items/structs.md +[visibility]: ../visibility-and-privacy.md From 4f47e3ffe75d40fc724741f17dc1cb165dc3c564 Mon Sep 17 00:00:00 2001 From: Conrad Ludgate Date: Tue, 16 Apr 2024 06:55:59 +0100 Subject: [PATCH 306/315] Update clone reference to include closures --- src/special-types-and-traits.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/special-types-and-traits.md b/src/special-types-and-traits.md index 6355f3fb2..cadced52e 100644 --- a/src/special-types-and-traits.md +++ b/src/special-types-and-traits.md @@ -80,6 +80,7 @@ types: * Types with a built-in `Copy` implementation (see above) * [Tuples] of `Clone` types +* [Closures] that only capture values of `Clone` types ## `Send` From a432cf4afdb6f0f452de19c4d123fae81a840d50 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Tue, 16 Apr 2024 09:35:51 -0700 Subject: [PATCH 307/315] Expand and clarify primitive alignment These changes are intended to make the section more informative and readable, without making any new normative claims. * Specify that the alignment might be _less_ than the size, rather than just that it might be different. This is mandatory and stated in the previous section, but I think it's useful to reiterate here. * Mention `u128`/`i128` as another example of alignment less than size, so that this doesn't sound like a mainly 32-bit thing. * Add `usize`/`isize` to the size table, so it can be spotted at a glance. --- src/type-layout.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index c21ab622a..c53e9d097 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -44,17 +44,20 @@ The size of most primitives is given in this table. | `u32` / `i32` | 4 | | `u64` / `i64` | 8 | | `u128` / `i128` | 16 | +| `usize` / `isize` | See below | | `f32` | 4 | | `f64` | 8 | | `char` | 4 | `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 +target platform. For example, on a 32 bit target, this is 4 bytes, and on a 64 bit target, this is 8 bytes. -Most primitives are generally aligned to their size, although this is -platform-specific behavior. In particular, on many 32-bit platforms `u64` -and `f64` are only aligned to 32 bits. +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. ## Pointers and References Layout From 330ef9569444a7414633ba08cf5090da312f1f18 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 17 Apr 2024 08:04:47 -0700 Subject: [PATCH 308/315] Clone: Also mention closures that don't capture anything --- src/special-types-and-traits.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/special-types-and-traits.md b/src/special-types-and-traits.md index cadced52e..21cab3dc8 100644 --- a/src/special-types-and-traits.md +++ b/src/special-types-and-traits.md @@ -80,7 +80,7 @@ types: * Types with a built-in `Copy` implementation (see above) * [Tuples] of `Clone` types -* [Closures] that only capture values of `Clone` types +* [Closures] that only capture values of `Clone` types or capture no values from the environment ## `Send` From 2d51a2aec405dd54a617f5ee1b27cef326f30ced Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Apr 2024 10:53:08 -0700 Subject: [PATCH 309/315] Add an example of collapse_debuginfo --- src/attributes/debugger.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/attributes/debugger.md b/src/attributes/debugger.md index 60dc16b6a..6d184e87e 100644 --- a/src/attributes/debugger.md +++ b/src/attributes/debugger.md @@ -157,5 +157,14 @@ For built-in macros the default is `yes`. > **Note**: `rustc` has a `-C collapse-macro-debuginfo` CLI option to override both the default collapsing behavior and `#[collapse_debuginfo]` attributes. +```rust +#[collapse_debuginfo(yes)] +macro_rules! example { + () => { + println!("hello!"); + }; +} +``` + [attribute]: ../attributes.md [_MetaListIdents_]: ../attributes.md#meta-item-attribute-syntax From 01c8196e0120f0577f6aa05ada9d962f0019a86c Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 7 Nov 2022 04:53:59 +0000 Subject: [PATCH 310/315] Add const blocks --- src/const_eval.md | 4 +++- src/expressions.md | 2 ++ src/expressions/block-expr.md | 40 +++++++++++++++++++++++++++++++++++ src/macros-by-example.md | 2 ++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/const_eval.md b/src/const_eval.md index 34e34d703..af8d4862c 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -27,7 +27,7 @@ to be run. * [Tuple expressions]. * [Array expressions]. * [Struct] expressions. -* [Block expressions], including `unsafe` blocks. +* [Block expressions], including `unsafe` and `const` blocks. * [let statements] and thus irrefutable [patterns], including mutable bindings * [assignment expressions] * [compound assignment expressions] @@ -59,6 +59,7 @@ A _const context_ is one of the following: * [statics] * [enum discriminants] * A [const generic argument] +* A [const block] ## Const Functions @@ -106,6 +107,7 @@ Conversely, the following are possible in a const function, but not in a const c [cast]: expressions/operator-expr.md#type-cast-expressions [closure expressions]: expressions/closure-expr.md [comparison]: expressions/operator-expr.md#comparison-operators +[const block]: expressions/block-expr.md#const-blocks [const functions]: items/functions.md#const-functions [const generic argument]: items/generics.md#const-generics [const generic parameters]: items/generics.md#const-generics diff --git a/src/expressions.md b/src/expressions.md index ad4cc5f54..9e10dcea3 100644 --- a/src/expressions.md +++ b/src/expressions.md @@ -35,6 +35,7 @@ >    [_OuterAttribute_]\*[†](#expression-attributes)\ >    (\ >          [_BlockExpression_]\ +>       | [_ConstBlockExpression_]\ >       | [_UnsafeBlockExpression_]\ >       | [_LoopExpression_]\ >       | [_IfExpression_]\ @@ -311,6 +312,7 @@ They are never allowed before: [_ClosureExpression_]: expressions/closure-expr.md [_ComparisonExpression_]: expressions/operator-expr.md#comparison-operators [_CompoundAssignmentExpression_]: expressions/operator-expr.md#compound-assignment-expressions +[_ConstBlockExpression_]: expressions/block-expr.md#const-blocks [_ContinueExpression_]: expressions/loop-expr.md#continue-expressions [_FieldExpression_]: expressions/field-expr.md [_GroupedExpression_]: expressions/grouped-expr.md diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index bd9c0a623..c12e1de53 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -117,6 +117,44 @@ loop { } ``` +## `const` blocks + +> **Syntax**\ +> _ConstBlockExpression_ :\ +>    `const` _BlockExpression_ + +A *const block* is a variant of a block expression which evaluates in the compile time instead of in the run time. + +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 have ability to reference generic parameters in scope, unlike [free][free item] constant items. +They are desugared to associated constant items with generic parameters in scope. +For example, this code: + +```rust +fn foo() -> usize { + const { std::mem::size_of::() + 1 } +} +``` + +is equivalent to: + +```rust +fn foo() -> usize { + { + struct Const(T); + impl Const { + const CONST: usize = std::mem::size_of::() + 1; + } + Const::::CONST + } +} +``` + +This also means that const blocks are treated similarly to associated constants. +For example, they are not guaranteed to be evaluated when the enclosing function is unused. + ## `unsafe` blocks > **Syntax**\ @@ -181,6 +219,8 @@ fn is_unix_platform() -> bool { [array expressions]: array-expr.md [call expressions]: call-expr.md [capture modes]: ../types/closure.md#capture-modes +[constant items]: ../items/constant-items.md +[free item]: ../glossary.md#free-item [function]: ../items/functions.md [inner attributes]: ../attributes.md [method]: ../items/associated-items.md#methods diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 51aa919fc..014fb852b 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -146,6 +146,7 @@ For reasons of backwards compatibility, though `_` [is also an expression][_UnderscoreExpression_], a standalone underscore is not matched by the `expr` fragment specifier. However, `_` is matched by the `expr` fragment specifier when it appears as a subexpression. +For the same reason, a standalone [const block] is not matched but it is matched when appearing as a subexpression. > **Edition Differences**: Starting with the 2021 edition, `pat` fragment-specifiers match top-level or-patterns (that is, they accept [_Pattern_]). > @@ -492,6 +493,7 @@ expansions, taking separators into account. This means: For more detail, see the [formal specification]. +[const block]: expressions/block-expr.md#const-blocks [Hygiene]: #hygiene [IDENTIFIER]: identifiers.md [IDENTIFIER_OR_KEYWORD]: identifiers.md From c6719b5d8dc04f8855f0c1e3ee2bb798465c793b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 3 May 2024 16:08:14 +0200 Subject: [PATCH 311/315] mention associated consts --- src/patterns.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/patterns.md b/src/patterns.md index e9eb13d14..96bd827b7 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -787,6 +787,7 @@ Furthermore we require that the value of `C` *has (recursive) structural equalit - Nothing else has structural equality. In particular, the value of `C` must be known at pattern-building time (which is pre-monomorphization). +This means that associated consts cannot be used as patterns. 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. From 2f63507ae20c2e2223258a58153ff6af54c965a7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 7 May 2024 08:15:24 +0200 Subject: [PATCH 312/315] clarifications --- src/patterns.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index 96bd827b7..b413c59f1 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -776,7 +776,7 @@ They are refutable when they refer to refutable constants or enum variants for e When a constant `C` of type `T` is used as a pattern, we first check that `T: PartialEq`. Furthermore we require that the value of `C` *has (recursive) structural equality*, which is defined recursively as follows: -- Integers as well as `bool` and `char` values always have structural equality. +- Integers as well as `str`, `bool` and `char` values 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.) - References have structural equality if the value they point to has structural equality. @@ -787,7 +787,7 @@ Furthermore we require that the value of `C` *has (recursive) structural equalit - Nothing else has structural equality. In particular, the value of `C` must be known at pattern-building time (which is pre-monomorphization). -This means that associated consts cannot be used as patterns. +This means that associated consts that involve generic parameters cannot be used as patterns. 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. From 95ab92091f775889d150cb9b78c3b36ea650c08d Mon Sep 17 00:00:00 2001 From: MultisampledNight Date: Fri, 22 Mar 2024 23:35:01 +0100 Subject: [PATCH 313/315] patterns: include new exclusive range patterns See also https://github.com/rust-lang/rust/issues/37854. --- src/patterns.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index c92e2dcda..4e68e0aee 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -397,6 +397,9 @@ match tuple { >    | _RangeToInclusivePattern_\ >    | _ObsoleteRangePattern_ > +> _RangeExclusivePattern_ :\ +>       _RangePatternBound_ `..` _RangePatternBound_ +> > _RangeInclusivePattern_ :\ >       _RangePatternBound_ `..=` _RangePatternBound_ > @@ -422,10 +425,11 @@ A bound on the left of the sigil is a *lower bound*. A bound on the right is an *upper bound*. A range pattern with both a lower and upper bound will match all values between and including both of its bounds. -It is written as its lower bound, followed by `..=`, followed by its upper bound. +It is written as its lower bound, followed by `..` for end-exclusive or `..=` for end-inclusive, followed by its upper bound. The type of the range pattern is the type unification of its upper and lower bounds. For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. +Similarly, `'m'..'p'` will match only `'m'`, `'n'` and `'o'`, specifically **not** including `'p'`. The lower bound cannot be greater than the upper bound. That is, in `a..=b`, a ≤ b must be the case. @@ -467,7 +471,7 @@ let valid_variable = match c { # let ph = 10; println!("{}", match ph { - 0..=6 => "acid", + 0..7 => "acid", 7 => "neutral", 8..=14 => "base", _ => unreachable!(), @@ -539,9 +543,6 @@ See [issue #41620](https://github.com/rust-lang/rust/issues/41620) for more info > **Edition Differences**: Before the 2021 edition, range patterns with both a lower and upper bound may also be written using `...` in place of `..=`, with the same meaning. -> **Note**: Although range patterns use the same syntax as [range expressions], there are no exclusive range patterns. -> That is, neither `x .. y` nor `.. x` are valid range patterns. - ## Reference patterns > **Syntax**\ From efdc9b6fe3e794bf3d668429cbf6ad68e302b679 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 8 May 2024 09:50:26 -0700 Subject: [PATCH 314/315] Small editorial updates for const blocks. --- src/expressions/block-expr.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index c12e1de53..890cf856d 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -123,12 +123,12 @@ loop { > _ConstBlockExpression_ :\ >    `const` _BlockExpression_ -A *const block* is a variant of a block expression which evaluates in the compile time instead of in the run time. +A *const block* is a variant of a block expression which evaluates at compile-time instead of at runtime. 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 have ability to reference generic parameters in scope, unlike [free][free item] constant items. +Const blocks have the ability to reference generic parameters in scope, unlike [free][free item] constant items. They are desugared to associated constant items with generic parameters in scope. For example, this code: From d33e4b03f0f810a315915412448a1f73c30e0feb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 10 May 2024 08:52:15 +0200 Subject: [PATCH 315/315] document guarantee about evaluation of associated consts and const blocks --- src/expressions/block-expr.md | 26 ++++++++++++++++++++++---- src/expressions/path-expr.md | 3 +++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index 890cf856d..0dda00c56 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -123,13 +123,13 @@ loop { > _ConstBlockExpression_ :\ >    `const` _BlockExpression_ -A *const block* is a variant of a block expression which evaluates at compile-time instead of at runtime. +A *const block* is a variant of a block expression whose body evaluates at compile-time instead of at runtime. 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 have the ability to reference generic parameters in scope, unlike [free][free item] constant items. -They are desugared to associated constant items with generic parameters in scope. +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 @@ -152,8 +152,26 @@ fn foo() -> usize { } ``` -This also means that const blocks are treated similarly to associated constants. -For example, they are not guaranteed to be evaluated when the enclosing function is unused. +If the const block expression is executed at runtime, then the constant is guaranteed to be evaluated, even if its return value is ignored: + +```rust +fn foo() -> usize { + // If this code ever gets executed, then the assertion has definitely + // been evaluated at compile-time. + const { assert!(std::mem::size_of::() > 0); } + // Here we can have unsafe code relying on the type being non-zero-sized. + /* ... */ + 42 +} +``` + +If the const block expression is not executed at runtime, it may or may not be evaluated: +```rust,compile_fail +if false { + // The panic may or may not occur when the program is built. + const { panic!(); } +} +``` ## `unsafe` blocks diff --git a/src/expressions/path-expr.md b/src/expressions/path-expr.md index 0909c5ddb..0707e9d41 100644 --- a/src/expressions/path-expr.md +++ b/src/expressions/path-expr.md @@ -23,6 +23,8 @@ let push_integer = Vec::::push; let slice_reverse = <[i32]>::reverse; ``` +Evaluation of associated constants is handled the same way as [`const` blocks]. + [_PathInExpression_]: ../paths.md#paths-in-expressions [_QualifiedPathInExpression_]: ../paths.md#qualified-paths [place expressions]: ../expressions.md#place-expressions-and-value-expressions @@ -30,3 +32,4 @@ let slice_reverse = <[i32]>::reverse; [path]: ../paths.md [`static mut`]: ../items/static-items.md#mutable-statics [`unsafe` block]: block-expr.md#unsafe-blocks +[`const` blocks]: block-expr.md#const-blocks