From c8d9761ff37a695b75a4a9543ee638d0286cda94 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 4 Jun 2021 20:13:08 +0200 Subject: [PATCH 001/463] 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 15d8468..8f20636 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 5c1b8d7c9fdaf1ea4f7bb7c672573c3f1aa3cbd9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 31 Jan 2022 14:05:27 +0100 Subject: [PATCH 002/463] 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 22b5752..9b23b9e 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 486d838104fc9a3c3fc774d269d27d90f8673ef9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Feb 2022 16:13:00 +0100 Subject: [PATCH 003/463] 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 9b23b9e..915e9cb 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 466fedbb489eeace5c779d9ec3eeeb29702a9df3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 9 Feb 2022 06:32:21 -0800 Subject: [PATCH 004/463] Clarify guarantees provided by repr(packed) Clarify that `repr(packed)` minimizes inter-field padding and, in the special case of `repr(packed(1))`/`repr(packed)`, guarantees no inter-field padding. --- src/type-layout.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/type-layout.md b/src/type-layout.md index 22b5752..252bdbf 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -515,6 +515,11 @@ For `packed`, if the specified alignment is greater than the type's alignment without the `packed` modifier, then the alignment and layout is unaffected. The alignments of each field, for the purpose of positioning fields, is the smaller of the specified alignment and the alignment of the field's type. +Inter-field padding is guaranteed to be the minimum required in order to +satisfy each field's (possibly altered) alignment (although note that, on its +own, `packed` does not provide any guarantee about field ordering). An +important special case is `#[repr(packed(1))]` (or `#[repr(packed)]`), which +guarantees that no inter-field padding will be present. The `align` and `packed` modifiers cannot be applied on the same type and a `packed` type cannot transitively contain another `align`ed type. `align` and From c8c633cc18c391306195ff63b34f801ae938fb13 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 9 Feb 2022 06:33:54 -0800 Subject: [PATCH 005/463] Update type-layout.md --- 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 252bdbf..f45c960 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -501,7 +501,7 @@ assert_eq!(std::mem::size_of::(), 4); The `align` and `packed` modifiers can be used to respectively raise or lower the alignment of `struct`s and `union`s. `packed` may also alter the padding -between fields. +between fields (although it will not alter the padding inside of any field). The alignment is specified as an integer parameter in the form of `#[repr(align(x))]` or `#[repr(packed(x))]`. The alignment value must be a From 56a1e3e3bf0220c057ac54b2e4aeb03788ced457 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 5 Mar 2022 22:29:25 +0000 Subject: [PATCH 006/463] tokens.md: move the link reference definitions to the end of the file --- src/tokens.md | 77 +++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 5516fb7..9a34844 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -430,8 +430,6 @@ Note that the Rust syntax considers `-1i8` as an application of the [unary minus operator] to an integer literal `1i8`, rather than a single integer literal. -[unary minus operator]: expressions/operator-expr.md#negation-operators - #### Tuple index > **Lexer**\ @@ -542,8 +540,6 @@ 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 macros. -[loop labels]: expressions/loop-expr.md - ## Punctuation Punctuation symbol tokens are listed here for completeness. Their individual @@ -609,6 +605,41 @@ them are referred to as "token trees" in [macros]. The three types of brackets | `[` `]` | Square brackets | | `(` `)` | Parentheses | +## Reserved prefixes + +> **Lexer 2021+**\ +> RESERVED_TOKEN_DOUBLE_QUOTE : ( IDENTIFIER_OR_KEYWORD _Except `b` or `r` or `br`_ | `_` ) `"`\ +> RESERVED_TOKEN_SINGLE_QUOTE : ( IDENTIFIER_OR_KEYWORD _Except `b`_ | `_` ) `'`\ +> RESERVED_TOKEN_POUND : ( IDENTIFIER_OR_KEYWORD _Except `r` or `br`_ | `_` ) `#` + +Some lexical forms known as _reserved prefixes_ are reserved for future use. + +Source input which would otherwise be lexically interpreted as a non-raw identifier (or a keyword or `_`) which is immediately followed by a `#`, `'`, or `"` character (without intervening whitespace) is identified as a reserved prefix. + +Note that raw identifiers, raw string literals, and raw byte string literals may contain a `#` character but are not interpreted as containing a reserved prefix. + +Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte literals, byte string literals, and raw byte string literals are not interpreted as reserved prefixes. + +> **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). +> +> Examples accepted in all editions: +> ```rust +> macro_rules! lexes {($($_:tt)*) => {}} +> lexes!{a #foo} +> lexes!{continue 'foo} +> lexes!{match "..." {}} +> lexes!{r#let#foo} // three tokens: r#let # foo +> ``` +> +> Examples accepted before the 2021 edition but rejected later: +> ```rust,edition2018 +> macro_rules! lexes {($($_:tt)*) => {}} +> lexes!{a#foo} +> lexes!{continue'foo} +> lexes!{match"..." {}} +> ``` [Inferred types]: types/inferred.md [Range patterns]: patterns.md#range-patterns @@ -636,6 +667,7 @@ them are referred to as "token trees" in [macros]. The three types of brackets [if let]: expressions/if-expr.md#if-let-expressions [keywords]: keywords.md [lazy-bool]: expressions/operator-expr.md#lazy-boolean-operators +[loop labels]: expressions/loop-expr.md [machine types]: types/numeric.md [macros]: macros-by-example.md [match]: expressions/match-expr.md @@ -656,42 +688,7 @@ them are referred to as "token trees" in [macros]. The three types of brackets [tuple structs]: items/structs.md [tuple variants]: items/enumerations.md [tuples]: types/tuple.md +[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 - -## Reserved prefixes - -> **Lexer 2021+**\ -> RESERVED_TOKEN_DOUBLE_QUOTE : ( IDENTIFIER_OR_KEYWORD _Except `b` or `r` or `br`_ | `_` ) `"`\ -> RESERVED_TOKEN_SINGLE_QUOTE : ( IDENTIFIER_OR_KEYWORD _Except `b`_ | `_` ) `'`\ -> RESERVED_TOKEN_POUND : ( IDENTIFIER_OR_KEYWORD _Except `r` or `br`_ | `_` ) `#` - -Some lexical forms known as _reserved prefixes_ are reserved for future use. - -Source input which would otherwise be lexically interpreted as a non-raw identifier (or a keyword or `_`) which is immediately followed by a `#`, `'`, or `"` character (without intervening whitespace) is identified as a reserved prefix. - -Note that raw identifiers, raw string literals, and raw byte string literals may contain a `#` character but are not interpreted as containing a reserved prefix. - -Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte literals, byte string literals, and raw byte string literals are not interpreted as reserved prefixes. - -> **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). -> -> Examples accepted in all editions: -> ```rust -> macro_rules! lexes {($($_:tt)*) => {}} -> lexes!{a #foo} -> lexes!{continue 'foo} -> lexes!{match "..." {}} -> lexes!{r#let#foo} // three tokens: r#let # foo -> ``` -> -> Examples accepted before the 2021 edition but rejected later: -> ```rust,edition2018 -> macro_rules! lexes {($($_:tt)*) => {}} -> lexes!{a#foo} -> lexes!{continue'foo} -> lexes!{match"..." {}} -> ``` From a3b14b070ce5a063c055d3530b5b389be4680f4e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 007/463] Move the general description of literal expressions from tokens.md to literal-expr.md --- src/expressions/literal-expr.md | 9 +++++++-- src/tokens.md | 7 ++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 0e2d7c0..ec439f6 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -12,8 +12,11 @@ >    | [FLOAT_LITERAL]\ >    | [BOOLEAN_LITERAL] -A _literal expression_ consists of one of the [literal](../tokens.md#literals) forms described earlier. -It directly describes a number, character, string, or boolean value. +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. + +A literal is a form of [constant expression], so is evaluated (primarily) at compile time. + +Each of the lexical [literal][literal tokens] forms described earlier can make up a literal expression. ```rust "hello"; // string type @@ -21,6 +24,8 @@ It directly describes a number, character, string, or boolean value. 5; // integer type ``` +[constant expression]: ../const_eval.md#constant-expressions +[literal tokens]: ../tokens.md#literals [CHAR_LITERAL]: ../tokens.md#character-literals [STRING_LITERAL]: ../tokens.md#string-literals [RAW_STRING_LITERAL]: ../tokens.md#raw-string-literals diff --git a/src/tokens.md b/src/tokens.md index 9a34844..ed8ae1f 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -18,11 +18,7 @@ table production] form, and appear in `monospace` font. ## Literals -A literal 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. A literal is -a form of [constant expression](const_eval.md#constant-expressions), so is -evaluated (primarily) at compile time. +Literals are tokens used in [literal expressions]. ### Examples @@ -667,6 +663,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [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 [loop labels]: expressions/loop-expr.md [machine types]: types/numeric.md [macros]: macros-by-example.md From 15204c09b532db601b168ef5ddc93ff069e1f6db Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 008/463] Describe the effect of integer literal suffixes in literal-expr.md rather than tokens.md --- src/expressions/literal-expr.md | 37 +++++++++++++++++++++++++++ src/tokens.md | 45 ++++++++++++--------------------- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index ec439f6..5494d22 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -24,8 +24,45 @@ Each of the lexical [literal][literal tokens] forms described earlier can make u 5; // integer type ``` +## Integer literal expressions + +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 no suffix, the expression's type is determined by type inference: + +* If an integer type can be _uniquely_ determined from the surrounding program context, the expression has that type. + +* If the program context under-constrains the type, it defaults to the signed 32-bit integer `i32`. + +* If the program context over-constrains the type, it is considered a static type error. + +Examples of integer literal expressions: + +```rust +123; // type i32 +123i32; // type i32 +123u32; // type u32 +123_u32; // type u32 +let a: u64 = 123; // type u64 + +0xff; // type i32 +0xff_u8; // type u8 + +0o70; // type i32 +0o70_i16; // type i16 + +0b1111_1111_1001_0000; // type i32 +0b1111_1111_1001_0000i64; // type i64 + +0usize; // type usize +``` + [constant expression]: ../const_eval.md#constant-expressions [literal tokens]: ../tokens.md#literals +[numeric types]: ../types/numeric.md +[suffix]: ../tokens.md#suffixes [CHAR_LITERAL]: ../tokens.md#character-literals [STRING_LITERAL]: ../tokens.md#string-literals [RAW_STRING_LITERAL]: ../tokens.md#raw-string-literals diff --git a/src/tokens.md b/src/tokens.md index ed8ae1f..bbc1037 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -359,43 +359,29 @@ 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 forcibly sets the -type of the literal. The integer suffix must be the name of one of the -integral types: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, -`u128`, `i128`, `usize`, or `isize`. - -The type of an _unsuffixed_ integer literal is determined by type inference: - -* If an integer type can be _uniquely_ determined from the surrounding - program context, the unsuffixed integer literal has that type. - -* If the program context under-constrains the type, it defaults to the - signed 32-bit integer `i32`. - -* If the program context over-constrains the type, it is considered a - static type error. +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`. +See [literal expressions] for the effect of these suffixes. Examples of integer literals of various forms: ```rust -123; // type i32 -123i32; // type i32 -123u32; // type u32 -123_u32; // type u32 -let a: u64 = 123; // type u64 +123; +123i32; +123u32; +123_u32; -0xff; // type i32 -0xff_u8; // type u8 +0xff; +0xff_u8; -0o70; // type i32 -0o70_i16; // type i16 +0o70; +0o70_i16; -0b1111_1111_1001_0000; // type i32 -0b1111_1111_1001_0000i64; // type i64 -0b________1; // type i32 +0b1111_1111_1001_0000; +0b1111_1111_1001_0000i64; +0b________1; -0usize; // type usize +0usize; ``` Examples of invalid integer literals: @@ -671,6 +657,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [negation]: expressions/operator-expr.md#negation-operators [negative impls]: items/implementations.md [never type]: types/never.md +[numeric types]: types/numeric.md [paths]: paths.md [patterns]: patterns.md [question]: expressions/operator-expr.md#the-question-mark-operator From af35a7723d53cd64eedc990d6f3b20b9448415f1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 009/463] Describe the effect of floating-point literal suffixes in literal-expr.md rather than tokens.md --- src/expressions/literal-expr.md | 26 +++++++++++++++++++++++++ src/tokens.md | 34 +++++++++------------------------ 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 5494d22..c2d035b 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -59,7 +59,33 @@ let a: u64 = 123; // type u64 0usize; // type usize ``` +## Floating-point literal expressions + +A floating-point literal expression consists of a single [FLOAT_LITERAL] token. + +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 no suffix, the expression's type is determined by type inference: + +* If a floating-point type can be _uniquely_ determined from the surrounding program context, the expression has that type. + +* If the program context under-constrains the type, it defaults to `f64`. + +* If the program context over-constrains the type, it is considered a static type error. + +Examples of floating-point literal expressions: + +```rust +123.0f64; // type f64 +0.1f64; // type f64 +0.1f32; // type f32 +12E+99_f64; // type f64 +5f32; // type f32 +let x: f64 = 2.; // type f64 +``` + [constant expression]: ../const_eval.md#constant-expressions +[floating-point types]: ../types/numeric.md#floating-point-types [literal tokens]: ../tokens.md#literals [numeric types]: ../types/numeric.md [suffix]: ../tokens.md#suffixes diff --git a/src/tokens.md b/src/tokens.md index bbc1037..d68b080 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -465,40 +465,24 @@ A _floating-point literal_ has one of two forms: 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` (`.`). -The suffix forcibly sets the type of the literal. There are two valid -_floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point -types), which explicitly determine the type of the literal. - -The type of an _unsuffixed_ floating-point literal is determined by -type inference: - -* If a floating-point type can be _uniquely_ determined from the - surrounding program context, the unsuffixed floating-point literal - has that type. - -* If the program context under-constrains the type, it defaults to `f64`. - -* If the program context over-constrains the type, it is considered a - static type error. +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]). +See [literal expressions] for the effect of these suffixes. Examples of floating-point literals of various forms: ```rust -123.0f64; // type f64 -0.1f64; // type f64 -0.1f32; // type f32 -12E+99_f64; // type f64 -5f32; // type f32 -let x: f64 = 2.; // type f64 +123.0f64; +0.1f64; +0.1f32; +12E+99_f64; +5f32; +let x: f64 = 2.; ``` This last example is different because it is not possible to use the suffix syntax with a floating point literal ending in a period. `2.f64` would attempt to call a method named `f64` on `2`. -The representation semantics of floating-point numbers are described in -["Machine Types"][machine types]. - ### Boolean literals > **Lexer**\ @@ -642,6 +626,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [extern crates]: items/extern-crates.md [extern]: items/external-blocks.md [field]: expressions/field-expr.md +[floating-point types]: types/numeric.md#floating-point-types [function pointer type]: types/function-pointer.md [functions]: items/functions.md [generics]: items/generics.md @@ -651,7 +636,6 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite [lazy-bool]: expressions/operator-expr.md#lazy-boolean-operators [literal expressions]: expressions/literal-expr.md [loop labels]: expressions/loop-expr.md -[machine types]: types/numeric.md [macros]: macros-by-example.md [match]: expressions/match-expr.md [negation]: expressions/operator-expr.md#negation-operators From 47996f074921e4ab1767ee8c8bd99aac455a4bfe Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 010/463] Document how the value of an integer literal expression is determined --- src/expressions/literal-expr.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index c2d035b..11e280b 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -59,6 +59,18 @@ let a: u64 = 123; // type u64 0usize; // type usize ``` +The value of the expression is determined from the string representation of the token as follows: + +* An integer radix is chosen by inspecting the first two characters of the string: `0b` indicates radix 2, `0o` indicates radix 8, `0x` indicates radix 16; otherwise the radix is 10. + +* If the radix is not 10, the first two characters are 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. + +* The `u128` value is converted to the expression's type via a [numeric cast]. + ## Floating-point literal expressions A floating-point literal expression consists of a single [FLOAT_LITERAL] token. @@ -87,8 +99,10 @@ let x: f64 = 2.; // type f64 [constant expression]: ../const_eval.md#constant-expressions [floating-point types]: ../types/numeric.md#floating-point-types [literal tokens]: ../tokens.md#literals +[numeric cast]: operator-expr.md#numeric-cast [numeric types]: ../types/numeric.md [suffix]: ../tokens.md#suffixes +[`u128::from_str_radix`]: ../../core/primitive.u128.md#method.from_str_radix [CHAR_LITERAL]: ../tokens.md#character-literals [STRING_LITERAL]: ../tokens.md#string-literals [RAW_STRING_LITERAL]: ../tokens.md#raw-string-literals From 11af6b84b80855dd5dc24604d036637459d178e2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 011/463] Say that integer literals out of the u128 range are a parse-time error --- src/expressions/literal-expr.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 11e280b..0851177 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -8,9 +8,11 @@ >    | [BYTE_LITERAL]\ >    | [BYTE_STRING_LITERAL]\ >    | [RAW_BYTE_STRING_LITERAL]\ ->    | [INTEGER_LITERAL]\ +>    | [INTEGER_LITERAL][^out-of-range]\ >    | [FLOAT_LITERAL]\ >    | [BOOLEAN_LITERAL] +> +> [^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. @@ -68,6 +70,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. * The `u128` value is converted to the expression's type via a [numeric cast]. From 012e207616aa1e11bedb0b4eb4b6315625a621f3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 012/463] Literal expressions: add a Note describing the overflowing_literals lint --- 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 0851177..b5b591c 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -74,6 +74,9 @@ If the value does not fit in `u128`, the expression is rejected by the parser. * The `u128` value is converted to the expression's type via a [numeric cast]. +> **Note**: The final cast will truncate the value of the literal if it does not fit in the expression's type. +> There is a [lint check] named `overflowing_literals`, defaulting to `deny`, which rejects expressions where this occurs. + ## Floating-point literal expressions A floating-point literal expression consists of a single [FLOAT_LITERAL] token. @@ -101,6 +104,7 @@ let x: f64 = 2.; // type f64 [constant expression]: ../const_eval.md#constant-expressions [floating-point types]: ../types/numeric.md#floating-point-types +[lint check]: ../attributes/diagnostics.md#lint-check-attributes [literal tokens]: ../tokens.md#literals [numeric cast]: operator-expr.md#numeric-cast [numeric types]: ../types/numeric.md From 44f72100d1812dd74262625f8d3a58f9f531d5f9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 013/463] Document how the value of a floating-point literal expression is determined For now, refer to the stdlib docs for the actual interpretation. --- src/expressions/literal-expr.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index b5b591c..37930db 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -102,6 +102,12 @@ Examples of floating-point literal expressions: let x: f64 = 2.; // type f64 ``` +The value of the expression is determined from the string representation of the token as follows: + +* 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`]. + [constant expression]: ../const_eval.md#constant-expressions [floating-point types]: ../types/numeric.md#floating-point-types [lint check]: ../attributes/diagnostics.md#lint-check-attributes @@ -109,6 +115,8 @@ let x: f64 = 2.; // type f64 [numeric cast]: operator-expr.md#numeric-cast [numeric types]: ../types/numeric.md [suffix]: ../tokens.md#suffixes +[`f32::from_str`]: ../../core/primitive.f32.md#method.from_str +[`f64::from_str`]: ../../core/primitive.f64.md#method.from_str [`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 1313a5ad9adb034dfa64ff9ab90464ab164dbcad Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 014/463] Literal expressions: add a Note on infinite and NaN floating-point literals --- src/expressions/literal-expr.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 37930db..b4b7ddf 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -108,6 +108,10 @@ The value of the expression is determined from the string representation of the * The string is converted to the expression's type as if by [`f32::from_str`] or [`f64::from_str`]. +> **Note**: `inf` and `NaN` are not literal tokens. +> The [`f32::INFINITY`], [`f64::INFINITY`], [`f32::NAN`], and [`f64::NAN`] constants can be used instead of literal expressions. +> A literal large enough to be evaluated as infinite will trigger the `overflowing_literals` lint check. + [constant expression]: ../const_eval.md#constant-expressions [floating-point types]: ../types/numeric.md#floating-point-types [lint check]: ../attributes/diagnostics.md#lint-check-attributes @@ -116,7 +120,11 @@ The value of the expression is determined from the string representation of the [numeric types]: ../types/numeric.md [suffix]: ../tokens.md#suffixes [`f32::from_str`]: ../../core/primitive.f32.md#method.from_str +[`f32::INFINITY`]: ../../core/primitive.f32.md#associatedconstant.INFINITY +[`f32::NAN`]: ../../core/primitive.f32.md#associatedconstant.NAN [`f64::from_str`]: ../../core/primitive.f64.md#method.from_str +[`f64::INFINITY`]: ../../core/primitive.f64.md#associatedconstant.INFINITY +[`f64::NAN`]: ../../core/primitive.f64.md#associatedconstant.NAN [`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 505c0603ab3b3751c885dbdf7ea5e8648192683a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 015/463] Notes about negated literals --- src/expressions/literal-expr.md | 5 +++++ src/tokens.md | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index b4b7ddf..e01ac17 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -77,6 +77,8 @@ If the value does not fit in `u128`, the expression is rejected by the parser. > **Note**: The final cast will truncate the value of the literal if it does not fit in the expression's type. > There is a [lint check] named `overflowing_literals`, defaulting to `deny`, which rejects expressions where this occurs. +> **Note**: `-1i8`, for example, is an application of the [negation operator] to the literal expression `1i8`, not a single integer literal expression. + ## Floating-point literal expressions A floating-point literal expression consists of a single [FLOAT_LITERAL] token. @@ -108,6 +110,8 @@ The value of the expression is determined from the string representation of the * The string is converted to the expression's type as if by [`f32::from_str`] or [`f64::from_str`]. +> **Note**: `-1.0`, for example, is an application of the [negation operator] to the literal expression `1.0`, not a single floating-point literal expression. + > **Note**: `inf` and `NaN` are not literal tokens. > The [`f32::INFINITY`], [`f64::INFINITY`], [`f32::NAN`], and [`f64::NAN`] constants can be used instead of literal expressions. > A literal large enough to be evaluated as infinite will trigger the `overflowing_literals` lint check. @@ -119,6 +123,7 @@ The value of the expression is determined from the string representation of the [numeric cast]: operator-expr.md#numeric-cast [numeric types]: ../types/numeric.md [suffix]: ../tokens.md#suffixes +[negation operator]: operator-expr.md#negation-operators [`f32::from_str`]: ../../core/primitive.f32.md#method.from_str [`f32::INFINITY`]: ../../core/primitive.f32.md#associatedconstant.INFINITY [`f32::NAN`]: ../../core/primitive.f32.md#associatedconstant.NAN diff --git a/src/tokens.md b/src/tokens.md index d68b080..8f4e5cc 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -384,6 +384,8 @@ Examples of integer literals of various forms: 0usize; ``` +Note that `-1i8`, for example, is analyzed as two tokens: `-` followed by `1i8`. + Examples of invalid integer literals: ```rust,compile_fail @@ -408,10 +410,6 @@ Examples of invalid integer literals: 0b____; ``` -Note that the Rust syntax considers `-1i8` as an application of the [unary minus -operator] to an integer literal `1i8`, rather than -a single integer literal. - #### Tuple index > **Lexer**\ @@ -483,6 +481,8 @@ This last example is different because it is not possible to use the suffix syntax with a floating point literal ending in a period. `2.f64` would attempt to call a method named `f64` on `2`. +Note that `-1.0`, for example, is analyzed as two tokens: `-` followed by `1.0`. + ### Boolean literals > **Lexer**\ From 9a839b562ab27be3d1fcefe19cc43b4bcda4a8bf Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 016/463] Say that out-of-range suffixed integer literals are valid lexer tokens --- src/tokens.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 8f4e5cc..cc5b8bf 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -366,6 +366,7 @@ See [literal expressions] for the effect of these suffixes. Examples of integer literals of various forms: ```rust +# #![allow(overflowing_literals)] 123; 123i32; 123u32; @@ -382,6 +383,12 @@ Examples of integer literals of various forms: 0b________1; 0usize; + +// These are too big for their type, but are still valid tokens + +128_i8; +256_u8; + ``` Note that `-1i8`, for example, is analyzed as two tokens: `-` followed by `1i8`. @@ -399,11 +406,6 @@ Examples of invalid integer literals: 0b0102; 0o0581; -// integers too big for their type (they overflow) - -128_i8; -256_u8; - // bin, hex, and octal literals must have at least one digit 0b_; From 5e834170807dc3cf379ee4a217c9fdc718e40d4a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 017/463] Make the FLOAT_LITERAL rule mention keywords as well as identifiers --- src/tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tokens.md b/src/tokens.md index cc5b8bf..8058ddc 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -444,7 +444,7 @@ let horse = example.0b10; // ERROR no field named `0b10` > **Lexer**\ > FLOAT_LITERAL :\ >       DEC_LITERAL `.` -> _(not immediately followed by `.`, `_` or an [identifier]_)\ +> _(not immediately followed by `.`, `_` or an [identifier] or [keyword][keywords]_)\ >    | DEC_LITERAL FLOAT_EXPONENT\ >    | DEC_LITERAL `.` DEC_LITERAL FLOAT_EXPONENT?\ >    | DEC_LITERAL (`.` DEC_LITERAL)? From 65f29fc57a25369475161c02e4e56f5505ec2216 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 018/463] Add the 5f32 case to the text description of floating-point literals --- src/tokens.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tokens.md b/src/tokens.md index 8058ddc..234864c 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -457,11 +457,12 @@ let horse = example.0b10; // ERROR no field named `0b10` > FLOAT_SUFFIX :\ >    `f32` | `f64` -A _floating-point literal_ has one of two forms: +A _floating-point literal_ has one of three 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` (`.`). From 42b1f5afe920807567750faf3aa01cf1e3b50cbc Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 019/463] Add some examples of possibly confusing hexadecimal literals --- src/tokens.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tokens.md b/src/tokens.md index 234864c..4cb3665 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -374,6 +374,8 @@ Examples of integer literals of various forms: 0xff; 0xff_u8; +0x01_f32; // integer 7986, not floating-point 1.0 +0x01_e3; // integer 483, not floating-point 1000.0 0o70; 0o70_i16; From ad8a58602e3582cc8269d1eaf1ea6628a267e3ab Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 020/463] Add a Lexer rules block for number literals with arbitrary suffixes --- src/tokens.md | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 4cb3665..8ad43fd 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -398,13 +398,8 @@ Note that `-1i8`, for example, is analyzed as two tokens: `-` followed by `1i8`. Examples of invalid integer literals: ```rust,compile_fail -// invalid suffixes - -0invalidSuffix; - // uses numbers of the wrong base -123AFB43; 0b0102; 0o0581; @@ -488,6 +483,42 @@ 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\ +>    | DEC_LITERAL ( . DEC_LITERAL)? NUMBER_PSEUDOLITERAL_SUFFIX_NO_E\ +>    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) NUMBER_PSEUDOLITERAL_SUFFIX_NO_E +> +> 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`_ + +As described [above](#suffixes), tokens with the same form as numeric literals other than in the content of their suffix are accepted by the lexer, with the exception of some cases in which the suffix begins with `e` or `E`. + +Examples of such tokens: +```rust,compile_fail +0invalidSuffix; +123AFB43; +0b010a; +0xAB_CD_EF_GH; +2.0f80; +2e5f80; +2e5e6; +2.0e5e6; + +// Lexer errors: +2e; +2.0e; +0b101e; +2em; +2.0em; +0b101em; +``` + ### Boolean literals > **Lexer**\ From 5eedcc3863210b40252b19cd602336dbbd9efcd8 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 021/463] Document reserved forms similar to number literals --- src/tokens.md | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 8ad43fd..7b3d799 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -497,7 +497,7 @@ Note that `-1.0`, for example, is analyzed as two tokens: `-` followed by `1.0`. > NUMBER_PSEUDOLITERAL_SUFFIX_NO_E :\ >    NUMBER_PSEUDOLITERAL_SUFFIX _not beginning with `e` or `E`_ -As described [above](#suffixes), tokens with the same form as numeric literals other than in the content of their suffix are accepted by the lexer, with the exception of some cases in which the suffix begins with `e` or `E`. +As described [above](#suffixes), tokens with the same form as numeric literals other than in the content of their suffix are accepted by the lexer (with the exception of some reserved forms described below). Examples of such tokens: ```rust,compile_fail @@ -509,14 +509,49 @@ Examples of such tokens: 2e5f80; 2e5e6; 2.0e5e6; +``` + +#### Reserved forms similar to number literals + +> **Lexer**\ +> RESERVED_NUMBER :\ +>       BIN_LITERAL \[`2`-`9`]\ +>    | OCT_LITERAL \[`8`-`9`]\ +>    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) `.` \ +>          _(not immediately followed by `.`, `_` or an [identifier] or [keyword][keywords]_)\ +>    | ( BIN_LITERAL | OCT_LITERAL ) `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_\ +>    | DEC_LITERAL ( . DEC_LITERAL)? (`e`|`E`) (`+`|`-`)? _end of input or not DEC_DIGIT_ + +The following lexical forms similar to number literals are _reserved forms_: + +* An unsuffixed binary or octal literal followed, without intervening whitespace, by a decimal digit out of the range for its radix. + +* 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). -// Lexer errors: -2e; -2.0e; -0b101e; -2em; -2.0em; -0b101em; +* An unsuffixed binary or octal literal followed, without intervening whitespace, by the character `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). + +* Input which has the form of a floating-point literal with no digits in the exponent. + +Any input containing one of these reserved forms is reported as an error by the lexer. + +Examples of reserved forms: + +```rust,compile_fail +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` ``` ### Boolean literals From c2365846f626f6711bba2b237d2777f4690744fc Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 6 Mar 2022 16:46:44 +0000 Subject: [PATCH 022/463] tokens.md: add two zero-width spaces to placate linkchecker A LINKCHECK_EXCEPTIONS entry in linkchecker/main.rs seems to be the right way to do this, but that's not in this repository. --- src/tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 7b3d799..365c4e8 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -515,8 +515,8 @@ Examples of such tokens: > **Lexer**\ > RESERVED_NUMBER :\ ->       BIN_LITERAL \[`2`-`9`]\ ->    | OCT_LITERAL \[`8`-`9`]\ +>       BIN_LITERAL \[`2`-`9`​]\ +>    | OCT_LITERAL \[`8`-`9`​]\ >    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) `.` \ >          _(not immediately followed by `.`, `_` or an [identifier] or [keyword][keywords]_)\ >    | ( BIN_LITERAL | OCT_LITERAL ) `e`\ From b767719ac8c7761782de2d4e6c965491932112b1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 16 Mar 2022 15:30:03 +0100 Subject: [PATCH 023/463] Add upper bound to hashes in raw string literals --- src/tokens.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index fb27052..0a96f7a 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -28,14 +28,14 @@ evaluated (primarily) at compile time. #### Characters and strings -| | Example | `#` sets | Characters | Escapes | -|----------------------------------------------|-----------------|-------------|-------------|---------------------| -| [Character](#character-literals) | `'H'` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | -| [String](#string-literals) | `"hello"` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | -| [Raw string](#raw-string-literals) | `r#"hello"#` | 0 or more\* | All Unicode | `N/A` | -| [Byte](#byte-literals) | `b'H'` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Byte string](#byte-string-literals) | `b"hello"` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | 0 or more\* | All ASCII | `N/A` | +| | Example | `#` sets | Characters | Escapes | +|----------------------------------------------|-----------------|-------------------|-------------|---------------------| +| [Character](#character-literals) | `'H'` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | +| [String](#string-literals) | `"hello"` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | +| [Raw string](#raw-string-literals) | `r#"hello"#` | <216\* | All Unicode | `N/A` | +| [Byte](#byte-literals) | `b'H'` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Byte string](#byte-string-literals) | `b"hello"` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | <216\* | All ASCII | `N/A` | \* The number of `#`s on each side of the same literal must be equivalent From 7360d73c762e7e8369a09b06a44ace5ad88d98d7 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 16 Mar 2022 15:46:21 +0100 Subject: [PATCH 024/463] Raw string token style change --- src/tokens.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 0a96f7a..3661ee7 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -28,16 +28,16 @@ evaluated (primarily) at compile time. #### Characters and strings -| | Example | `#` sets | Characters | Escapes | -|----------------------------------------------|-----------------|-------------------|-------------|---------------------| -| [Character](#character-literals) | `'H'` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | -| [String](#string-literals) | `"hello"` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | -| [Raw string](#raw-string-literals) | `r#"hello"#` | <216\* | All Unicode | `N/A` | -| [Byte](#byte-literals) | `b'H'` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Byte string](#byte-string-literals) | `b"hello"` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | <216\* | All ASCII | `N/A` | - -\* The number of `#`s on each side of the same literal must be equivalent +| | Example | `#` sets\* | Characters | Escapes | +|----------------------------------------------|-----------------|-----------------|-------------|---------------------| +| [Character](#character-literals) | `'H'` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | +| [String](#string-literals) | `"hello"` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | +| [Raw string](#raw-string-literals) | `r#"hello"#` | <216 | All Unicode | `N/A` | +| [Byte](#byte-literals) | `b'H'` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Byte string](#byte-string-literals) | `b"hello"` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | <216 | All ASCII | `N/A` | + +\* The number of `#`s on each side of the same literal must be equivalent. #### ASCII escapes From 2720a722fdd7c9efcf213801b7232b3cb703ee91 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 21 Mar 2022 12:45:51 -0700 Subject: [PATCH 025/463] Use "An important consequence" language --- src/type-layout.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/type-layout.md b/src/type-layout.md index f45c960..ce92966 100644 --- a/src/type-layout.md +++ b/src/type-layout.md @@ -517,9 +517,9 @@ The alignments of each field, for the purpose of positioning fields, is the smaller of the specified alignment and the alignment of the field's type. Inter-field padding is guaranteed to be the minimum required in order to satisfy each field's (possibly altered) alignment (although note that, on its -own, `packed` does not provide any guarantee about field ordering). An -important special case is `#[repr(packed(1))]` (or `#[repr(packed)]`), which -guarantees that no inter-field padding will be present. +own, `packed` does not provide any guarantee about field ordering). An +important consequence of these rules is that a type with `#[repr(packed(1))]` +(or `#[repr(packed)]`) will have no inter-field padding. The `align` and `packed` modifiers cannot be applied on the same type and a `packed` type cannot transitively contain another `align`ed type. `align` and From 8fb199dfdec8b8c0cdeceadb6b7c3c1b72689aef Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 21 Mar 2022 21:09:56 +0000 Subject: [PATCH 026/463] Cover two missing cases of number pseudoliterals --- src/tokens.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 365c4e8..7a4dfce 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -487,9 +487,13 @@ Note that `-1.0`, for example, is analyzed as two tokens: `-` followed by `1.0`. > **Lexer**\ > NUMBER_PSEUDOLITERAL :\ ->       DEC_LITERAL ( . DEC_LITERAL)? FLOAT_EXPONENT NUMBER_PSEUDOLITERAL_SUFFIX\ ->    | DEC_LITERAL ( . DEC_LITERAL)? NUMBER_PSEUDOLITERAL_SUFFIX_NO_E\ ->    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) NUMBER_PSEUDOLITERAL_SUFFIX_NO_E +>       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_ @@ -509,6 +513,8 @@ Examples of such tokens: 2e5f80; 2e5e6; 2.0e5e6; +1.3e10u64; +0b1111_f32; ``` #### Reserved forms similar to number literals From 6ebfea2f7ceab5584b2489c77bb8487430110b65 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 22 Mar 2022 18:58:39 +0100 Subject: [PATCH 027/463] 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 915e9cb..c63371f 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 7a218edd55683f8789eba514e7d2b22fa5245a9f Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 22 Mar 2022 22:17:50 +0000 Subject: [PATCH 028/463] Make the FLOAT_LITERAL rule about final `.` more accurate The previous phrasing missed raw identifiers, raw string literals, and byte literals. Writing in terms of characters rather than tokens matches the implementation more closely. --- src/tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 7a4dfce..10bef7e 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -441,7 +441,7 @@ let horse = example.0b10; // ERROR no field named `0b10` > **Lexer**\ > FLOAT_LITERAL :\ >       DEC_LITERAL `.` -> _(not immediately followed by `.`, `_` or an [identifier] or [keyword][keywords]_)\ +> _(not immediately followed by `.`, `_` or an XID_Start character)_\ >    | DEC_LITERAL FLOAT_EXPONENT\ >    | DEC_LITERAL `.` DEC_LITERAL FLOAT_EXPONENT?\ >    | DEC_LITERAL (`.` DEC_LITERAL)? @@ -524,7 +524,7 @@ Examples of such tokens: >       BIN_LITERAL \[`2`-`9`​]\ >    | OCT_LITERAL \[`8`-`9`​]\ >    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) `.` \ ->          _(not immediately followed by `.`, `_` or an [identifier] or [keyword][keywords]_)\ +>          _(not immediately followed by `.`, `_` or an XID_Start character)_\ >    | ( BIN_LITERAL | OCT_LITERAL ) `e`\ >    | `0b` `_`\* _end of input or not BIN_DIGIT_\ >    | `0o` `_`\* _end of input or not OCT_DIGIT_\ From d51d4ea6051e869d12d09aae860cb2e37203a92a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 22 Mar 2022 22:29:33 +0000 Subject: [PATCH 029/463] Literal expressions: text improvements from ehuss --- src/expressions/literal-expr.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index e01ac17..9a61140 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -75,7 +75,7 @@ If the value does not fit in `u128`, the expression is rejected by the parser. * The `u128` value is converted to the expression's type via a [numeric cast]. > **Note**: The final cast will truncate the value of the literal if it does not fit in the expression's type. -> There is a [lint check] named `overflowing_literals`, defaulting to `deny`, which rejects expressions where this occurs. +> `rustc` includes a [lint check] named `overflowing_literals`, defaulting to `deny`, which rejects expressions where this occurs. > **Note**: `-1i8`, for example, is an application of the [negation operator] to the literal expression `1i8`, not a single integer literal expression. @@ -114,7 +114,7 @@ The value of the expression is determined from the string representation of the > **Note**: `inf` and `NaN` are not literal tokens. > The [`f32::INFINITY`], [`f64::INFINITY`], [`f32::NAN`], and [`f64::NAN`] constants can be used instead of literal expressions. -> A literal large enough to be evaluated as infinite will trigger the `overflowing_literals` lint check. +> In `rustc`, a literal large enough to be evaluated as infinite will trigger the `overflowing_literals` lint check. [constant expression]: ../const_eval.md#constant-expressions [floating-point types]: ../types/numeric.md#floating-point-types From d8ed83c48adf1999657981e9a057ea668a98a709 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 22 Mar 2022 22:31:33 +0000 Subject: [PATCH 030/463] tokens.md: add missing superscript markup --- src/tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 10bef7e..fba0da0 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -448,7 +448,7 @@ let horse = example.0b10; // ERROR no field named `0b10` > FLOAT_EXPONENT? FLOAT_SUFFIX > > FLOAT_EXPONENT :\ ->    (`e`|`E`) (`+`|`-`)? +>    (`e`|`E`) (`+`|`-`)? > (DEC_DIGIT|`_`)\* DEC_DIGIT (DEC_DIGIT|`_`)\* > > FLOAT_SUFFIX :\ @@ -529,7 +529,7 @@ Examples of such tokens: >    | `0b` `_`\* _end of input or not BIN_DIGIT_\ >    | `0o` `_`\* _end of input or not OCT_DIGIT_\ >    | `0x` `_`\* _end of input or not HEX_DIGIT_\ ->    | DEC_LITERAL ( . DEC_LITERAL)? (`e`|`E`) (`+`|`-`)? _end of input or not DEC_DIGIT_ +>    | DEC_LITERAL ( . DEC_LITERAL)? (`e`|`E`) (`+`|`-`)? _end of input or not DEC_DIGIT_ The following lexical forms similar to number literals are _reserved forms_: From efc44b2486d85438ba34852c6e666af735feea6b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 22 Mar 2022 22:40:33 +0000 Subject: [PATCH 031/463] Number pseudoliterals and reserved forms: text improvements from ehuss --- src/tokens.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index fba0da0..0db5583 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -501,7 +501,8 @@ Note that `-1.0`, for example, is analyzed as two tokens: `-` followed by `1.0`. > NUMBER_PSEUDOLITERAL_SUFFIX_NO_E :\ >    NUMBER_PSEUDOLITERAL_SUFFIX _not beginning with `e` or `E`_ -As described [above](#suffixes), tokens with the same form as numeric literals other than in the content of their suffix are accepted by the lexer (with the exception of some reserved forms described below). +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 such tokens: ```rust,compile_fail @@ -531,7 +532,8 @@ Examples of such tokens: >    | `0x` `_`\* _end of input or not HEX_DIGIT_\ >    | DEC_LITERAL ( . DEC_LITERAL)? (`e`|`E`) (`+`|`-`)? _end of input or not DEC_DIGIT_ -The following lexical forms similar to number literals are _reserved forms_: +The following lexical forms similar to number literals are _reserved forms_. +Due to the possible ambiguity these raise, they are rejected by the tokenizer instead of being interpreted as separate tokens. * An unsuffixed binary or octal literal followed, without intervening whitespace, by a decimal digit out of the range for its radix. @@ -543,8 +545,6 @@ The following lexical forms similar to number literals are _reserved forms_: * Input which has the form of a floating-point literal with no digits in the exponent. -Any input containing one of these reserved forms is reported as an error by the lexer. - Examples of reserved forms: ```rust,compile_fail From c88eca7b6816759aef355ebdbf1b9f85af1bf58d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 23 Mar 2022 19:55:14 +0000 Subject: [PATCH 032/463] Literal expressions: use a sublist when describing choice of radix --- src/expressions/literal-expr.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 9a61140..f6687eb 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -63,7 +63,12 @@ let a: u64 = 123; // type u64 The value of the expression is determined from the string representation of the token as follows: -* An integer radix is chosen by inspecting the first two characters of the string: `0b` indicates radix 2, `0o` indicates radix 8, `0x` indicates radix 16; otherwise the radix is 10. +* An integer radix is chosen by inspecting the first two characters of the string, as follows: + + * `0b` indicates radix 2 + * `0o` indicates radix 8 + * `0x` indicates radix 16 + * otherwise the radix is 10. * If the radix is not 10, the first two characters are removed from the string. From abe967481d0ee06d751e26a902abe6d5e393088e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 23 Mar 2022 20:07:52 +0000 Subject: [PATCH 033/463] Literal expressions: add placeholder sections for types not yet documented --- src/expressions/literal-expr.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index f6687eb..24552a9 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -26,6 +26,30 @@ Each of the lexical [literal][literal tokens] forms described earlier can make u 5; // integer type ``` +## Character literal expressions + +A character literal expression consists of a single [CHAR_LITERAL] token. + +> **Note**: This section is incomplete. + +## String literal expressions + +A string literal expression consists of a single [STRING_LITERAL] or [RAW_STRING_LITERAL] token. + +> **Note**: This section is incomplete. + +## Byte literal expressions + +A byte literal expression consists of a single [BYTE_LITERAL] token. + +> **Note**: This section is incomplete. + +## Byte string literal expressions + +A string literal expression consists of a single [BYTE_STRING_LITERAL] or [RAW_BYTE_STRING_LITERAL] token. + +> **Note**: This section is incomplete. + ## Integer literal expressions An integer literal expression consists of a single [INTEGER_LITERAL] token. @@ -121,6 +145,12 @@ The value of the expression is determined from the string representation of the > The [`f32::INFINITY`], [`f64::INFINITY`], [`f32::NAN`], and [`f64::NAN`] constants can be used instead of literal expressions. > In `rustc`, a literal large enough to be evaluated as infinite will trigger the `overflowing_literals` lint check. +## Boolean literal expressions + +A boolean literal expression consists of a single [BOOLEAN_LITERAL] token. + +> **Note**: This section is incomplete. + [constant expression]: ../const_eval.md#constant-expressions [floating-point types]: ../types/numeric.md#floating-point-types [lint check]: ../attributes/diagnostics.md#lint-check-attributes From 663b2c0f4cdab341e403127cb9ff496a77badd5b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 23 Mar 2022 17:02:16 -0700 Subject: [PATCH 034/463] Update aarch64 to use neon as fp --- src/attributes/codegen.md | 8 +++----- src/inline-assembly.md | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index dff4a67..4ebabac 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -148,7 +148,6 @@ Reference Manual], or elsewhere on [developer.arm.com]. > ***Note***: The following pairs of features should both be marked as enabled > or disabled together if used: -> - `fp` and `neon`, in order facilitate inlining in more places, among other reasons. > - `paca` and `pacg`, which LLVM currently implements as one feature. @@ -167,15 +166,14 @@ Feature | Implicitly Enables | Feature Name `fcma` | `neon` | FEAT_FCMA - Floating point complex number support `fhm` | `fp16` | FEAT_FHM - Half-precision FP FMLAL instructions `flagm` | | FEAT_FlagM - Conditional flag manipulation -`fp` | | FEAT_FP - Floating point extension -`fp16` | `fp`, `neon` | FEAT_FP16 - Half-precision FP data processing +`fp16` | `neon` | FEAT_FP16 - Half-precision FP data processing `frintts` | | FEAT_FRINTTS - Floating-point to int helper instructions `i8mm` | | FEAT_I8MM - Int8 Matrix Multiplication -`jsconv` | `fp`, `neon` | FEAT_JSCVT - JavaScript conversion instruction +`jsconv` | `neon` | FEAT_JSCVT - JavaScript conversion instruction `lse` | | FEAT_LSE - Large System Extension `lor` | | FEAT_LOR - Limited Ordering Regions extension `mte` | | FEAT_MTE - Memory Tagging Extension -`neon` | `fp` | FEAT_AdvSIMD - Advanced SIMD extension +`neon` | | FEAT_FP & FEAT_AdvSIMD - Floating Point and Advanced SIMD extension `pan` | | FEAT_PAN - Privileged Access-Never extension `paca` | | FEAT_PAuth - Pointer Authentication (address authentication) `pacg` | | FEAT_PAuth - Pointer Authentication (generic authentication) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index 243887b..073d741 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -204,7 +204,7 @@ The availability of supported types for a particular register class may depend o | x86 | `mmx_reg` | N/A | Only clobbers | | x86 | `x87_reg` | N/A | Only clobbers | | AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | -| AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | +| AArch64 | `vreg` | `neon` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | | AArch64 | `preg` | N/A | Only clobbers | | ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` | | ARM | `sreg` | `vfp2` | `i32`, `f32` | From 7f62788c1bdcf29f71fa7688d5b0e2705a653387 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 26 Mar 2022 10:08:52 -0400 Subject: [PATCH 035/463] 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 c4a9980..e5a0554 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 d0c717fa610a47a239da258eec111ed92dbc3fad Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 31 Mar 2022 13:30:40 +0200 Subject: [PATCH 036/463] Update 2^16 to 2^8 --- src/tokens.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index 3661ee7..d036c0d 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -28,14 +28,14 @@ evaluated (primarily) at compile time. #### Characters and strings -| | Example | `#` sets\* | Characters | Escapes | -|----------------------------------------------|-----------------|-----------------|-------------|---------------------| -| [Character](#character-literals) | `'H'` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | -| [String](#string-literals) | `"hello"` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | -| [Raw string](#raw-string-literals) | `r#"hello"#` | <216 | All Unicode | `N/A` | -| [Byte](#byte-literals) | `b'H'` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Byte string](#byte-string-literals) | `b"hello"` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | -| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | <216 | All ASCII | `N/A` | +| | Example | `#` sets\* | Characters | Escapes | +|----------------------------------------------|-----------------|------------|-------------|---------------------| +| [Character](#character-literals) | `'H'` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | +| [String](#string-literals) | `"hello"` | 0 | All Unicode | [Quote](#quote-escapes) & [ASCII](#ascii-escapes) & [Unicode](#unicode-escapes) | +| [Raw string](#raw-string-literals) | `r#"hello"#` | <256 | All Unicode | `N/A` | +| [Byte](#byte-literals) | `b'H'` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Byte string](#byte-string-literals) | `b"hello"` | 0 | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | <256 | All ASCII | `N/A` | \* The number of `#`s on each side of the same literal must be equivalent. From 00135bd4820680c08e7af17da2eed6499d211506 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 15 Feb 2022 18:33:15 +0800 Subject: [PATCH 037/463] Document compatibility between declarative and procedural macro tokens --- src/procedural-macros.md | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index 3b020b1..d983394 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -271,12 +271,73 @@ fn invoke4() {} // out: item: "fn invoke4() {}" ``` +### Declarative macro tokens and procedural macro tokens + +Declarative `macro_rules` macros and procedural macros use similar, but +different definitions for tokens (or rather [`TokenTree`s].) + +Token trees in `macro_rules` (corresponding to `tt` matchers) are defined as +- Delimited groups (`(...)`, `{...}`, etc) +- All operators supported by the language, both single-character and + multi-character ones (`+`, `+=`). + - Note that this set doesn't include the single quote `'`. +- Literals (`"string"`, `1`, etc) + - Note that negation (e.g. `-1`) is never a part of such literal tokens, + but a separate operator token. +- Identifiers, including keywords (`ident`, `r#ident`, `fn`) +- Lifetimes (`'ident`) +- Metavariable substitutions in `macro_rules` (e.g. `$my_expr` in + `macro_rules! mac { ($my_expr: expr) => { $my_expr } }` after the `mac`'s + expansion, which will be considered a single token tree regardless of the + passed expression) + +Token trees in procedural macros are defined as +- Delimited groups (`(...)`, `{...}`, etc) +- All punctuation characters used in operators supported by the language (`+`, + but not `+=`), and also the single quote `'` character (typically used in + lifetimes, see below for lifetime splitting and joining behavior) +- Literals (`"string"`, `1`, etc) + - Negation (e.g. `-1`) is supported as a part of integer + and floating point literals. +- Identifiers, including keywords (`ident`, `r#ident`, `fn`) + +Mismatches between these two definitions are accounted for when token streams +are passed to and from procedural macros. \ +Note that the conversions below may happen lazily, so they might not happen if +the tokens are not actually inspected. + +When passed to a proc-macro +- All multi-character operators are broken into single characters. +- Lifetimes are broken into a `'` character and an identifier. +- All metavariable substitutions are represented as their underlying token + streams. + - Such token streams may be wrapped into delimited groups ([`Group`]) with + implicit delimiters ([`Delimiter::None`]) when it's necessary for + preserving parsing priorities. + - `tt` and `ident` substitutions are never wrapped into such groups and + always represented as their underlying token trees. + +When emitted from a proc macro +- Punctuation characters are glued into multi-character operators + when applicable. +- Single quotes `'` joined with identifiers are glued into lifetimes. +- Negative literals are converted into two tokens (the `-` and the literal) + possibly wrapped into a delimited group ([`Group`]) with implicit delimiters + ([`Delimiter::None`]) when it's necessary for preserving parsing priorities. + +Note that neither declarative nor procedural macros support doc comment tokens +(e.g. `/// Doc`), so they are always converted to token streams representing +their equivalent `#[doc = r"str"]` attributes when passed to macros. + [Attribute macros]: #attribute-macros [Cargo's build scripts]: ../cargo/reference/build-scripts.html [Derive macros]: #derive-macros [Function-like macros]: #function-like-procedural-macros +[`Delimiter::None`]: ../proc_macro/enum.Delimiter.html#variant.None +[`Group`]: ../proc_macro/struct.Group.html [`TokenStream`]: ../proc_macro/struct.TokenStream.html [`TokenStream`s]: ../proc_macro/struct.TokenStream.html +[`TokenTree`s]: ../proc_macro/enum.TokenTree.html [`compile_error`]: ../std/macro.compile_error.html [`derive` attribute]: attributes/derive.md [`extern` blocks]: items/external-blocks.md From 4e2f926a2296528ae114734c1137a29b82b8585a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 1 Apr 2022 07:02:52 +0200 Subject: [PATCH 038/463] Update formal raw string literal token definition --- src/tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tokens.md b/src/tokens.md index d036c0d..ecd3b5a 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -197,7 +197,7 @@ following forms: >    | `#` RAW_STRING_CONTENT `#` Raw string literals do not process any escapes. They start with the character -`U+0072` (`r`), followed by zero or more of the character `U+0023` (`#`) and a +`U+0072` (`r`), followed by fewer than 256 of the character `U+0023` (`#`) and a `U+0022` (double-quote) character. The _raw string body_ can contain any sequence of Unicode characters and is terminated only by another `U+0022` (double-quote) character, followed by the same number of `U+0023` (`#`) characters that preceded @@ -288,7 +288,7 @@ following forms: >    _any ASCII (i.e. 0x00 to 0x7F)_ Raw byte string literals do not process any escapes. They start with the -character `U+0062` (`b`), followed by `U+0072` (`r`), followed by zero or more +character `U+0062` (`b`), followed by `U+0072` (`r`), followed by fewer than 256 of the character `U+0023` (`#`), and a `U+0022` (double-quote) character. The _raw string body_ can contain any sequence of ASCII characters and is terminated only by another `U+0022` (double-quote) character, followed by the same number of From 5795a4380e4db5b816c4db53c0e1ea9d714d9d84 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 15 Feb 2022 21:14:18 +0800 Subject: [PATCH 039/463] Document native library modifier syntax and the `whole-archive` modifier specifically --- src/items/external-blocks.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 9ad100f..84f8046 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -125,6 +125,15 @@ specifies the kind of library with the following possible values: The `name` key must be included if `kind` is specified. +The optional `modifiers` argument is a way to specify linking modifiers for the +library to link. +Modifiers are specified as a comma-delimited string with each modifier prefixed +with either a `+` or `-` to indicate that the modifier is enabled or disabled, +respectively. +Specifying multiple `modifiers` arguments in a single `link` attribute, +or multiple identical modifiers in the same `modifiers` argument is not currently supported. \ +Example: `#[link(name = "mylib", kind = "static", modifiers = "+whole-archive")`. + The `wasm_import_module` key may be used to specify the [WebAssembly module] name for the items within an `extern` block when importing symbols from the host environment. The default module name is `env` if `wasm_import_module` is @@ -153,6 +162,16 @@ 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: `whole-archive` + +This modifier is only compatible with the `static` linking kind. +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 `link_name` attribute The `link_name` attribute may be specified on declarations inside an `extern` @@ -186,3 +205,4 @@ 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 From 2f032766c236e495b8aab0e5358c66fcbfde349c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 3 Apr 2022 14:08:47 +0100 Subject: [PATCH 040/463] Document that unary negation of a signed integer literal cannot cause an overflow error --- src/expressions/literal-expr.md | 2 ++ src/expressions/operator-expr.md | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 24552a9..82363b7 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -107,6 +107,7 @@ If the value does not fit in `u128`, the expression is rejected by the parser. > `rustc` includes a [lint check] named `overflowing_literals`, defaulting to `deny`, which rejects expressions where this occurs. > **Note**: `-1i8`, for example, is an application of the [negation operator] to the literal expression `1i8`, not a single integer literal expression. +> See [Overflow] for notes on representing the most negative value for a signed type. ## Floating-point literal expressions @@ -159,6 +160,7 @@ A boolean literal expression consists of a single [BOOLEAN_LITERAL] token. [numeric types]: ../types/numeric.md [suffix]: ../tokens.md#suffixes [negation operator]: operator-expr.md#negation-operators +[overflow]: operator-expr.md#overflow [`f32::from_str`]: ../../core/primitive.f32.md#method.from_str [`f32::INFINITY`]: ../../core/primitive.f32.md#associatedconstant.INFINITY [`f32::NAN`]: ../../core/primitive.f32.md#associatedconstant.NAN diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index 94bd0ca..83e0e0a 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -22,12 +22,20 @@ Integer operators will panic when they overflow when compiled in debug mode. The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used to control this more directly. The following things are considered to be overflow: -* When `+`, `*` or `-` create a value greater than the maximum value, or less than the minimum value that can be stored. - This includes unary `-` on the smallest value of any signed integer type. +* When `+`, `*` or binary `-` create a value greater than the maximum value, or less than the minimum value that can be stored. +* Applying unary `-` to the most negative value of any signed integer type, unless the operand is a [literal expression] (or a literal expression standing alone inside one or more [grouped expressions][grouped expression]). * Using `/` or `%`, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is `-1`. These checks occur even when `-C overflow-checks` is disabled, for legacy reasons. * Using `<<` or `>>` where the right-hand argument is greater than or equal to the number of bits in the type of the left-hand argument, or is negative. +> **Note**: The exception for literal expressions behind unary `-` means that forms such as `-128_i8` or `let j: i8 = -(128)` never cause a panic and have the expected value of -128. +> +> In these cases, the literal expression already has the most negative value for its type (for example, `128_i8` has the value -128) because integer literals are truncated to their type per the description in [Integer literal expressions][literal expression]. +> +> Negation of these most negative values leaves the value unchanged due to two's complement overflow conventions. +> +> In `rustc`, these most negative expressions are also ignored by the `overflowing_literals` lint check. + ## Borrow operators > **Syntax**\ @@ -580,6 +588,8 @@ See [this test] for an example of using this dependency. [copies or moves]: ../expressions.md#moved-and-copied-types [dropping]: ../destructors.md +[grouped expression]: grouped-expr.md +[literal expression]: literal-expr.md#integer-literal-expressions [logical and]: ../types/boolean.md#logical-and [logical not]: ../types/boolean.md#logical-not [logical or]: ../types/boolean.md#logical-or From 59682e34c9061bbff0f00eb4e02dc0778492c86c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 7 Apr 2022 20:14:04 +0100 Subject: [PATCH 041/463] Stop defining a separate BOOLEAN_LITERAL token `true` and `false` are already listed as keywords. --- src/expressions/literal-expr.md | 7 +++---- src/patterns.md | 3 +-- src/tokens.md | 9 --------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 82363b7..5f00d0b 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -10,7 +10,7 @@ >    | [RAW_BYTE_STRING_LITERAL]\ >    | [INTEGER_LITERAL][^out-of-range]\ >    | [FLOAT_LITERAL]\ ->    | [BOOLEAN_LITERAL] +>    | `true` | `false` > > [^out-of-range]: A value ≥ 2128 is not allowed. @@ -18,7 +18,7 @@ A _literal expression_ is an expression consisting of a single token, rather tha A literal is a form of [constant expression], so is evaluated (primarily) at compile time. -Each of the lexical [literal][literal tokens] forms described earlier can make up a literal expression. +Each of the lexical [literal][literal tokens] forms described earlier can make up a literal expression, as can the keywords `true` and `false`. ```rust "hello"; // string type @@ -148,7 +148,7 @@ The value of the expression is determined from the string representation of the ## Boolean literal expressions -A boolean literal expression consists of a single [BOOLEAN_LITERAL] token. +A boolean literal expression consists of one of the keywords `true` or `false`. > **Note**: This section is incomplete. @@ -176,4 +176,3 @@ A boolean literal expression consists of a single [BOOLEAN_LITERAL] token. [RAW_BYTE_STRING_LITERAL]: ../tokens.md#raw-byte-string-literals [INTEGER_LITERAL]: ../tokens.md#integer-literals [FLOAT_LITERAL]: ../tokens.md#floating-point-literals -[BOOLEAN_LITERAL]: ../tokens.md#boolean-literals diff --git a/src/patterns.md b/src/patterns.md index e13f198..91b8a7f 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -122,7 +122,7 @@ if let (a, 3) = (1, 2) { // "(a, 3)" is refutable, and will not match > **Syntax**\ > _LiteralPattern_ :\ ->       [BOOLEAN_LITERAL]\ +>       `true` | `false`\ >    | [CHAR_LITERAL]\ >    | [BYTE_LITERAL]\ >    | [STRING_LITERAL]\ @@ -132,7 +132,6 @@ if let (a, 3) = (1, 2) { // "(a, 3)" is refutable, and will not match >    | `-`? [INTEGER_LITERAL]\ >    | `-`? [FLOAT_LITERAL] -[BOOLEAN_LITERAL]: tokens.md#boolean-literals [CHAR_LITERAL]: tokens.md#character-literals [BYTE_LITERAL]: tokens.md#byte-literals [STRING_LITERAL]: tokens.md#string-literals diff --git a/src/tokens.md b/src/tokens.md index 589d9ea..cdb4f07 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -560,15 +560,6 @@ Examples of reserved forms: 2.0em; // this is not a pseudoliteral, or `2.0` followed by `em` ``` -### Boolean literals - -> **Lexer**\ -> BOOLEAN_LITERAL :\ ->       `true`\ ->    | `false` - -The two values of the boolean type are written `true` and `false`. - ## Lifetimes and loop labels > **Lexer**\ From 7cb0d03d4ebee3d4548c9f80df302bcc0642ac82 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 7 Apr 2022 20:15:03 +0100 Subject: [PATCH 042/463] Document boolean literal expressions --- src/expressions/literal-expr.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/expressions/literal-expr.md b/src/expressions/literal-expr.md index 5f00d0b..4eec37d 100644 --- a/src/expressions/literal-expr.md +++ b/src/expressions/literal-expr.md @@ -150,8 +150,12 @@ The value of the expression is determined from the string representation of the A boolean literal expression consists of one of the keywords `true` or `false`. -> **Note**: This section is incomplete. +The expression's type is the primitive [boolean type], and its value is: + * true if the keyword is `true` + * false if the keyword is `false` + +[boolean type]: ../types/boolean.md [constant expression]: ../const_eval.md#constant-expressions [floating-point types]: ../types/numeric.md#floating-point-types [lint check]: ../attributes/diagnostics.md#lint-check-attributes From a3b48b8dd229c64aa91b5f95ff0ffe5e6b23abcb Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 11 Apr 2022 05:05:42 +0300 Subject: [PATCH 043/463] Fix typo: `?` should be inside `` tags --- src/paths.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/paths.md b/src/paths.md index 562a6f0..51bd8ca 100644 --- a/src/paths.md +++ b/src/paths.md @@ -88,7 +88,7 @@ Const arguments must be surrounded by braces unless they are a >    _QualifiedPathType_ (`::` _PathExprSegment_)+ > > _QualifiedPathType_ :\ ->    `<` [_Type_] (`as` _TypePath_)? `>` +>    `<` [_Type_] (`as` _TypePath_)? `>` > > _QualifiedPathInType_ :\ >    _QualifiedPathType_ (`::` _TypePathSegment_)+ From 54b732cb865363d42f209a5f409c49e3e9cabc00 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 12 Apr 2022 16:30:39 +0000 Subject: [PATCH 044/463] Inline assembly: Clarify references to quoted regs For `lateout` and similar operand direction specifiers, a quoted argument must be an explicit register name, per the EBNF grammar we give. As such, we should not use quotes when describing syntax used with register classes. Further, correct the EBNF: in EBNF, quoted strings are always terminals, but `""` is intended to be a nonterminal surrounded by literal (terminal) quotation marks. Moving the quotes to their own terminal symbols does require escaping, but makes the terminal/nonterminal distinction clearer. The only other place double-quotes are present in the grammar is inside `STRING_LITERAL`/`RAW_STRING_LITERAL`, so calling attention to this case is worthwhile for clarity. --- src/inline-assembly.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index 073d741..e2e78f5 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -41,7 +41,7 @@ The following ABNF specifies the general syntax: ```text format_string := STRING_LITERAL / RAW_STRING_LITERAL dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout" -reg_spec := / "" +reg_spec := / "\"" "\"" operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" reg_operand := dir_spec "(" reg_spec ")" operand_expr operand := reg_operand @@ -184,7 +184,7 @@ Here is the list of currently supported register classes: > > - On x86-64 the high byte registers (e.g. `ah`) are not available in the `reg_byte` register class. > -> - Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out("reg") _` or `lateout("reg") _`. +> - Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out() _` or `lateout() _`. Each register class has constraints on which value types they can be used with. This is necessary because the way a value is loaded into a register depends on its type. @@ -356,7 +356,7 @@ If all references to an operand already have modifiers then the warning is suppr ## ABI clobbers The `clobber_abi` keyword can be used to apply a default set of clobbers to an `asm!` block. -This will automatically insert the necessary clobber constraints as needed for calling a function with a particular calling convention: if the calling convention does not fully preserve the value of a register across a call then a `lateout("reg") _` is implicitly added to the operands list. +This will automatically insert the necessary clobber constraints as needed for calling a function with a particular calling convention: if the calling convention does not fully preserve the value of a register across a call then `lateout("...") _` is implicitly added to the operands list (where the `...` is replaced by the register's name). `clobber_abi` may be specified any number of times. It will insert a clobber for all unique registers in the union of all specified calling conventions. From 7983b2f707e93f1859be3d9c8dd0c524e69a004a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 17 Apr 2022 17:41:52 +0100 Subject: [PATCH 045/463] Document the Termination trait for main and tests --- src/attributes/testing.md | 23 ++++++++++++----------- src/crates-and-source-files.md | 31 ++++++++++++++++++++++++------- src/special-types-and-traits.md | 7 +++++++ 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/attributes/testing.md b/src/attributes/testing.md index e0181b1..63df999 100644 --- a/src/attributes/testing.md +++ b/src/attributes/testing.md @@ -9,16 +9,12 @@ enables the [`test` conditional compilation option]. The *`test` attribute* marks a function to be executed as a test. These functions are only compiled when in test mode. Test functions must be free, -monomorphic functions that take no arguments, and the return type must be one -of the following: +monomorphic functions that take no arguments, and the return type must implement the [`Termination`] trait, for example: * `()` -* `Result<(), E> where E: Error` - - - -> Note: The implementation of which return types are allowed is determined by -> the unstable [`Termination`] trait. +* `Result<(), E> where E: Debug` +* `!` + @@ -26,9 +22,12 @@ of the following: > Note: The test mode is enabled by passing the `--test` argument to `rustc` > or using `cargo test`. -Tests that return `()` pass as long as they terminate and do not panic. Tests -that return a `Result<(), E>` pass as long as they return `Ok(())`. Tests that -do not terminate neither pass nor fail. +The test harness calls the returned value's [`report`] method, and classifies the test as passed or failed depending on whether the resulting [`ExitCode`] represents successful termination. +In particular: +* Tests that return `()` pass as long as they terminate and do not panic. +* Tests that return a `Result<(), E>` pass as long as they return `Ok(())`. +* Tests that return `ExitCode::SUCCESS` pass, and tests that return `ExitCode::FAILURE` fail. +* Tests that do not terminate neither pass nor fail. ```rust # use std::io; @@ -85,5 +84,7 @@ fn mytest() { [_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax [_MetaNameValueStr_]: ../attributes.md#meta-item-attribute-syntax [`Termination`]: ../../std/process/trait.Termination.html +[`report`]: ../../std/process/trait.Termination.html#tymethod.report [`test` conditional compilation option]: ../conditional-compilation.md#test [attributes]: ../attributes.md +[`ExitCode`]: ../../std/process/struct.ExitCode.html diff --git a/src/crates-and-source-files.md b/src/crates-and-source-files.md index 494e454..6922b0e 100644 --- a/src/crates-and-source-files.md +++ b/src/crates-and-source-files.md @@ -103,15 +103,30 @@ This section has been moved to the [Preludes chapter](names/preludes.md). A crate that contains a `main` [function] can be compiled to an executable. If a `main` function is present, it must take no arguments, must not declare any [trait or lifetime bounds], must not have any [where clauses], and its return -type must be one of the following: +type must implement the [`Termination`] trait. -* `()` -* `Result<(), E> where E: Error` - - +```rust +fn main() {} +``` +```rust +fn main() -> ! { + std::process::exit(0); +} +``` +```rust +fn main() -> impl std::process::Termination { + std::process::ExitCode::SUCCESS +} +``` -> Note: The implementation of which return types are allowed is determined by -> the unstable [`Termination`] trait. +> **Note**: Types with implementations of [`Termination`] in the standard library include: +> +> * `()` +> * [`!`] +> * [`ExitCode`] +> * `Result<(), E> where E: Debug` +> * `Result where E: Debug` + @@ -143,11 +158,13 @@ or `_` (U+005F) characters. in the Owens and Flatt module system, or a *configuration* in Mesa. [Unicode alphanumeric]: ../std/primitive.char.html#method.is_alphanumeric +[`!`]: types/never.md [_InnerAttribute_]: attributes.md [_Item_]: items.md [_MetaNameValueStr_]: attributes.md#meta-item-attribute-syntax [_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 [`Termination`]: ../std/process/trait.Termination.html [attribute]: attributes.md [attributes]: attributes.md diff --git a/src/special-types-and-traits.md b/src/special-types-and-traits.md index 4bb4e65..ca53b3c 100644 --- a/src/special-types-and-traits.md +++ b/src/special-types-and-traits.md @@ -92,6 +92,10 @@ The [`Sync`] trait indicates that a value of this type is safe to share between multiple threads. This trait must be implemented for all types used in immutable [`static` items]. +## `Termination` + +The [`Termination`] trait indicates the acceptable return types for the [main function] and [test functions]. + ## Auto traits The [`Send`], [`Sync`], [`Unpin`], [`UnwindSafe`], and [`RefUnwindSafe`] traits are _auto @@ -151,6 +155,7 @@ These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound [`std::cmp`]: ../std/cmp/index.html [`std::marker::PhantomData`]: ../std/marker/struct.PhantomData.html [`std::ops`]: ../std/ops/index.html +[`Termination`]: ../std/process/trait.Termination.html [`UnwindSafe`]: ../std/panic/trait.UnwindSafe.html [`Sync`]: ../std/marker/trait.Sync.html [`Unpin`]: ../std/marker/trait.Unpin.html @@ -168,11 +173,13 @@ These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound [implementation items]: items/implementations.md [indexing expressions]: expressions/array-expr.md#array-and-slice-indexing-expressions [interior mutability]: interior-mutability.md +[main function]: crates-and-source-files.md#main-functions [Methods]: items/associated-items.md#associated-functions-and-methods [method resolution]: expressions/method-call-expr.md [operators]: expressions/operator-expr.md [orphan rules]: items/implementations.md#trait-implementation-coherence [`static` items]: items/static-items.md +[test functions]: attributes/testing.md#the-test-attribute [the standard library]: ../std/index.html [trait object]: types/trait-object.md [Tuples]: types/tuple.md From ea1e00e3b67c9e620a2d7c7c5d3f2b4f861b7b7d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 15 Feb 2022 21:50:35 -0500 Subject: [PATCH 046/463] 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 6966cec..a9a63da 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 048edbcb191cbd0701cf8ff2dc91c10f00e4ddba Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 20 Apr 2022 17:16:30 -0700 Subject: [PATCH 047/463] 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 a9a63da..3f6173e 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 831db02a8f42f0c67f7cb2fc0a8601b64f6d2f53 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 1 May 2022 17:19:45 +0100 Subject: [PATCH 048/463] functions.md: one sentence per line for the first section --- src/items/functions.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/items/functions.md b/src/items/functions.md index 8142210..9bbcb6d 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -43,15 +43,11 @@ > in an associated function of a [trait item] in the 2015 edition. A _function_ consists of a [block], along with a name and a set of parameters. -Other than a name, all these are optional. Functions are declared with the -keyword `fn`. Functions may declare a set of *input* [*variables*][variables] -as parameters, through which the caller passes arguments into the function, and -the *output* [*type*][type] of the value the function will return to its caller -on completion. - -When referred to, a _function_ yields a first-class *value* of the -corresponding zero-sized [*function item type*], which -when called evaluates to a direct call to the function. +Other than a name, all these are optional. +Functions are declared with the keyword `fn`. +Functions may declare a set of *input* [*variables*][variables] as parameters, through which the caller passes arguments into the function, and the *output* [*type*][type] of the value the function will return to its caller on completion. + +When referred to, a _function_ yields a first-class *value* of the corresponding zero-sized [*function item type*], which when called evaluates to a direct call to the function. For example, this is a simple function: ```rust From b67f5c71e0e0e52147a190d6434d21019ff55140 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 1 May 2022 17:23:01 +0100 Subject: [PATCH 049/463] functions.md: state that the default return type is the unit type --- src/items/functions.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/items/functions.md b/src/items/functions.md index 9bbcb6d..adffd2a 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -42,10 +42,11 @@ > [^fn-param-2015]: Function parameters with only a type are only allowed > in an associated function of a [trait item] in the 2015 edition. -A _function_ consists of a [block], along with a name and a set of parameters. +A _function_ consists of a [block], along with a name, a set of parameters, and an output type. Other than a name, all these are optional. Functions are declared with the keyword `fn`. Functions may declare a set of *input* [*variables*][variables] as parameters, through which the caller passes arguments into the function, and the *output* [*type*][type] of the value the function will return to its caller on completion. +If the output type is not explicitly stated, it is the [unit type]. When referred to, a _function_ yields a first-class *value* of the corresponding zero-sized [*function item type*], which when called evaluates to a direct call to the function. @@ -387,6 +388,7 @@ fn foo_oof(#[some_inert_attribute] arg: u8) { [block]: ../expressions/block-expr.md [variables]: ../variables.md [type]: ../types.md#type-expressions +[unit type]: ../types/tuple.md [*function item type*]: ../types/function-item.md [Trait]: traits.md [attributes]: ../attributes.md From 7416ae3e16ded3bf1f24348a454cdb53b05883c1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 4 May 2022 08:43:43 -0400 Subject: [PATCH 050/463] Fix crate_type attribute examples As a crate-level attribute, this must be an inner attribute. --- src/linkage.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/linkage.md b/src/linkage.md index 2ffc052..b152005 100644 --- a/src/linkage.md +++ b/src/linkage.md @@ -15,13 +15,13 @@ through the usage of either command line flags or the `crate_type` attribute. If one or more command line flags are specified, all `crate_type` attributes will be ignored in favor of only building the artifacts specified by command line. -* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be +* `--crate-type=bin`, `#![crate_type = "bin"]` - A runnable executable will be produced. This requires that there is a `main` function in the crate which will be run when the program begins executing. This will link in all Rust and native dependencies, producing a single distributable binary. This is the default crate type. -* `--crate-type=lib`, `#[crate_type = "lib"]` - A Rust library will be produced. +* `--crate-type=lib`, `#![crate_type = "lib"]` - A Rust library will be produced. This is an ambiguous concept as to what exactly is produced because a library can manifest itself in several forms. The purpose of this generic `lib` option is to generate the "compiler recommended" style of library. The output library @@ -30,14 +30,14 @@ be ignored in favor of only building the artifacts specified by command line. libraries, and the `lib` type can be seen as an alias for one of them (but the actual one is compiler-defined). -* `--crate-type=dylib`, `#[crate_type = "dylib"]` - A dynamic Rust library will +* `--crate-type=dylib`, `#![crate_type = "dylib"]` - A dynamic Rust library will be produced. This is different from the `lib` output type in that this forces dynamic library generation. The resulting dynamic library can be used as a dependency for other libraries and/or executables. This output type will create `*.so` files on Linux, `*.dylib` files on macOS, and `*.dll` files on Windows. -* `--crate-type=staticlib`, `#[crate_type = "staticlib"]` - A static system +* `--crate-type=staticlib`, `#![crate_type = "staticlib"]` - A static system library will be produced. This is different from other library outputs in that the compiler will never attempt to link to `staticlib` outputs. The purpose of this output type is to create a static library containing all of @@ -47,13 +47,13 @@ be ignored in favor of only building the artifacts specified by command line. linking Rust code into an existing non-Rust application because it will not have dynamic dependencies on other Rust code. -* `--crate-type=cdylib`, `#[crate_type = "cdylib"]` - A dynamic system +* `--crate-type=cdylib`, `#![crate_type = "cdylib"]` - A dynamic system library will be produced. This is used when compiling a dynamic library to be loaded from another language. This output type will create `*.so` files on Linux, `*.dylib` files on macOS, and `*.dll` files on Windows. -* `--crate-type=rlib`, `#[crate_type = "rlib"]` - A "Rust library" file will be +* `--crate-type=rlib`, `#![crate_type = "rlib"]` - A "Rust library" file will be produced. This is used as an intermediate artifact and can be thought of as a "static Rust library". These `rlib` files, unlike `staticlib` files, are interpreted by the compiler in future linkage. This essentially means @@ -61,7 +61,7 @@ be ignored in favor of only building the artifacts specified by command line. in dynamic libraries. This form of output is used to produce statically linked executables as well as `staticlib` outputs. -* `--crate-type=proc-macro`, `#[crate_type = "proc-macro"]` - The output +* `--crate-type=proc-macro`, `#![crate_type = "proc-macro"]` - The output produced is not specified, but if a `-L` path is provided to it then the compiler will recognize the output artifacts as a macro and it can be loaded for a program. Crates compiled with this crate type must only export From e065c6035e6489b559aecd09cc1097ea33a7a548 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 4 May 2022 14:51:03 -0400 Subject: [PATCH 051/463] Dyn traits must also be used --- src/attributes/diagnostics.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index dd07fdb..1dd9363 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -236,7 +236,7 @@ five(); ``` When used on a [trait declaration], a [call expression] of an [expression -statement] to a function that returns an [impl trait] of that trait violates +statement] to a function that returns an [impl trait] or a [dyn trait] of that trait violates the `unused_must_use` lint. ```rust @@ -309,6 +309,7 @@ When used on a function in a trait implementation, the attribute does nothing. [attributes]: ../attributes.md [block expression]: ../expressions/block-expr.md [call expression]: ../expressions/call-expr.md +[dyn trait]: ../types/trait-object.md [enum variant]: ../items/enumerations.md [enum]: ../items/enumerations.md [expression statement]: ../statements.md#expression-statements From 3e0bf480b43b0476f4fe6cc35fc0b0da8e6844a4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 5 May 2022 12:11:01 +0200 Subject: [PATCH 052/463] Don't use PathPattern in RangePattern bounds The use of `PathPattern` instead of `PathExpression` in `RangePattern` is IMO confusing, since these values are not patterns and are not represented as patterns in the AST. --- src/patterns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patterns.md b/src/patterns.md index 91b8a7f..5c81ecd 100644 --- a/src/patterns.md +++ b/src/patterns.md @@ -423,7 +423,7 @@ match tuple { >    | [BYTE_LITERAL]\ >    | `-`? [INTEGER_LITERAL]\ >    | `-`? [FLOAT_LITERAL]\ ->    | [_PathPattern_] +>    | [_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 From eb3c2a853ac23fe7b2b4279907ec1b5a1b58014e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 5 May 2022 12:19:05 +0100 Subject: [PATCH 053/463] Inline assembly: Add kreg0 register class This was added by https://github.com/rust-lang/rust/pull/95740. --- src/inline-assembly.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index 073d741..dc4bc54 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -159,6 +159,7 @@ Here is the list of currently supported register classes: | x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` | | x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` | | x86 | `kreg` | `k[1-7]` | `Yk` | +| x86 | `kreg0` | `k0` | Only clobbers | | x86 | `x87_reg` | `st([0-7])` | Only clobbers | | x86 | `mmx_reg` | `mm[0-7]` | Only clobbers | | AArch64 | `reg` | `x[0-30]` | `r` | @@ -285,7 +286,6 @@ Some registers cannot be used for input or output operands: | All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V) | The frame pointer cannot be used as an input or output. | | ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. | | All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64), `x9` (RISC-V) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | -| x86 | `k0` | This is a constant zero register which can't be modified. | | x86 | `ip` | This is the program counter, not a real register. | | AArch64 | `xzr` | This is a constant zero register which can't be modified. | | AArch64 | `x18` | This is an OS-reserved register on some AArch64 targets. | @@ -366,9 +366,9 @@ The following ABIs can be used with `clobber_abi`: | Architecture | ABI name | Clobbered registers | | ------------ | -------- | ------------------- | -| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | +| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[0-7]`, `st([0-7])` | +| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])` | +| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])` | | AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x18`\*, `x30`, `v[0-31]`, `p[0-15]`, `ffr` | | ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` | | RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` | From 51508ff075838ea7f91bc254d6eccb4290a9d5b4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 7 May 2022 11:11:58 +0100 Subject: [PATCH 054/463] Stop saying that const functions cannot use 'extern' --- src/items/functions.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/items/functions.md b/src/items/functions.md index adffd2a..f4837e0 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -216,8 +216,7 @@ Functions qualified with the `const` keyword are [const functions], as are [tuple struct] and [tuple variant] constructors. _Const functions_ can be called from within [const contexts]. -Const functions are not allowed to be [async](#async-functions), and cannot -use the [`extern` function qualifier](#extern-function-qualifier). +Const functions are not allowed to be [async](#async-functions). ## Async functions From e17fbfdef5e9b01ccaa54d64eab039900cc6d329 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 7 May 2022 16:06:45 -0400 Subject: [PATCH 055/463] Moved the option variant imports --- src/items/use-declarations.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/items/use-declarations.md b/src/items/use-declarations.md index f9695f5..e2e2027 100644 --- a/src/items/use-declarations.md +++ b/src/items/use-declarations.md @@ -35,13 +35,15 @@ Use declarations support a number of convenient shortcuts: An example of `use` declarations: ```rust -use std::option::Option::{Some, None}; use std::collections::hash_map::{self, HashMap}; fn foo(_: T){} fn bar(map1: HashMap, map2: hash_map::HashMap){} fn main() { + // use declarations can also exist inside of functions + use std::option::Option::{Some, None}; + // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64), // std::option::Option::None]);' foo(vec![Some(1.0f64), None]); From f6b6c55535097d410f9b7e1dfbe1752b76daf51d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 8 May 2022 21:57:31 +0300 Subject: [PATCH 056/463] 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 84f8046..dbe30cc 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 eaf6bc0a005c9f03428028c4268ef7de3eb217e2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 9 May 2022 12:24:33 +0100 Subject: [PATCH 057/463] 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 51bd8ca..cb6b24a 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 236873a4efa2a369f61be6e0b789bf1f11de76ae Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 9 May 2022 17:05:34 +0200 Subject: [PATCH 058/463] 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 c63371f..b2e80b5 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 06692cab9df1d4a28d2eea0eb372ba8d3716e513 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 9 May 2022 17:11:10 +0200 Subject: [PATCH 059/463] 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 b2e80b5..c236add 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 633a48375fcd89e4022fbe38217f9c85f035fcfb Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 9 May 2022 17:13:17 +0200 Subject: [PATCH 060/463] 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 c236add..467ad65 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 12cbe4edb0e683d23e656b46df94a8b3afa17fda Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 9 May 2022 19:34:15 +0100 Subject: [PATCH 061/463] Say that `const extern` functions can only use "Rust" or "C" --- src/items/functions.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/items/functions.md b/src/items/functions.md index f4837e0..6a2ab4e 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -216,6 +216,8 @@ Functions qualified with the `const` keyword are [const functions], as are [tuple struct] and [tuple variant] constructors. _Const functions_ can be called from within [const contexts]. +Const functions may use the [`extern`] function qualifier, but only with the `"Rust"` and `"C"` ABIs. + Const functions are not allowed to be [async](#async-functions). ## Async functions @@ -382,6 +384,7 @@ fn foo_oof(#[some_inert_attribute] arg: u8) { [const functions]: ../const_eval.md#const-functions [tuple struct]: structs.md [tuple variant]: enumerations.md +[`extern`]: #extern-function-qualifier [external block]: external-blocks.md [path]: ../paths.md [block]: ../expressions/block-expr.md From 2eb89c65a7e842b2d0417e474d6ba116b042988b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 13 May 2022 13:18:12 +0800 Subject: [PATCH 062/463] Update "Match Expressions" to remove 'cold' --- src/expressions/match-expr.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/expressions/match-expr.md b/src/expressions/match-expr.md index febf60c..edbc636 100644 --- a/src/expressions/match-expr.md +++ b/src/expressions/match-expr.md @@ -125,7 +125,7 @@ Moreover, by holding a shared reference while evaluating the guard, mutation ins ## Attributes on match arms Outer attributes are allowed on match arms. -The only attributes that have meaning on match arms are [`cfg`], [`cold`], and the [lint check attributes]. +The only attributes that have meaning on match arms are [`cfg`] and the [lint check attributes]. [Inner attributes] are allowed directly after the opening brace of the match expression in the same expression contexts as [attributes on block expressions]. @@ -135,7 +135,6 @@ The only attributes that have meaning on match arms are [`cfg`], [`cold`], and t [_InnerAttribute_]: ../attributes.md [_OuterAttribute_]: ../attributes.md [`cfg`]: ../conditional-compilation.md -[`cold`]: ../attributes/codegen.md#the-cold-attribute [lint check attributes]: ../attributes/diagnostics.md#lint-check-attributes [Range Expression]: range-expr.md From 88c4eb11b847c4b7b01c0d410cc45946fd7b0d4c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 16 May 2022 00:30:17 +0800 Subject: [PATCH 063/463] Update procedural-macros.md --- src/procedural-macros.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index d983394..1090ced 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -52,8 +52,9 @@ type, unlike `Vec`, is cheap to clone. All tokens have an associated `Span`. A `Span` is an opaque value that cannot be modified but can be manufactured. `Span`s represent an extent of source -code within a program and are primarily used for error reporting. You can modify -the `Span` of any token. +code within a program and are primarily used for error reporting. While you +cannot modify a `Span` itself, you can always change the `Span` associated with +any token. ### Procedural macro hygiene From d810bc3e019090d7fdb88df30e888c70b2df15ec Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 16 May 2022 00:34:33 +0800 Subject: [PATCH 064/463] italics makes everything clearer --- 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 1090ced..b1824af 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -53,8 +53,8 @@ type, unlike `Vec`, is cheap to clone. All tokens have an associated `Span`. A `Span` is an opaque value that cannot be modified but can be manufactured. `Span`s represent an extent of source code within a program and are primarily used for error reporting. While you -cannot modify a `Span` itself, you can always change the `Span` associated with -any token. +cannot modify a `Span` itself, you can always change the `Span` *associated* +with any token, such as through getting a `Span` from another token. ### Procedural macro hygiene From a76712dd762e83eff800c6b5e933437678f707ba Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 16 May 2022 22:11:12 +0800 Subject: [PATCH 065/463] Update procedural-macros.md --- src/procedural-macros.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/procedural-macros.md b/src/procedural-macros.md index b1824af..31f029a 100644 --- a/src/procedural-macros.md +++ b/src/procedural-macros.md @@ -53,7 +53,7 @@ type, unlike `Vec`, is cheap to clone. All tokens have an associated `Span`. A `Span` is an opaque value that cannot be modified but can be manufactured. `Span`s represent an extent of source code within a program and are primarily used for error reporting. While you -cannot modify a `Span` itself, you can always change the `Span` *associated* +cannot modify a `Span` itself, you can always change the `Span` *associated* with any token, such as through getting a `Span` from another token. ### Procedural macro hygiene From 5f217c20a4226c2d1dbbd48d8d3d1b006772e546 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 10 May 2022 23:19:09 +0200 Subject: [PATCH 066/463] Remove footnote on warning about lifetime shadowing labels. --- src/names/namespaces.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/names/namespaces.md b/src/names/namespaces.md index 1b07d9f..1481169 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -50,7 +50,7 @@ The following is a list of namespaces, with their corresponding entities: * [Attribute macros] * Lifetime Namespace * [Generic lifetime parameters] -* Label Namespace[^rustc-lifetime-shadow] +* Label Namespace * [Loop labels] An example of how overlapping names in different namespaces can be used unambiguously: @@ -115,12 +115,6 @@ For example, the [`cfg` attribute] and the [`cfg` macro] are two different entit It is still an error for a [`use` import] to shadow another macro, regardless of their sub-namespaces. -[^rustc-lifetime-shadow]: `rustc` currently warns about shadowing when using - the same name for a label and lifetime in the same scope, but it still - treats them independently. 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). - [`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute [`cfg` macro]: ../conditional-compilation.md#the-cfg-macro [`for`]: ../expressions/loop-expr.md#iterator-loops From 02abf1aab781cdb121d6813cc6de2359025e44b2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 18 May 2022 20:33:54 -0400 Subject: [PATCH 067/463] Add tile registers to inline-assembly documentation --- src/inline-assembly.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index dc4bc54..a5f4631 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -162,6 +162,7 @@ Here is the list of currently supported register classes: | x86 | `kreg0` | `k0` | Only clobbers | | x86 | `x87_reg` | `st([0-7])` | Only clobbers | | x86 | `mmx_reg` | `mm[0-7]` | Only clobbers | +| x86-64 | `tmm_reg` | `tmm[0-7]` | Only clobbers | | AArch64 | `reg` | `x[0-30]` | `r` | | AArch64 | `vreg` | `v[0-31]` | `w` | | AArch64 | `vreg_low16` | `v[0-15]` | `x` | @@ -204,6 +205,7 @@ The availability of supported types for a particular register class may depend o | x86 | `kreg` | `avx512bw` | `i32`, `i64` | | x86 | `mmx_reg` | N/A | Only clobbers | | x86 | `x87_reg` | N/A | Only clobbers | +| x86 | `tmm_reg` | N/A | Only clobbers | | AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | AArch64 | `vreg` | `neon` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | | AArch64 | `preg` | N/A | Only clobbers | @@ -367,8 +369,8 @@ The following ABIs can be used with `clobber_abi`: | Architecture | ABI name | Clobbered registers | | ------------ | -------- | ------------------- | | x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[0-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])` | +| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])`, `tmm[0-7]` | +| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[0-7]`, `st([0-7])`, `tmm[0-7]` | | AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x18`\*, `x30`, `v[0-31]`, `p[0-15]`, `ffr` | | ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` | | RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` | From a87c46f2bc42911ee2be1e9e771ec9658e20519c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 20 May 2022 03:53:33 +0300 Subject: [PATCH 068/463] Reflect changes about unsizing casts in const context Since Rust 1.61.0 it is possible to do unsizing casts in const context --- src/const_eval.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/const_eval.md b/src/const_eval.md index b46e94e..c056037 100644 --- a/src/const_eval.md +++ b/src/const_eval.md @@ -42,9 +42,8 @@ to be run. * The [dereference operator] except for raw pointers. * [Grouped] expressions. * [Cast] expressions, except - * pointer to address casts, - * function pointer to address casts, and - * unsizing casts to trait objects. + * 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. From d3e285b87299661d7dcc6eb72cd81a6b4c8ee89b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 20 May 2022 15:23:48 +0000 Subject: [PATCH 069/463] Fix confusion around clobbers and register classes --- src/inline-assembly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index e2e78f5..eeced6b 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -184,7 +184,7 @@ Here is the list of currently supported register classes: > > - On x86-64 the high byte registers (e.g. `ah`) are not available in the `reg_byte` register class. > -> - Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out() _` or `lateout() _`. +> - Some register classes are marked as "Only clobbers" which means that registers in these classes cannot be used for inputs or outputs, only clobbers of the form `out() _` or `lateout() _`. Each register class has constraints on which value types they can be used with. This is necessary because the way a value is loaded into a register depends on its type. From 210251fa993208d217425f5b86102a742a5e91cb Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 3 Jun 2022 16:49:45 +0200 Subject: [PATCH 070/463] 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 15b0b20..40f5a15 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 1b411cebb242a0a1461693c30fe9cb545f20a3d7 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 4 Jun 2021 05:07:50 -0700 Subject: [PATCH 071/463] 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 a68b27e..e3ab496 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 addbe0e..9bc07a6 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 5ffcd15..adea301 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 fd8f50c..46d3445 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 288781b..066faed 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 5c81ecd..5254a73 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 8d9c21d..753d01a 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 f284ca4..2aa41e5 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 575abe9c8885b6c3bb4d01ae40720f7a4f7f3172 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 21 Jun 2021 06:24:37 -0700 Subject: [PATCH 072/463] 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 066faed..25c8a53 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 9709058418323b60587a00b0fa1cdce33691fbe1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 26 Jun 2021 18:42:08 -0700 Subject: [PATCH 073/463] 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 25c8a53..617c1aa 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 887d55770b143f058a5106c216ecc6ec9691d72a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 30 Jun 2021 17:40:51 -0700 Subject: [PATCH 074/463] 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 9bc07a6..3d7f532 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 617c1aa..035676a 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 b4207f3517f39ea43bb4a409d3cc707652a72bd5 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 7 May 2022 12:24:17 -0700 Subject: [PATCH 075/463] 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 3d7f532..00639ac 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 035676a..012bb25 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 86bcd96f5e2120a1d98cbf444479e703e78b6284 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 3 Jun 2022 15:00:29 -0700 Subject: [PATCH 076/463] 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 012bb25..58ee99b 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 fbe2a73968f80f49643df584244fad7fad31977c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 11 Jun 2022 22:02:03 -0300 Subject: [PATCH 077/463] 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 2c49300..17a68f8 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 8745a8248d9120233a5c1710290cf3f92a87962e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 11 Jun 2022 22:41:39 -0300 Subject: [PATCH 078/463] 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 17a68f8..b70b94e 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 5cddcb9658ee5592a4e96a897107f138e551e9e3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 13 Jun 2022 08:14:31 +0200 Subject: [PATCH 079/463] 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 8f20636..5e7a591 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 4f5f77938a97f07e5758cb0f5020dc8c3906c0cf Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 21 Jun 2022 13:54:21 +0200 Subject: [PATCH 080/463] 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 a7ce5bc..aed10fd 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 779d9a8679fbd4e33f2e42d6de6ad65582cb23f8 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 24 Jun 2022 18:55:01 +0100 Subject: [PATCH 081/463] 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 0696692..a281d50 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 20ef0ddfa2fa2d6fcfd757d44b8eb11d06b7d102 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 1 Jul 2022 13:00:09 +0200 Subject: [PATCH 082/463] 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 e7fc45d..84cae07 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 4ff66ecad9ae14a407a0d19f9c263e65443b5869 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 11 Jul 2022 17:57:57 -0400 Subject: [PATCH 083/463] 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 e5a0554..e810e8c 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 3f583aa3eceaa3e33164319642e0a0a69965864a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 17 Jul 2022 08:45:34 -0400 Subject: [PATCH 084/463] 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 7ad5da7..325b227 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 3f96cc9..326e720 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 447bd64b7eb73db8c1766f0e4008a580cfccdb8f Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 3 Apr 2021 19:12:08 +0200 Subject: [PATCH 085/463] 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 83e0e0a..5a45080 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 f0f926c4652a22cccaf32ff3dbabb434b1dee2c2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 6 Apr 2021 14:22:25 +0200 Subject: [PATCH 086/463] 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 5a45080..410aa96 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 7c603dcbbc231e4e14397a7cdbb155b7da149661 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 6 Apr 2021 14:26:46 +0200 Subject: [PATCH 087/463] 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 5b40929..32ee658 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 410aa96..e3225dc 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 7866e557a4cf427ca1cc531210f8a9463ee01dc0 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 7 Apr 2021 14:50:14 +0200 Subject: [PATCH 088/463] 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 e3225dc..b2b6032 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 b60b626dbfa8ff31b6ed38183e82318ebf271441 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 27 Feb 2022 21:52:12 -0500 Subject: [PATCH 089/463] 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 b2b6032..d8658d6 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 c7a360e9969838e84112bf38a97f09dd3eebed46 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 21 Jul 2022 09:22:11 -0500 Subject: [PATCH 090/463] 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 40f5a15..7bca6c9 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 717c1d292c60637ba021aa421ec532a9ff0be932 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 21 Jul 2022 09:26:07 -0500 Subject: [PATCH 091/463] 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 ff15950..46074b4 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 e786d56..9146007 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 6a2ab4e..325588a 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 bb59108..b093972 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 47bda4f..9c8d80f 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 209b9bc..df9f05a 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 cad4a1b27d28e0212bf04c34852333c8178f1f3d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 22 Jul 2022 02:21:29 +0200 Subject: [PATCH 092/463] 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 b70b94e..2c49300 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 c3b5e3d4e99cf90a5b0552099ab284e17dd83bfb Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 21 Jul 2022 18:58:23 -0700 Subject: [PATCH 093/463] 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 84cae07..b52cda1 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 23c85f4074718e9de0057a19ea317f06956305a5 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 24 Jul 2022 10:21:19 +0200 Subject: [PATCH 094/463] 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 432a45a..fd7e2d3 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 8298247a12fe9dc34db545125723160b4277c640 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 25 Jul 2022 08:14:36 -0300 Subject: [PATCH 095/463] 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 591437f..c82cad3 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 308f3e3..5033a1c 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 9d6100e0167bdf9125ba01f8103df75766e4d300 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 25 Jul 2022 15:40:07 -0700 Subject: [PATCH 096/463] 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 82d70d0..6a8f724 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 729069d..d15836f 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 c056037..d735a20 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 6d616b3..083ed86 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 32ee658..5b6525f 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 a68b27e..01e6ef9 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 c82cad3..9de65df 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 5033a1c..d9458d5 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 8caeff2..e0643fe 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 fd8f50c..26bce0b 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 1481169..1c94745 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 5c81ecd..3a1c609 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 197c201..71a3527 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 16c0aae93249b0aa21f5246c64f45afbd2bd4583 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 27 Jul 2022 09:22:18 -0500 Subject: [PATCH 097/463] 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 7bca6c9..b31e25d 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 6e51ed43006b5a994320f857a99d46a280c8261e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 8 Aug 2022 14:49:20 +0800 Subject: [PATCH 098/463] 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 b52cda1..feea1a3 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 a5365a2b88b2dc863459e67b4a8ca1be229ed77f Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 8 Aug 2022 18:11:13 +0300 Subject: [PATCH 099/463] 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 dbe30cc..e768a15 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 a496bf9ddd299e8807aa21eaf19316183dcb80f2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 14 Aug 2022 14:15:35 +0200 Subject: [PATCH 100/463] 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 d15836f..7f08557 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 0d1c0a2cdebe0c3840832148506cff0bbaafba44 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 14 Aug 2022 21:00:49 +0000 Subject: [PATCH 101/463] 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 6a8f724..82d70d0 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 d15836f..729069d 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 d735a20..c056037 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 083ed86..6d616b3 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 5b6525f..32ee658 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 01e6ef9..a68b27e 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 9de65df..c82cad3 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 d9458d5..5033a1c 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 e0643fe..8caeff2 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 26bce0b..fd8f50c 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 1c94745..1481169 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 3a1c609..5c81ecd 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 71a3527..197c201 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 805e4f683067e14e8b29ab265aeb09ae09d27790 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 14 Aug 2022 21:00:55 +0000 Subject: [PATCH 102/463] 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 c82cad3..591437f 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 5033a1c..308f3e3 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 68c6515f4df5f5b1289cd5272d7a99b6dbb8e543 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Aug 2022 19:54:12 +0200 Subject: [PATCH 103/463] 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 7f08557..f378c4d 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 feadfb6a6334446f1db35450bb0d33642a280a21 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Aug 2022 21:47:56 +0100 Subject: [PATCH 104/463] 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 4ebabac..e18c867 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 9244db826c3df3ecb5c1b562c0477fc539b72a07 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Aug 2022 21:50:47 +0100 Subject: [PATCH 105/463] 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 e18c867..ff38f3d 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 ab755fa9b0d73b7116a31c05de556e0cec55c93a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Aug 2022 23:13:41 +0100 Subject: [PATCH 106/463] 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 857cd7d..194261c 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 ff38f3d..f75129d 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 8eca2f6f68e0901d28dc7f274bff7d04edb271d7 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 17 Aug 2022 08:16:50 +0100 Subject: [PATCH 107/463] 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 f75129d..925b9de 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 0932421286a7e08f2241b4edb2a6b159bad33f8f Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 19 Aug 2022 08:48:36 +0100 Subject: [PATCH 108/463] Add link reference --- src/attributes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/attributes.md b/src/attributes.md index 194261c..7da4238 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 967f6b299871d14f6302d599aeedd939be84deb5 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 19 Aug 2022 08:49:34 +0100 Subject: [PATCH 109/463] 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 925b9de..60f924d 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 84bef621c72ae9cb43c2a216b3244c8cd82c7d17 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 19 Aug 2022 09:01:48 +0100 Subject: [PATCH 110/463] 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 60f924d..57c1d5a 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 a136b9e31dec0e02a38816fc4550011442f5b85e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 19 Aug 2022 09:26:53 +0100 Subject: [PATCH 111/463] 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 7da4238..7da406b 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 976ba565c8231b55800a3fbd5ddcd6470890038c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 22 Aug 2022 18:04:32 +0200 Subject: [PATCH 112/463] 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 2bc218f..19b9afc 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 f073a08740f889f45ece684053778a9ca042df70 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 27 Aug 2022 13:39:39 +0100 Subject: [PATCH 113/463] 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 63df999..2c3b292 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 6922b0e..8d54c3f 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 5778dbfb866bbdad675ebf2ebe9d0882d03a5d5d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 3 Sep 2022 17:41:29 -0700 Subject: [PATCH 114/463] 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 ce92966..dc9bed9 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 9ee590c2a7697f17590ace62391602ba97c950b4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 5 Sep 2022 11:26:17 +0100 Subject: [PATCH 115/463] 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 a68b27e..3f18e67 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 d4d4e59aa88bfd3199fe01b8b4077e1bc44d125e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 6 Sep 2022 14:18:22 -0400 Subject: [PATCH 116/463] 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 b8909ac..4916b6f 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 6752207b539023abc4bf78a19dfb339b5197d9b8 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 8 Sep 2022 15:18:03 -0700 Subject: [PATCH 117/463] 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 5c81ecd..ea7beb3 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 c5fb1b350bd643421924efc8671e93c2a5305f54 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 8 Sep 2022 20:22:14 -0400 Subject: [PATCH 118/463] 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 4916b6f..bb5631f 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 d5311f58080352a5e4159fa7df3ca734589f5a56 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 8 Sep 2022 20:45:12 -0400 Subject: [PATCH 119/463] 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 f5dc31a..66db45b 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 ff0cc75..2b53076 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 9893cd957af6e6f9a083557c382da919458feaa1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 8 Sep 2022 21:47:36 -0400 Subject: [PATCH 120/463] 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 66db45b..48f0eca 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 5e6d8bbf9b4241bcd1370dac109349c0d62fd613 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 9 Sep 2022 19:57:12 -0400 Subject: [PATCH 121/463] 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 48f0eca..009ccd0 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 26870a0..3c5d31d 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 2b53076..74463ea 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 7a48b18862e1d008d32b11482bdfe80eace59b19 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 9 Sep 2022 20:21:18 -0400 Subject: [PATCH 122/463] 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 009ccd0..33eb4a7 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 d239537504a9135ab87c04635be4bbb15d9b5a8b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 9 Sep 2022 20:26:02 -0400 Subject: [PATCH 123/463] 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 74463ea..dd0efee 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 3319b96c202adab206e931a17fbfe463ef0c59b4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 11 Sep 2022 17:11:16 +0200 Subject: [PATCH 124/463] 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 32ee658..0c01238 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 6dc770b43ce06ce53b89ec56ae37712415d5e090 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 11 Sep 2022 21:55:36 -0400 Subject: [PATCH 125/463] 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 33eb4a7..d28ab6b 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 ba84d749a60047d549726f3802393d37028b3fcb Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 29 Jul 2022 10:26:06 -0700 Subject: [PATCH 126/463] 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 857cd7d..b7c1ef6 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 e768a15..e13ca54 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 e10f3cdd76ff07cab409ce5606be985dd5220051 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 13 Sep 2022 14:59:49 -0400 Subject: [PATCH 127/463] 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 bdc177b..103f747 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 8e1bca81c951b40dcb95163571b0765dee8a0cde Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 14 Jul 2022 08:49:47 -0500 Subject: [PATCH 128/463] 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 3f18e67..e46f2e8 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 308f3e3..d3c4d38 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 6f23a00bef879a39a434189d0cf3d7e9a2315469 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 16 Sep 2022 18:52:29 +0800 Subject: [PATCH 129/463] 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 6233475..996b157 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 2e9966d68cc68267cccc9eeda93209334b5186a1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 16 Sep 2022 10:10:46 -0400 Subject: [PATCH 130/463] 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 d28ab6b..97b2c20 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 c960ca0d7fe63c521e8e406e9da7e2a867c9352b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 16 Sep 2022 10:20:59 -0400 Subject: [PATCH 131/463] 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 dd0efee..5ab885a 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 aa99849da0ef40891650ca7a887bba05e79ca8b1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 18 Sep 2022 06:20:15 -0400 Subject: [PATCH 132/463] 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 97b2c20..4996ff7 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 998fe854f1a78859360937cd31401ca4e84867e7 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 19 Sep 2022 14:32:31 -0700 Subject: [PATCH 133/463] 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 467ad65..6154fe1 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 1201bcc3d5126b436899c328d7f693c7ff908a67 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 19 Sep 2022 16:18:44 -0700 Subject: [PATCH 134/463] 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 e13ca54..c91e1d1 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 1da0a271b51318dc35732cc77636dc42b0e62569 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 20 Sep 2022 08:24:17 +0800 Subject: [PATCH 135/463] 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 a4e972c..c760f68 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 04a29ea2348069130f29802635272504e0d3faa8 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 26 May 2022 02:00:53 +0300 Subject: [PATCH 136/463] 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 47bda4f..f627cdc 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 f017b9b6d0c838e0f5e2f72cba9ff34c7b9a1636 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 24 Sep 2022 08:25:06 -0400 Subject: [PATCH 137/463] 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 1dd9363..45f9cc4 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 9515bc9985ed4be287bf7b641d805b72f955027d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 11 Sep 2022 02:09:51 -0700 Subject: [PATCH 138/463] 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 ea7beb3..987a90d 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 92c0168f99a423a21adef4abc32203ce5bf8eba3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 25 Sep 2022 22:04:33 +0200 Subject: [PATCH 139/463] 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 e810e8c..10954a0 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 bbf5c77364185d382d74f6cb82313f62fce0c8d4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 26 Sep 2022 22:43:23 -0700 Subject: [PATCH 140/463] 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 987a90d..14bbac1 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 452d592e41873e8f6385a9f3c7ab6762d7bda406 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 27 Sep 2022 14:13:36 +0200 Subject: [PATCH 141/463] 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 197c201..8f9bcb1 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 9e7a8cb9eed682c879536a14aae81a555fa0d9c9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 27 Sep 2022 15:19:39 -0400 Subject: [PATCH 142/463] 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 e46f2e8..bd9c0a6 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 d3c4d38..204207e 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 f1f7dce465839cbf21b2dca0f66f82664dbc24ea Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 28 Sep 2022 17:31:50 +0200 Subject: [PATCH 143/463] 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 19b9afc..9fb3730 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 82d70d0..4d9cc1d 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 4ebabac..3a36a10 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 a51f761..82103be 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 7a5064c..0000000 --- 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 7542784..1c7b4c8 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 f71656a01386a643476db2f2768dabbc349675e2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 28 Sep 2022 18:11:43 -0400 Subject: [PATCH 144/463] 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 4996ff7..0bc1a2b 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 5ab885a..d2e14b9 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 a60ddf0501dd1ed163d0c13ab53b5f9661427c44 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 29 Sep 2022 15:45:27 +0200 Subject: [PATCH 145/463] 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 1c7b4c8..71e055c 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 9ea466196f053873e533e6cfbb1ea9464828e13b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 30 Sep 2022 11:09:25 +0200 Subject: [PATCH 146/463] 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 71e055c..5fa5dee 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 af02b02889c608dac4e29d09d0ec49785bd5c260 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 3 Oct 2022 18:57:35 -0400 Subject: [PATCH 147/463] 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 3f6173e..97840e4 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 b4d7f300ca7302f90877d6ca92f471b64ef6aeb3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 3 Feb 2022 19:31:43 +0100 Subject: [PATCH 148/463] 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 8d9c21d..67e77ef 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 4cdc75f9e64129e5ded2822d2c37d66b0790d5a6 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 20 Sep 2022 04:28:31 +0200 Subject: [PATCH 149/463] Add example --- src/statements.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/statements.md b/src/statements.md index 67e77ef..7acb0dc 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 bd6dc58f38a58a80ac7e5154524c0d924944c5af Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 26 Sep 2022 09:26:12 +0200 Subject: [PATCH 150/463] 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 325588a..5b4ac7a 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 a018c44b3d7d968b2aaf1be65969efccb33ab39e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 28 Sep 2022 16:51:48 -0700 Subject: [PATCH 151/463] 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 0c01238..b2411cd 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 692f3b8961e712dcec812130b1c962753c56370d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 28 Sep 2022 17:20:41 -0700 Subject: [PATCH 152/463] 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 b2411cd..0b446af 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 7acb0dc..c2ae585 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 b65b8fccedfb78f9f86c50fc0601eae8f5ce6a67 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 28 Sep 2022 17:21:45 -0700 Subject: [PATCH 153/463] 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 0b446af..b2411cd 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 b093972..fede411 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 14d6d4aebbe646866af278b85f671db1297b9c05 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 8 Oct 2022 11:43:07 +0900 Subject: [PATCH 154/463] 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 6d616b3..242d9b2 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 93e34af5e3c154db98af613c669ba04d4a9dbca1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 18 Oct 2022 20:14:44 -0400 Subject: [PATCH 155/463] 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 0bc1a2b..2401127 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 41016d5c3c4e99827b212dbd2fe00fc7e0b15d46 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 19 Oct 2022 11:46:48 +0200 Subject: [PATCH 156/463] 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 ca53b3c..6355f3f 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 a4342f8c9eef1dc2f777bc5b1b4857f446bd1e86 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 21 Oct 2022 04:57:01 +0200 Subject: [PATCH 157/463] 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 0ff7e2c..1ae2209 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 577a6ba80407adcbc6706fa5afd1d859b0aadcc9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 26 Oct 2022 20:17:48 +0900 Subject: [PATCH 158/463] 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 f284ca4..c8dab3f 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 e591df7e8683adb35b1a810ec39dd35b6eb334ba Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 14 Jul 2019 16:25:25 -0400 Subject: [PATCH 159/463] 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 d8658d6..2162163 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 28d3ba8..3b30cd4 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 522e710a367b21b845ad23c00ca136cd6a708848 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 15 Jul 2019 13:27:25 -0400 Subject: [PATCH 160/463] "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 3b30cd4..72c7820 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 a5155a979f27df1e31fb24997fb1e6a59283d00c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 4 Jul 2021 14:14:32 +0800 Subject: [PATCH 161/463] 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 72c7820..08c06cf 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 80a36ab..191567a 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 755e7bcd7771ee9871aa577078428c4bec59c22a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 19 Aug 2021 04:39:07 +0000 Subject: [PATCH 162/463] 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 c056037..34e34d7 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 08c06cf..b023991 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 a1e36650f8864e1983c93a4bb74fe509ce3d4cb5 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 28 Oct 2022 14:59:51 +0800 Subject: [PATCH 163/463] 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 2162163..99d815d 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 b023991..ff0a347 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 99f66a25c0a1ede622cc479545b5028f0dcdc144 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 31 Oct 2022 16:09:58 +0800 Subject: [PATCH 164/463] 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 5ffcd15..5b71707 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 a00519b9f9563cd58181d29f990645410a612e74 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 31 Oct 2022 11:24:39 +0100 Subject: [PATCH 165/463] 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 e810e8c..baa0645 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 61b252e3e086ad9e8e56e11b4377fb3f1aaa6882 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 31 Oct 2022 19:19:09 +0100 Subject: [PATCH 166/463] 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 baa0645..3f4e7d8 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 b99c9e37fdaf233d6956edf64b8c11db2f84e8d3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 31 Oct 2022 20:51:54 +0100 Subject: [PATCH 167/463] 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 3f4e7d8..12cbc43 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 df7dcc31b723def55290bf3cd69bb0a42acf332b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 1 Nov 2022 19:52:37 +0100 Subject: [PATCH 168/463] 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 12cbc43..6fc96a9 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 2b7207677ffac00b7ae20017be3b300f53386a1b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 1 Nov 2022 20:06:30 +0100 Subject: [PATCH 169/463] 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 6fc96a9..f8bffd1 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 e398e786756784f3278016dfa782929fe9bdcd35 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 4 Nov 2022 02:17:41 +0000 Subject: [PATCH 170/463] 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 46074b4..ad29c58 100644 --- a/src/comments.md +++ b/src/comments.md @@ -2,7 +2,7 @@ > **Lexer**\ > LINE_COMMENT :\ ->       `//` (~\[`/` `!`] | `//`) ~`\n`\*\ +>       `//` (~\[`/` `!` `\n`] | `//`) ~`\n`\*\ >    | `//` > > BLOCK_COMMENT :\ From aea65d73feb38586d6757f09e685fb86b11a5da4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 13 Nov 2022 15:43:18 +0300 Subject: [PATCH 171/463] 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 c91e1d1..d895369 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 6058f38832f4cb6c268bcb80475a946a6432f1fe Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 15 Nov 2022 12:32:20 +0100 Subject: [PATCH 172/463] 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 2c49300..8617791 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 b66477d643d6b145455b85946fa3cde2b0890738 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 15 Nov 2022 21:25:08 +0100 Subject: [PATCH 173/463] 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 8617791..cd9dc34 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 86f97aee34cc16d3f9ea73472f517d7643c1110f Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 16 Nov 2022 17:44:56 -0800 Subject: [PATCH 174/463] 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 57c1d5a..56840c4 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 8dcacf638526cfbf66444fccb2f0e0aacc3dd776 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 175/463] 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 4eec37d..ac42dab 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 3dc11d34722e4efb2a95b4dc73ad5fc919ffd0b5 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 176/463] 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 8f9bcb1..39b95cd 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 b601c82218f253051c1bf76ce458c8e6b512719b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 177/463] 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 39b95cd..ef1f07c 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 a935884a90f874e897b7cb3c4b8dfbefd24dc901 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 178/463] 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 ac42dab..e5bc2df 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 ef1f07c..721c4ad 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 5cea76422099b614da5d98156331b0a1a15e8b54 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 20 Nov 2022 11:59:45 +0000 Subject: [PATCH 179/463] 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 721c4ad..0067b64 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 eb3431893d54654ae79c194e910021424a6f67d0 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 23 Nov 2022 09:43:02 -0700 Subject: [PATCH 180/463] 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 69ad341..27230e4 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 d477ac4dbccf6202247b8712d1d6f457048593fd Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 27 Nov 2022 18:46:08 -0500 Subject: [PATCH 181/463] 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 c91e1d1..5454f8e 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 50e2cc7117fc05f2d8e412837ab22c69e04e5ac6 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 30 Nov 2022 21:27:06 +0800 Subject: [PATCH 182/463] 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 f4dc735..d6b3a9a 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 ee267197c71ee1d2586ee81c53fa91704b05d4c9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 21 Feb 2024 13:20:15 -0800 Subject: [PATCH 349/463] 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 d5af503..d3fa33b 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 951cd06394d85e5d057a73d9e294bb8994430d22 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 27 Feb 2024 21:52:50 +0000 Subject: [PATCH 350/463] 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 c4811a6..c92e2dc 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 c5a327288268c83b987160dbc440270143d03d92 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 3 Mar 2024 15:20:34 +0100 Subject: [PATCH 351/463] underscore-expr: add more examples --- src/expressions/underscore-expr.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/expressions/underscore-expr.md b/src/expressions/underscore-expr.md index 3d17040..d68c6a9 100644 --- a/src/expressions/underscore-expr.md +++ b/src/expressions/underscore-expr.md @@ -10,10 +10,25 @@ side of an assignment. Note that this is distinct from the [wildcard pattern](../patterns.md#wildcard-pattern). -An example of an `_` expression: +Examples of `_` expressions: ```rust let p = (1, 2); let mut a = 0; (_, a) = p; + +struct Position { + x: u32, + y: u32, +} + +Position { x: a, y: _ } = Position{ x: 2, y: 3 }; + +// unused result, assignment to `_` used to declare intent and remove a warning +_ = 2 + 2; +// triggers unused_must_use warning +// 2 + 2; + +// equivalent technique using a wildcard pattern in a let-binding +let _ = 2 + 2; ``` From 6aa529b61823e01722d263996bdb50e15d08a537 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 4 Mar 2024 21:32:01 +0000 Subject: [PATCH 352/463] 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 cf76e72..eded55e 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 21e00b1d13d482173e747a9cb8e45cd272add306 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 7 Mar 2024 19:36:58 +0000 Subject: [PATCH 353/463] 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 828758c..39b9445 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 0a84cd55887ed8386c591916e795b4a912a40b74 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 8 Mar 2024 11:42:32 -0500 Subject: [PATCH 354/463] 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 39b9445..7a851f3 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 74520ac613b2425db131ce842a0e50b7973d8fb3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 8 Mar 2024 11:42:50 -0500 Subject: [PATCH 355/463] 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 7a851f3..dbc73c4 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 4c36dda8e26bbab832353c76d1e53348cc5f734b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 18 Jan 2024 08:08:27 +0100 Subject: [PATCH 356/463] 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 a1ad5c6..3b26a31 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 506e284..142b78f 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 9ccc379bf29e818e9f36a2520ab36428c1fe5c9c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 19 Jan 2024 08:11:40 +0000 Subject: [PATCH 357/463] 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 3b26a31..1218fcb 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 142b78f..a704368 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 988c9f7070f259883efd41ca960ccf622e23cddd Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 19 Jan 2024 09:43:09 +0100 Subject: [PATCH 358/463] 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 a704368..c0c5c82 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 7f7a17549bb3a6f8b1de5e51a46c0a7f86ff39d3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 12 Mar 2024 09:21:17 -0700 Subject: [PATCH 359/463] 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 c0c5c82..45ed645 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 71d721e9256ac3c98e17dfc7e7f4a55ee5eba744 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 19 Mar 2024 19:36:32 +0000 Subject: [PATCH 360/463] 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 5a74425..2d8d5f9 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 1d49bfe9d04a29df8a8c738f383ee4e3c1918367 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 24 Mar 2024 14:02:49 +0900 Subject: [PATCH 361/463] 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 946e678..8d921bf 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 4320782e7bdab0386215d2bba0264850f3231717 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 30 Mar 2024 23:14:03 +0300 Subject: [PATCH 362/463] 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 7d69ab7..32b847c 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 f01fd88420c29cd51c26631aee151751268dcc79 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 3 Apr 2024 14:29:34 -0700 Subject: [PATCH 363/463] 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 45ed645..c636a96 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 618b19cee71a1c2b0942fe4dace22122c1510fc9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 14 Apr 2024 14:07:07 +0100 Subject: [PATCH 364/463] 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 348f92f..76ec6fd 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 4c3d948d610715cf2147dee587d3a39d9c20eea4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 14 Apr 2024 08:45:19 -0700 Subject: [PATCH 365/463] 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 71b0243..6ff83d0 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 407e2fd12ec6ff50f698806bc585d1f45d8dc5bf Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 15 Apr 2024 11:13:52 -0700 Subject: [PATCH 366/463] =?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 6ff83d0..dd3ea98 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 8afd73e083523a0470c2064b9b80607ded1f2a06 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Apr 2024 06:55:59 +0100 Subject: [PATCH 367/463] 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 6355f3f..cadced5 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 f368b3dc42aef3bdd7801ddf9a8ce3537d0a1812 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Apr 2024 09:35:51 -0700 Subject: [PATCH 368/463] 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 c21ab62..c53e9d0 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 a220bce915c2efa4eeae48fa98710c7a1f5ca04e Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 17 Apr 2024 08:04:47 -0700 Subject: [PATCH 369/463] 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 cadced5..21cab3d 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 bdd9f11f1d44957b34d85f4148630e0099358d75 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 27 Apr 2024 10:53:08 -0700 Subject: [PATCH 370/463] 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 60dc16b..6d184e8 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 7c74dfd8abf84a6b6f4916eaafde6a12f4c45675 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 7 Nov 2022 04:53:59 +0000 Subject: [PATCH 371/463] 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 34e34d7..af8d486 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 ad4cc5f..9e10dce 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 bd9c0a6..c12e1de 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 51aa919..014fb85 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 6344eab3e7969d11d0324f3824834a882feb374a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 1 May 2024 14:34:32 -0700 Subject: [PATCH 372/463] Remove outdated info about impl Trait and generics in the same function --- src/types/impl-trait.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/types/impl-trait.md b/src/types/impl-trait.md index b46c209..0269098 100644 --- a/src/types/impl-trait.md +++ b/src/types/impl-trait.md @@ -48,10 +48,7 @@ That is, `impl Trait` in argument position is syntactic sugar for a generic type > **Note:** > For function parameters, generic type parameters and `impl Trait` are not exactly equivalent. > With a generic parameter such as ``, the caller has the option to explicitly specify the generic argument for `T` at the call site using [_GenericArgs_], for example, `foo::(1)`. -> If `impl Trait` is the type of *any* function parameter, then the caller can't ever provide any generic arguments when calling that function. -This includes generic arguments for the return type or any const generics. -> -> Therefore, changing the function signature from either one to the other can constitute a breaking change for the callers of a function. +> Changing a parameter from either one to the other can constitute a breaking change for the callers of a function, since this changes the number of generic arguments. ## Abstract return types From 3bc9fa35826d0631c08bd2ef6d1e8ebcfbbf9ae5 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 3 May 2024 16:08:14 +0200 Subject: [PATCH 373/463] mention associated consts --- src/patterns.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/patterns.md b/src/patterns.md index e9eb13d..96bd827 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 24d01ba7663a0b86d3c7b138ea8f2be5776bc100 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 7 May 2024 08:15:24 +0200 Subject: [PATCH 374/463] clarifications --- src/patterns.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patterns.md b/src/patterns.md index 96bd827..b413c59 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 7d5ac61d6ca8f04129adbb22129bcc8bea9f4d68 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 22 Mar 2024 23:35:01 +0100 Subject: [PATCH 375/463] 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 c92e2dc..4e68e0a 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 ba5e1761492c5b99a8eae917ec431db7fc4c20fa Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 8 May 2024 09:50:26 -0700 Subject: [PATCH 376/463] 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 c12e1de..890cf85 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 bcc4c3ee2c51cf79998f2d8862462ea58af03445 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 10 May 2024 08:52:15 +0200 Subject: [PATCH 377/463] 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 890cf85..0dda00c 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 0909c5d..0707e9d 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 From a4073edb168519e6309d76ce2f2b2aadd8322d32 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 19 May 2024 06:53:59 +0200 Subject: [PATCH 378/463] Update recognized tool attributes --- src/attributes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/attributes.md b/src/attributes.md index 5ce6313..9ce8166 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -196,7 +196,8 @@ struct S { pub fn f() {} ``` -> Note: `rustc` currently recognizes the tools "clippy", "rustfmt" and "diagnostic". +> Note: `rustc` currently recognizes the tools "clippy", "rustfmt", "diagnostic", +> "miri" and "rust_analyzer". ## Built-in attributes index From a33810e5550cd686ab47c7bbd1166ab15d69b569 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 23 May 2024 07:34:33 +0200 Subject: [PATCH 379/463] elaborate on slice wide pointer metadata --- src/behavior-considered-undefined.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 756b86d..15eb9d1 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -72,11 +72,14 @@ Please read the [Rustonomicon] before writing unsafe code. * An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer obtained from [uninitialized memory][undef], or uninitialized memory in a `str`. * A reference or `Box` that is [dangling], misaligned, or points to an invalid value. - * Invalid metadata in a wide reference, `Box`, or raw pointer: + * Invalid metadata in a wide reference, `Box`, or raw pointer. The requirement + for the metadata is determined by the type of the unsized tail: * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for `Trait` that matches the actual dynamic trait the pointer or reference points to. * Slice metadata is invalid if the length is not a valid `usize` (i.e., it must not be read from uninitialized memory). + Furthermore, for wide references and `Box`, slice metadata is invalid + if it makes the total size of the pointed-to value bigger than `isize::MAX`. * Invalid values for a type with a custom definition of invalid values. In the standard library, this affects [`NonNull`] and [`NonZero*`]. From 701b2b28e9393790aa491ae1aea284b95f9f1efa Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 26 May 2024 09:37:46 +0200 Subject: [PATCH 380/463] more explicitly explain the UB around immutable extern statics --- src/behavior-considered-undefined.md | 2 +- src/items/external-blocks.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 756b86d..3e4c8a0 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -50,7 +50,7 @@ Please read the [Rustonomicon] before writing unsafe code. types are passed in a (nested) field of a compound type, but not behind pointer indirections. * Mutating immutable bytes. All bytes inside a [`const`] item are immutable. - The bytes owned by an immutable binding are immutable, unless those bytes are part of an [`UnsafeCell`]. + The bytes owned by an immutable binding or immutable `static` are immutable, unless those bytes are part of an [`UnsafeCell`]. Moreover, the bytes [pointed to] by a shared reference, including transitively through other references (both shared and mutable) and `Box`es, are immutable; transitivity includes those references stored in fields of compound types. diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 5b911a3..95d16d6 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -56,6 +56,8 @@ of initializing the static. Extern statics can be either immutable or mutable just like [statics] outside of external blocks. An immutable static *must* be initialized before any Rust code is executed. It is not enough for the static to be initialized before Rust code reads from it. +Once Rust code runs, mutating an immutable static (from inside or outside Rust) is UB, +except if the mutation happens inside an `UnsafeCell`. ## ABI From 1aafe7a2530ba59b34cc2f97245bf6bfa97095c1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 18 Apr 2024 17:18:03 -0400 Subject: [PATCH 381/463] Mention Variadics With No Fixed Parameter There's an open PR to support C23's variadics without a named parameter in Rust's extern blocks. Currently, it's waiting on approval from T-lang to get merged. This PR removes the line "There must be at least one parameter before the variadic parameter" and adds an example to highlight that we support variadics without any named parameters. Opening this now so it can get merged after the implementation gets approved by T-lang. --- 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 5b911a3..697ac2d 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -97,13 +97,13 @@ There are also some platform-specific ABI strings: ## Variadic functions Functions within external blocks may be variadic by specifying `...` as the -last argument. There must be at least one parameter before the variadic -parameter. The variadic parameter may optionally be specified with an +last argument. The variadic parameter may optionally be specified with an identifier. ```rust extern "C" { - fn foo(x: i32, ...); + fn foo(...); + fn bar(x: i32, ...); fn with_name(format: *const u8, args: ...); } ``` From b287af589bd0b9d7bd8cfb67f5fb6d07e84fe3a0 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 31 May 2024 18:26:39 +0200 Subject: [PATCH 382/463] this needs a space else it looks kinda off --- 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 63eab9b..2b28d39 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -12,7 +12,7 @@ >    [LIFETIME_OR_LABEL] ( `:` [_LifetimeBounds_] )? > > _TypeParam_ :\ ->    [IDENTIFIER]( `:` [_TypeParamBounds_]? )? ( `=` [_Type_] )? +>    [IDENTIFIER] ( `:` [_TypeParamBounds_]? )? ( `=` [_Type_] )? > > _ConstParam_:\ >    `const` [IDENTIFIER] `:` [_Type_] ( `=` _[Block][block]_ | [IDENTIFIER] | -?[LITERAL] )? From 756f6a66ab29281d49b60175f0e3607a2d469d94 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 2 Jun 2024 19:28:07 +0200 Subject: [PATCH 383/463] Add Apple target_abi values to the example values --- src/conditional-compilation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index e245c13..f83dbfe 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -180,6 +180,8 @@ Example values: * `"llvm"` * `"eabihf"` * `"abi64"` +* `"sim"` +* `"macabi"` ### `target_endian` From b1ce53faee21e61f0e43f996d28796e91f3fba40 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 7 Jun 2024 17:05:10 +0200 Subject: [PATCH 384/463] union syntax fix --- src/items/unions.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/items/unions.md b/src/items/unions.md index 3c6c83d..049564f 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -3,7 +3,7 @@ > **Syntax**\ > _Union_ :\ >    `union` [IDENTIFIER] [_GenericParams_]? [_WhereClause_]? -> `{`[_StructFields_] `}` +> `{`[_StructFields_]? `}` A union declaration uses the same syntax as a struct declaration, except with `union` in place of `struct`. @@ -30,6 +30,8 @@ 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. +Unions without any fields are not accepted by the compiler, but can be accepted by macros. + ## Initialization of a union A value of a union type can be created using the same syntax that is used for From 62381fba56876a58fb1a363ea89f2340b3060176 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 23 May 2024 07:34:47 +0200 Subject: [PATCH 385/463] typo fix and clarifications --- src/behavior-considered-undefined.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index 15eb9d1..96844f7 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -71,12 +71,13 @@ Please read the [Rustonomicon] before writing unsafe code. * A `!` (all values are invalid for this type). * An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer obtained from [uninitialized memory][undef], or uninitialized memory in a `str`. - * A reference or `Box` that is [dangling], misaligned, or points to an invalid value. + * A reference or `Box` that is [dangling], misaligned, or points to an invalid value + (in case of dynamically sized types, using the actual dynamic type of the + pointee as determined by the metadata). * Invalid metadata in a wide reference, `Box`, or raw pointer. The requirement for the metadata is determined by the type of the unsized tail: - * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for - `Trait` that matches the actual dynamic trait the pointer or reference points to. - * Slice metadata is invalid if the length is not a valid `usize` + * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for `Trait`. + * Slice (`[T]`) metadata is invalid if the length is not a valid `usize` (i.e., it must not be read from uninitialized memory). Furthermore, for wide references and `Box`, slice metadata is invalid if it makes the total size of the pointed-to value bigger than `isize::MAX`. From 7a0077aff6d8e42de1f5f7ca98ce79dc3afa7d7a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 21 Jun 2024 14:56:54 +0200 Subject: [PATCH 386/463] Added example of 1-ary tuple type --- src/types/tuple.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/types/tuple.md b/src/types/tuple.md index df21e1c..7d92f51 100644 --- a/src/types/tuple.md +++ b/src/types/tuple.md @@ -27,6 +27,7 @@ Its one value is also called *unit* or *the unit value*. Some examples of tuple types: * `()` (unit) +* `(i32, )` (1-ary tuple) * `(f64, f64)` * `(String, i32)` * `(i32, String)` (different type from the previous example) From 8768b6be8974a68a0629cb1bea97ff522f1790de Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 21 Jun 2024 07:39:46 -0700 Subject: [PATCH 387/463] Remove 1-ary space This follows the formatting standards of rustfmt and rustc. --- src/types/tuple.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/tuple.md b/src/types/tuple.md index 7d92f51..804d8a0 100644 --- a/src/types/tuple.md +++ b/src/types/tuple.md @@ -27,7 +27,7 @@ Its one value is also called *unit* or *the unit value*. Some examples of tuple types: * `()` (unit) -* `(i32, )` (1-ary tuple) +* `(i32,)` (1-ary tuple) * `(f64, f64)` * `(String, i32)` * `(i32, String)` (different type from the previous example) From 95e5635e644660717fd27a12ebed6fbf21f13cf1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 24 Jun 2024 14:35:45 -0700 Subject: [PATCH 388/463] Remove stubs needed for the link checker. --- src/crates-and-source-files.md | 5 ----- src/items/extern-crates.md | 5 ----- 2 files changed, 10 deletions(-) diff --git a/src/crates-and-source-files.md b/src/crates-and-source-files.md index 7329090..b0e607b 100644 --- a/src/crates-and-source-files.md +++ b/src/crates-and-source-files.md @@ -60,11 +60,6 @@ apply to the crate as a whole. #![warn(non_camel_case_types)] ``` -## Preludes and `no_std` - -This section has been moved to the [Preludes chapter](names/preludes.md). - - ## Main Functions A crate that contains a `main` [function] can be compiled to an executable. If a diff --git a/src/items/extern-crates.md b/src/items/extern-crates.md index d6b3a9a..9dd6a5e 100644 --- a/src/items/extern-crates.md +++ b/src/items/extern-crates.md @@ -52,11 +52,6 @@ Here is an example: extern crate hello_world; // hyphen replaced with an underscore ``` -## Extern Prelude - -This section has been moved to [Preludes — Extern Prelude](../names/preludes.md#extern-prelude). - - ## Underscore Imports An external crate dependency can be declared without binding its name in scope From 03c71ba411b033e9e36dac44d0f08ebe2df3112d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 9 Jul 2022 17:19:35 +0200 Subject: [PATCH 389/463] Document new `#[expect]` attribute and `reasons` parameter (RFC 2383) --- src/attributes.md | 3 +- src/attributes/diagnostics.md | 67 +++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index 9ce8166..16a72a0 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -222,7 +222,7 @@ The following is an index of all built-in attributes. - [`proc_macro_derive`] — Defines a derive macro. - [`proc_macro_attribute`] — Defines an attribute macro. - Diagnostics - - [`allow`], [`warn`], [`deny`], [`forbid`] — Alters the default lint level. + - [`allow`], [`expect`], [`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 @@ -303,6 +303,7 @@ The following is an index of all built-in attributes. [`deprecated`]: attributes/diagnostics.md#the-deprecated-attribute [`derive`]: attributes/derive.md [`export_name`]: abi.md#the-export_name-attribute +[`expect`]: attributes/diagnostics.md#lint-check-attributes [`forbid`]: attributes/diagnostics.md#lint-check-attributes [`global_allocator`]: runtime.md#the-global_allocator-attribute [`ignore`]: attributes/testing.md#the-ignore-attribute diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index c636a96..f8aaa00 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -7,17 +7,19 @@ messages during compilation. A lint check names a potentially undesirable coding pattern, such as unreachable code or omitted documentation. The lint attributes `allow`, -`warn`, `deny`, and `forbid` use the [_MetaListPaths_] syntax to specify a -list of lint names to change the lint level for the entity to which the -attribute applies. +`expect`, `warn`, `deny`, and `forbid` use the [_MetaListPaths_] syntax +to specify a list of lint names to change the lint level for the entity +to which the attribute applies. For any lint check `C`: -* `allow(C)` overrides the check for `C` so that violations will go +* `#[allow(C)]` overrides the check for `C` so that violations will go unreported, -* `warn(C)` warns about violations of `C` but continues compilation. -* `deny(C)` signals an error after encountering a violation of `C`, -* `forbid(C)` is the same as `deny(C)`, but also forbids changing the lint +* `#[expect(c)]` suppresses all lint emissions of `C`, but will issue + a warning, if the lint wasn't emitted in the expected scope. +* `#[warn(C)]` warns about violations of `C` but continues compilation. +* `#[deny(C)]` signals an error after encountering a violation of `C`, +* `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint level afterwards, > Note: The lint checks supported by `rustc` can be found via `rustc -W help`, @@ -83,6 +85,56 @@ pub mod m3 { > [command-line][rustc-lint-cli], and also supports [setting > caps][rustc-lint-caps] on the lints that are reported. +All lint attributes support an additional `reason` parameter, to give context why +a certain attribute was added. This reason will be displayed as part of the lint +message, if the lint is emitted at the defined level. + +```rust +use std::path::PathBuf; + +pub fn get_path() -> PathBuf { + #[allow(unused_mut, reason = "this is only modified on some platforms")] + let mut file_name = PathBuf::from("git"); + + #[cfg(target_os = "windows")] + file_name.set_extension("exe"); + + file_name +} +``` + +### Lint expectations + +With the `#[expect]` attributes lints can be expected in a certain scope. If +this expectation is not fulfilled a new warning is emitted to the user. The +lint levels can be overridden with other lint attributes as usual. + +```rust +#[warn(missing_docs)] +pub mod m2{ + #[expect(missing_docs)] + pub mod nested { + // This missing documentation fulfills the expectation above + pub fn undocumented_one() -> i32 { 1 } + + // Missing documentation signals a warning here, despite the expectation + // above. This emission would not fulfill the expectation + #[warn(missing_docs)] + pub fn undocumented_two() -> i32 { 2 } + } + + #[expect(missing_docs)] + /// This comment explains something cool about the function. The + /// expectation will not be fulfilled and in turn issue a warning. + pub fn undocumented_too() -> i32 { 3 } +} +``` + +> Note: Lint expectations have been proposed in [RFC 2383]. It was not defined +> how expectations of the expectation lint should be handled. The rustc +> implementation currently doesn't allow the expextation of the +> `unfulfilled_lint_expectation` lint. This can change in the future. + ### Lint groups Lints may be organized into named groups so that the level of related lints @@ -392,6 +444,7 @@ error[E0277]: My Message for `ImportantTrait` implemented for `String` [let statement]: ../statements.md#let-statements [macro definition]: ../macros-by-example.md [module]: ../items/modules.md +[RFC 2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html [rustc book]: ../../rustc/lints/index.html [rustc-lint-caps]: ../../rustc/lints/levels.html#capping-lints [rustc-lint-cli]: ../../rustc/lints/levels.html#via-compiler-flag From af07f4071cd143ee9d2ea87c0e681b6761c674cf Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 10 Jul 2022 17:17:10 +0200 Subject: [PATCH 390/463] Improve `#[expect]` documentation and address review comments --- src/attributes/diagnostics.md | 124 ++++++++++++++++++++++++++-------- 1 file changed, 96 insertions(+), 28 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index f8aaa00..268cb6f 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -15,8 +15,8 @@ For any lint check `C`: * `#[allow(C)]` overrides the check for `C` so that violations will go unreported, -* `#[expect(c)]` suppresses all lint emissions of `C`, but will issue - a warning, if the lint wasn't emitted in the expected scope. +* `#[expect(C)]` suppresses all lint emissions of `C`, but will issue + a warning if the lint wasn't emitted in the expected scope. * `#[warn(C)]` warns about violations of `C` but continues compilation. * `#[deny(C)]` signals an error after encountering a violation of `C`, * `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint @@ -68,8 +68,8 @@ pub mod m2 { } ``` -This example shows how one can use `forbid` to disallow uses of `allow` for -that lint check: +This example shows how one can use `forbid` to disallow uses of `allow` or +`expect` for that lint check: ```rust,compile_fail #[forbid(missing_docs)] @@ -85,14 +85,33 @@ pub mod m3 { > [command-line][rustc-lint-cli], and also supports [setting > caps][rustc-lint-caps] on the lints that are reported. +### Lint Reasons + All lint attributes support an additional `reason` parameter, to give context why a certain attribute was added. This reason will be displayed as part of the lint -message, if the lint is emitted at the defined level. +message if the lint is emitted at the defined level. + +```rust,edition2015 +// `keyword_idents` is allowed by default. Here we deny it to +// avoid migration of identifies when we update the edition. +#![deny( + keyword_idents, + reason = "we want to avoid these idents to be future compatible" +)] + +// This name was allowed in Rust's 2015 edition. We still aim to avoid +// this to be future compatible and not confuse end users. +fn dyn() {} +``` + +Here we have another example, where the lint is allowed with a reason: ```rust use std::path::PathBuf; pub fn get_path() -> PathBuf { + // Using `reason` with an `allow` attribute has no effect other than to + // provide documentation to the reader. #[allow(unused_mut, reason = "this is only modified on some platforms")] let mut file_name = PathBuf::from("git"); @@ -103,37 +122,86 @@ pub fn get_path() -> PathBuf { } ``` -### Lint expectations +### The `expect` attribute -With the `#[expect]` attributes lints can be expected in a certain scope. If -this expectation is not fulfilled a new warning is emitted to the user. The -lint levels can be overridden with other lint attributes as usual. +The *`expect` attribute* is used to mark that a particular lint must be triggered +within its scope. If this expectation is not fulfilled a new warning is emitted to +the user. ```rust -#[warn(missing_docs)] -pub mod m2{ - #[expect(missing_docs)] - pub mod nested { - // This missing documentation fulfills the expectation above - pub fn undocumented_one() -> i32 { 1 } +fn main() { + // This `expect` attribute creates an expectation, that the `unused_variables` + // will be triggered by the following statement. This expectation will not be + // fulfilled, since the `question` variable is used by the `println!` macro. + #[expect(unused_variables)] + let question = "who lives in a pineapple under the sea?"; + println!("{question}"); + + // This `expect` attribute creates an expectation that will be fulfilled, since + // the `answer` variable is never used. It will therefore trigger the + // `unused_variables` lint which will be suppressed by the expectation and fullfil + // it as well. + #[expect(unused_variables)] + let answer = "SpongeBob SquarePants!"; +} +``` - // Missing documentation signals a warning here, despite the expectation - // above. This emission would not fulfill the expectation - #[warn(missing_docs)] - pub fn undocumented_two() -> i32 { 2 } - } +The lint expectation is only fulfilled by lint emissions which have been suppressed by +the `expect` attribute. If the lint level is modified in the scope with other level +attributes like `warn` or `deny`, the lint will be emitted at the defined level and not +satisdy the expectation. Lint suppressions via `allow` or `expect` attributes inside the +scope will also not fulfill the expectation. - #[expect(missing_docs)] - /// This comment explains something cool about the function. The - /// expectation will not be fulfilled and in turn issue a warning. - pub fn undocumented_too() -> i32 { 3 } +```rust +#[expect(unused_variables)] +fn select_song() { + // This will emit the `unused_variables` lint at the warn level + // as defined by the `warn` attribute. This will not fulfill the + // expectation above the function. + #[warn(unused_variables)] + let song_name = "Crab Rave"; + + // The `allow` attribute suppresses the lint emission. This will not + // fulfill the expectation as it has been suppressed by the `allow` + // attribute and not the `expect` attribute above the function. + #[allow(unused_variables)] + let song_creator = "Noisestorm"; + + // This `expect` attribute will suppress the `unused_variables` lint emission + // at the variable. The `expect` attribute above the function will still not + // be fulfilled, since this lint emission has been suppressed by the local + // expect attribute. + #[expect(unused_variables)] + let song_version = "Monstercat Release"; +} +``` + +If the `expect` attribute contains several lints, each one is expected separatly. For a +lint group it's enough if one lint inside the group has been emitted: + +```rust +// This expectation will be fulfilled by the unused value inside the function +// since the emitted `unused_variables` lint is inside the `unused` lint group. +#[expect(unused)] +pub fn thoughts() { + let unused = "I'm running out of examples"; +} + +pub fn another_example() { + // This attribute creates two lint expectations. The `unused_mut` lint will be + // suppressed and with that fulfill the first expectation. The `unused_variables` + // won't be emitted, since the variable is used. That expectation will therefore + // not be satisfied, and a warning will be emitted. + #[expect(unused_mut, unused_variables)] + let mut link = "https://www.rust-lang.org/"; + + println!("Welcome to our community: {link}"); } ``` -> Note: Lint expectations have been proposed in [RFC 2383]. It was not defined -> how expectations of the expectation lint should be handled. The rustc -> implementation currently doesn't allow the expextation of the -> `unfulfilled_lint_expectation` lint. This can change in the future. +> Note: The behavior of `#[expect(unfulfilled_lint_expectations)]` is currently +> defined to always generate the `unfulfilled_lint_expectations` lint. This may +> change in the future. ### Lint groups From f83bca147b791eb74b7426d52b00a24aba9b86dc Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 10 Feb 2024 17:49:08 +0100 Subject: [PATCH 391/463] Improve `#[expect]` documentation again --- src/attributes/diagnostics.md | 46 ++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index 268cb6f..f6774ad 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -14,9 +14,10 @@ to which the attribute applies. For any lint check `C`: * `#[allow(C)]` overrides the check for `C` so that violations will go - unreported, -* `#[expect(C)]` suppresses all lint emissions of `C`, but will issue - a warning if the lint wasn't emitted in the expected scope. + unreported. +* `#[expect(C)]` indicates that lint `C` is expected to be emitted. The + attribute will suppres the emission of `C` or issue a warning, if the + expectation is unfillfilled. * `#[warn(C)]` warns about violations of `C` but continues compilation. * `#[deny(C)]` signals an error after encountering a violation of `C`, * `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint @@ -104,14 +105,13 @@ message if the lint is emitted at the defined level. fn dyn() {} ``` -Here we have another example, where the lint is allowed with a reason: +Here is another example, where the lint is allowed with a reason: ```rust use std::path::PathBuf; pub fn get_path() -> PathBuf { - // Using `reason` with an `allow` attribute has no effect other than to - // provide documentation to the reader. + // The `reason` parameter on `allow` attributes acts as documentation for the reader. #[allow(unused_mut, reason = "this is only modified on some platforms")] let mut file_name = PathBuf::from("git"); @@ -122,25 +122,28 @@ pub fn get_path() -> PathBuf { } ``` -### The `expect` attribute +### The `#[expect]` attribute -The *`expect` attribute* is used to mark that a particular lint must be triggered -within its scope. If this expectation is not fulfilled a new warning is emitted to -the user. +The `#[expect(C)]` attribute creates a lint expectation for lint `C`. The +expectation will be fulfilled, if a `#[warn(C)]` attribute at the same location +would result in a lint emission. If the expectation is unfulfilled, because +lint `C` would not be emitted, the `unfulfilled_lint_expectations` lint will +be emitted at the attribute. ```rust fn main() { - // This `expect` attribute creates an expectation, that the `unused_variables` - // will be triggered by the following statement. This expectation will not be - // fulfilled, since the `question` variable is used by the `println!` macro. + // This `#[expect]` attribute creates a lint expectation, that the `unused_variables` + // lint would be emitted by the following statement. This expectation is + // unfulfilled, since the `question` variable is used by the `println!` macro. + // Therefore, the `unfulfilled_lint_expectations` lint will be emitted at the + // attribute. #[expect(unused_variables)] let question = "who lives in a pineapple under the sea?"; println!("{question}"); - // This `expect` attribute creates an expectation that will be fulfilled, since - // the `answer` variable is never used. It will therefore trigger the - // `unused_variables` lint which will be suppressed by the expectation and fullfil - // it as well. + // This `#[expect]` attribute creates a lint expectation that will be fulfilled, since + // the `answer` variable is never used. The `unused_variables` lint, that would usually + // be emitted, is supressed. No warning will be issued for the statement or attribute. #[expect(unused_variables)] let answer = "SpongeBob SquarePants!"; } @@ -148,9 +151,8 @@ fn main() { The lint expectation is only fulfilled by lint emissions which have been suppressed by the `expect` attribute. If the lint level is modified in the scope with other level -attributes like `warn` or `deny`, the lint will be emitted at the defined level and not -satisdy the expectation. Lint suppressions via `allow` or `expect` attributes inside the -scope will also not fulfill the expectation. +attributes like `allow` or `warn`, the lint emission will be handled accordingly and the +expectation will remain unfulfilled. ```rust #[expect(unused_variables)] @@ -190,8 +192,8 @@ pub fn thoughts() { pub fn another_example() { // This attribute creates two lint expectations. The `unused_mut` lint will be // suppressed and with that fulfill the first expectation. The `unused_variables` - // won't be emitted, since the variable is used. That expectation will therefore - // not be satisfied, and a warning will be emitted. + // wouldn't be emitted, since the variable is used. That expectation will therefore + // be unsatified, and a warning will be emitted. #[expect(unused_mut, unused_variables)] let mut link = "https://www.rust-lang.org/"; From b85e18ee3d844e6db8eaaa3d0e16f65585336ff0 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 17 Feb 2024 12:02:26 +0100 Subject: [PATCH 392/463] Fix Typos --- src/attributes/diagnostics.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index f6774ad..d750f04 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -16,8 +16,8 @@ For any lint check `C`: * `#[allow(C)]` overrides the check for `C` so that violations will go unreported. * `#[expect(C)]` indicates that lint `C` is expected to be emitted. The - attribute will suppres the emission of `C` or issue a warning, if the - expectation is unfillfilled. + attribute will suppress the emission of `C` or issue a warning, if the + expectation is unfulfilled. * `#[warn(C)]` warns about violations of `C` but continues compilation. * `#[deny(C)]` signals an error after encountering a violation of `C`, * `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint @@ -69,7 +69,7 @@ pub mod m2 { } ``` -This example shows how one can use `forbid` to disallow uses of `allow` or +This example shows how one can use `forbid` to disallow uses of `allow` or `expect` for that lint check: ```rust,compile_fail @@ -92,7 +92,7 @@ All lint attributes support an additional `reason` parameter, to give context wh a certain attribute was added. This reason will be displayed as part of the lint message if the lint is emitted at the defined level. -```rust,edition2015 +```edition2015,fail // `keyword_idents` is allowed by default. Here we deny it to // avoid migration of identifies when we update the edition. #![deny( @@ -143,7 +143,7 @@ fn main() { // This `#[expect]` attribute creates a lint expectation that will be fulfilled, since // the `answer` variable is never used. The `unused_variables` lint, that would usually - // be emitted, is supressed. No warning will be issued for the statement or attribute. + // be emitted, is suppressed. No warning will be issued for the statement or attribute. #[expect(unused_variables)] let answer = "SpongeBob SquarePants!"; } @@ -178,7 +178,7 @@ fn select_song() { } ``` -If the `expect` attribute contains several lints, each one is expected separatly. For a +If the `expect` attribute contains several lints, each one is expected separately. For a lint group it's enough if one lint inside the group has been emitted: ```rust @@ -193,7 +193,7 @@ pub fn another_example() { // This attribute creates two lint expectations. The `unused_mut` lint will be // suppressed and with that fulfill the first expectation. The `unused_variables` // wouldn't be emitted, since the variable is used. That expectation will therefore - // be unsatified, and a warning will be emitted. + // be unsatisfied, and a warning will be emitted. #[expect(unused_mut, unused_variables)] let mut link = "https://www.rust-lang.org/"; @@ -202,8 +202,7 @@ pub fn another_example() { ``` > Note: The behavior of `#[expect(unfulfilled_lint_expectations)]` is currently -> defined to always generate the `unfulfilled_lint_expectations` lint. This may -> change in the future. +> defined to always generate the `unfulfilled_lint_expectations` lint. ### Lint groups @@ -514,7 +513,6 @@ error[E0277]: My Message for `ImportantTrait` implemented for `String` [let statement]: ../statements.md#let-statements [macro definition]: ../macros-by-example.md [module]: ../items/modules.md -[RFC 2383]: https://rust-lang.github.io/rfcs/2383-lint-reasons.html [rustc book]: ../../rustc/lints/index.html [rustc-lint-caps]: ../../rustc/lints/levels.html#capping-lints [rustc-lint-cli]: ../../rustc/lints/levels.html#via-compiler-flag From 3fe498d401e029efff01c993745ab565d2beef7d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 27 Jun 2024 10:27:03 -0700 Subject: [PATCH 393/463] Fix a code example to use the correct code tags. --- src/attributes/diagnostics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index d750f04..e9b6726 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -92,9 +92,9 @@ All lint attributes support an additional `reason` parameter, to give context wh a certain attribute was added. This reason will be displayed as part of the lint message if the lint is emitted at the defined level. -```edition2015,fail +```rust,edition2015,compile_fail // `keyword_idents` is allowed by default. Here we deny it to -// avoid migration of identifies when we update the edition. +// avoid migration of identifiers when we update the edition. #![deny( keyword_idents, reason = "we want to avoid these idents to be future compatible" From 7454ec225666889a95946d2c5a46549c11c1d97b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 28 Jun 2024 16:56:35 +0200 Subject: [PATCH 394/463] Provide an example of `target_family` being multi-valued --- src/conditional-compilation.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index f83dbfe..f52c90d 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -142,6 +142,7 @@ Example values: * `"unix"` * `"windows"` * `"wasm"` +* Both `"unix"` and `"wasm"` ### `unix` and `windows` From 6adb86491fcd5b0c58ddef82b426cbe573a084f3 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 24 Jun 2024 14:29:05 -0700 Subject: [PATCH 395/463] Enable mdbook smart-punctuation. --- .github/workflows/main.yml | 2 +- STYLE.md | 10 +- book.toml | 1 + src/attributes.md | 90 ++++++++-------- src/attributes/codegen.md | 188 +++++++++++++++++----------------- src/attributes/debugger.md | 6 +- src/attributes/diagnostics.md | 18 ++-- src/inline-assembly.md | 4 +- src/items/constant-items.md | 4 +- src/items/external-blocks.md | 8 +- src/macros-by-example.md | 6 +- src/names.md | 12 +-- src/names/namespaces.md | 2 +- src/names/preludes.md | 10 +- src/tokens.md | 2 +- src/types.md | 8 +- 16 files changed, 186 insertions(+), 185 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aff2084..2196952 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.14/mdbook-v0.4.14-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.40/mdbook-v0.4.40-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> $GITHUB_PATH - name: Report versions run: | diff --git a/STYLE.md b/STYLE.md index f51cba3..977637b 100644 --- a/STYLE.md +++ b/STYLE.md @@ -41,11 +41,11 @@ See https://highlightjs.org/ for a list of supported languages. Rust examples are tested via rustdoc, and should include the appropriate annotations when tests are expected to fail: -* `edition2015` or `edition2018` — If it is edition-specific (see `book.toml` for the default). -* `no_run` — The example should compile successfully, but should not be executed. -* `should_panic` — The example should compile and run, but produce a panic. -* `compile_fail` — The example is expected to fail to compile. -* `ignore` — The example shouldn't be built or tested. +* `edition2015` or `edition2018` --- If it is edition-specific (see `book.toml` for the default). +* `no_run` --- The example should compile successfully, but should not be executed. +* `should_panic` --- The example should compile and run, but produce a panic. +* `compile_fail` --- The example is expected to fail to compile. +* `ignore` --- The example shouldn't be built or tested. This should be avoided if possible. Usually this is only necessary when the testing framework does not support it (such as external crates or modules, or a proc-macro), or it contains pseudo-code which is not valid Rust. An HTML comment such as `` should be placed before the example to explain why it is ignored. diff --git a/book.toml b/book.toml index 9fb3730..505e081 100644 --- a/book.toml +++ b/book.toml @@ -7,6 +7,7 @@ author = "The Rust Project Developers" 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}" +smart-punctuation = true [output.html.redirect] "/expressions/enum-variant-expr.html" = "struct-expr.html" diff --git a/src/attributes.md b/src/attributes.md index 16a72a0..08b6c06 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -204,79 +204,79 @@ pub fn f() {} The following is an index of all built-in attributes. - Conditional compilation - - [`cfg`] — Controls conditional compilation. - - [`cfg_attr`] — Conditionally includes attributes. + - [`cfg`] --- Controls conditional compilation. + - [`cfg_attr`] --- Conditionally includes attributes. - Testing - - [`test`] — Marks a function as a test. - - [`ignore`] — Disables a test function. - - [`should_panic`] — Indicates a test should generate a panic. + - [`test`] --- Marks a function as a test. + - [`ignore`] --- Disables a test function. + - [`should_panic`] --- Indicates a test should generate a panic. - Derive - - [`derive`] — Automatic trait implementations. - - [`automatically_derived`] — Marker for implementations created by + - [`derive`] --- Automatic trait implementations. + - [`automatically_derived`] --- Marker for implementations created by `derive`. - Macros - - [`macro_export`] — Exports a `macro_rules` macro for cross-crate usage. - - [`macro_use`] — Expands macro visibility, or imports macros from other + - [`macro_export`] --- Exports a `macro_rules` macro for cross-crate usage. + - [`macro_use`] --- Expands macro visibility, or imports macros from other crates. - - [`proc_macro`] — Defines a function-like macro. - - [`proc_macro_derive`] — Defines a derive macro. - - [`proc_macro_attribute`] — Defines an attribute macro. + - [`proc_macro`] --- Defines a function-like macro. + - [`proc_macro_derive`] --- Defines a derive macro. + - [`proc_macro_attribute`] --- Defines an attribute macro. - Diagnostics - - [`allow`], [`expect`], [`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 + - [`allow`], [`expect`], [`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 + - [`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 + - [`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.). - - [`no_main`] — Disables emitting the `main` symbol. - - [`export_name`] — Specifies the exported symbol name for a function or + - [`no_link`] --- Prevents linking an extern crate. + - [`repr`] --- Controls type layout. + - [`crate_type`] --- Specifies the type of crate (library, executable, etc.). + - [`no_main`] --- Disables emitting the `main` symbol. + - [`export_name`] --- Specifies the exported symbol name for a function or static. - - [`link_section`] — Specifies the section of an object file to use for a + - [`link_section`] --- Specifies the section of an object file to use for a function or static. - - [`no_mangle`] — Disables symbol name encoding. - - [`used`] — Forces the compiler to keep a static item in the output + - [`no_mangle`] --- Disables symbol name encoding. + - [`used`] --- Forces the compiler to keep a static item in the output object file. - - [`crate_name`] — Specifies the crate name. + - [`crate_name`] --- Specifies the crate name. - Code generation - - [`inline`] — Hint to inline code. - - [`cold`] — Hint that a function is unlikely to be called. - - [`no_builtins`] — Disables use of certain built-in functions. - - [`target_feature`] — Configure platform-specific code generation. + - [`inline`] --- Hint to inline code. + - [`cold`] --- Hint that a function is unlikely to be called. + - [`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 + - `doc` --- Specifies documentation. See [The Rustdoc Book] for more information. [Doc comments] are transformed into `doc` attributes. - Preludes - - [`no_std`] — Removes std from the prelude. - - [`no_implicit_prelude`] — Disables prelude lookups within a module. + - [`no_std`] --- Removes std from the prelude. + - [`no_implicit_prelude`] --- Disables prelude lookups within a module. - Modules - - [`path`] — Specifies the filename for a module. + - [`path`] --- Specifies the filename for a module. - Limits - - [`recursion_limit`] — Sets the maximum recursion limit for certain + - [`recursion_limit`] --- Sets the maximum recursion limit for certain compile-time operations. - - [`type_length_limit`] — Sets the maximum size of a polymorphic type. + - [`type_length_limit`] --- Sets the maximum size of a polymorphic type. - Runtime - - [`panic_handler`] — Sets the function to handle panics. - - [`global_allocator`] — Sets the global memory allocator. - - [`windows_subsystem`] — Specifies the windows subsystem to link with. + - [`panic_handler`] --- Sets the function to handle panics. + - [`global_allocator`] --- Sets the global memory allocator. + - [`windows_subsystem`] --- Specifies the windows subsystem to link with. - Features - - `feature` — Used to enable unstable or experimental compiler features. See + - `feature` --- Used to enable unstable or experimental compiler features. See [The Unstable Book] for features implemented in `rustc`. - Type System - - [`non_exhaustive`] — Indicate that a type will have more fields/variants + - [`non_exhaustive`] --- Indicate that a type will have more fields/variants added in future. - Debugger - - [`debugger_visualizer`] — Embeds a file that specifies debugger output for a type. - - [`collapse_debuginfo`] — Controls how macro invocations are encoded in debuginfo. + - [`debugger_visualizer`] --- Embeds a file that specifies debugger output for a type. + - [`collapse_debuginfo`] --- Controls how macro invocations are encoded in debuginfo. [Doc comments]: comments.md#doc-comments [ECMA-334]: https://www.ecma-international.org/publications-and-standards/standards/ecma-334/ diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 195df2f..e7de843 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -82,33 +82,33 @@ functions][unsafe function]. Feature | Implicitly Enables | Description ------------|--------------------|------------------- -`adx` | | [ADX] — Multi-Precision Add-Carry Instruction Extensions -`aes` | `sse2` | [AES] — Advanced Encryption Standard -`avx` | `sse4.2` | [AVX] — Advanced Vector Extensions -`avx2` | `avx` | [AVX2] — Advanced Vector Extensions 2 -`bmi1` | | [BMI1] — Bit Manipulation Instruction Sets -`bmi2` | | [BMI2] — Bit Manipulation Instruction Sets 2 -`cmpxchg16b`| | [`cmpxchg16b`] - Compares and exchange 16 bytes (128 bits) of data atomically -`f16c` | `avx` | [F16C] — 16-bit floating point conversion instructions -`fma` | `avx` | [FMA3] — Three-operand fused multiply-add -`fxsr` | | [`fxsave`] and [`fxrstor`] — Save and restore x87 FPU, MMX Technology, and SSE State -`lzcnt` | | [`lzcnt`] — Leading zeros count -`movbe` | | [`movbe`] - Move data after swapping bytes -`pclmulqdq` | `sse2` | [`pclmulqdq`] — Packed carry-less multiplication quadword -`popcnt` | | [`popcnt`] — Count of bits set to 1 -`rdrand` | | [`rdrand`] — Read random number -`rdseed` | | [`rdseed`] — Read random seed -`sha` | `sse2` | [SHA] — Secure Hash Algorithm -`sse` | | [SSE] — Streaming SIMD Extensions -`sse2` | `sse` | [SSE2] — Streaming SIMD Extensions 2 -`sse3` | `sse2` | [SSE3] — Streaming SIMD Extensions 3 -`sse4.1` | `ssse3` | [SSE4.1] — Streaming SIMD Extensions 4.1 -`sse4.2` | `sse4.1` | [SSE4.2] — Streaming SIMD Extensions 4.2 -`ssse3` | `sse3` | [SSSE3] — Supplemental Streaming SIMD Extensions 3 -`xsave` | | [`xsave`] — Save processor extended states -`xsavec` | | [`xsavec`] — Save processor extended states with compaction -`xsaveopt` | | [`xsaveopt`] — Save processor extended states optimized -`xsaves` | | [`xsaves`] — Save processor extended states supervisor +`adx` | | [ADX] --- Multi-Precision Add-Carry Instruction Extensions +`aes` | `sse2` | [AES] --- Advanced Encryption Standard +`avx` | `sse4.2` | [AVX] --- Advanced Vector Extensions +`avx2` | `avx` | [AVX2] --- Advanced Vector Extensions 2 +`bmi1` | | [BMI1] --- Bit Manipulation Instruction Sets +`bmi2` | | [BMI2] --- Bit Manipulation Instruction Sets 2 +`cmpxchg16b`| | [`cmpxchg16b`] --- Compares and exchange 16 bytes (128 bits) of data atomically +`f16c` | `avx` | [F16C] --- 16-bit floating point conversion instructions +`fma` | `avx` | [FMA3] --- Three-operand fused multiply-add +`fxsr` | | [`fxsave`] and [`fxrstor`] --- Save and restore x87 FPU, MMX Technology, and SSE State +`lzcnt` | | [`lzcnt`] --- Leading zeros count +`movbe` | | [`movbe`] --- Move data after swapping bytes +`pclmulqdq` | `sse2` | [`pclmulqdq`] --- Packed carry-less multiplication quadword +`popcnt` | | [`popcnt`] --- Count of bits set to 1 +`rdrand` | | [`rdrand`] --- Read random number +`rdseed` | | [`rdseed`] --- Read random seed +`sha` | `sse2` | [SHA] --- Secure Hash Algorithm +`sse` | | [SSE] --- Streaming SIMD Extensions +`sse2` | `sse` | [SSE2] --- Streaming SIMD Extensions 2 +`sse3` | `sse2` | [SSE3] --- Streaming SIMD Extensions 3 +`sse4.1` | `ssse3` | [SSE4.1] --- Streaming SIMD Extensions 4.1 +`sse4.2` | `sse4.1` | [SSE4.2] --- Streaming SIMD Extensions 4.2 +`ssse3` | `sse3` | [SSSE3] --- Supplemental Streaming SIMD Extensions 3 +`xsave` | | [`xsave`] --- Save processor extended states +`xsavec` | | [`xsavec`] --- Save processor extended states with compaction +`xsaveopt` | | [`xsaveopt`] --- Save processor extended states optimized +`xsaves` | | [`xsaves`] --- Save processor extended states supervisor @@ -159,50 +159,50 @@ Reference Manual], or elsewhere on [developer.arm.com]. Feature | Implicitly Enables | Feature Name ---------------|--------------------|------------------- -`aes` | `neon` | FEAT_AES & FEAT_PMULL - Advanced SIMD AES & PMULL instructions -`bf16` | | FEAT_BF16 - BFloat16 instructions -`bti` | | FEAT_BTI - Branch Target Identification -`crc` | | FEAT_CRC - CRC32 checksum instructions -`dit` | | FEAT_DIT - Data Independent Timing instructions -`dotprod` | | FEAT_DotProd - Advanced SIMD Int8 dot product instructions -`dpb` | | FEAT_DPB - Data cache clean to point of persistence -`dpb2` | | FEAT_DPB2 - Data cache clean to point of deep persistence -`f32mm` | `sve` | FEAT_F32MM - SVE single-precision FP matrix multiply instruction -`f64mm` | `sve` | FEAT_F64MM - SVE double-precision FP matrix multiply instruction -`fcma` | `neon` | FEAT_FCMA - Floating point complex number support -`fhm` | `fp16` | FEAT_FHM - Half-precision FP FMLAL instructions -`flagm` | | FEAT_FlagM - Conditional flag manipulation -`fp16` | `neon` | FEAT_FP16 - Half-precision FP data processing -`frintts` | | FEAT_FRINTTS - Floating-point to int helper instructions -`i8mm` | | FEAT_I8MM - Int8 Matrix Multiplication -`jsconv` | `neon` | FEAT_JSCVT - JavaScript conversion instruction -`lse` | | FEAT_LSE - Large System Extension -`lor` | | FEAT_LOR - Limited Ordering Regions extension -`mte` | | FEAT_MTE & FEAT_MTE2 - Memory Tagging Extension -`neon` | | FEAT_FP & FEAT_AdvSIMD - Floating Point and Advanced SIMD extension -`pan` | | FEAT_PAN - Privileged Access-Never extension -`paca` | | FEAT_PAuth - Pointer Authentication (address authentication) -`pacg` | | FEAT_PAuth - Pointer Authentication (generic authentication) -`pmuv3` | | FEAT_PMUv3 - Performance Monitors extension (v3) -`rand` | | FEAT_RNG - Random Number Generator -`ras` | | FEAT_RAS & FEAT_RASv1p1 - Reliability, Availability and Serviceability extension -`rcpc` | | FEAT_LRCPC - Release consistent Processor Consistent -`rcpc2` | `rcpc` | FEAT_LRCPC2 - RcPc with immediate offsets -`rdm` | | FEAT_RDM - Rounding Double Multiply accumulate -`sb` | | FEAT_SB - Speculation Barrier -`sha2` | `neon` | FEAT_SHA1 & FEAT_SHA256 - Advanced SIMD SHA instructions -`sha3` | `sha2` | FEAT_SHA512 & FEAT_SHA3 - Advanced SIMD SHA instructions -`sm4` | `neon` | FEAT_SM3 & FEAT_SM4 - Advanced SIMD SM3/4 instructions -`spe` | | FEAT_SPE - Statistical Profiling Extension -`ssbs` | | FEAT_SSBS & FEAT_SSBS2 - Speculative Store Bypass Safe -`sve` | `fp16` | FEAT_SVE - Scalable Vector Extension -`sve2` | `sve` | FEAT_SVE2 - Scalable Vector Extension 2 -`sve2-aes` | `sve2`, `aes` | FEAT_SVE_AES - SVE AES instructions -`sve2-sm4` | `sve2`, `sm4` | FEAT_SVE_SM4 - SVE SM4 instructions -`sve2-sha3` | `sve2`, `sha3` | FEAT_SVE_SHA3 - SVE SHA3 instructions -`sve2-bitperm` | `sve2` | FEAT_SVE_BitPerm - SVE Bit Permute -`tme` | | FEAT_TME - Transactional Memory Extension -`vh` | | FEAT_VHE - Virtualization Host Extensions +`aes` | `neon` | FEAT_AES & FEAT_PMULL --- Advanced SIMD AES & PMULL instructions +`bf16` | | FEAT_BF16 --- BFloat16 instructions +`bti` | | FEAT_BTI --- Branch Target Identification +`crc` | | FEAT_CRC --- CRC32 checksum instructions +`dit` | | FEAT_DIT --- Data Independent Timing instructions +`dotprod` | | FEAT_DotProd --- Advanced SIMD Int8 dot product instructions +`dpb` | | FEAT_DPB --- Data cache clean to point of persistence +`dpb2` | | FEAT_DPB2 --- Data cache clean to point of deep persistence +`f32mm` | `sve` | FEAT_F32MM --- SVE single-precision FP matrix multiply instruction +`f64mm` | `sve` | FEAT_F64MM --- SVE double-precision FP matrix multiply instruction +`fcma` | `neon` | FEAT_FCMA --- Floating point complex number support +`fhm` | `fp16` | FEAT_FHM --- Half-precision FP FMLAL instructions +`flagm` | | FEAT_FlagM --- Conditional flag manipulation +`fp16` | `neon` | FEAT_FP16 --- Half-precision FP data processing +`frintts` | | FEAT_FRINTTS --- Floating-point to int helper instructions +`i8mm` | | FEAT_I8MM --- Int8 Matrix Multiplication +`jsconv` | `neon` | FEAT_JSCVT --- JavaScript conversion instruction +`lse` | | FEAT_LSE --- Large System Extension +`lor` | | FEAT_LOR --- Limited Ordering Regions extension +`mte` | | FEAT_MTE & FEAT_MTE2 --- Memory Tagging Extension +`neon` | | FEAT_FP & FEAT_AdvSIMD --- Floating Point and Advanced SIMD extension +`pan` | | FEAT_PAN --- Privileged Access-Never extension +`paca` | | FEAT_PAuth --- Pointer Authentication (address authentication) +`pacg` | | FEAT_PAuth --- Pointer Authentication (generic authentication) +`pmuv3` | | FEAT_PMUv3 --- Performance Monitors extension (v3) +`rand` | | FEAT_RNG --- Random Number Generator +`ras` | | FEAT_RAS & FEAT_RASv1p1 --- Reliability, Availability and Serviceability extension +`rcpc` | | FEAT_LRCPC --- Release consistent Processor Consistent +`rcpc2` | `rcpc` | FEAT_LRCPC2 --- RcPc with immediate offsets +`rdm` | | FEAT_RDM --- Rounding Double Multiply accumulate +`sb` | | FEAT_SB --- Speculation Barrier +`sha2` | `neon` | FEAT_SHA1 & FEAT_SHA256 --- Advanced SIMD SHA instructions +`sha3` | `sha2` | FEAT_SHA512 & FEAT_SHA3 --- Advanced SIMD SHA instructions +`sm4` | `neon` | FEAT_SM3 & FEAT_SM4 --- Advanced SIMD SM3/4 instructions +`spe` | | FEAT_SPE --- Statistical Profiling Extension +`ssbs` | | FEAT_SSBS & FEAT_SSBS2 --- Speculative Store Bypass Safe +`sve` | `fp16` | FEAT_SVE --- Scalable Vector Extension +`sve2` | `sve` | FEAT_SVE2 --- Scalable Vector Extension 2 +`sve2-aes` | `sve2`, `aes` | FEAT_SVE_AES --- SVE AES instructions +`sve2-sm4` | `sve2`, `sm4` | FEAT_SVE_SM4 --- SVE SM4 instructions +`sve2-sha3` | `sve2`, `sha3` | FEAT_SVE_SHA3 --- SVE SHA3 instructions +`sve2-bitperm` | `sve2` | FEAT_SVE_BitPerm --- SVE Bit Permute +`tme` | | FEAT_TME --- Transactional Memory Extension +`vh` | | FEAT_VHE --- Virtualization Host Extensions #### `riscv32` or `riscv64` @@ -218,27 +218,27 @@ in another manual hosted on the [RISC-V GitHub Account]. Feature | Implicitly Enables | Description ------------|---------------------|------------------- -`a` | | [A][rv-a] — Atomic instructions -`c` | | [C][rv-c] — Compressed instructions -`m` | | [M][rv-m] — Integer Multiplication and Division instructions -`zb` | `zba`, `zbc`, `zbs` | [Zb][rv-zb] — Bit Manipulation instructions -`zba` | | [Zba][rv-zb-zba] — Address Generation instructions -`zbb` | | [Zbb][rv-zb-zbb] — Basic bit-manipulation -`zbc` | | [Zbc][rv-zb-zbc] — Carry-less multiplication -`zbkb` | | [Zbkb][rv-zb-zbkb] — Bit Manipulation Instructions for Cryptography -`zbkc` | | [Zbkc][rv-zb-zbc] — Carry-less multiplication for Cryptography -`zbkx` | | [Zbkx][rv-zb-zbkx] — Crossbar permutations -`zbs` | | [Zbs][rv-zb-zbs] — Single-bit instructions -`zk` | `zkn`, `zkr`, `zks`, `zkt`, `zbkb`, `zbkc`, `zkbx` | [Zk][rv-zk] — Scalar Cryptography -`zkn` | `zknd`, `zkne`, `zknh`, `zbkb`, `zbkc`, `zkbx` | [Zkn][rv-zkn] — NIST Algorithm suite extension -`zknd` | | [Zknd][rv-zknd] — NIST Suite: AES Decryption -`zkne` | | [Zkne][rv-zkne] — NIST Suite: AES Encryption -`zknh` | | [Zknh][rv-zknh] — NIST Suite: Hash Function Instructions -`zkr` | | [Zkr][rv-zkr] — Entropy Source Extension -`zks` | `zksed`, `zksh`, `zbkb`, `zbkc`, `zkbx` | [Zks][rv-zks] — ShangMi Algorithm Suite -`zksed` | | [Zksed][rv-zksed] — ShangMi Suite: SM4 Block Cipher Instructions -`zksh` | | [Zksh][rv-zksh] — ShangMi Suite: SM3 Hash Function Instructions -`zkt` | | [Zkt][rv-zkt] — Data Independent Execution Latency Subset +`a` | | [A][rv-a] --- Atomic instructions +`c` | | [C][rv-c] --- Compressed instructions +`m` | | [M][rv-m] --- Integer Multiplication and Division instructions +`zb` | `zba`, `zbc`, `zbs` | [Zb][rv-zb] --- Bit Manipulation instructions +`zba` | | [Zba][rv-zb-zba] --- Address Generation instructions +`zbb` | | [Zbb][rv-zb-zbb] --- Basic bit-manipulation +`zbc` | | [Zbc][rv-zb-zbc] --- Carry-less multiplication +`zbkb` | | [Zbkb][rv-zb-zbkb] --- Bit Manipulation Instructions for Cryptography +`zbkc` | | [Zbkc][rv-zb-zbc] --- Carry-less multiplication for Cryptography +`zbkx` | | [Zbkx][rv-zb-zbkx] --- Crossbar permutations +`zbs` | | [Zbs][rv-zb-zbs] --- Single-bit instructions +`zk` | `zkn`, `zkr`, `zks`, `zkt`, `zbkb`, `zbkc`, `zkbx` | [Zk][rv-zk] --- Scalar Cryptography +`zkn` | `zknd`, `zkne`, `zknh`, `zbkb`, `zbkc`, `zkbx` | [Zkn][rv-zkn] --- NIST Algorithm suite extension +`zknd` | | [Zknd][rv-zknd] --- NIST Suite: AES Decryption +`zkne` | | [Zkne][rv-zkne] --- NIST Suite: AES Encryption +`zknh` | | [Zknh][rv-zknh] --- NIST Suite: Hash Function Instructions +`zkr` | | [Zkr][rv-zkr] --- Entropy Source Extension +`zks` | `zksed`, `zksh`, `zbkb`, `zbkc`, `zkbx` | [Zks][rv-zks] --- ShangMi Algorithm Suite +`zksed` | | [Zksed][rv-zksed] --- ShangMi Suite: SM4 Block Cipher Instructions +`zksh` | | [Zksh][rv-zksh] --- ShangMi Suite: SM3 Hash Function Instructions +`zkt` | | [Zkt][rv-zkt] --- Data Independent Execution Latency Subset @@ -443,8 +443,8 @@ It is a compilation error to use the `instruction_set` attribute on a target tha For the `ARMv4T` and `ARMv5te` architectures, the following are supported: -* `arm::a32` - Generate the function as A32 "ARM" code. -* `arm::t32` - Generate the function as T32 "Thumb" code. +* `arm::a32` --- Generate the function as A32 "ARM" code. +* `arm::t32` --- Generate the function as T32 "Thumb" code. ```rust,ignore diff --git a/src/attributes/debugger.md b/src/attributes/debugger.md index 6d184e8..21add01 100644 --- a/src/attributes/debugger.md +++ b/src/attributes/debugger.md @@ -148,9 +148,9 @@ when generating debuginfo for code calling this macro. The attribute uses the [_MetaListIdents_] syntax to specify its inputs, and can only be applied to macro definitions. Accepted options: -- `#[collapse_debuginfo(yes)]` — code locations in debuginfo are collapsed. -- `#[collapse_debuginfo(no)]` — code locations in debuginfo are not collapsed. -- `#[collapse_debuginfo(external)]` — code locations in debuginfo are collapsed only if the macro comes from a different crate. +- `#[collapse_debuginfo(yes)]` --- code locations in debuginfo are collapsed. +- `#[collapse_debuginfo(no)]` --- code locations in debuginfo are not collapsed. +- `#[collapse_debuginfo(external)]` --- code locations in debuginfo are collapsed only if the macro comes from a different crate. The `external` behavior is the default for macros that don't have this attribute, unless they are built-in macros. For built-in macros the default is `yes`. diff --git a/src/attributes/diagnostics.md b/src/attributes/diagnostics.md index e9b6726..4f1af4d 100644 --- a/src/attributes/diagnostics.md +++ b/src/attributes/diagnostics.md @@ -281,14 +281,14 @@ deprecation, including the `since` version and `note`, if available. The `deprecated` attribute has several forms: -- `deprecated` — Issues a generic message. -- `deprecated = "message"` — Includes the given string in the deprecation +- `deprecated` --- Issues a generic message. +- `deprecated = "message"` --- Includes the given string in the deprecation message. - [_MetaListNameValueStr_] syntax with two optional fields: - - `since` — Specifies a version number when the item was deprecated. `rustc` + - `since` --- Specifies a version number when the item was deprecated. `rustc` does not currently interpret the string, but external tools like [Clippy] may check the validity of the value. - - `note` — Specifies a string that should be included in the deprecation + - `note` --- Specifies a string that should be included in the deprecation message. This is typically used to provide an explanation about the deprecation and preferred alternatives. @@ -437,9 +437,9 @@ The attribute should be placed on a [trait declaration], though it is not an err 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` — 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. +* `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. @@ -449,8 +449,8 @@ For any other non-existing option a lint-warning is generated. 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. +* `{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. diff --git a/src/inline-assembly.md b/src/inline-assembly.md index 414a36b..9d505a5 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -515,8 +515,8 @@ To avoid undefined behavior, these rules must be followed when using function-sc ### Correctness and Validity -In addition to all of the previous rules, the string argument to `asm!` must ultimately become— -after all other arguments are evaluated, formatting is performed, and operands are translated— +In addition to all of the previous rules, the string argument to `asm!` must ultimately become--- +after all other arguments are evaluated, formatting is performed, and operands are translated--- assembly that is both syntactically correct and semantically valid for the target architecture. The formatting rules allow the compiler to generate assembly with correct syntax. Rules concerning operands permit valid translation of Rust operands into and out of `asm!`. diff --git a/src/items/constant-items.md b/src/items/constant-items.md index 85d3e01..9d48762 100644 --- a/src/items/constant-items.md +++ b/src/items/constant-items.md @@ -15,8 +15,8 @@ Constants must be explicitly typed. The type must have a `'static` lifetime: any references in the initializer must have `'static` lifetimes. Constants may refer to the address of other constants, in which case the -address will have elided lifetimes where applicable, otherwise – in most cases -– defaulting to the `static` lifetime. (See [static lifetime +address will have elided lifetimes where applicable, otherwise -- in most cases +-- defaulting to the `static` lifetime. (See [static lifetime elision].) The compiler is, however, still at liberty to translate the constant many times, so the address referred to may not be stable. diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 697ac2d..ca42889 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -120,12 +120,12 @@ compiler should link with for the items within an `extern` block. It uses the name of the native library to link. The `kind` key is an optional value which specifies the kind of library with the following possible values: -- `dylib` — Indicates a dynamic library. This is the default if `kind` is not +- `dylib` --- Indicates a dynamic library. This is the default if `kind` is not specified. -- `static` — Indicates a static library. -- `framework` — Indicates a macOS framework. This is only valid for macOS +- `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. diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 014fb85..69a236d 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -165,9 +165,9 @@ identifiers separated by commas. Nested repetitions are permitted. The repetition operators are: -- `*` — indicates any number of repetitions. -- `+` — indicates any number but at least one. -- `?` — indicates an optional fragment with zero or one occurrence. +- `*` --- indicates any number of repetitions. +- `+` --- indicates any number but at least one. +- `?` --- indicates an optional fragment with zero or one occurrence. Since `?` represents at most one occurrence, it cannot be used with a separator. diff --git a/src/names.md b/src/names.md index 46d3445..44a20ab 100644 --- a/src/names.md +++ b/src/names.md @@ -6,7 +6,7 @@ the source program, usually via a [path]. Entities include [types], [items], [fields], [attributes], and [lints]. A *declaration* is a syntactical construct that can introduce a *name* to -refer to an entity. Entity names are valid within a [*scope*] — a region of +refer to an entity. Entity names are valid within a [*scope*] --- a region of source text where that name may be referenced. Some entities are [explicitly declared](#explicitly-declared-entities) in the @@ -65,11 +65,11 @@ The following entities are implicitly defined by the language, or are introduced by compiler options and extensions: * [Language prelude]: - * [Boolean type] — `bool` - * [Textual types] — `char` and `str` - * [Integer types] — `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128` - * [Machine-dependent integer types] — `usize` and `isize` - * [floating-point types] — `f32` and `f64` + * [Boolean type] --- `bool` + * [Textual types] --- `char` and `str` + * [Integer types] --- `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128` + * [Machine-dependent integer types] --- `usize` and `isize` + * [floating-point types] --- `f32` and `f64` * [Built-in attributes] * [Standard library prelude] items, attributes, and macros * [Standard library][extern-prelude] crates in the root module diff --git a/src/names/namespaces.md b/src/names/namespaces.md index bb4409b..36b2e10 100644 --- a/src/names/namespaces.md +++ b/src/names/namespaces.md @@ -37,7 +37,7 @@ The following is a list of namespaces, with their corresponding entities: * [Generic const parameters] * [Associated const declarations] * [Associated function declarations] - * Local bindings — [`let`], [`if let`], [`while let`], [`for`], [`match`] + * Local bindings --- [`let`], [`if let`], [`while let`], [`for`], [`match`] arms, [function parameters], [closure parameters] * Captured [closure] variables * Macro Namespace diff --git a/src/names/preludes.md b/src/names/preludes.md index 00a1129..f557699 100644 --- a/src/names/preludes.md +++ b/src/names/preludes.md @@ -105,11 +105,11 @@ The language prelude includes names of types and attributes that are built-in to the language. The language prelude is always in scope. It includes the following: * [Type namespace] - * [Boolean type] — `bool` - * [Textual types] — `char` and `str` - * [Integer types] — `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128` - * [Machine-dependent integer types] — `usize` and `isize` - * [floating-point types] — `f32` and `f64` + * [Boolean type] --- `bool` + * [Textual types] --- `char` and `str` + * [Integer types] --- `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, `u128` + * [Machine-dependent integer types] --- `usize` and `isize` + * [floating-point types] --- `f32` and `f64` * [Macro namespace] * [Built-in attributes] diff --git a/src/tokens.md b/src/tokens.md index 46c521f..3b5cef7 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -93,7 +93,7 @@ A suffix is a sequence of characters following the primary part of a literal (wi > **Lexer**\ > SUFFIX : IDENTIFIER_OR_KEYWORD\ -> SUFFIX_NO_E : SUFFIX _not beginning with `e` or `E`_ +> 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. diff --git a/src/types.md b/src/types.md index aed10fd..0f82638 100644 --- a/src/types.md +++ b/src/types.md @@ -12,10 +12,10 @@ limited capabilities. The list of types is: * Primitive types: - * [Boolean] — `bool` - * [Numeric] — integer and float - * [Textual] — `char` and `str` - * [Never] — `!` — a type with no values + * [Boolean] --- `bool` + * [Numeric] --- integer and float + * [Textual] --- `char` and `str` + * [Never] --- `!` --- a type with no values * Sequence types: * [Tuple] * [Array] From 4e5aaf23590dc0c7f984ce7f5cf0918eedc0ef1d Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 1 Jul 2024 13:24:01 -0700 Subject: [PATCH 396/463] Add checks for hard-to-see characters. --- style-check/src/main.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/style-check/src/main.rs b/style-check/src/main.rs index 2589cd6..8452b26 100644 --- a/style-check/src/main.rs +++ b/style-check/src/main.rs @@ -51,7 +51,7 @@ fn check_directory(dir: &Path, bad: &mut bool) -> Result<(), Box> { if contents.contains("#![feature") { style_error!(bad, path, "#![feature] attributes are not allowed"); } - if contents.contains('\r') { + if !cfg!(windows) && contents.contains('\r') { style_error!( bad, path, @@ -64,6 +64,15 @@ fn check_directory(dir: &Path, bad: &mut bool) -> Result<(), Box> { if !contents.ends_with('\n') { style_error!(bad, path, "file must end with a newline"); } + if contents.contains('\u{2013}') { + style_error!(bad, path, "en-dash not allowed, use two dashes like --"); + } + if contents.contains('\u{2014}') { + style_error!(bad, path, "em-dash not allowed, use three dashes like ---"); + } + if contents.contains('\u{a0}') { + style_error!(bad, path, "don't use 0xa0 no-break-space, use   instead"); + } for line in contents.lines() { if line.ends_with(' ') { style_error!(bad, path, "lines must not end with spaces"); From 812bf59c65c630d692b17cda774250201ef18199 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 1 Jul 2024 13:24:22 -0700 Subject: [PATCH 397/463] Update pulldown-cmark to 0.10. This is to bring it in-sync with mdbook. --- style-check/Cargo.lock | 33 +++++++++++++++++++++------------ style-check/Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/style-check/Cargo.lock b/style-check/Cargo.lock index 1b62290..941c366 100644 --- a/style-check/Cargo.lock +++ b/style-check/Cargo.lock @@ -1,10 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "bitflags" -version = "1.2.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "getopts" @@ -17,22 +19,29 @@ dependencies = [ [[package]] name = "memchr" -version = "2.3.3" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "pulldown-cmark" -version = "0.8.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" +checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ "bitflags", "getopts", "memchr", + "pulldown-cmark-escape", "unicase", ] +[[package]] +name = "pulldown-cmark-escape" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" + [[package]] name = "style-check" version = "0.1.0" @@ -42,21 +51,21 @@ dependencies = [ [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/style-check/Cargo.toml b/style-check/Cargo.toml index d592f65..1fa5780 100644 --- a/style-check/Cargo.toml +++ b/style-check/Cargo.toml @@ -5,4 +5,4 @@ authors = ["steveklabnik "] edition = "2021" [dependencies] -pulldown-cmark = "0.8" +pulldown-cmark = "0.10.0" From 1290f424b494f2e99e692e48ba88f49dcccff948 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 27 Jun 2024 10:07:13 -0700 Subject: [PATCH 398/463] Start using mdbook-spec for the reference. This preprocessor adds support for several Markdown extensions that should assist with writing. --- README.md | 7 ++ book.toml | 2 + theme/reference.css | 166 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 175 insertions(+) diff --git a/README.md b/README.md index c525617..ff75557 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ what we have for now. - Nightly Rust - [mdbook](https://rust-lang.github.io/mdBook/) +- [`mdbook-spec`](https://github.com/rust-lang/spec/tree/main/mdbook-spec) ## Installing dependencies @@ -29,6 +30,12 @@ build the Reference: cargo install --locked mdbook ``` +Also install `mdbook-spec` which is a preprocessor which adds some Markdown extensions: + +```sh +cargo install --locked mdbook-spec +``` + ## Building To build the Reference, first clone the project: diff --git a/book.toml b/book.toml index 505e081..3bafa24 100644 --- a/book.toml +++ b/book.toml @@ -16,3 +16,5 @@ smart-punctuation = true [rust] edition = "2021" + +[preprocessor.spec] diff --git a/theme/reference.css b/theme/reference.css index 02e5f63..8d000fb 100644 --- a/theme/reference.css +++ b/theme/reference.css @@ -1,3 +1,5 @@ +/* Custom CSS for the Rust Specification. */ + /* .parenthetical class used to keep e.g. "less-than symbol (<)" from wrapping the end parenthesis onto its own line. Use in a span between the last word and @@ -51,3 +53,167 @@ main .warning p::before { .ayu main .warning p a { color: #80d0d0; } + +/* tags can be used to highlight specific character elements. */ +kbd { + border: 1px solid #999; + display: inline-block; + border-radius: 3px; + padding: 0 0.6ex; + background: #eee; + box-shadow: inset -1px -1px 0 #999; + vertical-align: baseline; + color: #000; + height: 1.55em; + font-style: normal; + font-weight: bold; + font-family: inherit; + font-size: revert; + line-height: revert; +} +kbd.optional { + border-style: dashed; + background: #fff; +} +var.optional { + border-style: dashed; +} + +/* tags can be used for non-terminals. */ +var { + border: 1px solid #9c9; + box-shadow: inset -1px -1px 0 #9c9; + font-style: normal; + display: inline-block; + vertical-align: baseline; + border-radius: 7px; + padding: 0 4px; + background: #dfd; + margin: 2px; +} +var.type { + box-shadow: inset -1px -1px 0 #c99; + border-color: #c99; + background: #fdd; +} + +/* can be used for a grammar production that repeats zero or more times. */ +span.repeat { + position: relative; + border: 1px dashed #393; + border-radius: 10px; + display: inline-block; + padding: 6px; + margin-left: 0.5ex; + margin-top: 1em; + margin-bottom: 0.5ex; + min-width: 3.8em; + text-align: center; +} +span.repeat::before { + content: "zero or more"; + white-space: nowrap; + display: block; + text-align: center; + font-size: 0.75em; + position: absolute; + left: 0; + right: 0; + top: -1.4em; + color: #393; +} +var > span { + display: inline-block; + border-right: 1px dotted green; + padding-right: 0.5ex; + margin-right: 0.5ex; + font-style: italic; +} + +/* can be used to highlight a specific version of Rust. */ +span.version { + float: right; + margin-left: 1em; + margin-bottom: 1em; + background: #f7c0eb; + padding: 0.2ex 0.5ex; + border-radius: 5px; + display: block; + box-shadow: inset -1px -1px 0 #a06894; + font-size: 0.9em; +} + +/* tags are used to indicate a specific word or phrase is being defined. */ +dfn { + font-style: italic; + text-decoration: underline; +} + +.content main { + /* Provides space on the left for the rule call-outs. */ + padding-left: 4em; +} + +/* Rules are generated via r[foo.bar] syntax, processed by mdbook-spec. */ +.rule { + /* Allows the rule to be positioned. */ + position: relative; + /* Position slightly to the left. */ + left: -4em; + color: #999; + font-size: 0.8em; +} +/* mdbook will wrap the rule content in a

    tag, with a margin. However, we + don't need the extra space +*/ +.rule ~ p { + margin-top: 0px; +} + +/* Change the default styling of blockquotes. */ +blockquote { + padding: 1ex 1em; + margin: 1ex; + margin-left: 2em; + /* vw units allow this to be adaptive to the screen size so it isn't too small on mobile. */ + margin-right: 12vw; +} + +/* mdbook will wrap the blockquote content in a

    tag, with a margin. However, + that adds too much space, so remove it. +*/ +blockquote > p { + margin-top: 0px; + margin-bottom: 0px; +} + +/* When the sidebar is visible, reduce the spacing of rules so that the + content doesn't get shifted too far, and make the text too narrow. +*/ +.sidebar-visible .rule { + left: -1em; +} +.sidebar-visible .content main { + padding-left: 1em; +} + +/* Remove the blue coloring of links on rules that mdbook normally sets. */ +.rule-link { + color: #999 !important; +} + +/* When clicking a rule, it is added as a URL fragment and the browser will + navigate to it. This adds an indicator that the linked rule is the one that + is "current", just like normal headers are in mdbook. +*/ +.rule:target::before { + display: inline-block; + content: "»"; + margin-inline-start: -20px; + width: 20px; +} + +/* Sets the color for [!HISTORY] blockquote admonitions. */ +.history > blockquote { + background: #f7c0eb; +} From 002e19cb5c118b3dcad947535c1eac61fcb06f66 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 1 Jul 2024 13:43:42 -0700 Subject: [PATCH 399/463] Copy the spec authoring guide over verbatim. The next commit will update to keep in sync with the reference. --- docs/authoring.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docs/authoring.md diff --git a/docs/authoring.md b/docs/authoring.md new file mode 100644 index 0000000..f92b442 --- /dev/null +++ b/docs/authoring.md @@ -0,0 +1,79 @@ +# Authoring Guide + +## Markdown formatting + +* Use [ATX-style headings][atx] (not Setext) with [sentence case]. +* Do not use tabs, only spaces. +* Files must end with a newline. +* Lines must not end with spaces. Double spaces have semantic meaning, but can be invisible. Use a trailing backslash if you need a hard line break. +* If possible, avoid double blank lines. +* Do not use indented code blocks, use 3+ backticks code blocks instead. +* Code blocks should have an explicit language tag. +* Do not wrap long lines. This helps with reviewing diffs of the source. +* Use [smart punctuation] instead of Unicode characters. For example, use `---` for em-dash instead of the Unicode character. Characters like em-dash can be difficult to see in a fixed-width editor, and some editors may not have easy methods to enter such characters. + +There are automated checks for some of these rules. Run `cargo run --manifest-path style-check/Cargo.toml -- spec` to run them locally. + +[atx]: https://spec.commonmark.org/0.31.2/#atx-headings +[sentence case]: https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case +[smart punctuation]: https://rust-lang.github.io/mdBook/format/markdown.html#smart-punctuation + +## Special markdown constructs + +### Rules + +Most clauses should be preceded with a rule. +Rules can be specified in the markdown source with the following on a line by itself: + +``` +r[foo.bar] +``` + +The rule name should be lowercase, with periods separating from most general to most specific (like `r[array.repeat.zero]`). + +Rules can be linked to by their ID using markdown such as `[foo.bar]`. There are automatic link references so that any rule can be referred to from any page in the book. + +In the HTML, the rules are clickable just like headers. + +### Standard library links + +You should link to the standard library without specifying a URL in a fashion similar to [rustdoc intra-doc links][intra]. Some examples: + +``` +Link to Option is [`std::option::Option`] + +You can include generics, they are ignored, like [`std::option::Option`] + +You can shorthand things if you don't want the full path in the text, +like [`Option`](std::option::Option). + +Macros can use `!`, which also works for disambiguation, +like [`alloc::vec!`] is the macro, not the module. + +Explicit namespace disambiguation is also supported, such as [`std::vec`](mod@std::vec). +``` + +[intra]: https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html + +### Admonitions + +Admonitions use a style similar to GitHub-flavored markdown, where the style name is placed at the beginning of a blockquote, such as: + +``` +> [!WARNING] +> This is a warning. +``` + +All this does is apply a CSS class to the blockquote. You should define the color or style of the rule in the `css/custom.css` file if it isn't already defined. + +## Content guidelines + +The following are guidelines for the content of the spec. + +### Targets + +The spec does not document which targets exist, or the properties of specific targets. The spec may refer to *platforms* or *target properties* where required by the language. Some examples: + +* Conditional-compilation keys like `target_os` are specified to exist, but not what their values must be. +* The `windows_subsystem` attribute specifies that it only works on Windows platforms. +* Inline assembly and the `target_feature` attribute specify the architectures that are supported. From b2ffe291c605802acf20477d04253f635ee892f0 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 1 Jul 2024 13:53:37 -0700 Subject: [PATCH 400/463] Merge the Reference style guide to the authoring guide. --- CONTRIBUTING.md | 4 +-- docs/authoring.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8cf73c1..6a9fe6a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ enough that we can remove the warning. It is encouraged for you to read the [introduction] to familiarize yourself with the kind of content the reference is expected to contain and the -conventions it uses. Also, the [style guide] provides more detailed guidelines +conventions it uses. Also, the [Authoring Guide] provides more detailed guidelines for formatting and content. ## Critiquing the Reference @@ -72,5 +72,5 @@ helpful for writing the documentation. [issue tracker]: https://github.com/rust-lang/reference/issues [playpen]: https://play.rust-lang.org/ [rust-lang/rust]: https://github.com/rust-lang/rust/ -[style guide]: STYLE.md +[Authoring Guide]: docs/authoring.md [unstable]: https://doc.rust-lang.org/nightly/unstable-book/ diff --git a/docs/authoring.md b/docs/authoring.md index f92b442..3a92006 100644 --- a/docs/authoring.md +++ b/docs/authoring.md @@ -1,5 +1,10 @@ # Authoring Guide +This document serves as a guide for editors and reviewers. +Some conventions and content guidelines are specified in the [introduction]. + +[introduction]: ../src/introduction.md + ## Markdown formatting * Use [ATX-style headings][atx] (not Setext) with [sentence case]. @@ -11,15 +16,58 @@ * Code blocks should have an explicit language tag. * Do not wrap long lines. This helps with reviewing diffs of the source. * Use [smart punctuation] instead of Unicode characters. For example, use `---` for em-dash instead of the Unicode character. Characters like em-dash can be difficult to see in a fixed-width editor, and some editors may not have easy methods to enter such characters. +* Links should be relative with the `.md` extension. + Links to other rust-lang books that are published with the reference or the standard library API should also be relative so that the linkchecker can validate them. +* The use of reference links is preferred, with shortcuts if appropriate. + Place the sorted link reference definitions at the bottom of the file, or at the bottom of a section if there is an unusually large number of links that are specific to the section. + + ``` + Example of shortcut link: [enumerations] + Example of reference link with label: [block expression][block] -There are automated checks for some of these rules. Run `cargo run --manifest-path style-check/Cargo.toml -- spec` to run them locally. + [block]: expressions/block-expr.md + [enumerations]: types/enum.md + ``` +* See the [Conventions] section for formatting callouts such as notes, edition differences, and warnings. + +There are automated checks for some of these rules. Run `cargo run --manifest-path style-check/Cargo.toml -- src` to run them locally. [atx]: https://spec.commonmark.org/0.31.2/#atx-headings [sentence case]: https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case [smart punctuation]: https://rust-lang.github.io/mdBook/format/markdown.html#smart-punctuation +[conventions]: ../src/introduction.md#conventions + +### Code examples + +Code examples should use code blocks with triple backticks. +The language should always be specified (such as `rust`). + +```rust +println!("Hello!"); +``` + +See for a list of supported languages. + +Rust examples are tested via rustdoc, and should include the appropriate annotations when tests are expected to fail: + +* `edition2015` or `edition2018` — If it is edition-specific (see `book.toml` for the default). +* `no_run` — The example should compile successfully, but should not be executed. +* `should_panic` — The example should compile and run, but produce a panic. +* `compile_fail` — The example is expected to fail to compile. +* `ignore` — The example shouldn't be built or tested. + This should be avoided if possible. + Usually this is only necessary when the testing framework does not support it (such as external crates or modules, or a proc-macro), or it contains pseudo-code which is not valid Rust. + An HTML comment such as `` should be placed before the example to explain why it is ignored. +* `Exxxx` — If the example is expected to fail to compile with a specific error code, include that code so that rustdoc will check that the expected code is used. + +See the [rustdoc documentation] for more detail. + +[rustdoc documentation]: https://doc.rust-lang.org/rustdoc/documentation-tests.html ## Special markdown constructs +The following are extensions provided by [`mdbook-spec`](https://github.com/rust-lang/spec/tree/main/mdbook-spec). + ### Rules Most clauses should be preceded with a rule. @@ -66,6 +114,13 @@ Admonitions use a style similar to GitHub-flavored markdown, where the style nam All this does is apply a CSS class to the blockquote. You should define the color or style of the rule in the `css/custom.css` file if it isn't already defined. +## Style + +Idioms and styling to avoid: + +* Avoid slashes for alternatives ("program/binary"), use conjunctions or rewrite it ("program or binary"). +* Avoid qualifying something as "in Rust", the entire reference is about Rust. + ## Content guidelines The following are guidelines for the content of the spec. @@ -77,3 +132,8 @@ The spec does not document which targets exist, or the properties of specific ta * Conditional-compilation keys like `target_os` are specified to exist, but not what their values must be. * The `windows_subsystem` attribute specifies that it only works on Windows platforms. * Inline assembly and the `target_feature` attribute specify the architectures that are supported. + +### Editions + +The main text and flow should document only the current edition. +Whenever there is a difference between editions, the differences should be called out with an "Edition Differences" block. From 0463d4f66ef26970a184d80ddcb30510398cdad4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 1 Jul 2024 14:13:49 -0700 Subject: [PATCH 401/463] Update CI to use mdbook-spec --- .github/workflows/main.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2196952..227aeba 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,12 +3,25 @@ on: pull_request: merge_group: +env: + MDBOOK_VERSION: 0.4.40 + # When updating, be sure to also update rust-lang/rust. + MDBOOK_SPEC_VERSION: 0.1.0 + jobs: test: name: Test runs-on: ubuntu-latest steps: - uses: actions/checkout@master + - name: Cache + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/.crates.toml + ~/.cargo/.crates2.json + key: ms-${MDBOOK_SPEC_VERSION} - name: Update rustup run: rustup self update - name: Install Rust @@ -19,13 +32,15 @@ jobs: - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.40/mdbook-v0.4.40-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v${MDBOOK_VERSION}/mdbook-v${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> $GITHUB_PATH - name: Report versions run: | rustup --version rustc -Vv mdbook --version + - name: Install mdbook-spec + run: cargo install --locked mdbook-spec@${MDBOOK_SPEC_VERSION} - name: Run tests run: mdbook test - name: Style checks From 6022b2ff80001fb80f42d04c44163be8ea0cfe74 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 28 Jan 2024 09:14:42 +0000 Subject: [PATCH 402/463] Remove confusing usage of terminology "block of a function" It's usually referred to as the "body" of the function, and I'm making it consistent here. In order to emphasize the nature of the body of a block, occasionally "body block" is used. (One instance of "body block" was already present.) This particularly improves the sentence that used to explain "The block of a function is conceptually wrapped in a block that binds ..." which was just plain confusing. --- src/items/functions.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/items/functions.md b/src/items/functions.md index 5b4ac7a..47059ad 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -42,7 +42,8 @@ > [^fn-param-2015]: Function parameters with only a type are only allowed > in an associated function of a [trait item] in the 2015 edition. -A _function_ consists of a [block], along with a name, a set of parameters, and an output type. +A _function_ consists of a [block] (that's the _body_ of the function), +along with a name, a set of parameters, and an output type. Other than a name, all these are optional. Functions are declared with the keyword `fn`. Functions may declare a set of *input* [*variables*][variables] as parameters, through which the caller passes arguments into the function, and the *output* [*type*][type] of the value the function will return to its caller on completion. @@ -76,8 +77,8 @@ parameter may have an optional identifier, such as `args: ...`. ## Function body -The block of a function is conceptually wrapped in a block that binds the -argument patterns and then `return`s the value of the function's block. This +The body block of a function is conceptually wrapped in another block that first binds the +argument patterns and then `return`s the value of the function's body. This means that the tail expression of the block, if evaluated, ends up being returned to the caller. As usual, an explicit return expression within the body of the function will short-cut that implicit return, if reached. @@ -321,7 +322,7 @@ responsibility to ensure that. ## Attributes on functions [Outer attributes][attributes] are allowed on functions. [Inner -attributes][attributes] are allowed directly after the `{` inside its [block]. +attributes][attributes] are allowed directly after the `{` inside its body [block]. This example shows an inner attribute on a function. The function is documented with just the word "Example". From b2ba04219de7b39927e001e55e59087febbf1217 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 3 Jul 2024 19:57:13 +0000 Subject: [PATCH 403/463] Add clarification from nikomatsakis Niko requested this clarification about whether "happens inside an `UnsafeCell` meant "happens to bytes inside of an `UnsafeCell`", so let's go ahead and just add that language to the text. --- src/items/external-blocks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items/external-blocks.md b/src/items/external-blocks.md index 95d16d6..8e1aa2f 100644 --- a/src/items/external-blocks.md +++ b/src/items/external-blocks.md @@ -57,7 +57,7 @@ Extern statics can be either immutable or mutable just like [statics] outside of An immutable static *must* be initialized before any Rust code is executed. It is not enough for the static to be initialized before Rust code reads from it. Once Rust code runs, mutating an immutable static (from inside or outside Rust) is UB, -except if the mutation happens inside an `UnsafeCell`. +except if the mutation happens to bytes inside of an `UnsafeCell`. ## ABI From c278b265ebd0cba8bb5abf4c5836c33cf7f23824 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 3 Jul 2024 22:33:01 +0000 Subject: [PATCH 404/463] Add clarification on linking Co-authored-by: Vadim Petrochenkov --- src/linkage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linkage.md b/src/linkage.md index 4864a49..3ac6bb2 100644 --- a/src/linkage.md +++ b/src/linkage.md @@ -50,7 +50,7 @@ be ignored in favor of only building the artifacts specified by command line. Note that any dynamic dependencies that the static library may have (such as dependencies on system libraries, or dependencies on Rust libraries that are compiled as dynamic libraries) will have to be specified manually when - linking. The `--print=native-static-libs` flag may help with this. + linking that static library from somewhere. The `--print=native-static-libs` flag may help with this. * `--crate-type=cdylib`, `#![crate_type = "cdylib"]` - A dynamic system library will be produced. This is used when compiling From 4cdcd332da69ceba5aba0c7aa42aaac91657beb0 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 4 Jul 2024 03:59:19 +0000 Subject: [PATCH 405/463] Sort link section alphabetically This link section was already sorted but for a recent change (that understandably probably preferred to keep the diff contained). Let's restore the sort order of the links here. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6a9fe6a..af811b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,9 +68,9 @@ This should include links to any relevant information, such as the stabilization PR, the RFC, the tracking issue, and anything else that would be helpful for writing the documentation. +[Authoring Guide]: docs/authoring.md [introduction]: src/introduction.md [issue tracker]: https://github.com/rust-lang/reference/issues [playpen]: https://play.rust-lang.org/ [rust-lang/rust]: https://github.com/rust-lang/rust/ -[Authoring Guide]: docs/authoring.md [unstable]: https://doc.rust-lang.org/nightly/unstable-book/ From 68ab1221ef4e443e6e1e97206d75557c44f53ef2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 4 Jul 2024 04:02:19 +0000 Subject: [PATCH 406/463] Rewrap paragraph The CONTRIBUTING guide seems wrapped at 80 character lines. Let's rewrap a paragraph with a line that had overflowed. --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index af811b2..4877903 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,10 +14,10 @@ for the Reference. As such, we have the warning saying there's work that needs to be done. Eventually, we plan to make sure everything is well documented enough that we can remove the warning. -It is encouraged for you to read the [introduction] to familiarize yourself -with the kind of content the reference is expected to contain and the -conventions it uses. Also, the [Authoring Guide] provides more detailed guidelines -for formatting and content. +It is encouraged for you to read the [introduction] to familiarize yourself with +the kind of content the reference is expected to contain and the conventions it +uses. Also, the [Authoring Guide] provides more detailed guidelines for +formatting and content. ## Critiquing the Reference From 6f11d3cd7c213f4cb1a871452869949a0ff3bc5b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 4 Jul 2024 04:49:01 +0000 Subject: [PATCH 407/463] Follow the authoring guide in the authoring guide Let's follow our own rules in the authoring guide by, e.g., using `---` rather than the Unicode em-dash character, not wrapping lines, specifying the language for code block sections, etc. To improve formatting, we broke out some descriptions that were in code block sections into the main text. We replaced references to "the spec" with "the reference" for consistency, as that's what most of this document uses. And we made some other small editorial improvements. --- docs/authoring.md | 83 +++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/docs/authoring.md b/docs/authoring.md index 3a92006..beafaa3 100644 --- a/docs/authoring.md +++ b/docs/authoring.md @@ -1,7 +1,6 @@ # Authoring Guide -This document serves as a guide for editors and reviewers. -Some conventions and content guidelines are specified in the [introduction]. +This document serves as a guide for editors and reviewers. Some conventions and content guidelines are specified in the [introduction]. [introduction]: ../src/introduction.md @@ -12,16 +11,14 @@ Some conventions and content guidelines are specified in the [introduction]. * Files must end with a newline. * Lines must not end with spaces. Double spaces have semantic meaning, but can be invisible. Use a trailing backslash if you need a hard line break. * If possible, avoid double blank lines. -* Do not use indented code blocks, use 3+ backticks code blocks instead. +* Do not use indented code blocks; use 3+ backticks code blocks instead. * Code blocks should have an explicit language tag. * Do not wrap long lines. This helps with reviewing diffs of the source. * Use [smart punctuation] instead of Unicode characters. For example, use `---` for em-dash instead of the Unicode character. Characters like em-dash can be difficult to see in a fixed-width editor, and some editors may not have easy methods to enter such characters. -* Links should be relative with the `.md` extension. - Links to other rust-lang books that are published with the reference or the standard library API should also be relative so that the linkchecker can validate them. -* The use of reference links is preferred, with shortcuts if appropriate. - Place the sorted link reference definitions at the bottom of the file, or at the bottom of a section if there is an unusually large number of links that are specific to the section. +* Links should be relative with the `.md` extension. Links to other rust-lang books that are published with the reference or the standard library API should also be relative so that the linkchecker can validate them. +* The use of reference links is preferred, with shortcuts if appropriate. Place the sorted link reference definitions at the bottom of the file, or at the bottom of a section if there are an unusually large number of links that are specific to the section. - ``` + ```markdown Example of shortcut link: [enumerations] Example of reference link with label: [block expression][block] @@ -33,14 +30,13 @@ Some conventions and content guidelines are specified in the [introduction]. There are automated checks for some of these rules. Run `cargo run --manifest-path style-check/Cargo.toml -- src` to run them locally. [atx]: https://spec.commonmark.org/0.31.2/#atx-headings +[conventions]: ../src/introduction.md#conventions [sentence case]: https://apastyle.apa.org/style-grammar-guidelines/capitalization/sentence-case [smart punctuation]: https://rust-lang.github.io/mdBook/format/markdown.html#smart-punctuation -[conventions]: ../src/introduction.md#conventions ### Code examples -Code examples should use code blocks with triple backticks. -The language should always be specified (such as `rust`). +Code examples should use code blocks with triple backticks. The language should always be specified (such as `rust`). ```rust println!("Hello!"); @@ -48,17 +44,14 @@ println!("Hello!"); See for a list of supported languages. -Rust examples are tested via rustdoc, and should include the appropriate annotations when tests are expected to fail: +Rust examples are tested via rustdoc, and should include the appropriate annotations: -* `edition2015` or `edition2018` — If it is edition-specific (see `book.toml` for the default). -* `no_run` — The example should compile successfully, but should not be executed. -* `should_panic` — The example should compile and run, but produce a panic. -* `compile_fail` — The example is expected to fail to compile. -* `ignore` — The example shouldn't be built or tested. - This should be avoided if possible. - Usually this is only necessary when the testing framework does not support it (such as external crates or modules, or a proc-macro), or it contains pseudo-code which is not valid Rust. - An HTML comment such as `` should be placed before the example to explain why it is ignored. -* `Exxxx` — If the example is expected to fail to compile with a specific error code, include that code so that rustdoc will check that the expected code is used. +* `edition2015` or `edition2018` --- If it is edition-specific (see `book.toml` for the default). +* `no_run` --- The example should compile successfully, but should not be executed. +* `should_panic` --- The example should compile and run, but produce a panic. +* `compile_fail` --- The example is expected to fail to compile. +* `ignore` --- The example shouldn't be built or tested. This should be avoided if possible. Usually this is only necessary when the testing framework does not support it (such as external crates or modules, or a proc-macro), or it contains pseudo-code which is not valid Rust. An HTML comment such as `` should be placed before the example to explain why it is ignored. +* `Exxxx` --- If the example is expected to fail to compile with a specific error code, include that code so that rustdoc will check that the expected code is used. See the [rustdoc documentation] for more detail. @@ -70,10 +63,9 @@ The following are extensions provided by [`mdbook-spec`](https://github.com/rust ### Rules -Most clauses should be preceded with a rule. -Rules can be specified in the markdown source with the following on a line by itself: +Most clauses should be preceded with a rule. Rules can be specified in the markdown source with the following on a line by itself: -``` +```markdown r[foo.bar] ``` @@ -87,18 +79,34 @@ In the HTML, the rules are clickable just like headers. You should link to the standard library without specifying a URL in a fashion similar to [rustdoc intra-doc links][intra]. Some examples: +We can link to the page on `Option`: + +```markdown +[`std::option::Option`] ``` -Link to Option is [`std::option::Option`] -You can include generics, they are ignored, like [`std::option::Option`] +In these links, generics are ignored and can be included: -You can shorthand things if you don't want the full path in the text, -like [`Option`](std::option::Option). +```markdown +[`std::option::Option`] +``` -Macros can use `!`, which also works for disambiguation, -like [`alloc::vec!`] is the macro, not the module. +If we don't want the full path in the text, we can write: -Explicit namespace disambiguation is also supported, such as [`std::vec`](mod@std::vec). +```markdown +[`Option`](std::option::Option) +``` + +Macros can end in `!`. This can be helpful for disambiguation. For example, this refers to the macro rather than the module: + +```markdown +[`alloc::vec!`] +``` + +Explicit namespace disambiguation is also supported: + +```markdown +[`std::vec`](mod@std::vec) ``` [intra]: https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html @@ -107,7 +115,7 @@ Explicit namespace disambiguation is also supported, such as [`std::vec`](mod@st Admonitions use a style similar to GitHub-flavored markdown, where the style name is placed at the beginning of a blockquote, such as: -``` +```markdown > [!WARNING] > This is a warning. ``` @@ -118,16 +126,16 @@ All this does is apply a CSS class to the blockquote. You should define the colo Idioms and styling to avoid: -* Avoid slashes for alternatives ("program/binary"), use conjunctions or rewrite it ("program or binary"). -* Avoid qualifying something as "in Rust", the entire reference is about Rust. +* Avoid slashes for alternatives ("program/binary"); use conjunctions or rewrite it ("program or binary"). +* Avoid qualifying something as "in Rust"; the entire reference is about Rust. ## Content guidelines -The following are guidelines for the content of the spec. +The following are guidelines for the content of the reference. ### Targets -The spec does not document which targets exist, or the properties of specific targets. The spec may refer to *platforms* or *target properties* where required by the language. Some examples: +The reference does not document which targets exist, or the properties of specific targets. The reference may refer to *platforms* or *target properties* where required by the language. Some examples: * Conditional-compilation keys like `target_os` are specified to exist, but not what their values must be. * The `windows_subsystem` attribute specifies that it only works on Windows platforms. @@ -135,5 +143,4 @@ The spec does not document which targets exist, or the properties of specific ta ### Editions -The main text and flow should document only the current edition. -Whenever there is a difference between editions, the differences should be called out with an "Edition Differences" block. +The main text and flow should document only the current edition. Whenever there is a difference between editions, the differences should be called out with an "Edition Differences" block. From 00fa182043cd7d36eebabf66effba6953e69cb6f Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 4 Jul 2024 04:55:59 +0000 Subject: [PATCH 408/463] Copy remaining style guidance to authoring guide These two items of style were the only bits present in the style guide and missing from the authoring guide. Let's copy them over, since they are true of the Reference, and this will let us delete the style guide entirely. --- docs/authoring.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/authoring.md b/docs/authoring.md index beafaa3..256cb30 100644 --- a/docs/authoring.md +++ b/docs/authoring.md @@ -126,6 +126,8 @@ All this does is apply a CSS class to the blockquote. You should define the colo Idioms and styling to avoid: +* Use American English spelling. +* Use Oxford commas. * Avoid slashes for alternatives ("program/binary"); use conjunctions or rewrite it ("program or binary"). * Avoid qualifying something as "in Rust"; the entire reference is about Rust. From af851d7e29d6bba6974b217741f4c60c5d8b4e1c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 4 Jul 2024 04:59:54 +0000 Subject: [PATCH 409/463] Replace style guide with a link to the authoring guide The authoring guide now fully incorporates and supersedes the style guide, so let's simply link to that from the style guide. --- STYLE.md | 70 ++------------------------------------------------------ 1 file changed, 2 insertions(+), 68 deletions(-) diff --git a/STYLE.md b/STYLE.md index 977637b..5a64884 100644 --- a/STYLE.md +++ b/STYLE.md @@ -1,71 +1,5 @@ # Rust reference style guide -Some conventions and content guidelines are specified in the [introduction]. -This document serves as a guide for editors and reviewers. +See the [Authoring Guide] for details on the style used in the reference. -There is a [`style-check`](style-check/) tool which is run in CI to check some of these. To use it locally, run `cargo run --manifest-path=style-check/Cargo.toml src`. - -## Markdown formatting - -* Use ATX-style heading with sentence case. -* Use one line per sentence to make diffs nicer. - Do not wrap long lines. -* Use reference links, with shortcuts if appropriate. - Place the sorted link reference definitions at the bottom of the file, or at the bottom of a section if there is an unusually large number of links that are specific to the section. - - ``` - Example of shortcut link: [enumerations] - Example of reference link with label: [block expression][block] - - [block]: expressions/block-expr.md - [enumerations]: types/enum.md - ``` - -* Links should be relative with the `.md` extension. - Links to other rust-lang books that are published with the reference or the standard library API should also be relative so that the linkchecker can validate them. -* See the [Conventions] section for formatting callouts such as notes, edition differences, and warnings. -* Formatting to avoid: - * Avoid trailing spaces. - * Avoid double blank lines. - -### Code examples - -Code examples should use code blocks with triple backticks. -The language should always be specified (such as `rust`). - -```rust -println!("Hello!"); -``` - -See https://highlightjs.org/ for a list of supported languages. - -Rust examples are tested via rustdoc, and should include the appropriate annotations when tests are expected to fail: - -* `edition2015` or `edition2018` --- If it is edition-specific (see `book.toml` for the default). -* `no_run` --- The example should compile successfully, but should not be executed. -* `should_panic` --- The example should compile and run, but produce a panic. -* `compile_fail` --- The example is expected to fail to compile. -* `ignore` --- The example shouldn't be built or tested. - This should be avoided if possible. - Usually this is only necessary when the testing framework does not support it (such as external crates or modules, or a proc-macro), or it contains pseudo-code which is not valid Rust. - An HTML comment such as `` should be placed before the example to explain why it is ignored. - -See the [rustdoc documentation] for more detail. - -## Language and grammar - -* Use American English spelling. -* Use Oxford commas. -* Idioms and styling to avoid: - * Avoid slashes for alternatives ("program/binary"), use conjunctions or rewrite it ("program or binary"). - * Avoid qualifying something as "in Rust", the entire reference is about Rust. - -## Content - -* Whenever there is a difference between editions, the differences should be called out with an "Edition Differences" block. - The main text should stick to what is common between the editions. - However, for large differences (such as "async"), the main text may contain edition-specific content as long as it is made clear which editions it applies to. - -[conventions]: src/introduction.md#conventions -[introduction]: src/introduction.md -[rustdoc documentation]: https://doc.rust-lang.org/rustdoc/documentation-tests.html +[Authoring Guide]: docs/authoring.md From cefc315891d365f4ea44e9be68346522ddcc8120 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 24 Jan 2024 09:48:21 +0800 Subject: [PATCH 410/463] Add `.insn` assembly directive. `.insn` was added to gnu-as in 2018 in https://github.com/bminor/binutils-gdb/commit/0e35537d754f1c687850d1caccb2d78d2e418391 and in llvm in llvm-14 in https://github.com/llvm/llvm-project/commit/283879793dc787225992496587581ec77b6b0610 (I think, from some quick googling). --- src/inline-assembly.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index e905fcb..d8e7f10 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -570,6 +570,7 @@ The following directives are guaranteed to be supported by the assembler: - `.global` - `.globl` - `.inst` +- `.insn` - `.lcomm` - `.long` - `.octa` From f83bd2e60930e441bfe1cea4f9b23d1cdcca497a Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sun, 14 Jul 2024 15:03:32 -0400 Subject: [PATCH 411/463] Suppress type length limit test and note that it is not enforced --- src/attributes/limits.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/attributes/limits.md b/src/attributes/limits.md index 65cb55b..6c4ae38 100644 --- a/src/attributes/limits.md +++ b/src/attributes/limits.md @@ -35,6 +35,12 @@ a!{} ## The `type_length_limit` attribute +> [!NOTE] +> This limit is only enforced when the nightly `-Zenforce-type-length-limit` +> flag is active. +> +> For more information, see . + The *`type_length_limit` attribute* limits the maximum number of type substitutions made when constructing a concrete type during monomorphization. It is applied at the [crate] level, and uses the [_MetaNameValueStr_] syntax @@ -42,7 +48,7 @@ to set the limit based on the number of type substitutions. > Note: The default in `rustc` is 1048576. -```rust,compile_fail +```rust,ignore #![type_length_limit = "4"] fn f(x: T) {} From d9363d657b91ebd4c2b465f144480faecd5f7ce7 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 15 Jul 2024 10:47:59 -0700 Subject: [PATCH 412/463] Don't use admonition syntax. The reference isn't quite ready for this via the extension. --- src/attributes/limits.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/attributes/limits.md b/src/attributes/limits.md index 6c4ae38..79f292a 100644 --- a/src/attributes/limits.md +++ b/src/attributes/limits.md @@ -35,9 +35,7 @@ a!{} ## The `type_length_limit` attribute -> [!NOTE] -> This limit is only enforced when the nightly `-Zenforce-type-length-limit` -> flag is active. +> **Note**: This limit is only enforced when the nightly `-Zenforce-type-length-limit` flag is active. > > For more information, see . From fdbd635439a987ce9ed0487323d7f1a1cc12fa2c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 15 Jul 2024 10:44:35 -0700 Subject: [PATCH 413/463] Enforce `cargo fmt` on the style-check code. --- .github/workflows/main.yml | 8 ++++++-- style-check/src/main.rs | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 227aeba..98093a7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,7 +27,7 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install nightly -c rust-docs + rustup toolchain install nightly -c rust-docs,rustfmt rustup default nightly - name: Install mdbook run: | @@ -44,7 +44,11 @@ jobs: - name: Run tests run: mdbook test - name: Style checks - run: (cd style-check && cargo run -- ../src) + working-directory: style-check + run: cargo run -- ../src + - name: Style fmt + working-directory: style-check + run: cargo fmt --check - name: Check for broken links run: | curl -sSLo linkcheck.sh \ diff --git a/style-check/src/main.rs b/style-check/src/main.rs index 8452b26..e8bac07 100644 --- a/style-check/src/main.rs +++ b/style-check/src/main.rs @@ -71,7 +71,11 @@ fn check_directory(dir: &Path, bad: &mut bool) -> Result<(), Box> { style_error!(bad, path, "em-dash not allowed, use three dashes like ---"); } if contents.contains('\u{a0}') { - style_error!(bad, path, "don't use 0xa0 no-break-space, use   instead"); + style_error!( + bad, + path, + "don't use 0xa0 no-break-space, use   instead" + ); } for line in contents.lines() { if line.ends_with(' ') { From a6afc88b3e28c1efdbfa5e34cc6929d2eec9d1a2 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Jul 2024 16:22:45 +0200 Subject: [PATCH 414/463] add missing associated type link in type-aliases.md --- 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 d2e14b9..24c6f4e 100644 --- a/src/items/type-aliases.md +++ b/src/items/type-aliases.md @@ -31,7 +31,7 @@ let _ = UseAlias(5); // OK let _ = TypeAlias(5); // Doesn't work ``` -A type alias, when not used as an associated type, must include a [_Type_] and +A type alias, when not used as an [associated type], must include a [_Type_] and may not include [_TypeParamBounds_]. A type alias, when used as an [associated type] in a [trait], must not include a From f446ec477d43bb4f02c542c896e89701bd764ac1 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Jul 2024 08:49:27 -0700 Subject: [PATCH 415/463] Remove broken link checker. --- style-check/src/main.rs | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/style-check/src/main.rs b/style-check/src/main.rs index 8452b26..4a9ff9a 100644 --- a/style-check/src/main.rs +++ b/style-check/src/main.rs @@ -84,7 +84,7 @@ fn check_directory(dir: &Path, bad: &mut bool) -> Result<(), Box> { } fn cmark_check(path: &Path, bad: &mut bool, contents: &str) -> Result<(), Box> { - use pulldown_cmark::{BrokenLink, CodeBlockKind, Event, Options, Parser, Tag}; + use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag}; macro_rules! cmark_error { ($bad:expr, $path:expr, $range:expr, $($arg:tt)*) => { @@ -96,20 +96,7 @@ fn cmark_check(path: &Path, bad: &mut bool, contents: &str) -> Result<(), Box| { - cmark_error!( - &mut link_err, - path, - link.span, - "broken {:?} link (reference `{}`)", - link.link_type, - link.reference - ); - None - }; - let parser = Parser::new_with_broken_link_callback(contents, options, Some(&mut cb)); + let parser = Parser::new_ext(contents, options); for (event, range) in parser.into_offset_iter() { match event { @@ -135,6 +122,5 @@ fn cmark_check(path: &Path, bad: &mut bool, contents: &str) -> Result<(), Box {} } } - *bad |= link_err; Ok(()) } From 86661194d0fc66feb9bc01bdb3631b19bcecaa48 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 16 Jul 2024 14:03:46 -0700 Subject: [PATCH 416/463] Add '_ to LIFETIME_OR_LABEL --- src/expressions/loop-expr.md | 2 ++ src/items/generics.md | 2 ++ src/tokens.md | 2 ++ src/trait-bounds.md | 3 +-- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index c8b93ea..9366c7f 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -209,6 +209,8 @@ Labels follow the hygiene and shadowing rules of local variables. For example, t } ``` +`'_` is not a valid loop label. + ## `break` expressions > **Syntax**\ diff --git a/src/items/generics.md b/src/items/generics.md index 2b28d39..65f17bd 100644 --- a/src/items/generics.md +++ b/src/items/generics.md @@ -44,6 +44,8 @@ See [generic parameter scopes] for more details. [function pointers] have lifetime or type parameters as well, but are not referred to with path syntax. +`'_` is not a valid lifetime parameter. + ### Const generics *Const generic parameters* allow items to be generic over constant values. The diff --git a/src/tokens.md b/src/tokens.md index 3b5cef7..1c50ed1 100644 --- a/src/tokens.md +++ b/src/tokens.md @@ -645,6 +645,8 @@ Examples of reserved forms: > > LIFETIME_OR_LABEL :\ >       `'` [NON_KEYWORD_IDENTIFIER][identifier] +> _(not immediately followed by `'`)_\ +>    | `'_` > _(not immediately followed by `'`)_ Lifetime parameters and [loop labels] use LIFETIME_OR_LABEL tokens. Any diff --git a/src/trait-bounds.md b/src/trait-bounds.md index 9ce7392..96a8f8e 100644 --- a/src/trait-bounds.md +++ b/src/trait-bounds.md @@ -18,8 +18,7 @@ > > _Lifetime_ :\ >       [LIFETIME_OR_LABEL]\ ->    | `'static`\ ->    | `'_` +>    | `'static` [Trait] and lifetime bounds provide a way for [generic items][generic] to restrict which types and lifetimes are used as their parameters. Bounds can be From a2667a2522752d0376d6ca39f39c93f17cafaec9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 18 Sep 2023 00:24:03 -0400 Subject: [PATCH 417/463] Update conditional-compilation.md * Clarify * Reduce redundancy --- src/conditional-compilation.md | 48 +++++++++++----------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index f52c90d..1439824 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -22,43 +22,31 @@ > _ConfigurationPredicateList_\ >    _ConfigurationPredicate_ (`,` _ConfigurationPredicate_)\* `,`? -*Conditionally compiled source code* is source code that may or may not be -considered a part of the source code depending on certain conditions. Source code can be conditionally compiled -using the [attributes] [`cfg`] and [`cfg_attr`] and the built-in [`cfg` macro]. -These conditions are based on the target architecture of the compiled crate, -arbitrary values passed to the compiler, and a few other miscellaneous things -further described below in detail. +*Conditionally compiled source code* is source code that is compiled only under certain conditions. Source code can be made conditionally compiled using the [`cfg`] and [`cfg_attr`] [attributes] and the built-in [`cfg` macro]. Whether to compile can depend on the target architecture of the compiled crate, arbitrary values passed to the compiler, and other things further described below. Each form of conditional compilation takes a _configuration predicate_ that evaluates to true or false. The predicate is one of the following: -* A configuration option. It is true if the option is set and false if it is +* A configuration option. The predicate is true if the option is set, and false if it is unset. -* `all()` with a comma separated list of configuration predicates. It is false - if at least one predicate is false. If there are no predicates, it is true. -* `any()` with a comma separated list of configuration predicates. It is true - if at least one predicate is true. If there are no predicates, it is false. -* `not()` with a configuration predicate. It is true if its predicate is false - and false if its predicate is true. +* `all()` with a comma-separated list of configuration predicates. It is true precisely if all of the given predicates are true. +* `any()` with a comma-separated list of configuration predicates. It is true precisely if at least one of the given predicates is true. +* `not()` with a configuration predicate. It is true precisely if the given predicate is false. -_Configuration options_ are names and key-value pairs that are either set or -unset. Names are written as a single identifier such as, for example, `unix`. -Key-value pairs are written as an identifier, `=`, and then a string. For -example, `target_arch = "x86_64"` is a configuration option. +_Configuration options_ are either names or key-value pairs, and are either set or +unset. Configuration options that are names, such as `unix`, are specified by simply writing them. +Configuration options that are key-value pairs are written in the form `key = "value"`, such as `target_arch = "x86_64"`. -> **Note**: Whitespace around the `=` is ignored. `foo="bar"` and `foo = "bar"` -> are equivalent configuration options. +> **Note**: Whitespace around the `=` is ignored, so `foo="bar"` and `foo = "bar"` are equivalent. -Keys are not unique in the set of key-value configuration options. For example, -both `feature = "std"` and `feature = "serde"` can be set at the same time. +Keys do not need to be unique. For example, both `feature = "std"` and `feature = "serde"` can be set at the same time. ## Set Configuration Options Which configuration options are set is determined statically during the -compilation of the crate. Certain options are _compiler-set_ based on data -about the compilation. Other options are _arbitrarily-set_, set based on input -passed to the compiler outside of the code. It is not possible to set a +compilation of the crate. Some options are _compiler-set_ based on data +about the compilation. Other options are _arbitrarily-set_ based on input +passed to the compiler outside of the code. It is impossible to set a configuration option from within the source code of the crate being compiled. > **Note**: For `rustc`, arbitrary-set configuration options are set using the @@ -70,11 +58,7 @@ configuration option from within the source code of the crate being compiled.

    -Warning: It is possible for arbitrarily-set configuration options to have the -same value as compiler-set configuration options. For example, it is possible -to do `rustc --cfg "unix" program.rs` while compiling to a Windows target, and -have both `unix` and `windows` configuration options set at the same time. It -is unwise to actually do this. +Warning: Arbitrarily-set configuration options can clash with compiler-set configuration options. For example, it is possible to do `rustc --cfg "unix" program.rs` while compiling to a Windows target, and have both `unix` and `windows` configuration options set at the same time. Doing this would be unwise.
    @@ -266,9 +250,7 @@ Example values: The `cfg` [attribute] conditionally includes the thing it is attached to based -on a configuration predicate. - -It is written as `cfg`, `(`, a configuration predicate, and finally `)`. +on the given configuration predicate (_ConfigurationPredicate_ in the syntax above). If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. From 90c2b74e0ab3483bb205a3f9117f9923cb905c66 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 17 Jul 2024 11:10:27 -0700 Subject: [PATCH 418/463] Apply review suggestions. This reverts some of the changes since they were done intentionally, and tries to improve the clarity in other areas. --- src/conditional-compilation.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/conditional-compilation.md b/src/conditional-compilation.md index 1439824..f98b323 100644 --- a/src/conditional-compilation.md +++ b/src/conditional-compilation.md @@ -27,15 +27,14 @@ Each form of conditional compilation takes a _configuration predicate_ that evaluates to true or false. The predicate is one of the following: -* A configuration option. The predicate is true if the option is set, and false if it is - unset. -* `all()` with a comma-separated list of configuration predicates. It is true precisely if all of the given predicates are true. -* `any()` with a comma-separated list of configuration predicates. It is true precisely if at least one of the given predicates is true. -* `not()` with a configuration predicate. It is true precisely if the given predicate is false. +* A configuration option. The predicate is true if the option is set, and false if it is unset. +* `all()` with a comma-separated list of configuration predicates. It is true if all of the given predicates are true, or if the list is empty. +* `any()` with a comma-separated list of configuration predicates. It is true if at least one of the given predicates is true. If there are no predicates, it is false. +* `not()` with a configuration predicate. It is true if its predicate is false and false if its predicate is true. -_Configuration options_ are either names or key-value pairs, and are either set or -unset. Configuration options that are names, such as `unix`, are specified by simply writing them. -Configuration options that are key-value pairs are written in the form `key = "value"`, such as `target_arch = "x86_64"`. +_Configuration options_ are either names or key-value pairs, and are either set or unset. +Names are written as a single identifier, such as `unix`. +Key-value pairs are written as an identifier, `=`, and then a string, such as `target_arch = "x86_64"`. > **Note**: Whitespace around the `=` is ignored, so `foo="bar"` and `foo = "bar"` are equivalent. @@ -46,7 +45,7 @@ Keys do not need to be unique. For example, both `feature = "std"` and `feature Which configuration options are set is determined statically during the compilation of the crate. Some options are _compiler-set_ based on data about the compilation. Other options are _arbitrarily-set_ based on input -passed to the compiler outside of the code. It is impossible to set a +passed to the compiler outside of the code. It is not possible to set a configuration option from within the source code of the crate being compiled. > **Note**: For `rustc`, arbitrary-set configuration options are set using the @@ -250,7 +249,9 @@ Example values: The `cfg` [attribute] conditionally includes the thing it is attached to based -on the given configuration predicate (_ConfigurationPredicate_ in the syntax above). +on a configuration predicate. + +It is written as `cfg`, `(`, a configuration predicate, and finally `)`. If the predicate is true, the thing is rewritten to not have the `cfg` attribute on it. If the predicate is false, the thing is removed from the source code. From d01b3dbb9c666a3dc2e2a64b21320f56de1ad723 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Wed, 17 Jul 2024 15:21:07 -0700 Subject: [PATCH 419/463] Add review policy for the reference and specification work --- README.md | 12 +++++++++++ docs/review-policy.md | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 docs/review-policy.md diff --git a/README.md b/README.md index ff75557..2554292 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,21 @@ To test all of the code examples in the Reference, run: mdbook test ``` +For authors, consider using the server functionality which supports automatic reload. + To build the Reference locally (in `build/`) and open it in a web browser, run: ```sh mdbook build --open ``` + +This will open a browser with a websocket live-link to automatically reload whenever the source is updated. + +You can also open any current build of the reference by running: + +```sh +mdbook serve --open +``` + + diff --git a/docs/review-policy.md b/docs/review-policy.md new file mode 100644 index 0000000..f7bdeb1 --- /dev/null +++ b/docs/review-policy.md @@ -0,0 +1,47 @@ +Team members are given permission to merge changes from other contributors in the repository. There are different guidelines for reviewing based on the kind of changes being made: + +## Policy changes + +- Significant changes to the policy of how the team operates, such as changes to this document, should have agreement of the team without any blocking objections. +- Minor changes to something like the style enforcement can be made with the review of a team member, as long as there is high confidence that it is unlikely any team member would object (for example, codifying a guideline that is already in practice), and that the change can be easily reversed. + +## Meaningful content addition or changes + +- When adding or changing content in the spec, the reviewer should consult with appropriate experts to validate the changes. This may not be required if the reviewer has high confidence that the changes are correct, and consider themselves well-versed enough in the topic to understand it, or the relevant experts are the author or have been heavily involved in the process. It is up to the reviewer to use their best judgement when to consult. +- Content should always follow the guidelines from the [authoring guide]. + +## Minor content changes +- Minor content changes, such as small cleanups or wording fixes, can be made with the review from a team member without further consultation. + +## Tooling changes +- Minor changes to the tooling may be made with a review from a team member. This includes bug fixes, minor additions that are unlikely to have objections, and additions that have already been discussed. +- Major changes, such as a change in how content is authored, or major changes to how the tooling works should be approved by the team without blocking objections. + +## Review Process Flowchart + +When reviewing a pull request, ask yourself the following questions: + +### Are the proposed changes true? + +If we're not sure and can't easily verify it ourselves, we ask someone who would know. + +### Does this make any new guarantees about the language? + +If this would make a new guarantee about the language, this needs to go through the `lang` team to be accepted (unless the `lang` team has clearly accepted this guarantee elsewhere). Ask @traviscross or @pnkfelix if at all unsure about any of these. + +### Would we have added this to the Reference ourselves? + +There are a number of PRs that might be true, but when we look at them, we think to ourselves, in our heart of hearts, that this just isn't something we would have bothered to write ourselves. We don't want to accept a PR just because it's in front of us and not obviously false. It should clearly add value. + +### Is this editorially sound? + +Some PRs try to "sell" the language too much, or try to explain more (or less) than needed, or give too many (or too few) examples, etc. The PR should match the general flavor of the Reference here. + +### Is this well written? + +Some PRs are right but are awkwardly worded or have typographical problems. If the changes are small, we'll just add commits to the branch to clean things up, then merge. + + +This policy does not yet cover the process for getting final approval from the relevant teams. + +[authoring guide]: authoring.md \ No newline at end of file From 24f2570cc6d44d835cd347c312805caccd758125 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Sat, 20 Jul 2024 09:02:13 +0200 Subject: [PATCH 420/463] Describe all cases for which the weak `dyn` keyword is parsed as a keyword --- src/keywords.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/keywords.md b/src/keywords.md index 9df5b2a..40a785f 100644 --- a/src/keywords.md +++ b/src/keywords.md @@ -105,7 +105,8 @@ is possible to declare a variable or method with the name `union`. fn invalid_lifetime_parameter<'static>(s: &'static str) -> &'static str { s } ``` * In the 2015 edition, [`dyn`] is a keyword when used in a type position - followed by a path that does not start with `::`. + followed by a path that does not start with `::` or `<`, a lifetime, a question mark, a `for` + keyword or an opening parenthesis. Beginning in the 2018 edition, `dyn` has been promoted to a strict keyword. From 2cace488ef129ff51f8b4a5935c58a823f1846b5 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 22 Jul 2024 12:13:07 +0200 Subject: [PATCH 421/463] re-structure 'invalid values' enumeration to instead define what is *valid* --- src/behavior-considered-undefined.md | 73 ++++++++++++++++------------ 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index aab0554..efa1d37 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -59,33 +59,10 @@ Please read the [Rustonomicon] before writing unsafe code. * Executing code compiled with platform features that the current platform does not support (see [`target_feature`]), *except* if the platform explicitly documents this to be safe. * Calling a function with the wrong call ABI or unwinding from a function with the wrong unwind ABI. -* Producing an invalid value, even in private fields and locals. "Producing" a +* Producing an [invalid value][invalid-values]. "Producing" a value happens any time a value is assigned to or read from a place, passed to a function/primitive operation or returned from a function/primitive operation. - The following values are invalid (at their respective type): - * A value other than `false` (`0`) or `true` (`1`) in a [`bool`]. - * A discriminant in an `enum` not included in the type definition. - * A null `fn` pointer. - * A value in a `char` which is a surrogate or above `char::MAX`. - * A `!` (all values are invalid for this type). - * An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer obtained - from [uninitialized memory][undef], or uninitialized memory in a `str`. - * A reference or `Box` that is [dangling], misaligned, or points to an invalid value - (in case of dynamically sized types, using the actual dynamic type of the - pointee as determined by the metadata). - * Invalid metadata in a wide reference, `Box`, or raw pointer. The requirement - for the metadata is determined by the type of the unsized tail: - * `dyn Trait` metadata is invalid if it is not a pointer to a vtable for `Trait`. - * Slice (`[T]`) metadata is invalid if the length is not a valid `usize` - (i.e., it must not be read from uninitialized memory). - Furthermore, for wide references and `Box`, slice metadata is invalid - if it makes the total size of the pointed-to value bigger than `isize::MAX`. - * Invalid values for a type with a custom definition of invalid values. - In the standard library, this affects [`NonNull`] and [`NonZero*`]. - - > **Note**: `rustc` achieves this with the unstable - > `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 @@ -94,11 +71,6 @@ Please read the [Rustonomicon] before writing unsafe code. '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 -reading uninitialized memory is permitted are inside `union`s and in "padding" -(the gaps between the fields/elements of a type). - > **Note**: Undefined behavior affects the entire program. For example, calling > a function in C that exhibits undefined behavior of C means your entire > program contains undefined behaviour that can also affect the Rust code. And @@ -155,6 +127,46 @@ 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`. +### Invalid values +[invalid-values]: #invalid-values + +The Rust compiler assumes that all values produced during program execution are +"valid", and producing an invalid value is hence immediate UB. + +Whether a value is valid depends on the type: +* A [`bool`] value must be `false` (`0`) or `true` (`1`). +* A `fn` pointer value must be non-null. +* A `char` value must not be a surrogate (i.e., must not be in the range `0xD800..=0xDFFF`) and must be equal to or less than `char::MAX`. +* A `!` value must never exist. +* An integer (`i*`/`u*`), floating point value (`f*`), or raw pointer must be + initialized, i.e., must not be obtained from [uninitialized memory][undef]. +* A `str` value is treated like `[u8]`, i.e. it must be initialized. +* An `enum` must have a valid discriminant, and all fields of the variant indicated by that discriminant must be valid at their respective type. +* A `struct`, tuple, and array requires all fields/elements to be valid at their respective type. +* For a `union`, the exact validity requirements are not decided yet. The following is certain: + * If the `union` has a zero-sized field, then all values are valid. + * If a value is valid for a particular `union` field, then it is valid for the union. +* A reference or [`Box`] must be aligned, it cannot be [dangling], and it must point to a valid value + (in case of dynamically sized types, using the actual dynamic type of the + pointee as determined by the metadata). +* The metadata of a wide reference, [`Box`], or raw pointer must match + the type of the unsized tail: + * `dyn Trait` metadata must be a pointer to a compiler-generated vtable for `Trait`. + * Slice (`[T]`) metadata must be a valid `usize`. + Furthermore, for wide references and [`Box`], slice metadata is invalid + if it makes the total size of the pointed-to value bigger than `isize::MAX`. +* If a type has a custom range of a valid values, then a valid value must be in that range. + In the standard library, this affects [`NonNull`] and [`NonZero`]. + + > **Note**: `rustc` achieves this with the unstable + > `rustc_layout_scalar_valid_range_*` attributes. + +**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 +reading uninitialized memory is permitted are inside `union`s and in "padding" +(the gaps between the fields of a type). + + [`bool`]: types/boolean.md [`const`]: items/constant-items.md [noalias]: http://llvm.org/docs/LangRef.html#noalias @@ -164,7 +176,8 @@ must never exceed `isize::MAX`. [`UnsafeCell`]: ../std/cell/struct.UnsafeCell.html [Rustonomicon]: ../nomicon/index.html [`NonNull`]: ../core/ptr/struct.NonNull.html -[`NonZero*`]: ../core/num/index.html +[`NonZero`]: ../core/num/struct.NonZero.html +[`Box`]: ../alloc/boxed/struct.Box.html [place expression context]: expressions.md#place-expressions-and-value-expressions [rules]: inline-assembly.md#rules-for-inline-assembly [points to]: #pointed-to-bytes From ac059af453ac7cb8977699e57c6012d135fc2854 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 22 Jul 2024 16:00:39 +0200 Subject: [PATCH 422/463] update 'dangling pointers' to new zero-sized rules --- src/behavior-considered-undefined.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index aab0554..7a210ad 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -142,18 +142,18 @@ new reference is aligned, but it is not always necessary. ### Dangling pointers [dangling]: #dangling-pointers -A reference/pointer is "dangling" if it is null or not all of the bytes it +A reference/pointer is "dangling" if not all of the bytes it [points to] are part of the same live allocation (so in particular they all have to be part of *some* allocation). -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. +If the size is 0, then the pointer is trivially never "dangling" +(even if it is a null pointer). 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`. +must never exceed `isize::MAX`, since it is impossible for a single allocation +to be larger than `isize::MAX`. [`bool`]: types/boolean.md [`const`]: items/constant-items.md From a767e2e92710a9e17f62e6e5cff8234f30e3c4af Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Mon, 22 Jul 2024 16:16:50 +0200 Subject: [PATCH 423/463] say more clearly what is still being debated --- src/behavior-considered-undefined.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index efa1d37..f3db7bc 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -143,15 +143,18 @@ Whether a value is valid depends on the type: * A `str` value is treated like `[u8]`, i.e. it must be initialized. * An `enum` must have a valid discriminant, and all fields of the variant indicated by that discriminant must be valid at their respective type. * A `struct`, tuple, and array requires all fields/elements to be valid at their respective type. -* For a `union`, the exact validity requirements are not decided yet. The following is certain: - * If the `union` has a zero-sized field, then all values are valid. - * If a value is valid for a particular `union` field, then it is valid for the union. +* For a `union`, the exact validity requirements are not decided yet. + Obviously, all values that can be created entirely in safe code are valid. + If the union has a zero-sized field, then every possible value is valid. + Further details are [still being debated](https://github.com/rust-lang/unsafe-code-guidelines/issues/438). * A reference or [`Box`] must be aligned, it cannot be [dangling], and it must point to a valid value (in case of dynamically sized types, using the actual dynamic type of the pointee as determined by the metadata). + Note that the last point (about pointing to a valid value) is still subject of debate. * The metadata of a wide reference, [`Box`], or raw pointer must match the type of the unsized tail: * `dyn Trait` metadata must be a pointer to a compiler-generated vtable for `Trait`. + (For raw pointers, this requirement is still subject of debate.) * Slice (`[T]`) metadata must be a valid `usize`. Furthermore, for wide references and [`Box`], slice metadata is invalid if it makes the total size of the pointed-to value bigger than `isize::MAX`. From be055154e998ad22cf6a8c16573e9306c8ba7690 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 23 Jul 2024 11:38:39 -0700 Subject: [PATCH 424/463] Update link for unsafe blocks. This link was pointing to a redirect, but the redirect isn't capable of handling linking to a specific section. This updates the link to point to the intended part of the chapter. --- src/expressions/block-expr.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/expressions/block-expr.md b/src/expressions/block-expr.md index 1d2425d..08baec3 100644 --- a/src/expressions/block-expr.md +++ b/src/expressions/block-expr.md @@ -180,7 +180,7 @@ if false { > _UnsafeBlockExpression_ :\ >    `unsafe` _BlockExpression_ -_See [`unsafe` block](../unsafe-blocks.md) for more information on when to use `unsafe`_ +_See [`unsafe` blocks] for more information on when to use `unsafe`_. A block of code can be prefixed with the `unsafe` keyword to permit [unsafe operations]. Examples: @@ -233,6 +233,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 +[`unsafe` blocks]: ../unsafe-keyword.md#unsafe-blocks-unsafe- [`while let`]: loop-expr.md#predicate-pattern-loops [`while`]: loop-expr.md#predicate-loops [array expressions]: array-expr.md From ba0c4238415ee0ef5008531121f5b4c778831529 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 23 Jul 2024 11:55:03 -0700 Subject: [PATCH 425/463] Update mutable static items example for modern Rust. This updates the mutable static item example to fix some issues with how it works and how it is presented. First, the unsafe operations are wrapped in an `unsafe` block so that it doesn't trigger `unsafe_op_in_unsafe_fn`. Second, it switches the mutation example to use addr_of_mut to avoid the undefined behavior, and to compile correctly in 2024 edition. Third, it rewrites the second example to be safe with a different description. My understanding is that the original example was written at a time when it was considered that any potential race condition was considered unsafe. However, that is no longer a widely held view. The example has been rewritten to illustrate the two different ways you can wrap mutable static access. --- src/items/static-items.md | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/items/static-items.md b/src/items/static-items.md index e543b4f..d1e4618 100644 --- a/src/items/static-items.md +++ b/src/items/static-items.md @@ -88,23 +88,30 @@ Mutable statics are still very useful, however. They can be used with C libraries and can also be bound from C libraries in an `extern` block. ```rust -# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 } +# fn atomic_add(_: *mut u32, _: u32) -> u32 { 2 } static mut LEVELS: u32 = 0; // This violates the idea of no shared state, and this doesn't internally // protect against races, so this function is `unsafe` -unsafe fn bump_levels_unsafe1() -> u32 { - let ret = LEVELS; - LEVELS += 1; - return ret; +unsafe fn bump_levels_unsafe() -> u32 { + unsafe { + let ret = LEVELS; + LEVELS += 1; + return ret; + } } -// Assuming that we have an atomic_add function which returns the old value, -// this function is "safe" but the meaning of the return value may not be what -// callers expect, so it's still marked as `unsafe` -unsafe fn bump_levels_unsafe2() -> u32 { - return atomic_add(&mut LEVELS, 1); +// As an alternative to `bump_levels_unsafe`, this function is safe, assuming +// that we have an atomic_add function which returns the old value. This +// function is safe only if no other code accesses the static in a non-atomic +// fashion. If such accesses are possible (such as in `bump_levels_unsafe`), +// then this would need to be `unsafe` to indicate to the caller that they +// must still guard against concurrent access. +fn bump_levels_safe() -> u32 { + unsafe { + return atomic_add(std::ptr::addr_of_mut!(LEVELS), 1); + } } ``` From 8c9eac07f23da2dadfdc35d4503785050f27aaf8 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 23 Jul 2024 22:52:45 +0000 Subject: [PATCH 426/463] Improve some editorial bits --- src/behavior-considered-undefined.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index f3db7bc..1ee03e6 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -150,11 +150,11 @@ Whether a value is valid depends on the type: * A reference or [`Box`] must be aligned, it cannot be [dangling], and it must point to a valid value (in case of dynamically sized types, using the actual dynamic type of the pointee as determined by the metadata). - Note that the last point (about pointing to a valid value) is still subject of debate. + Note that the last point (about pointing to a valid value) remains a subject of some debate. * The metadata of a wide reference, [`Box`], or raw pointer must match the type of the unsized tail: * `dyn Trait` metadata must be a pointer to a compiler-generated vtable for `Trait`. - (For raw pointers, this requirement is still subject of debate.) + (For raw pointers, this requirement remains a subject of some debate.) * Slice (`[T]`) metadata must be a valid `usize`. Furthermore, for wide references and [`Box`], slice metadata is invalid if it makes the total size of the pointed-to value bigger than `isize::MAX`. From fde0db75c95156a86b3425dd1ddd7397007a0da9 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Tue, 23 Jul 2024 23:21:39 +0000 Subject: [PATCH 427/463] Improve some editorial bits and weaken claim Let's say "may" rather than "will" here. --- src/linkage.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/linkage.md b/src/linkage.md index de094c1..21f56af 100644 --- a/src/linkage.md +++ b/src/linkage.md @@ -47,15 +47,15 @@ be ignored in favor of only building the artifacts specified by command line. linking Rust code into an existing non-Rust application because it will not have dynamic dependencies on other Rust code. - Note that, because the resulting static library contains all of the + Note that, because the resulting static library contains the code of all the dependencies, including the standard library, and also exports all public symbols of them, linking the static library into an executable or shared - library will need special care. In case of a shared library the list of + library may need special care. In case of a shared library the list of exported symbols will have to be limited via e.g. a linker or symbol version - script, exported symbols list (macOS) or module definition file (Windows). + script, exported symbols list (macOS), or module definition file (Windows). Additionally, unused sections can be removed to remove all code of - dependencies that is not actually used (e.g. `--gc-sections` or - `-dead_strip` for macOS). + dependencies that is not actually used (e.g. `--gc-sections` or `-dead_strip` + for macOS). * `--crate-type=cdylib`, `#![crate_type = "cdylib"]` - A dynamic system library will be produced. This is used when compiling From b82f2333fa52b0b1315aece25e9d4f0ea087604b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 22 Feb 2024 15:10:48 -0800 Subject: [PATCH 428/463] Add mdbook-spec. --- mdbook-spec/.gitignore | 1 + mdbook-spec/Cargo.lock | 982 ++++++++++++++++++++++++++++++++++++++++ mdbook-spec/Cargo.toml | 14 + mdbook-spec/README.md | 3 + mdbook-spec/src/main.rs | 186 ++++++++ 5 files changed, 1186 insertions(+) create mode 100644 mdbook-spec/.gitignore create mode 100644 mdbook-spec/Cargo.lock create mode 100644 mdbook-spec/Cargo.toml create mode 100644 mdbook-spec/README.md create mode 100644 mdbook-spec/src/main.rs diff --git a/mdbook-spec/.gitignore b/mdbook-spec/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/mdbook-spec/.gitignore @@ -0,0 +1 @@ +/target diff --git a/mdbook-spec/Cargo.lock b/mdbook-spec/Cargo.lock new file mode 100644 index 0000000..a4da56e --- /dev/null +++ b/mdbook-spec/Cargo.lock @@ -0,0 +1,982 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "windows-targets 0.52.0", +] + +[[package]] +name = "clap" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", + "terminal_size", +] + +[[package]] +name = "clap_complete" +version = "4.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df631ae429f6613fcd3a7c1adbdb65f637271e561b03680adaa6573015dfb106" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "handlebars" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" +dependencies = [ + "log", + "pest", + "pest_derive", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "hermit-abi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "iana-time-zone" +version = "0.1.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "is-terminal" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "mdbook" +version = "0.4.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80992cb0e05f22cc052c99f8e883f1593b891014b96a8b4637fd274d7030c85e" +dependencies = [ + "anyhow", + "chrono", + "clap", + "clap_complete", + "env_logger", + "handlebars", + "log", + "memchr", + "once_cell", + "opener", + "pathdiff", + "pulldown-cmark", + "regex", + "serde", + "serde_json", + "shlex", + "tempfile", + "toml", + "topological-sort", +] + +[[package]] +name = "mdbook-spec" +version = "0.0.0" +dependencies = [ + "anyhow", + "mdbook", + "pathdiff", + "regex", + "semver", + "serde_json", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "normpath" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opener" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788" +dependencies = [ + "bstr", + "normpath", + "winapi", +] + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "pest" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.4.2", + "memchr", + "unicase", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + +[[package]] +name = "semver" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" + +[[package]] +name = "serde" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.113" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "topological-sort" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "unicase" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasm-bindgen" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/mdbook-spec/Cargo.toml b/mdbook-spec/Cargo.toml new file mode 100644 index 0000000..8832156 --- /dev/null +++ b/mdbook-spec/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "mdbook-spec" +edition = "2021" +license = "MIT OR Apache-2.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.79" +mdbook = { version = "0.4.36", default-features = false } +pathdiff = "0.2.1" +regex = "1.10.3" +semver = "1.0.21" +serde_json = "1.0.113" diff --git a/mdbook-spec/README.md b/mdbook-spec/README.md new file mode 100644 index 0000000..8c293fa --- /dev/null +++ b/mdbook-spec/README.md @@ -0,0 +1,3 @@ +# mdbook-spec + +This is an mdbook preprocessor to add some extensions for the Rust specification. diff --git a/mdbook-spec/src/main.rs b/mdbook-spec/src/main.rs new file mode 100644 index 0000000..1fd8e4e --- /dev/null +++ b/mdbook-spec/src/main.rs @@ -0,0 +1,186 @@ +use mdbook::book::{Book, Chapter}; +use mdbook::errors::Error; +use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext}; +use mdbook::BookItem; +use regex::{Captures, Regex}; +use semver::{Version, VersionReq}; +use std::collections::BTreeMap; +use std::io; +use std::path::PathBuf; +use std::process; + +fn main() { + let mut args = std::env::args().skip(1); + match args.next().as_deref() { + Some("supports") => { + // Supports all renderers. + return; + } + Some(arg) => { + eprintln!("unknown argument: {arg}"); + std::process::exit(1); + } + None => {} + } + + let preprocessor = Spec::new(); + + if let Err(e) = handle_preprocessing(&preprocessor) { + eprintln!("{}", e); + process::exit(1); + } +} + +fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> { + let (ctx, book) = CmdPreprocessor::parse_input(io::stdin())?; + + let book_version = Version::parse(&ctx.mdbook_version)?; + let version_req = VersionReq::parse(mdbook::MDBOOK_VERSION)?; + + if !version_req.matches(&book_version) { + eprintln!( + "warning: The {} plugin was built against version {} of mdbook, \ + but we're being called from version {}", + pre.name(), + mdbook::MDBOOK_VERSION, + ctx.mdbook_version + ); + } + + let processed_book = pre.run(&ctx, book)?; + serde_json::to_writer(io::stdout(), &processed_book)?; + + Ok(()) +} + +struct Spec { + deny_warnings: bool, + rule_re: Regex, + admonition_re: Regex, +} + +impl Spec { + pub fn new() -> Spec { + Spec { + deny_warnings: std::env::var("SPEC_DENY_WARNINGS").as_deref() == Ok("1"), + rule_re: Regex::new(r"(?m)^r\[([^]]+)]$").unwrap(), + admonition_re: Regex::new( + r"(?m)^ *> \[!(?[^]]+)\]\n(?
    (?: *> .*\n)+)", + ) + .unwrap(), + } + } + + /// Converts lines that start with `r[…]` into a "rule" which has special + /// styling and can be linked to. + fn rule_definitions( + &self, + chapter: &Chapter, + found_rules: &mut BTreeMap, + ) -> String { + let source_path = chapter.source_path.clone().unwrap_or_default(); + let path = chapter.path.clone().unwrap_or_default(); + self.rule_re + .replace_all(&chapter.content, |caps: &Captures| { + let rule_id = &caps[1]; + if let Some((old, _)) = + found_rules.insert(rule_id.to_string(), (source_path.clone(), path.clone())) + { + let message = format!( + "rule `{rule_id}` defined multiple times\n\ + First location: {old:?}\n\ + Second location: {source_path:?}" + ); + if self.deny_warnings { + panic!("error: {message}"); + } else { + eprintln!("warning: {message}"); + } + } + format!( + "\n" + ) + }) + .to_string() + } + + /// Generates link references to all rules on all pages, so you can easily + /// refer to rules anywhere in the book. + fn auto_link_references( + &self, + chapter: &Chapter, + found_rules: &BTreeMap, + ) -> String { + let current_path = chapter.path.as_ref().unwrap().parent().unwrap(); + let definitions: String = found_rules + .iter() + .map(|(rule_id, (_, path))| { + let relative = pathdiff::diff_paths(path, current_path).unwrap(); + format!("[{rule_id}]: {}#{rule_id}\n", relative.display()) + }) + .collect(); + format!( + "{}\n\ + {definitions}", + chapter.content + ) + } + + /// Converts blockquotes with special headers into admonitions. + /// + /// The blockquote should look something like: + /// + /// ``` + /// > [!WARNING] + /// > ... + /// ``` + /// + /// This will add a `
    ` around the blockquote so that + /// it can be styled differently. Any text between the brackets that can + /// be a CSS class is valid. The actual styling needs to be added in a CSS + /// file. + fn admonitions(&self, chapter: &Chapter) -> String { + self.admonition_re + .replace_all(&chapter.content, |caps: &Captures| { + let lower = caps["admon"].to_lowercase(); + format!( + "
    \n\n{}\n\n
    \n", + &caps["blockquote"] + ) + }) + .to_string() + } +} + +impl Preprocessor for Spec { + fn name(&self) -> &str { + "nop-preprocessor" + } + + fn run(&self, _ctx: &PreprocessorContext, mut book: Book) -> Result { + let mut found_rules = BTreeMap::new(); + for section in &mut book.sections { + let BookItem::Chapter(ch) = section else { + continue; + }; + if ch.is_draft_chapter() { + continue; + } + ch.content = self.rule_definitions(&ch, &mut found_rules); + ch.content = self.admonitions(&ch); + } + for section in &mut book.sections { + let BookItem::Chapter(ch) = section else { + continue; + }; + if ch.is_draft_chapter() { + continue; + } + ch.content = self.auto_link_references(&ch, &found_rules); + } + + Ok(book) + } +} From dc9f35f8d32e6e6ce555fa58ed3512f4312dedb4 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Fri, 8 Mar 2024 13:37:04 -0800 Subject: [PATCH 429/463] Support automatic links to the standard library. --- mdbook-spec/Cargo.lock | 25 ++----- mdbook-spec/Cargo.toml | 1 + mdbook-spec/src/main.rs | 144 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 148 insertions(+), 22 deletions(-) diff --git a/mdbook-spec/Cargo.lock b/mdbook-spec/Cargo.lock index a4da56e..d77a440 100644 --- a/mdbook-spec/Cargo.lock +++ b/mdbook-spec/Cargo.lock @@ -86,12 +86,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.4.2" @@ -398,6 +392,7 @@ dependencies = [ "regex", "semver", "serde_json", + "tempfile", ] [[package]] @@ -507,7 +502,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.4.2", + "bitflags", "memchr", "unicase", ] @@ -521,15 +516,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" version = "1.10.3" @@ -565,7 +551,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -651,13 +637,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", "windows-sys 0.52.0", ] diff --git a/mdbook-spec/Cargo.toml b/mdbook-spec/Cargo.toml index 8832156..bbfd903 100644 --- a/mdbook-spec/Cargo.toml +++ b/mdbook-spec/Cargo.toml @@ -12,3 +12,4 @@ pathdiff = "0.2.1" regex = "1.10.3" semver = "1.0.21" serde_json = "1.0.113" +tempfile = "3.10.1" diff --git a/mdbook-spec/src/main.rs b/mdbook-spec/src/main.rs index 1fd8e4e..7e617f0 100644 --- a/mdbook-spec/src/main.rs +++ b/mdbook-spec/src/main.rs @@ -5,9 +5,11 @@ use mdbook::BookItem; use regex::{Captures, Regex}; use semver::{Version, VersionReq}; use std::collections::BTreeMap; -use std::io; +use std::fmt::Write as _; +use std::fs; +use std::io::{self, Write as _}; use std::path::PathBuf; -use std::process; +use std::process::{self, Command}; fn main() { let mut args = std::env::args().skip(1); @@ -57,10 +59,16 @@ struct Spec { deny_warnings: bool, rule_re: Regex, admonition_re: Regex, + std_link_re: Regex, + std_link_extract_re: Regex, } impl Spec { pub fn new() -> Spec { + // This is roughly a rustdoc intra-doc link definition. + let std_link = r"(?: [a-z]+@ )? + (?: std|core|alloc|proc_macro|test ) + (?: ::[A-Za-z_!:<>{}()\[\]]+ )?"; Spec { deny_warnings: std::env::var("SPEC_DENY_WARNINGS").as_deref() == Ok("1"), rule_re: Regex::new(r"(?m)^r\[([^]]+)]$").unwrap(), @@ -68,6 +76,21 @@ impl Spec { r"(?m)^ *> \[!(?[^]]+)\]\n(?
    (?: *> .*\n)+)", ) .unwrap(), + std_link_re: Regex::new(&format!( + r"(?x) + (?: + ( \[`[^`]+`\] ) \( ({std_link}) \) + ) + | (?: + ( \[`{std_link}`\] ) + ) + " + )) + .unwrap(), + std_link_extract_re: Regex::new( + r#"
  • ]*href="(https://doc.rust-lang.org/[^"]+)""#, + ) + .unwrap(), } } @@ -152,6 +175,122 @@ impl Spec { }) .to_string() } + + /// Converts links to the standard library to the online documentation in + /// a fashion similar to rustdoc intra-doc links. + fn std_links(&self, chapter: &Chapter) -> String { + // This is very hacky, but should work well enough. + // + // Collect all standard library links. + // + // links are tuples of ("[`std::foo`]", None) for links without dest, + // or ("[`foo`]", "std::foo") with a dest. + let mut links: Vec<_> = self + .std_link_re + .captures_iter(&chapter.content) + .map(|cap| { + if let Some(no_dest) = cap.get(3) { + (no_dest.as_str(), None) + } else { + ( + cap.get(1).unwrap().as_str(), + Some(cap.get(2).unwrap().as_str()), + ) + } + }) + .collect(); + if links.is_empty() { + return chapter.content.clone(); + } + links.sort(); + links.dedup(); + + // Write a Rust source file to use with rustdoc to generate intra-doc links. + let tmp = tempfile::TempDir::with_prefix("mdbook-spec-").unwrap(); + let src_path = tmp.path().join("a.rs"); + // Allow redundant since there could some in-scope things that are + // technically not necessary, but we don't care about (like + // [`Option`](std::option::Option)). + let mut src = format!( + "#![deny(rustdoc::broken_intra_doc_links)]\n\ + #![allow(rustdoc::redundant_explicit_links)]\n" + ); + for (link, dest) in &links { + write!(src, "//! - {link}").unwrap(); + if let Some(dest) = dest { + write!(src, "({})", dest).unwrap(); + } + src.push('\n'); + } + writeln!( + src, + "extern crate alloc;\n\ + extern crate proc_macro;\n\ + extern crate test;\n" + ) + .unwrap(); + fs::write(&src_path, &src).unwrap(); + let output = Command::new("rustdoc") + .arg("--edition=2021") + .arg(&src_path) + .current_dir(tmp.path()) + .output() + .expect("rustdoc installed"); + if !output.status.success() { + eprintln!( + "error: failed to extract std links ({:?}) in chapter {} ({:?})\n", + output.status, + chapter.name, + chapter.source_path.as_ref().unwrap() + ); + io::stderr().write_all(&output.stderr).unwrap(); + process::exit(1); + } + + // Extract the links from the generated html. + let generated = + fs::read_to_string(tmp.path().join("doc/a/index.html")).expect("index.html generated"); + let urls: Vec<_> = self + .std_link_extract_re + .captures_iter(&generated) + .map(|cap| cap.get(1).unwrap().as_str()) + .collect(); + if urls.len() != links.len() { + eprintln!( + "error: expected rustdoc to generate {} links, but found {} in chapter {} ({:?})", + links.len(), + urls.len(), + chapter.name, + chapter.source_path.as_ref().unwrap() + ); + process::exit(1); + } + + // Replace any disambiguated links with just the disambiguation. + let mut output = self + .std_link_re + .replace_all(&chapter.content, |caps: &Captures| { + if let Some(dest) = caps.get(2) { + // Replace destination parenthesis with a link definition (square brackets). + format!("{}[{}]", &caps[1], dest.as_str()) + } else { + caps[0].to_string() + } + }) + .to_string(); + + // Append the link definitions to the bottom of the chapter. + write!(output, "\n").unwrap(); + for ((link, dest), url) in links.iter().zip(urls) { + if let Some(dest) = dest { + write!(output, "[{dest}]: {url}\n").unwrap(); + } else { + write!(output, "{link}: {url}\n").unwrap(); + } + } + + output + } } impl Preprocessor for Spec { @@ -170,6 +309,7 @@ impl Preprocessor for Spec { } ch.content = self.rule_definitions(&ch, &mut found_rules); ch.content = self.admonitions(&ch); + ch.content = self.std_links(&ch); } for section in &mut book.sections { let BookItem::Chapter(ch) = section else { From 5eeb0d05e2ae214a1cae6af7ca4fb23ef0b2d14c Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 27 Jun 2024 08:04:28 -0700 Subject: [PATCH 430/463] Move regular expressions to be global statics. This just makes it a little easier to refer to them. --- mdbook-spec/Cargo.lock | 1 + mdbook-spec/Cargo.toml | 1 + mdbook-spec/src/main.rs | 78 ++++++++++++++++++++++------------------- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/mdbook-spec/Cargo.lock b/mdbook-spec/Cargo.lock index d77a440..971edaf 100644 --- a/mdbook-spec/Cargo.lock +++ b/mdbook-spec/Cargo.lock @@ -388,6 +388,7 @@ version = "0.0.0" dependencies = [ "anyhow", "mdbook", + "once_cell", "pathdiff", "regex", "semver", diff --git a/mdbook-spec/Cargo.toml b/mdbook-spec/Cargo.toml index bbfd903..50a4b3d 100644 --- a/mdbook-spec/Cargo.toml +++ b/mdbook-spec/Cargo.toml @@ -8,6 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] anyhow = "1.0.79" mdbook = { version = "0.4.36", default-features = false } +once_cell = "1.19.0" pathdiff = "0.2.1" regex = "1.10.3" semver = "1.0.21" diff --git a/mdbook-spec/src/main.rs b/mdbook-spec/src/main.rs index 7e617f0..f5506e9 100644 --- a/mdbook-spec/src/main.rs +++ b/mdbook-spec/src/main.rs @@ -2,6 +2,7 @@ use mdbook::book::{Book, Chapter}; use mdbook::errors::Error; use mdbook::preprocess::{CmdPreprocessor, Preprocessor, PreprocessorContext}; use mdbook::BookItem; +use once_cell::sync::Lazy; use regex::{Captures, Regex}; use semver::{Version, VersionReq}; use std::collections::BTreeMap; @@ -11,6 +12,40 @@ use std::io::{self, Write as _}; use std::path::PathBuf; use std::process::{self, Command}; +/// The Regex for rules like `r[foo]`. +static RULE_RE: Lazy = Lazy::new(|| Regex::new(r"(?m)^r\[([^]]+)]$").unwrap()); + +/// The Regex for the syntax for blockquotes that have a specific CSS class, +/// like `> [!WARNING]`. +static ADMONITION_RE: Lazy = Lazy::new(|| { + Regex::new(r"(?m)^ *> \[!(?[^]]+)\]\n(?
    (?: *> .*\n)+)").unwrap() +}); + +/// A markdown link (without the brackets) that might possibly be a link to +/// the standard library using rustdoc's intra-doc notation. +const STD_LINK: &str = r"(?: [a-z]+@ )? + (?: std|core|alloc|proc_macro|test ) + (?: ::[A-Za-z_!:<>{}()\[\]]+ )?"; + +/// The Regex for a markdown link that might be a link to the standard library. +static STD_LINK_RE: Lazy = Lazy::new(|| { + Regex::new(&format!( + r"(?x) + (?: + ( \[`[^`]+`\] ) \( ({STD_LINK}) \) + ) + | (?: + ( \[`{STD_LINK}`\] ) + ) + " + )) + .unwrap() +}); + +/// The Regex used to extract the std links from the HTML generated by rustdoc. +static STD_LINK_EXTRACT_RE: Lazy = + Lazy::new(|| Regex::new(r#"
  • ]*href="(https://doc.rust-lang.org/[^"]+)""#).unwrap()); + fn main() { let mut args = std::env::args().skip(1); match args.next().as_deref() { @@ -56,41 +91,15 @@ fn handle_preprocessing(pre: &dyn Preprocessor) -> Result<(), Error> { } struct Spec { + /// Whether or not warnings should be errors (set by SPEC_DENY_WARNINGS + /// environment variable). deny_warnings: bool, - rule_re: Regex, - admonition_re: Regex, - std_link_re: Regex, - std_link_extract_re: Regex, } impl Spec { pub fn new() -> Spec { - // This is roughly a rustdoc intra-doc link definition. - let std_link = r"(?: [a-z]+@ )? - (?: std|core|alloc|proc_macro|test ) - (?: ::[A-Za-z_!:<>{}()\[\]]+ )?"; Spec { deny_warnings: std::env::var("SPEC_DENY_WARNINGS").as_deref() == Ok("1"), - rule_re: Regex::new(r"(?m)^r\[([^]]+)]$").unwrap(), - admonition_re: Regex::new( - r"(?m)^ *> \[!(?[^]]+)\]\n(?
    (?: *> .*\n)+)", - ) - .unwrap(), - std_link_re: Regex::new(&format!( - r"(?x) - (?: - ( \[`[^`]+`\] ) \( ({std_link}) \) - ) - | (?: - ( \[`{std_link}`\] ) - ) - " - )) - .unwrap(), - std_link_extract_re: Regex::new( - r#"
  • ]*href="(https://doc.rust-lang.org/[^"]+)""#, - ) - .unwrap(), } } @@ -103,7 +112,7 @@ impl Spec { ) -> String { let source_path = chapter.source_path.clone().unwrap_or_default(); let path = chapter.path.clone().unwrap_or_default(); - self.rule_re + RULE_RE .replace_all(&chapter.content, |caps: &Captures| { let rule_id = &caps[1]; if let Some((old, _)) = @@ -165,7 +174,7 @@ impl Spec { /// be a CSS class is valid. The actual styling needs to be added in a CSS /// file. fn admonitions(&self, chapter: &Chapter) -> String { - self.admonition_re + ADMONITION_RE .replace_all(&chapter.content, |caps: &Captures| { let lower = caps["admon"].to_lowercase(); format!( @@ -185,8 +194,7 @@ impl Spec { // // links are tuples of ("[`std::foo`]", None) for links without dest, // or ("[`foo`]", "std::foo") with a dest. - let mut links: Vec<_> = self - .std_link_re + let mut links: Vec<_> = STD_LINK_RE .captures_iter(&chapter.content) .map(|cap| { if let Some(no_dest) = cap.get(3) { @@ -250,8 +258,7 @@ impl Spec { // Extract the links from the generated html. let generated = fs::read_to_string(tmp.path().join("doc/a/index.html")).expect("index.html generated"); - let urls: Vec<_> = self - .std_link_extract_re + let urls: Vec<_> = STD_LINK_EXTRACT_RE .captures_iter(&generated) .map(|cap| cap.get(1).unwrap().as_str()) .collect(); @@ -267,8 +274,7 @@ impl Spec { } // Replace any disambiguated links with just the disambiguation. - let mut output = self - .std_link_re + let mut output = STD_LINK_RE .replace_all(&chapter.content, |caps: &Captures| { if let Some(dest) = caps.get(2) { // Replace destination parenthesis with a link definition (square brackets). From 9fa9532e1e83435481259767474a37317ced6bba Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 27 Jun 2024 08:05:03 -0700 Subject: [PATCH 431/463] Fix std links that have digits in them. --- mdbook-spec/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mdbook-spec/src/main.rs b/mdbook-spec/src/main.rs index f5506e9..69d762b 100644 --- a/mdbook-spec/src/main.rs +++ b/mdbook-spec/src/main.rs @@ -25,7 +25,7 @@ static ADMONITION_RE: Lazy = Lazy::new(|| { /// the standard library using rustdoc's intra-doc notation. const STD_LINK: &str = r"(?: [a-z]+@ )? (?: std|core|alloc|proc_macro|test ) - (?: ::[A-Za-z_!:<>{}()\[\]]+ )?"; + (?: ::[A-Za-z0-9_!:<>{}()\[\]]+ )?"; /// The Regex for a markdown link that might be a link to the standard library. static STD_LINK_RE: Lazy = Lazy::new(|| { From 6dae798cd98ebaf8968d4bfa0e8290ae0e987d79 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 27 Jun 2024 08:06:09 -0700 Subject: [PATCH 432/463] Move std_links to its own module. This code is getting long enough that it will help to organize it separately. --- mdbook-spec/src/main.rs | 148 ++--------------------------------- mdbook-spec/src/std_links.rs | 145 ++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 143 deletions(-) create mode 100644 mdbook-spec/src/std_links.rs diff --git a/mdbook-spec/src/main.rs b/mdbook-spec/src/main.rs index 69d762b..a12e95c 100644 --- a/mdbook-spec/src/main.rs +++ b/mdbook-spec/src/main.rs @@ -6,11 +6,11 @@ use once_cell::sync::Lazy; use regex::{Captures, Regex}; use semver::{Version, VersionReq}; use std::collections::BTreeMap; -use std::fmt::Write as _; -use std::fs; -use std::io::{self, Write as _}; +use std::io; use std::path::PathBuf; -use std::process::{self, Command}; +use std::process; + +mod std_links; /// The Regex for rules like `r[foo]`. static RULE_RE: Lazy = Lazy::new(|| Regex::new(r"(?m)^r\[([^]]+)]$").unwrap()); @@ -21,31 +21,6 @@ static ADMONITION_RE: Lazy = Lazy::new(|| { Regex::new(r"(?m)^ *> \[!(?[^]]+)\]\n(?
    (?: *> .*\n)+)").unwrap() }); -/// A markdown link (without the brackets) that might possibly be a link to -/// the standard library using rustdoc's intra-doc notation. -const STD_LINK: &str = r"(?: [a-z]+@ )? - (?: std|core|alloc|proc_macro|test ) - (?: ::[A-Za-z0-9_!:<>{}()\[\]]+ )?"; - -/// The Regex for a markdown link that might be a link to the standard library. -static STD_LINK_RE: Lazy = Lazy::new(|| { - Regex::new(&format!( - r"(?x) - (?: - ( \[`[^`]+`\] ) \( ({STD_LINK}) \) - ) - | (?: - ( \[`{STD_LINK}`\] ) - ) - " - )) - .unwrap() -}); - -/// The Regex used to extract the std links from the HTML generated by rustdoc. -static STD_LINK_EXTRACT_RE: Lazy = - Lazy::new(|| Regex::new(r#"
  • ]*href="(https://doc.rust-lang.org/[^"]+)""#).unwrap()); - fn main() { let mut args = std::env::args().skip(1); match args.next().as_deref() { @@ -184,119 +159,6 @@ impl Spec { }) .to_string() } - - /// Converts links to the standard library to the online documentation in - /// a fashion similar to rustdoc intra-doc links. - fn std_links(&self, chapter: &Chapter) -> String { - // This is very hacky, but should work well enough. - // - // Collect all standard library links. - // - // links are tuples of ("[`std::foo`]", None) for links without dest, - // or ("[`foo`]", "std::foo") with a dest. - let mut links: Vec<_> = STD_LINK_RE - .captures_iter(&chapter.content) - .map(|cap| { - if let Some(no_dest) = cap.get(3) { - (no_dest.as_str(), None) - } else { - ( - cap.get(1).unwrap().as_str(), - Some(cap.get(2).unwrap().as_str()), - ) - } - }) - .collect(); - if links.is_empty() { - return chapter.content.clone(); - } - links.sort(); - links.dedup(); - - // Write a Rust source file to use with rustdoc to generate intra-doc links. - let tmp = tempfile::TempDir::with_prefix("mdbook-spec-").unwrap(); - let src_path = tmp.path().join("a.rs"); - // Allow redundant since there could some in-scope things that are - // technically not necessary, but we don't care about (like - // [`Option`](std::option::Option)). - let mut src = format!( - "#![deny(rustdoc::broken_intra_doc_links)]\n\ - #![allow(rustdoc::redundant_explicit_links)]\n" - ); - for (link, dest) in &links { - write!(src, "//! - {link}").unwrap(); - if let Some(dest) = dest { - write!(src, "({})", dest).unwrap(); - } - src.push('\n'); - } - writeln!( - src, - "extern crate alloc;\n\ - extern crate proc_macro;\n\ - extern crate test;\n" - ) - .unwrap(); - fs::write(&src_path, &src).unwrap(); - let output = Command::new("rustdoc") - .arg("--edition=2021") - .arg(&src_path) - .current_dir(tmp.path()) - .output() - .expect("rustdoc installed"); - if !output.status.success() { - eprintln!( - "error: failed to extract std links ({:?}) in chapter {} ({:?})\n", - output.status, - chapter.name, - chapter.source_path.as_ref().unwrap() - ); - io::stderr().write_all(&output.stderr).unwrap(); - process::exit(1); - } - - // Extract the links from the generated html. - let generated = - fs::read_to_string(tmp.path().join("doc/a/index.html")).expect("index.html generated"); - let urls: Vec<_> = STD_LINK_EXTRACT_RE - .captures_iter(&generated) - .map(|cap| cap.get(1).unwrap().as_str()) - .collect(); - if urls.len() != links.len() { - eprintln!( - "error: expected rustdoc to generate {} links, but found {} in chapter {} ({:?})", - links.len(), - urls.len(), - chapter.name, - chapter.source_path.as_ref().unwrap() - ); - process::exit(1); - } - - // Replace any disambiguated links with just the disambiguation. - let mut output = STD_LINK_RE - .replace_all(&chapter.content, |caps: &Captures| { - if let Some(dest) = caps.get(2) { - // Replace destination parenthesis with a link definition (square brackets). - format!("{}[{}]", &caps[1], dest.as_str()) - } else { - caps[0].to_string() - } - }) - .to_string(); - - // Append the link definitions to the bottom of the chapter. - write!(output, "\n").unwrap(); - for ((link, dest), url) in links.iter().zip(urls) { - if let Some(dest) = dest { - write!(output, "[{dest}]: {url}\n").unwrap(); - } else { - write!(output, "{link}: {url}\n").unwrap(); - } - } - - output - } } impl Preprocessor for Spec { @@ -315,7 +177,7 @@ impl Preprocessor for Spec { } ch.content = self.rule_definitions(&ch, &mut found_rules); ch.content = self.admonitions(&ch); - ch.content = self.std_links(&ch); + ch.content = std_links::std_links(&ch); } for section in &mut book.sections { let BookItem::Chapter(ch) = section else { diff --git a/mdbook-spec/src/std_links.rs b/mdbook-spec/src/std_links.rs new file mode 100644 index 0000000..e0bc16c --- /dev/null +++ b/mdbook-spec/src/std_links.rs @@ -0,0 +1,145 @@ +use mdbook::book::Chapter; +use once_cell::sync::Lazy; +use regex::{Captures, Regex}; +use std::fmt::Write as _; +use std::fs; +use std::io::{self, Write as _}; +use std::process::{self, Command}; + +/// A markdown link (without the brackets) that might possibly be a link to +/// the standard library using rustdoc's intra-doc notation. +const STD_LINK: &str = r"(?: [a-z]+@ )? + (?: std|core|alloc|proc_macro|test ) + (?: ::[A-Za-z0-9_!:<>{}()\[\]]+ )?"; + +/// The Regex for a markdown link that might be a link to the standard library. +static STD_LINK_RE: Lazy = Lazy::new(|| { + Regex::new(&format!( + r"(?x) + (?: + ( \[`[^`]+`\] ) \( ({STD_LINK}) \) + ) + | (?: + ( \[`{STD_LINK}`\] ) + ) + " + )) + .unwrap() +}); + +/// The Regex used to extract the std links from the HTML generated by rustdoc. +static STD_LINK_EXTRACT_RE: Lazy = + Lazy::new(|| Regex::new(r#"
  • ]*href="(https://doc.rust-lang.org/[^"]+)""#).unwrap()); + +/// Converts links to the standard library to the online documentation in a +/// fashion similar to rustdoc intra-doc links. +pub fn std_links(chapter: &Chapter) -> String { + // This is very hacky, but should work well enough. + // + // Collect all standard library links. + // + // links are tuples of ("[`std::foo`]", None) for links without dest, + // or ("[`foo`]", "std::foo") with a dest. + let mut links: Vec<_> = STD_LINK_RE + .captures_iter(&chapter.content) + .map(|cap| { + if let Some(no_dest) = cap.get(3) { + (no_dest.as_str(), None) + } else { + ( + cap.get(1).unwrap().as_str(), + Some(cap.get(2).unwrap().as_str()), + ) + } + }) + .collect(); + if links.is_empty() { + return chapter.content.clone(); + } + links.sort(); + links.dedup(); + + // Write a Rust source file to use with rustdoc to generate intra-doc links. + let tmp = tempfile::TempDir::with_prefix("mdbook-spec-").unwrap(); + let src_path = tmp.path().join("a.rs"); + // Allow redundant since there could some in-scope things that are + // technically not necessary, but we don't care about (like + // [`Option`](std::option::Option)). + let mut src = format!( + "#![deny(rustdoc::broken_intra_doc_links)]\n\ + #![allow(rustdoc::redundant_explicit_links)]\n" + ); + for (link, dest) in &links { + write!(src, "//! - {link}").unwrap(); + if let Some(dest) = dest { + write!(src, "({})", dest).unwrap(); + } + src.push('\n'); + } + writeln!( + src, + "extern crate alloc;\n\ + extern crate proc_macro;\n\ + extern crate test;\n" + ) + .unwrap(); + fs::write(&src_path, &src).unwrap(); + let output = Command::new("rustdoc") + .arg("--edition=2021") + .arg(&src_path) + .current_dir(tmp.path()) + .output() + .expect("rustdoc installed"); + if !output.status.success() { + eprintln!( + "error: failed to extract std links ({:?}) in chapter {} ({:?})\n", + output.status, + chapter.name, + chapter.source_path.as_ref().unwrap() + ); + io::stderr().write_all(&output.stderr).unwrap(); + process::exit(1); + } + + // Extract the links from the generated html. + let generated = + fs::read_to_string(tmp.path().join("doc/a/index.html")).expect("index.html generated"); + let urls: Vec<_> = STD_LINK_EXTRACT_RE + .captures_iter(&generated) + .map(|cap| cap.get(1).unwrap().as_str()) + .collect(); + if urls.len() != links.len() { + eprintln!( + "error: expected rustdoc to generate {} links, but found {} in chapter {} ({:?})", + links.len(), + urls.len(), + chapter.name, + chapter.source_path.as_ref().unwrap() + ); + process::exit(1); + } + + // Replace any disambiguated links with just the disambiguation. + let mut output = STD_LINK_RE + .replace_all(&chapter.content, |caps: &Captures| { + if let Some(dest) = caps.get(2) { + // Replace destination parenthesis with a link definition (square brackets). + format!("{}[{}]", &caps[1], dest.as_str()) + } else { + caps[0].to_string() + } + }) + .to_string(); + + // Append the link definitions to the bottom of the chapter. + write!(output, "\n").unwrap(); + for ((link, dest), url) in links.iter().zip(urls) { + if let Some(dest) = dest { + write!(output, "[{dest}]: {url}\n").unwrap(); + } else { + write!(output, "{link}: {url}\n").unwrap(); + } + } + + output +} From 94b52975286d2b4bedb016642ebab633b062d9e8 Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 27 Jun 2024 08:11:46 -0700 Subject: [PATCH 433/463] Split std_links into multiple functions. The std_links function was getting a little long, this should help organize a little. --- mdbook-spec/src/std_links.rs | 124 ++++++++++++++++++++--------------- 1 file changed, 72 insertions(+), 52 deletions(-) diff --git a/mdbook-spec/src/std_links.rs b/mdbook-spec/src/std_links.rs index e0bc16c..1d38142 100644 --- a/mdbook-spec/src/std_links.rs +++ b/mdbook-spec/src/std_links.rs @@ -5,6 +5,7 @@ use std::fmt::Write as _; use std::fs; use std::io::{self, Write as _}; use std::process::{self, Command}; +use tempfile::TempDir; /// A markdown link (without the brackets) that might possibly be a link to /// the standard library using rustdoc's intra-doc notation. @@ -34,12 +35,65 @@ static STD_LINK_EXTRACT_RE: Lazy = /// Converts links to the standard library to the online documentation in a /// fashion similar to rustdoc intra-doc links. pub fn std_links(chapter: &Chapter) -> String { - // This is very hacky, but should work well enough. - // - // Collect all standard library links. - // - // links are tuples of ("[`std::foo`]", None) for links without dest, - // or ("[`foo`]", "std::foo") with a dest. + let links = collect_markdown_links(chapter); + if links.is_empty() { + return chapter.content.clone(); + } + + // Write a Rust source file to use with rustdoc to generate intra-doc links. + let tmp = TempDir::with_prefix("mdbook-spec-").unwrap(); + run_rustdoc(&tmp, &links, &chapter); + + // Extract the links from the generated html. + let generated = + fs::read_to_string(tmp.path().join("doc/a/index.html")).expect("index.html generated"); + let urls: Vec<_> = STD_LINK_EXTRACT_RE + .captures_iter(&generated) + .map(|cap| cap.get(1).unwrap().as_str()) + .collect(); + if urls.len() != links.len() { + eprintln!( + "error: expected rustdoc to generate {} links, but found {} in chapter {} ({:?})", + links.len(), + urls.len(), + chapter.name, + chapter.source_path.as_ref().unwrap() + ); + process::exit(1); + } + + // Replace any disambiguated links with just the disambiguation. + let mut output = STD_LINK_RE + .replace_all(&chapter.content, |caps: &Captures| { + if let Some(dest) = caps.get(2) { + // Replace destination parenthesis with a link definition (square brackets). + format!("{}[{}]", &caps[1], dest.as_str()) + } else { + caps[0].to_string() + } + }) + .to_string(); + + // Append the link definitions to the bottom of the chapter. + write!(output, "\n").unwrap(); + for ((link, dest), url) in links.iter().zip(urls) { + if let Some(dest) = dest { + write!(output, "[{dest}]: {url}\n").unwrap(); + } else { + write!(output, "{link}: {url}\n").unwrap(); + } + } + + output +} + +/// Collects all markdown links. +/// +/// Returns a `Vec` of `(link, Option)` where markdown text like +/// ``[`std::fmt`]`` would return that as a link. The dest is optional, for +/// example ``[`Option`](std::option::Option)`` would have the part in +/// parentheses as the dest. +fn collect_markdown_links(chapter: &Chapter) -> Vec<(&str, Option<&str>)> { let mut links: Vec<_> = STD_LINK_RE .captures_iter(&chapter.content) .map(|cap| { @@ -54,13 +108,21 @@ pub fn std_links(chapter: &Chapter) -> String { }) .collect(); if links.is_empty() { - return chapter.content.clone(); + return vec![]; } links.sort(); links.dedup(); + links +} - // Write a Rust source file to use with rustdoc to generate intra-doc links. - let tmp = tempfile::TempDir::with_prefix("mdbook-spec-").unwrap(); +/// Generates links using rustdoc. +/// +/// This takes the given links and creates a temporary Rust source file +/// containing those links within doc-comments, and then runs rustdoc to +/// generate intra-doc links on them. +/// +/// The output will be in the given `tmp` directory. +fn run_rustdoc(tmp: &TempDir, links: &[(&str, Option<&str>)], chapter: &Chapter) { let src_path = tmp.path().join("a.rs"); // Allow redundant since there could some in-scope things that are // technically not necessary, but we don't care about (like @@ -69,7 +131,7 @@ pub fn std_links(chapter: &Chapter) -> String { "#![deny(rustdoc::broken_intra_doc_links)]\n\ #![allow(rustdoc::redundant_explicit_links)]\n" ); - for (link, dest) in &links { + for (link, dest) in links { write!(src, "//! - {link}").unwrap(); if let Some(dest) = dest { write!(src, "({})", dest).unwrap(); @@ -100,46 +162,4 @@ pub fn std_links(chapter: &Chapter) -> String { io::stderr().write_all(&output.stderr).unwrap(); process::exit(1); } - - // Extract the links from the generated html. - let generated = - fs::read_to_string(tmp.path().join("doc/a/index.html")).expect("index.html generated"); - let urls: Vec<_> = STD_LINK_EXTRACT_RE - .captures_iter(&generated) - .map(|cap| cap.get(1).unwrap().as_str()) - .collect(); - if urls.len() != links.len() { - eprintln!( - "error: expected rustdoc to generate {} links, but found {} in chapter {} ({:?})", - links.len(), - urls.len(), - chapter.name, - chapter.source_path.as_ref().unwrap() - ); - process::exit(1); - } - - // Replace any disambiguated links with just the disambiguation. - let mut output = STD_LINK_RE - .replace_all(&chapter.content, |caps: &Captures| { - if let Some(dest) = caps.get(2) { - // Replace destination parenthesis with a link definition (square brackets). - format!("{}[{}]", &caps[1], dest.as_str()) - } else { - caps[0].to_string() - } - }) - .to_string(); - - // Append the link definitions to the bottom of the chapter. - write!(output, "\n").unwrap(); - for ((link, dest), url) in links.iter().zip(urls) { - if let Some(dest) = dest { - write!(output, "[{dest}]: {url}\n").unwrap(); - } else { - write!(output, "{link}: {url}\n").unwrap(); - } - } - - output } From 81e6c0f0f7595e01317f0b3b6f6dfbb341cd2a7b Mon Sep 17 00:00:00 2001 From: Tiger0202 Date: Thu, 27 Jun 2024 08:15:41 -0700 Subject: [PATCH 434/463] Don't override explicit link definitions. If the author has an explicit link definition, don't allow std_links to override it. --- mdbook-spec/src/std_links.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/mdbook-spec/src/std_links.rs b/mdbook-spec/src/std_links.rs index 1d38142..d3f1c2a 100644 --- a/mdbook-spec/src/std_links.rs +++ b/mdbook-spec/src/std_links.rs @@ -1,6 +1,7 @@ use mdbook::book::Chapter; use once_cell::sync::Lazy; use regex::{Captures, Regex}; +use std::collections::HashSet; use std::fmt::Write as _; use std::fs; use std::io::{self, Write as _}; @@ -32,6 +33,15 @@ static STD_LINK_RE: Lazy = Lazy::new(|| { static STD_LINK_EXTRACT_RE: Lazy = Lazy::new(|| Regex::new(r#"
  • ]*href="(https://doc.rust-lang.org/[^"]+)""#).unwrap()); +/// The Regex for a markdown link definition. +static LINK_DEF_RE: Lazy = Lazy::new(|| { + // This is a pretty lousy regex for a link definition. It doesn't + // handle things like blockquotes, code blocks, etc. Using a + // markdown parser isn't really feasible here, it would be nice to + // improve this. + Regex::new(r#"(?m)^(?