├── xtask ├── .gitignore ├── Cargo.toml ├── Cargo.lock └── src │ └── main.rs ├── style-check ├── .gitignore ├── Cargo.toml ├── Cargo.lock └── src │ └── main.rs ├── .gitignore ├── mdbook-spec ├── .gitignore ├── CHANGELOG.md ├── README.md ├── src │ ├── main.rs │ ├── admonitions.rs │ └── rules.rs ├── Cargo.toml └── LICENSE-MIT ├── src ├── appendices.md ├── type-system.md ├── lexical-structure.md ├── test-summary.md ├── grammar.md ├── types │ ├── parameters.md │ ├── never.md │ ├── inferred.md │ ├── array.md │ ├── union.md │ ├── slice.md │ ├── enum.md │ ├── struct.md │ ├── textual.md │ ├── function-pointer.md │ ├── tuple.md │ ├── function-item.md │ ├── numeric.md │ ├── pointer.md │ ├── trait-object.md │ └── boolean.md ├── statements-and-expressions.md ├── expressions │ ├── return-expr.md │ ├── underscore-expr.md │ ├── path-expr.md │ ├── grouped-expr.md │ ├── range-expr.md │ ├── field-expr.md │ ├── await-expr.md │ ├── call-expr.md │ ├── tuple-expr.md │ ├── closure-expr.md │ ├── method-call-expr.md │ ├── array-expr.md │ └── struct-expr.md ├── memory-allocation-and-lifetime.md ├── influences.md ├── memory-model.md ├── whitespace.md ├── unsafety.md ├── interior-mutability.md ├── variables.md ├── dynamically-sized-types.md ├── items │ ├── type-aliases.md │ ├── structs.md │ ├── constant-items.md │ └── extern-crates.md ├── behavior-not-considered-unsafe.md ├── input-format.md ├── attributes │ ├── limits.md │ └── derive.md ├── items.md ├── runtime.md ├── notation.md ├── identifiers.md ├── macros.md ├── comments.md ├── keywords.md ├── abi.md ├── subtyping.md ├── SUMMARY.md └── types.md ├── rustfmt.toml ├── rust-toolchain.toml ├── .cargo └── config.toml ├── .gitattributes ├── reference.md ├── STYLE.md ├── triagebot.toml ├── LICENSE-MIT ├── theme └── reference.js ├── CONTRIBUTING.md ├── docs ├── review-policy.md └── grammar.md ├── README.md └── .github └── workflows └── main.yml /xtask/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /style-check/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | stable-check/ 3 | -------------------------------------------------------------------------------- /mdbook-spec/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /src/appendices.md: -------------------------------------------------------------------------------- 1 | # Appendices 2 | -------------------------------------------------------------------------------- /src/type-system.md: -------------------------------------------------------------------------------- 1 | # Type system 2 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | style_edition = "2024" 2 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly" 3 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | xtask = "run --manifest-path=xtask/Cargo.toml --" 3 | -------------------------------------------------------------------------------- /xtask/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtask" 3 | edition = "2024" 4 | 5 | [dependencies] 6 | -------------------------------------------------------------------------------- /src/lexical-structure.md: -------------------------------------------------------------------------------- 1 | # Lexical structure 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /reference.md: -------------------------------------------------------------------------------- 1 | % The Rust Reference has moved 2 | 3 | We've split up the reference into chapters. Please find it at its new 4 | home [here](reference/index.html). 5 | -------------------------------------------------------------------------------- /STYLE.md: -------------------------------------------------------------------------------- 1 | # Rust reference style guide 2 | 3 | See the [Authoring Guide] for details on the style used in the reference. 4 | 5 | [Authoring Guide]: docs/authoring.md 6 | -------------------------------------------------------------------------------- /src/test-summary.md: -------------------------------------------------------------------------------- 1 | # Test summary 2 | 3 | The following is a summary of the total tests that are linked to individual rule identifiers within the reference. 4 | 5 | {{summary-table}} 6 | -------------------------------------------------------------------------------- /xtask/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "xtask" 7 | version = "0.0.0" 8 | -------------------------------------------------------------------------------- /src/grammar.md: -------------------------------------------------------------------------------- 1 | # Grammar summary 2 | 3 | The following is a summary of the grammar production rules. For details on the syntax of this grammar, see *[notation.grammar.syntax]*. 4 | 5 | {{ grammar-summary }} 6 | -------------------------------------------------------------------------------- /style-check/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "style-check" 3 | version = "0.1.0" 4 | authors = ["steveklabnik "] 5 | edition = "2024" 6 | 7 | [dependencies] 8 | pulldown-cmark = "0.10.0" 9 | -------------------------------------------------------------------------------- /mdbook-spec/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## mdbook-spec 0.1.2 4 | 5 | - Fixed some issues with rust-lang/rust build integration. 6 | 7 | ## mdbook-spec 0.1.1 8 | 9 | - Moved code to a library to support upstream integration. 10 | 11 | ## mdbook-spec 0.1.0 12 | 13 | - Initial release 14 | -------------------------------------------------------------------------------- /mdbook-spec/README.md: -------------------------------------------------------------------------------- 1 | # mdbook-spec 2 | 3 | This is an mdbook preprocessor to add some extensions for the Rust specification. 4 | 5 | > This crate is maintained by the [rust-lang/spec](https://github.com/rust-lang/spec/) team, primarily for use by the Rust Specification and not intended for external use (except as a transitive dependency). This crate may make major changes to its APIs or be deprecated without warning. 6 | -------------------------------------------------------------------------------- /mdbook-spec/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut args = std::env::args().skip(1); 3 | match args.next().as_deref() { 4 | Some("supports") => { 5 | // Supports all renderers. 6 | return; 7 | } 8 | Some(arg) => { 9 | eprintln!("unknown argument: {arg}"); 10 | std::process::exit(1); 11 | } 12 | None => {} 13 | } 14 | 15 | if let Err(e) = mdbook_spec::handle_preprocessing() { 16 | eprintln!("{}", e); 17 | std::process::exit(1); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/types/parameters.md: -------------------------------------------------------------------------------- 1 | r[type.generic] 2 | # Type parameters 3 | 4 | Within the body of an item that has type parameter declarations, the names of 5 | its type parameters are types: 6 | 7 | ```rust 8 | fn to_vec(xs: &[A]) -> Vec { 9 | if xs.is_empty() { 10 | return vec![]; 11 | } 12 | let first: A = xs[0].clone(); 13 | let mut rest: Vec = to_vec(&xs[1..]); 14 | rest.insert(0, first); 15 | rest 16 | } 17 | ``` 18 | 19 | Here, `first` has type `A`, referring to `to_vec`'s `A` type parameter; and 20 | `rest` has type `Vec`, a vector with element type `A`. 21 | -------------------------------------------------------------------------------- /src/statements-and-expressions.md: -------------------------------------------------------------------------------- 1 | r[stmt-expr] 2 | # Statements and expressions 3 | 4 | Rust is _primarily_ an expression language. 5 | This means that most forms of value-producing or effect-causing evaluation are directed by the uniform syntax category of _expressions_. 6 | 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. 7 | 8 | In contrast, statements serve _mostly_ to contain and explicitly sequence expression evaluation. 9 | -------------------------------------------------------------------------------- /src/expressions/return-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.return] 2 | # `return` expressions 3 | 4 | r[expr.return.syntax] 5 | ```grammar,expressions 6 | ReturnExpression -> `return` Expression? 7 | ``` 8 | 9 | r[expr.return.intro] 10 | Return expressions are denoted with the keyword `return`. 11 | 12 | r[expr.return.behavior] 13 | Evaluating a `return` expression moves its argument into the designated output location for the current function call, destroys the current function activation frame, and transfers control to the caller frame. 14 | 15 | An example of a `return` expression: 16 | 17 | ```rust 18 | fn max(a: i32, b: i32) -> i32 { 19 | if a > b { 20 | return a; 21 | } 22 | return b; 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /mdbook-spec/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mdbook-spec" 3 | version = "0.1.2" 4 | edition = "2024" 5 | license = "MIT OR Apache-2.0" 6 | description = "An mdBook preprocessor to help with the Rust specification." 7 | repository = "https://github.com/rust-lang/spec/" 8 | default-run = "mdbook-spec" 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | anyhow = "1.0.79" 14 | mdbook-markdown = "0.5.1" 15 | mdbook-preprocessor = "0.5.1" 16 | once_cell = "1.19.0" 17 | pathdiff = "0.2.1" 18 | railroad = { version = "0.3.2", default-features = false } 19 | regex = "1.9.4" 20 | semver = "1.0.21" 21 | serde_json = "1.0.113" 22 | tempfile = "3.10.1" 23 | walkdir = "2.5.0" 24 | -------------------------------------------------------------------------------- /src/types/never.md: -------------------------------------------------------------------------------- 1 | r[type.never] 2 | # Never type 3 | 4 | r[type.never.syntax] 5 | ```grammar,types 6 | NeverType -> `!` 7 | ``` 8 | 9 | r[type.never.intro] 10 | The never type `!` is a type with no values, representing the result of 11 | computations that never complete. 12 | 13 | r[type.never.coercion] 14 | Expressions of type `!` can be coerced into any other type. 15 | 16 | r[type.never.constraint] 17 | The `!` type can **only** appear in function return types presently, 18 | indicating it is a diverging function that never returns. 19 | 20 | ```rust 21 | fn foo() -> ! { 22 | panic!("This call never returns."); 23 | } 24 | ``` 25 | 26 | ```rust 27 | unsafe extern "C" { 28 | pub safe fn no_return_extern_func() -> !; 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /triagebot.toml: -------------------------------------------------------------------------------- 1 | [relabel] 2 | allow-unauthenticated = [ 3 | "S-*", "A-*", "New Content", "Language Cleanup", "Easy", "Formatting", "Enhancement", "Bug", 4 | ] 5 | 6 | [assign] 7 | 8 | [shortcut] 9 | 10 | # When rebasing, this will add a diff link in a comment. 11 | [range-diff] 12 | 13 | [issue-links] 14 | check-commits = false 15 | 16 | [merge-conflicts] 17 | remove = [] 18 | add = ["S-waiting-on-author"] 19 | unless = ["S-blocked", "S-waiting-on-team", "S-waiting-on-review"] 20 | 21 | [autolabel."S-waiting-on-review"] 22 | new_pr = true 23 | 24 | [review-submitted] 25 | reviewed_label = "S-waiting-on-author" 26 | review_labels = ["S-waiting-on-review"] 27 | 28 | [review-requested] 29 | remove_labels = ["S-waiting-on-author"] 30 | add_labels = ["S-waiting-on-review"] 31 | -------------------------------------------------------------------------------- /src/types/inferred.md: -------------------------------------------------------------------------------- 1 | r[type.inferred] 2 | # Inferred type 3 | 4 | r[type.inferred.syntax] 5 | ```grammar,types 6 | InferredType -> `_` 7 | ``` 8 | 9 | r[type.inferred.intro] 10 | The inferred type asks the compiler to infer the type if possible based on the 11 | surrounding information available. 12 | 13 | > [!EXAMPLE] 14 | > The inferred type is often used in generic arguments: 15 | > 16 | > ```rust 17 | > let x: Vec<_> = (0..10).collect(); 18 | > ``` 19 | 20 | r[type.inferred.constraint] 21 | The inferred type cannot be used in item signatures. 22 | 23 | 28 | -------------------------------------------------------------------------------- /src/memory-allocation-and-lifetime.md: -------------------------------------------------------------------------------- 1 | r[alloc] 2 | # Memory allocation and lifetime 3 | 4 | r[alloc.static] 5 | The _items_ of a program are those functions, modules, and types that have their 6 | value calculated at compile-time and stored uniquely in the memory image of the 7 | rust process. Items are neither dynamically allocated nor freed. 8 | 9 | r[alloc.dynamic] 10 | The _heap_ is a general term that describes boxes. The lifetime of an 11 | allocation in the heap depends on the lifetime of the box values pointing to 12 | it. Since box values may themselves be passed in and out of frames, or stored 13 | in the heap, heap allocations may outlive the frame they are allocated within. 14 | An allocation in the heap is guaranteed to reside at a single location in the 15 | heap for the whole lifetime of the allocation - it will never be relocated as 16 | a result of moving a box value. 17 | -------------------------------------------------------------------------------- /src/influences.md: -------------------------------------------------------------------------------- 1 | # Influences 2 | 3 | Rust is not a particularly original language, with design elements coming from 4 | a wide range of sources. Some of these are listed below (including elements 5 | that have since been removed): 6 | 7 | * SML, OCaml: algebraic data types, pattern matching, type inference, 8 | semicolon statement separation 9 | * C++: references, RAII, smart pointers, move semantics, monomorphization, 10 | memory model 11 | * ML Kit, Cyclone: region based memory management 12 | * Haskell (GHC): typeclasses, type families 13 | * Newsqueak, Alef, Limbo: channels, concurrency 14 | * Erlang: message passing, thread failure, ~~linked thread failure~~, 15 | ~~lightweight concurrency~~ 16 | * Swift: optional bindings 17 | * Scheme: hygienic macros 18 | * C#: attributes 19 | * Ruby: closure syntax, ~~block syntax~~ 20 | * NIL, Hermes: ~~typestate~~ 21 | * [Unicode Annex #31](http://www.unicode.org/reports/tr31/): identifier and 22 | pattern syntax 23 | -------------------------------------------------------------------------------- /src/memory-model.md: -------------------------------------------------------------------------------- 1 | r[memory] 2 | # Memory model 3 | 4 | > [!WARNING] 5 | > The memory model of Rust is incomplete and not fully decided. 6 | 7 | r[memory.bytes] 8 | ## Bytes 9 | 10 | r[memory.bytes.intro] 11 | The most basic unit of memory in Rust is a byte. 12 | 13 | > [!NOTE] 14 | > While bytes are typically lowered to hardware bytes, Rust uses an "abstract" notion of bytes that can make distinctions which are absent in hardware, such as being uninitialized, or storing part of a pointer. Those distinctions can affect whether your program has undefined behavior, so they still have tangible impact on how compiled Rust programs behave. 15 | 16 | r[memory.bytes.contents] 17 | Each byte may have one of the following values: 18 | 19 | r[memory.bytes.init] 20 | * An initialized byte containing a `u8` value and optional [provenance][std::ptr#provenance], 21 | 22 | r[memory.bytes.uninit] 23 | * An uninitialized byte. 24 | 25 | > [!NOTE] 26 | > The above list is not yet guaranteed to be exhaustive. 27 | -------------------------------------------------------------------------------- /src/types/array.md: -------------------------------------------------------------------------------- 1 | r[type.array] 2 | # Array types 3 | 4 | r[type.array.syntax] 5 | ```grammar,types 6 | ArrayType -> `[` Type `;` Expression `]` 7 | ``` 8 | 9 | r[type.array.intro] 10 | An array is a fixed-size sequence of `N` elements of type `T`. The array type 11 | is written as `[T; N]`. 12 | 13 | r[type.array.constraint] 14 | The size is a [constant expression] that evaluates to a [`usize`]. 15 | 16 | Examples: 17 | 18 | ```rust 19 | // A stack-allocated array 20 | let array: [i32; 3] = [1, 2, 3]; 21 | 22 | // A heap-allocated array, coerced to a slice 23 | let boxed_array: Box<[i32]> = Box::new([1, 2, 3]); 24 | ``` 25 | 26 | r[type.array.index] 27 | All elements of arrays are always initialized, and access to an array is 28 | always bounds-checked in safe methods and operators. 29 | 30 | > [!NOTE] 31 | > The [`Vec`] standard library type provides a heap-allocated resizable array type. 32 | 33 | [`usize`]: numeric.md#machine-dependent-integer-types 34 | [constant expression]: ../const_eval.md#constant-expressions 35 | -------------------------------------------------------------------------------- /src/types/union.md: -------------------------------------------------------------------------------- 1 | r[type.union] 2 | # Union types 3 | 4 | r[type.union.intro] 5 | A *union type* is a nominal, heterogeneous C-like union, denoted by the name of 6 | a [`union` item][item]. 7 | 8 | r[type.union.access] 9 | Unions have no notion of an "active field". Instead, every union access 10 | transmutes parts of the content of the union to the type of the accessed field. 11 | 12 | r[type.union.safety] 13 | Since transmutes can cause unexpected or undefined behaviour, `unsafe` is 14 | required to read from a union field. 15 | 16 | r[type.union.constraint] 17 | Union field types are also restricted to a 18 | subset of types which ensures that they never need dropping. See the [item] 19 | documentation for further details. 20 | 21 | r[type.union.layout] 22 | The memory layout of a `union` is undefined by default (in particular, fields do 23 | *not* have to be at offset 0), but the `#[repr(...)]` attribute can be used to 24 | fix a layout. 25 | 26 | [`Copy`]: ../special-types-and-traits.md#copy 27 | [item]: ../items/unions.md 28 | -------------------------------------------------------------------------------- /src/expressions/underscore-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.placeholder] 2 | # `_` expressions 3 | 4 | r[expr.placeholder.syntax] 5 | ```grammar,expressions 6 | UnderscoreExpression -> `_` 7 | ``` 8 | 9 | r[expr.placeholder.intro] 10 | Underscore expressions, denoted with the symbol `_`, are used to signify a 11 | placeholder in a destructuring assignment. 12 | 13 | r[expr.placeholder.lhs-assignment-only] 14 | They may only appear in the left-hand side of an assignment. 15 | 16 | r[expr.placeholder.pattern] 17 | Note that this is distinct from the [wildcard pattern](../patterns.md#wildcard-pattern). 18 | 19 | Examples of `_` expressions: 20 | 21 | ```rust 22 | let p = (1, 2); 23 | let mut a = 0; 24 | (_, a) = p; 25 | 26 | struct Position { 27 | x: u32, 28 | y: u32, 29 | } 30 | 31 | Position { x: a, y: _ } = Position{ x: 2, y: 3 }; 32 | 33 | // unused result, assignment to `_` used to declare intent and remove a warning 34 | _ = 2 + 2; 35 | // triggers unused_must_use warning 36 | // 2 + 2; 37 | 38 | // equivalent technique using a wildcard pattern in a let-binding 39 | let _ = 2 + 2; 40 | ``` 41 | -------------------------------------------------------------------------------- /src/types/slice.md: -------------------------------------------------------------------------------- 1 | r[type.slice] 2 | # Slice types 3 | 4 | r[type.slice.syntax] 5 | ```grammar,types 6 | SliceType -> `[` Type `]` 7 | ``` 8 | 9 | r[type.slice.intro] 10 | A slice is a [dynamically sized type] representing a 'view' into a sequence of 11 | elements of type `T`. The slice type is written as `[T]`. 12 | 13 | r[type.slice.unsized] 14 | Slice types are generally used through pointer types. For example: 15 | 16 | * `&[T]`: a 'shared slice', often just called a 'slice'. It doesn't own the 17 | data it points to; it borrows it. 18 | * `&mut [T]`: a 'mutable slice'. It mutably borrows the data it points to. 19 | * `Box<[T]>`: a 'boxed slice' 20 | 21 | Examples: 22 | 23 | ```rust 24 | // A heap-allocated array, coerced to a slice 25 | let boxed_array: Box<[i32]> = Box::new([1, 2, 3]); 26 | 27 | // A (shared) slice into an array 28 | let slice: &[i32] = &boxed_array[..]; 29 | ``` 30 | 31 | r[type.slice.safe] 32 | All elements of slices are always initialized, and access to a slice is always 33 | bounds-checked in safe methods and operators. 34 | 35 | [dynamically sized type]: ../dynamically-sized-types.md 36 | -------------------------------------------------------------------------------- /src/types/enum.md: -------------------------------------------------------------------------------- 1 | r[type.enum] 2 | # Enumerated types 3 | 4 | r[type.enum.intro] 5 | An *enumerated type* is a nominal, heterogeneous disjoint union type, denoted 6 | by the name of an [`enum` item]. [^enumtype] 7 | 8 | r[type.enum.declaration] 9 | An [`enum` item] declares both the type and a number of *variants*, each of 10 | which is independently named and has the syntax of a struct, tuple struct or 11 | unit-like struct. 12 | 13 | r[type.enum.constructor] 14 | New instances of an `enum` can be constructed with a [struct expression]. 15 | 16 | r[type.enum.value] 17 | Any `enum` value consumes as much memory as the largest variant for its 18 | corresponding `enum` type, as well as the size needed to store a discriminant. 19 | 20 | r[type.enum.name] 21 | Enum types cannot be denoted *structurally* as types, but must be denoted by 22 | named reference to an [`enum` item]. 23 | 24 | [^enumtype]: The `enum` type is analogous to a `data` constructor declaration in 25 | Haskell, or a *pick ADT* in Limbo. 26 | 27 | [`enum` item]: ../items/enumerations.md 28 | [struct expression]: ../expressions/struct-expr.md 29 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /mdbook-spec/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 The Rust Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /src/whitespace.md: -------------------------------------------------------------------------------- 1 | r[lex.whitespace] 2 | # Whitespace 3 | 4 | r[whitespace.syntax] 5 | ```grammar,lexer 6 | @root WHITESPACE -> 7 | U+0009 // Horizontal tab, `'\t'` 8 | | U+000A // Line feed, `'\n'` 9 | | U+000B // Vertical tab 10 | | U+000C // Form feed 11 | | U+000D // Carriage return, `'\r'` 12 | | U+0020 // Space, `' '` 13 | | U+0085 // Next line 14 | | U+200E // Left-to-right mark 15 | | U+200F // Right-to-left mark 16 | | U+2028 // Line separator 17 | | U+2029 // Paragraph separator 18 | 19 | TAB -> U+0009 // Horizontal tab, `'\t'` 20 | 21 | LF -> U+000A // Line feed, `'\n'` 22 | 23 | CR -> U+000D // Carriage return, `'\r'` 24 | ``` 25 | 26 | r[lex.whitespace.intro] 27 | Whitespace is any non-empty string containing only characters that have the [`Pattern_White_Space`] Unicode property. 28 | 29 | r[lex.whitespace.token-sep] 30 | Rust is a "free-form" language, meaning that all forms of whitespace serve only to separate _tokens_ in the grammar, and have no semantic significance. 31 | 32 | r[lex.whitespace.replacement] 33 | A Rust program has identical meaning if each whitespace element is replaced with any other legal whitespace element, such as a single space character. 34 | 35 | [`Pattern_White_Space`]: https://www.unicode.org/reports/tr31/ 36 | -------------------------------------------------------------------------------- /src/expressions/path-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.path] 2 | # Path expressions 3 | 4 | r[expr.path.syntax] 5 | ```grammar,expressions 6 | PathExpression -> 7 | PathInExpression 8 | | QualifiedPathInExpression 9 | ``` 10 | 11 | r[expr.path.intro] 12 | A [path] used as an expression context denotes either a local variable or an item. 13 | 14 | r[expr.path.place] 15 | Path expressions that resolve to local or static variables are [place expressions]; other paths are [value expressions]. 16 | 17 | r[expr.path.safety] 18 | Using a [`static mut`] variable requires an [`unsafe` block]. 19 | 20 | ```rust 21 | # mod globals { 22 | # pub static STATIC_VAR: i32 = 5; 23 | # pub static mut STATIC_MUT_VAR: i32 = 7; 24 | # } 25 | # let local_var = 3; 26 | local_var; 27 | globals::STATIC_VAR; 28 | unsafe { globals::STATIC_MUT_VAR }; 29 | let some_constructor = Some::; 30 | let push_integer = Vec::::push; 31 | let slice_reverse = <[i32]>::reverse; 32 | ``` 33 | 34 | r[expr.path.const] 35 | Evaluation of associated constants is handled the same way as [`const` blocks]. 36 | 37 | [place expressions]: ../expressions.md#place-expressions-and-value-expressions 38 | [value expressions]: ../expressions.md#place-expressions-and-value-expressions 39 | [path]: ../paths.md 40 | [`static mut`]: ../items/static-items.md#mutable-statics 41 | [`unsafe` block]: block-expr.md#unsafe-blocks 42 | [`const` blocks]: block-expr.md#const-blocks 43 | -------------------------------------------------------------------------------- /src/types/struct.md: -------------------------------------------------------------------------------- 1 | r[type.struct] 2 | # Struct types 3 | 4 | r[type.struct.intro] 5 | A `struct` *type* is a heterogeneous product of other types, called the 6 | *fields* of the type.[^structtype] 7 | 8 | r[type.struct.constructor] 9 | New instances of a `struct` can be constructed with a [struct expression]. 10 | 11 | r[type.struct.layout] 12 | The memory layout of a `struct` is undefined by default to allow for compiler 13 | optimizations like field reordering, but it can be fixed with the 14 | [`repr` attribute]. In either case, fields may be given in any order in a 15 | corresponding struct *expression*; the resulting `struct` value will always 16 | have the same memory layout. 17 | 18 | r[type.struct.field-visibility] 19 | The fields of a `struct` may be qualified by [visibility modifiers], to allow 20 | access to data in a struct outside a module. 21 | 22 | r[type.struct.tuple] 23 | A _tuple struct_ type is just like a struct type, except that the fields are 24 | anonymous. 25 | 26 | r[type.struct.unit] 27 | A _unit-like struct_ type is like a struct type, except that it has no fields. 28 | The one value constructed by the associated [struct expression] is the only 29 | value that inhabits such a type. 30 | 31 | [^structtype]: `struct` types are analogous to `struct` types in C, the 32 | *record* types of the ML family, or the *struct* types of the Lisp family. 33 | 34 | [`repr` attribute]: ../type-layout.md#representations 35 | [struct expression]: ../expressions/struct-expr.md 36 | [visibility modifiers]: ../visibility-and-privacy.md 37 | -------------------------------------------------------------------------------- /src/unsafety.md: -------------------------------------------------------------------------------- 1 | r[safety] 2 | # Unsafety 3 | 4 | r[safety.intro] 5 | Unsafe operations are those that can potentially violate the memory-safety 6 | guarantees of Rust's static semantics. 7 | 8 | r[safety.unsafe-ops] 9 | The following language level features cannot be used in the safe subset of 10 | Rust: 11 | 12 | r[safety.unsafe-deref] 13 | - Dereferencing a [raw pointer]. 14 | 15 | r[safety.unsafe-static] 16 | - Reading or writing a [mutable] or unsafe [external] static variable. 17 | 18 | r[safety.unsafe-union-access] 19 | - Accessing a field of a [`union`], other than to assign to it. 20 | 21 | r[safety.unsafe-call] 22 | - Calling an unsafe function. 23 | 24 | r[safety.unsafe-target-feature-call] 25 | - Calling a safe function marked with a [`target_feature`][attributes.codegen.target_feature] from a function that does not have a `target_feature` attribute enabling the same features (see [attributes.codegen.target_feature.safety-restrictions]). 26 | 27 | r[safety.unsafe-impl] 28 | - Implementing an [unsafe trait]. 29 | 30 | r[safety.unsafe-extern] 31 | - Declaring an [`extern`] block[^extern-2024]. 32 | 33 | r[safety.unsafe-attribute] 34 | - Applying an [unsafe attribute] to an item. 35 | 36 | [^extern-2024]: Prior to the 2024 edition, extern blocks were allowed to be declared without `unsafe`. 37 | 38 | [`extern`]: items/external-blocks.md 39 | [`union`]: items/unions.md 40 | [mutable]: items/static-items.md#mutable-statics 41 | [external]: items/external-blocks.md 42 | [raw pointer]: types/pointer.md 43 | [unsafe trait]: items/traits.md#unsafe-traits 44 | [unsafe attribute]: attributes.md 45 | -------------------------------------------------------------------------------- /src/interior-mutability.md: -------------------------------------------------------------------------------- 1 | r[interior-mut] 2 | # Interior mutability 3 | 4 | r[interior-mut.intro] 5 | Sometimes a type needs to be mutated while having multiple aliases. In Rust this 6 | is achieved using a pattern called _interior mutability_. 7 | 8 | r[interior-mut.shared-ref] 9 | A type has interior mutability if its internal state can be changed through a [shared reference] to 10 | it. 11 | 12 | r[interior-mut.no-constraint] 13 | This goes against the usual [requirement][ub] that the value pointed to by a 14 | shared reference is not mutated. 15 | 16 | r[interior-mut.unsafe-cell] 17 | [`std::cell::UnsafeCell`] type is the only allowed way to disable 18 | this requirement. When `UnsafeCell` is immutably aliased, it is still safe to 19 | mutate, or obtain a mutable reference to, the `T` it contains. 20 | 21 | r[interior-mut.mut-unsafe-cell] 22 | As with all other types, it is undefined behavior to have multiple `&mut UnsafeCell` 23 | aliases. 24 | 25 | r[interior-mut.abstraction] 26 | Other types with interior mutability can be created by using `UnsafeCell` as 27 | a field. The standard library provides a variety of types that provide safe 28 | interior mutability APIs. 29 | 30 | r[interior-mut.ref-cell] 31 | For example, [`std::cell::RefCell`] uses run-time borrow checks to ensure the usual rules around multiple references. 32 | 33 | r[interior-mut.atomic] 34 | The [`std::sync::atomic`] module contains types that wrap a value that is only 35 | accessed with atomic operations, allowing the value to be shared and mutated 36 | across threads. 37 | 38 | [shared reference]: types/pointer.md#shared-references- 39 | [ub]: behavior-considered-undefined.md 40 | -------------------------------------------------------------------------------- /src/expressions/grouped-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.paren] 2 | # Grouped expressions 3 | 4 | r[expr.paren.syntax] 5 | ```grammar,expressions 6 | GroupedExpression -> `(` Expression `)` 7 | ``` 8 | 9 | r[expr.paren.intro] 10 | A *parenthesized expression* wraps a single expression, evaluating to that expression. 11 | The syntax for a parenthesized expression is a `(`, then an expression, called the *enclosed operand*, and then a `)`. 12 | 13 | r[expr.paren.evaluation] 14 | Parenthesized expressions evaluate to the value of the enclosed operand. 15 | 16 | r[expr.paren.place-or-value] 17 | Unlike other expressions, parenthesized expressions are both [place expressions and value expressions][place]. 18 | When the enclosed operand is a place expression, it is a place expression and when the enclosed operand is a value expression, it is a value expression. 19 | 20 | r[expr.paren.override-precedence] 21 | Parentheses can be used to explicitly modify the precedence order of subexpressions within an expression. 22 | 23 | An example of a parenthesized expression: 24 | 25 | ```rust 26 | let x: i32 = 2 + 3 * 4; // not parenthesized 27 | let y: i32 = (2 + 3) * 4; // parenthesized 28 | assert_eq!(x, 14); 29 | assert_eq!(y, 20); 30 | ``` 31 | 32 | An example of a necessary use of parentheses is when calling a function pointer that is a member of a struct: 33 | 34 | ```rust 35 | # struct A { 36 | # f: fn() -> &'static str 37 | # } 38 | # impl A { 39 | # fn f(&self) -> &'static str { 40 | # "The method f" 41 | # } 42 | # } 43 | # let a = A{f: || "The field f"}; 44 | # 45 | assert_eq!( a.f (), "The method f"); 46 | assert_eq!((a.f)(), "The field f"); 47 | ``` 48 | 49 | [place]: ../expressions.md#place-expressions-and-value-expressions 50 | -------------------------------------------------------------------------------- /src/types/textual.md: -------------------------------------------------------------------------------- 1 | r[type.text] 2 | # Textual types 3 | 4 | r[type.text.intro] 5 | The types `char` and `str` hold textual data. 6 | 7 | r[type.text.char-value] 8 | A value of type `char` is a [Unicode scalar value] (i.e. a code point that is 9 | not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to 0xD7FF 10 | or 0xE000 to 0x10FFFF range. 11 | 12 | r[type.text.char-precondition] 13 | It is immediate [undefined behavior] to create a 14 | `char` that falls outside this range. A `[char]` is effectively a UCS-4 / UTF-32 15 | string of length 1. 16 | 17 | r[type.text.str-value] 18 | A value of type `str` is represented the same way as `[u8]`, a slice of 19 | 8-bit unsigned bytes. However, the Rust standard library makes extra assumptions 20 | about `str`: methods working on `str` assume and ensure that the data in there 21 | is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause 22 | [undefined behavior] now or in the future. 23 | 24 | r[type.text.str-unsized] 25 | Since `str` is a [dynamically sized type], it can only be instantiated through a 26 | pointer type, such as `&str`. The layout of `&str` is the same as the layout of 27 | `&[u8]`. 28 | 29 | r[type.text.layout] 30 | ## Layout and bit validity 31 | 32 | r[type.layout.char-layout] 33 | `char` is guaranteed to have the same size and alignment as `u32` on all platforms. 34 | 35 | r[type.layout.char-validity] 36 | Every byte of a `char` is guaranteed to be initialized (in other words, 37 | `transmute::()]>(...)` is always sound -- but since 38 | some bit patterns are invalid `char`s, the inverse is not always sound). 39 | 40 | [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value 41 | [undefined behavior]: ../behavior-considered-undefined.md 42 | [dynamically sized type]: ../dynamically-sized-types.md 43 | -------------------------------------------------------------------------------- /src/variables.md: -------------------------------------------------------------------------------- 1 | r[variable] 2 | # Variables 3 | 4 | r[variable.intro] 5 | A _variable_ is a component of a stack frame, either a named function parameter, 6 | an anonymous [temporary](expressions.md#temporaries), or a named local 7 | variable. 8 | 9 | r[variable.local] 10 | A _local variable_ (or *stack-local* allocation) holds a value directly, 11 | allocated within the stack's memory. The value is a part of the stack frame. 12 | 13 | r[variable.local-mut] 14 | Local variables are immutable unless declared otherwise. For example: 15 | `let mut x = ...`. 16 | 17 | r[variable.param-mut] 18 | Function parameters are immutable unless declared with `mut`. The `mut` keyword 19 | applies only to the following parameter. For example: `|mut x, y|` and 20 | `fn f(mut x: Box, y: Box)` declare one mutable variable `x` and one 21 | immutable variable `y`. 22 | 23 | r[variable.init] 24 | Local variables are not initialized when allocated. Instead, the entire frame 25 | worth of local variables are allocated, on frame-entry, in an uninitialized 26 | state. Subsequent statements within a function may or may not initialize the 27 | local variables. Local variables can be used only after they have been 28 | initialized through all reachable control flow paths. 29 | 30 | In this next example, `init_after_if` is initialized after the [`if` expression] 31 | while `uninit_after_if` is not because it is not initialized in the `else` case. 32 | 33 | ```rust 34 | # fn random_bool() -> bool { true } 35 | fn initialization_example() { 36 | let init_after_if: (); 37 | let uninit_after_if: (); 38 | 39 | if random_bool() { 40 | init_after_if = (); 41 | uninit_after_if = (); 42 | } else { 43 | init_after_if = (); 44 | } 45 | 46 | init_after_if; // ok 47 | // uninit_after_if; // err: use of possibly uninitialized `uninit_after_if` 48 | } 49 | ``` 50 | 51 | [`if` expression]: expressions/if-expr.md#if-expressions 52 | -------------------------------------------------------------------------------- /src/dynamically-sized-types.md: -------------------------------------------------------------------------------- 1 | r[dynamic-sized] 2 | # Dynamically sized types 3 | 4 | r[dynamic-sized.intro] 5 | Most types have a fixed size that is known at compile time and implement the trait [`Sized`][sized]. A type with a size that is known only at run-time is called a _dynamically sized type_ (_DST_) or, informally, an unsized type. [Slices], [trait objects], and [str] are examples of DSTs. 6 | 7 | r[dynamic-sized.restriction] 8 | Such types can only be used in certain cases: 9 | 10 | r[dynamic-sized.pointer-types] 11 | * [Pointer types] to DSTs are 12 | sized but have twice the size of pointers to sized types 13 | * Pointers to slices and `str` also store the number of elements. 14 | * Pointers to trait objects also store a pointer to a vtable. 15 | 16 | r[dynamic-sized.question-sized] 17 | * DSTs can be provided as 18 | type arguments to generic type parameters having the special `?Sized` bound. 19 | They can also be used for associated type definitions when the corresponding associated type declaration has a `?Sized` bound. 20 | By default, any type parameter or associated type has a `Sized` bound, unless it is relaxed using `?Sized`. 21 | 22 | r[dynamic-sized.trait-impl] 23 | * Traits may be implemented for DSTs. 25 | Unlike with generic type parameters, `Self: ?Sized` is the default in trait definitions. 26 | 27 | r[dynamic-sized.struct-field] 28 | * Structs may contain a DST as the 29 | last field; this makes the struct itself a 30 | DST. 31 | 32 | > [!NOTE] 33 | > [Variables], function parameters, [const] items, and [static] items must be `Sized`. 34 | 35 | [sized]: special-types-and-traits.md#sized 36 | [Slices]: types/slice.md 37 | [str]: types/textual.md 38 | [trait objects]: types/trait-object.md 39 | [Pointer types]: types/pointer.md 40 | [Variables]: variables.md 41 | [const]: items/constant-items.md 42 | [static]: items/static-items.md 43 | -------------------------------------------------------------------------------- /src/expressions/range-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.range] 2 | # Range expressions 3 | 4 | r[expr.range.syntax] 5 | ```grammar,expressions 6 | RangeExpression -> 7 | RangeExpr 8 | | RangeFromExpr 9 | | RangeToExpr 10 | | RangeFullExpr 11 | | RangeInclusiveExpr 12 | | RangeToInclusiveExpr 13 | 14 | RangeExpr -> Expression `..` Expression 15 | 16 | RangeFromExpr -> Expression `..` 17 | 18 | RangeToExpr -> `..` Expression 19 | 20 | RangeFullExpr -> `..` 21 | 22 | RangeInclusiveExpr -> Expression `..=` Expression 23 | 24 | RangeToInclusiveExpr -> `..=` Expression 25 | ``` 26 | 27 | r[expr.range.behavior] 28 | The `..` and `..=` operators will construct an object of one of the `std::ops::Range` (or `core::ops::Range`) variants, according to the following table: 29 | 30 | | Production | Syntax | Type | Range | 31 | |------------------------|---------------|------------------------------|-----------------------| 32 | | [RangeExpr] | start`..`end | [std::ops::Range] | start ≤ x < end | 33 | | [RangeFromExpr] | start`..` | [std::ops::RangeFrom] | start ≤ x | 34 | | [RangeToExpr] | `..`end | [std::ops::RangeTo] | x < end | 35 | | [RangeFullExpr] | `..` | [std::ops::RangeFull] | - | 36 | | [RangeInclusiveExpr] | start`..=`end | [std::ops::RangeInclusive] | start ≤ x ≤ end | 37 | | [RangeToInclusiveExpr] | `..=`end | [std::ops::RangeToInclusive] | x ≤ end | 38 | 39 | Examples: 40 | 41 | ```rust 42 | 1..2; // std::ops::Range 43 | 3..; // std::ops::RangeFrom 44 | ..4; // std::ops::RangeTo 45 | ..; // std::ops::RangeFull 46 | 5..=6; // std::ops::RangeInclusive 47 | ..=7; // std::ops::RangeToInclusive 48 | ``` 49 | 50 | r[expr.range.equivalence] 51 | The following expressions are equivalent. 52 | 53 | ```rust 54 | let x = std::ops::Range {start: 0, end: 10}; 55 | let y = 0..10; 56 | 57 | assert_eq!(x, y); 58 | ``` 59 | 60 | r[expr.range.for] 61 | Ranges can be used in `for` loops: 62 | 63 | ```rust 64 | for i in 1..11 { 65 | println!("{}", i); 66 | } 67 | ``` 68 | -------------------------------------------------------------------------------- /style-check/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "bitflags" 7 | version = "2.6.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 10 | 11 | [[package]] 12 | name = "getopts" 13 | version = "0.2.21" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" 16 | dependencies = [ 17 | "unicode-width", 18 | ] 19 | 20 | [[package]] 21 | name = "memchr" 22 | version = "2.7.4" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 25 | 26 | [[package]] 27 | name = "pulldown-cmark" 28 | version = "0.10.3" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" 31 | dependencies = [ 32 | "bitflags", 33 | "getopts", 34 | "memchr", 35 | "pulldown-cmark-escape", 36 | "unicase", 37 | ] 38 | 39 | [[package]] 40 | name = "pulldown-cmark-escape" 41 | version = "0.10.1" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | checksum = "bd348ff538bc9caeda7ee8cad2d1d48236a1f443c1fa3913c6a02fe0043b1dd3" 44 | 45 | [[package]] 46 | name = "style-check" 47 | version = "0.1.0" 48 | dependencies = [ 49 | "pulldown-cmark", 50 | ] 51 | 52 | [[package]] 53 | name = "unicase" 54 | version = "2.7.0" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" 57 | dependencies = [ 58 | "version_check", 59 | ] 60 | 61 | [[package]] 62 | name = "unicode-width" 63 | version = "0.1.13" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" 66 | 67 | [[package]] 68 | name = "version_check" 69 | version = "0.9.4" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 72 | -------------------------------------------------------------------------------- /src/items/type-aliases.md: -------------------------------------------------------------------------------- 1 | r[items.type] 2 | # Type aliases 3 | 4 | r[items.type.syntax] 5 | ```grammar,items 6 | TypeAlias -> 7 | `type` IDENTIFIER GenericParams? ( `:` TypeParamBounds )? 8 | WhereClause? 9 | ( `=` Type WhereClause?)? `;` 10 | ``` 11 | 12 | r[items.type.intro] 13 | A _type alias_ defines a new name for an existing [type] in the [type namespace] of the module or block where it is located. 14 | Type aliases are declared with the keyword `type`. 15 | Every value has a single, specific type, but may implement several different traits, and may be compatible with several different type constraints. 16 | 17 | For example, the following defines the type `Point` as a synonym for the type 18 | `(u8, u8)`, the type of pairs of unsigned 8 bit integers: 19 | 20 | ```rust 21 | type Point = (u8, u8); 22 | let p: Point = (41, 68); 23 | ``` 24 | 25 | r[items.type.constructor-alias] 26 | A type alias to a tuple-struct or unit-struct cannot be used to qualify that type's constructor: 27 | 28 | ```rust,compile_fail 29 | struct MyStruct(u32); 30 | 31 | use MyStruct as UseAlias; 32 | type TypeAlias = MyStruct; 33 | 34 | let _ = UseAlias(5); // OK 35 | let _ = TypeAlias(5); // Doesn't work 36 | ``` 37 | 38 | r[items.type.associated-type] 39 | A type alias, when not used as an [associated type], must include a [Type][grammar-Type] and 40 | may not include [TypeParamBounds]. 41 | 42 | r[items.type.associated-trait] 43 | A type alias, when used as an [associated type] in a [trait], must not include a 44 | [Type][grammar-Type] specification but may include [TypeParamBounds]. 45 | 46 | r[items.type.associated-impl] 47 | A type alias, when used as an [associated type] in a [trait impl], must include 48 | a [Type][grammar-Type] specification and may not include [TypeParamBounds]. 49 | 50 | r[items.type.deprecated] 51 | Where clauses before the equals sign on a type alias in a [trait impl] (like 52 | `type TypeAlias where T: Foo = Bar`) are deprecated. Where clauses after 53 | the equals sign (like `type TypeAlias = Bar where T: Foo`) are preferred. 54 | 55 | [associated type]: associated-items.md#associated-types 56 | [trait impl]: implementations.md#trait-implementations 57 | [trait]: traits.md 58 | [type namespace]: ../names/namespaces.md 59 | [type]: ../types.md 60 | -------------------------------------------------------------------------------- /src/types/function-pointer.md: -------------------------------------------------------------------------------- 1 | r[type.fn-pointer] 2 | # Function pointer types 3 | 4 | r[type.fn-pointer.syntax] 5 | ```grammar,types 6 | BareFunctionType -> 7 | ForLifetimes? FunctionTypeQualifiers `fn` 8 | `(` FunctionParametersMaybeNamedVariadic? `)` BareFunctionReturnType? 9 | 10 | FunctionTypeQualifiers -> `unsafe`? (`extern` Abi?)? 11 | 12 | BareFunctionReturnType -> `->` TypeNoBounds 13 | 14 | FunctionParametersMaybeNamedVariadic -> 15 | MaybeNamedFunctionParameters | MaybeNamedFunctionParametersVariadic 16 | 17 | MaybeNamedFunctionParameters -> 18 | MaybeNamedParam ( `,` MaybeNamedParam )* `,`? 19 | 20 | MaybeNamedParam -> 21 | OuterAttribute* ( ( IDENTIFIER | `_` ) `:` )? Type 22 | 23 | MaybeNamedFunctionParametersVariadic -> 24 | ( MaybeNamedParam `,` )* MaybeNamedParam `,` OuterAttribute* `...` 25 | ``` 26 | 27 | r[type.fn-pointer.intro] 28 | A function pointer type, written using the `fn` keyword, refers to a function whose identity is not necessarily known at compile-time. 29 | 30 | An example where `Binop` is defined as a function pointer type: 31 | 32 | ```rust 33 | fn add(x: i32, y: i32) -> i32 { 34 | x + y 35 | } 36 | 37 | let mut x = add(5,7); 38 | 39 | type Binop = fn(i32, i32) -> i32; 40 | let bo: Binop = add; 41 | x = bo(5,7); 42 | ``` 43 | 44 | r[type.fn-pointer.coercion] 45 | Function pointers can be created via a coercion from both [function items] and non-capturing, non-async [closures]. 46 | 47 | r[type.fn-pointer.qualifiers] 48 | The `unsafe` qualifier indicates that the type's value is an [unsafe 49 | function], and the `extern` qualifier indicates it is an [extern function]. 50 | 51 | r[type.fn-pointer.constraint-variadic] 52 | For the function to be variadic, its `extern` ABI must be one of those listed in [items.extern.variadic.conventions]. 53 | 54 | r[type.fn-pointer.attributes] 55 | ## Attributes on function pointer parameters 56 | 57 | Attributes on function pointer parameters follow the same rules and 58 | restrictions as [regular function parameters]. 59 | 60 | [`extern`]: ../items/external-blocks.md 61 | [closures]: closure.md 62 | [extern function]: ../items/functions.md#extern-function-qualifier 63 | [function items]: function-item.md 64 | [unsafe function]: ../unsafe-keyword.md 65 | [regular function parameters]: ../items/functions.md#attributes-on-function-parameters 66 | -------------------------------------------------------------------------------- /src/types/tuple.md: -------------------------------------------------------------------------------- 1 | r[type.tuple] 2 | # Tuple types 3 | 4 | r[type.tuple.syntax] 5 | ```grammar,types 6 | TupleType -> 7 | `(` `)` 8 | | `(` ( Type `,` )+ Type? `)` 9 | ``` 10 | 11 | r[type.tuple.intro] 12 | *Tuple types* are a family of structural types[^1] for heterogeneous lists of other types. 13 | 14 | The syntax for a tuple type is a parenthesized, comma-separated list of types. 15 | 16 | r[type.tuple.restriction] 17 | 1-ary tuples require a comma after their element type to be disambiguated with a [parenthesized type]. 18 | 19 | r[type.tuple.field-number] 20 | A tuple type has a number of fields equal to the length of the list of types. 21 | This number of fields determines the *arity* of the tuple. 22 | A tuple with `n` fields is called an *n-ary tuple*. 23 | For example, a tuple with 2 fields is a 2-ary tuple. 24 | 25 | r[type.tuple.field-name] 26 | Fields of tuples are named using increasing numeric names matching their position in the list of types. 27 | The first field is `0`. 28 | The second field is `1`. 29 | And so on. 30 | The type of each field is the type of the same position in the tuple's list of types. 31 | 32 | r[type.tuple.unit] 33 | For convenience and historical reasons, the tuple type with no fields (`()`) is often called *unit* or *the unit type*. 34 | Its one value is also called *unit* or *the unit value*. 35 | 36 | Some examples of tuple types: 37 | 38 | * `()` (unit) 39 | * `(i32,)` (1-ary tuple) 40 | * `(f64, f64)` 41 | * `(String, i32)` 42 | * `(i32, String)` (different type from the previous example) 43 | * `(i32, f64, Vec, Option)` 44 | 45 | r[type.tuple.constructor] 46 | Values of this type are constructed using a [tuple expression]. 47 | Furthermore, various expressions will produce the unit value if there is no other meaningful value for it to evaluate to. 48 | 49 | r[type.tuple.access] 50 | Tuple fields can be accessed by either a [tuple index expression] or [pattern matching]. 51 | 52 | [^1]: Structural types are always equivalent if their internal types are equivalent. 53 | For a nominal version of tuples, see [tuple structs]. 54 | 55 | [parenthesized type]: ../types.md#parenthesized-types 56 | [pattern matching]: ../patterns.md#tuple-patterns 57 | [tuple expression]: ../expressions/tuple-expr.md#tuple-expressions 58 | [tuple index expression]: ../expressions/tuple-expr.md#tuple-indexing-expressions 59 | [tuple structs]: ./struct.md 60 | -------------------------------------------------------------------------------- /src/items/structs.md: -------------------------------------------------------------------------------- 1 | r[items.struct] 2 | # Structs 3 | 4 | r[items.struct.syntax] 5 | ```grammar,items 6 | Struct -> 7 | StructStruct 8 | | TupleStruct 9 | 10 | StructStruct -> 11 | `struct` IDENTIFIER GenericParams? WhereClause? ( `{` StructFields? `}` | `;` ) 12 | 13 | TupleStruct -> 14 | `struct` IDENTIFIER GenericParams? `(` TupleFields? `)` WhereClause? `;` 15 | 16 | StructFields -> StructField (`,` StructField)* `,`? 17 | 18 | StructField -> OuterAttribute* Visibility? IDENTIFIER `:` Type 19 | 20 | TupleFields -> TupleField (`,` TupleField)* `,`? 21 | 22 | TupleField -> OuterAttribute* Visibility? Type 23 | ``` 24 | 25 | r[items.struct.intro] 26 | A _struct_ is a nominal [struct type] defined with the keyword `struct`. 27 | 28 | r[items.struct.namespace] 29 | A struct declaration defines the given name in the [type namespace] of the module or block where it is located. 30 | 31 | An example of a `struct` item and its use: 32 | 33 | ```rust 34 | struct Point {x: i32, y: i32} 35 | let p = Point {x: 10, y: 11}; 36 | let px: i32 = p.x; 37 | ``` 38 | 39 | r[items.struct.tuple] 40 | A _tuple struct_ is a nominal [tuple type], and is also defined with the keyword `struct`. 41 | In addition to defining a type, it also defines a constructor of the same name in the [value namespace]. 42 | The constructor is a function which can be called to create a new instance of the struct. 43 | For example: 44 | 45 | ```rust 46 | struct Point(i32, i32); 47 | let p = Point(10, 11); 48 | let px: i32 = match p { Point(x, _) => x }; 49 | ``` 50 | 51 | r[items.struct.unit] 52 | A _unit-like struct_ is a struct without any fields, defined by leaving off the 53 | list of fields entirely. Such a struct implicitly defines a [constant] of its 54 | type with the same name. For example: 55 | 56 | ```rust 57 | struct Cookie; 58 | let c = [Cookie, Cookie {}, Cookie, Cookie {}]; 59 | ``` 60 | 61 | is equivalent to 62 | 63 | ```rust 64 | struct Cookie {} 65 | const Cookie: Cookie = Cookie {}; 66 | let c = [Cookie, Cookie {}, Cookie, Cookie {}]; 67 | ``` 68 | 69 | r[items.struct.layout] 70 | The precise memory layout of a struct is not specified. One can specify a 71 | particular layout using the [`repr` attribute]. 72 | 73 | [`repr` attribute]: ../type-layout.md#representations 74 | [constant]: constant-items.md 75 | [struct type]: ../types/struct.md 76 | [tuple type]: ../types/tuple.md 77 | [type namespace]: ../names/namespaces.md 78 | [value namespace]: ../names/namespaces.md 79 | -------------------------------------------------------------------------------- /theme/reference.js: -------------------------------------------------------------------------------- 1 | /* On the test summary page, toggles the popup for the uncovered tests. */ 2 | function spec_toggle_uncovered(item_index) { 3 | let el = document.getElementById(`uncovered-${item_index}`); 4 | const currently_hidden = el.classList.contains('popup-hidden'); 5 | const all = document.querySelectorAll('.uncovered-rules-popup'); 6 | all.forEach(element => { 7 | element.classList.add('popup-hidden'); 8 | }); 9 | if (currently_hidden) { 10 | el.classList.remove('popup-hidden'); 11 | } 12 | } 13 | 14 | function spec_toggle_tests(rule_id) { 15 | let el = document.getElementById(`tests-${rule_id}`); 16 | const currently_hidden = el.classList.contains('popup-hidden'); 17 | const all = document.querySelectorAll('.tests-popup'); 18 | all.forEach(element => { 19 | element.classList.add('popup-hidden'); 20 | }); 21 | if (currently_hidden) { 22 | el.classList.remove('popup-hidden'); 23 | } 24 | } 25 | 26 | function toggle_railroad() { 27 | const grammarRailroad = get_railroad(); 28 | set_railroad(!grammarRailroad); 29 | update_railroad(); 30 | } 31 | 32 | function show_railroad() { 33 | set_railroad(true); 34 | update_railroad(); 35 | } 36 | 37 | function get_railroad() { 38 | let grammarRailroad = null; 39 | try { 40 | grammarRailroad = localStorage.getItem('grammar-railroad'); 41 | } catch (e) { 42 | // Ignore error. 43 | } 44 | grammarRailroad = grammarRailroad === 'true' ? true : false; 45 | return grammarRailroad; 46 | } 47 | 48 | function set_railroad(newValue) { 49 | try { 50 | localStorage.setItem('grammar-railroad', newValue); 51 | } catch (e) { 52 | // Ignore error. 53 | } 54 | } 55 | 56 | function update_railroad() { 57 | const grammarRailroad = get_railroad(); 58 | const railroads = document.querySelectorAll('.grammar-railroad'); 59 | railroads.forEach(element => { 60 | if (grammarRailroad) { 61 | element.classList.remove('grammar-hidden'); 62 | } else { 63 | element.classList.add('grammar-hidden'); 64 | } 65 | }); 66 | const buttons = document.querySelectorAll('.grammar-toggle-railroad'); 67 | buttons.forEach(button => { 68 | if (grammarRailroad) { 69 | button.innerText = "Hide syntax diagrams"; 70 | } else { 71 | button.innerText = "Show syntax diagrams"; 72 | } 73 | }); 74 | } 75 | 76 | (function railroad_onload() { 77 | update_railroad(); 78 | })(); 79 | -------------------------------------------------------------------------------- /src/types/function-item.md: -------------------------------------------------------------------------------- 1 | r[type.fn-item] 2 | # Function item types 3 | 4 | r[type.fn-item.intro] 5 | When referred to, a function item, or the constructor of a tuple-like struct or 6 | enum variant, yields a zero-sized value of its _function item type_. 7 | 8 | r[type.fn-item.unique] 9 | That type explicitly identifies the function - its name, its type arguments, and its 10 | early-bound lifetime arguments (but not its late-bound lifetime arguments, 11 | which are only assigned when the function is called) - so the value does not 12 | need to contain an actual function pointer, and no indirection is needed when 13 | the function is called. 14 | 15 | r[type.fn-item.name] 16 | There is no syntax that directly refers to a function item type, but the 17 | compiler will display the type as something like `fn(u32) -> i32 {fn_name}` in 18 | error messages. 19 | 20 | Because the function item type explicitly identifies the function, the item 21 | types of different functions - different items, or the same item with different 22 | generics - are distinct, and mixing them will create a type error: 23 | 24 | ```rust,compile_fail,E0308 25 | fn foo() { } 26 | let x = &mut foo::; 27 | *x = foo::; //~ ERROR mismatched types 28 | ``` 29 | 30 | r[type.fn-item.coercion] 31 | However, there is a [coercion] from function items to [function pointers] with 32 | the same signature, which is triggered not only when a function item is used 33 | when a function pointer is directly expected, but also when different function 34 | item types with the same signature meet in different arms of the same `if` or 35 | `match`: 36 | 37 | ```rust 38 | # let want_i32 = false; 39 | # fn foo() { } 40 | 41 | // `foo_ptr_1` has function pointer type `fn()` here 42 | let foo_ptr_1: fn() = foo::; 43 | 44 | // ... and so does `foo_ptr_2` - this type-checks. 45 | let foo_ptr_2 = if want_i32 { 46 | foo:: 47 | } else { 48 | foo:: 49 | }; 50 | ``` 51 | 52 | r[type.fn-item.traits] 53 | All function items implement [`Copy`], [`Clone`], [`Send`], and [`Sync`]. 54 | 55 | [`Fn`], [`FnMut`], and [`FnOnce`] are implemented unless the function has any of the following: 56 | 57 | - an [`unsafe`][unsafe.fn] qualifier 58 | - a [`target_feature` attribute][attributes.codegen.target_feature] 59 | - an [ABI][items.fn.extern] other than `"Rust"` 60 | 61 | [`Clone`]: ../special-types-and-traits.md#clone 62 | [`Copy`]: ../special-types-and-traits.md#copy 63 | [`Send`]: ../special-types-and-traits.md#send 64 | [`Sync`]: ../special-types-and-traits.md#sync 65 | [coercion]: ../type-coercions.md 66 | [function pointers]: function-pointer.md 67 | -------------------------------------------------------------------------------- /src/behavior-not-considered-unsafe.md: -------------------------------------------------------------------------------- 1 | # Behavior not considered `unsafe` 2 | 3 | The Rust compiler does not consider the following behaviors _unsafe_, 4 | though a programmer may (should) find them undesirable, unexpected, 5 | or erroneous. 6 | 7 | - Deadlocks 8 | - Leaks of memory and other resources 9 | - Exiting without calling destructors 10 | - Exposing randomized base addresses through pointer leaks 11 | 12 | ## Integer overflow 13 | 14 | If a program contains arithmetic overflow, the programmer has made an 15 | error. In the following discussion, we maintain a distinction between 16 | arithmetic overflow and wrapping arithmetic. The first is erroneous, 17 | while the second is intentional. 18 | 19 | When the programmer has enabled `debug_assert!` assertions (for 20 | example, by enabling a non-optimized build), implementations must 21 | insert dynamic checks that `panic` on overflow. Other kinds of builds 22 | may result in `panics` or silently wrapped values on overflow, at the 23 | implementation's discretion. 24 | 25 | In the case of implicitly-wrapped overflow, implementations must 26 | provide well-defined (even if still considered erroneous) results by 27 | using two's complement overflow conventions. 28 | 29 | The integral types provide inherent methods to allow programmers 30 | explicitly to perform wrapping arithmetic. For example, 31 | `i32::wrapping_add` provides two's complement, wrapping addition. 32 | 33 | The standard library also provides a `Wrapping` newtype which 34 | ensures all standard arithmetic operations for `T` have wrapping 35 | semantics. 36 | 37 | See [RFC 560] for error conditions, rationale, and more details about 38 | integer overflow. 39 | 40 | ## Logic errors 41 | 42 | Safe code may impose extra logical constraints that can be checked 43 | at neither compile-time nor runtime. If a program breaks such 44 | a constraint, the behavior may be unspecified but will not result in 45 | undefined behavior. This could include panics, incorrect results, 46 | aborts, and non-termination. The behavior may also differ between 47 | runs, builds, or kinds of build. 48 | 49 | For example, implementing both `Hash` and `Eq` requires that values 50 | considered equal have equal hashes. Another example are data structures 51 | like `BinaryHeap`, `BTreeMap`, `BTreeSet`, `HashMap` and `HashSet` 52 | which describe constraints on the modification of their keys while 53 | they are in the data structure. Violating such constraints is not 54 | considered unsafe, yet the program is considered erroneous and 55 | its behavior unpredictable. 56 | 57 | [RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md 58 | -------------------------------------------------------------------------------- /src/input-format.md: -------------------------------------------------------------------------------- 1 | r[input] 2 | # Input format 3 | 4 | r[input.syntax] 5 | ```grammar,lexer 6 | @root CHAR -> 7 | 8 | NUL -> U+0000 9 | ``` 10 | 11 | r[input.intro] 12 | This chapter describes how a source file is interpreted as a sequence of tokens. 13 | 14 | See [Crates and source files] for a description of how programs are organised into files. 15 | 16 | r[input.encoding] 17 | ## Source encoding 18 | 19 | r[input.encoding.utf8] 20 | Each source file is interpreted as a sequence of Unicode characters encoded in UTF-8. 21 | 22 | r[input.encoding.invalid] 23 | It is an error if the file is not valid UTF-8. 24 | 25 | r[input.byte-order-mark] 26 | ## Byte order mark removal 27 | 28 | If the first character in the sequence is `U+FEFF` ([BYTE ORDER MARK]), it is removed. 29 | 30 | r[input.crlf] 31 | ## CRLF normalization 32 | 33 | Each pair of characters `U+000D` (CR) immediately followed by `U+000A` (LF) is replaced by a single `U+000A` (LF). This happens once, not repeatedly, so after the normalization, there can still exist `U+000D` (CR) immediately followed by `U+000A` (LF) in the input (e.g. if the raw input contained "CR CR LF LF"). 34 | 35 | Other occurrences of the character `U+000D` (CR) are left in place (they are treated as [whitespace]). 36 | 37 | r[input.shebang] 38 | ## Shebang removal 39 | 40 | r[input.shebang.intro] 41 | If the remaining sequence begins with the characters `#!`, the characters up to and including the first `U+000A` (LF) are removed from the sequence. 42 | 43 | For example, the first line of the following file would be ignored: 44 | 45 | 46 | ```rust,ignore 47 | #!/usr/bin/env rustx 48 | 49 | fn main() { 50 | println!("Hello!"); 51 | } 52 | ``` 53 | 54 | r[input.shebang.inner-attribute] 55 | As an exception, if the `#!` characters are followed (ignoring intervening [comments] or [whitespace]) by a `[` token, nothing is removed. This prevents an [inner attribute] at the start of a source file being removed. 56 | 57 | > [!NOTE] 58 | > The standard library [`include!`] macro applies byte order mark removal, CRLF normalization, and shebang removal to the file it reads. The [`include_str!`] and [`include_bytes!`] macros do not. 59 | 60 | r[input.tokenization] 61 | ## Tokenization 62 | 63 | The resulting sequence of characters is then converted into tokens as described in the remainder of this chapter. 64 | 65 | [inner attribute]: attributes.md 66 | [BYTE ORDER MARK]: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 67 | [comments]: comments.md 68 | [Crates and source files]: crates-and-source-files.md 69 | [_shebang_]: https://en.wikipedia.org/wiki/Shebang_(Unix) 70 | [whitespace]: whitespace.md 71 | -------------------------------------------------------------------------------- /src/types/numeric.md: -------------------------------------------------------------------------------- 1 | r[type.numeric] 2 | # Numeric types 3 | 4 | r[type.numeric.int] 5 | ## Integer types 6 | 7 | r[type.numeric.int.unsigned] 8 | The unsigned integer types consist of: 9 | 10 | Type | Minimum | Maximum 11 | -------|---------|------------------- 12 | `u8` | 0 | 28-1 13 | `u16` | 0 | 216-1 14 | `u32` | 0 | 232-1 15 | `u64` | 0 | 264-1 16 | `u128` | 0 | 2128-1 17 | 18 | r[type.numeric.int.signed] 19 | The signed two's complement integer types consist of: 20 | 21 | Type | Minimum | Maximum 22 | -------|--------------------|------------------- 23 | `i8` | -(27) | 27-1 24 | `i16` | -(215) | 215-1 25 | `i32` | -(231) | 231-1 26 | `i64` | -(263) | 263-1 27 | `i128` | -(2127) | 2127-1 28 | 29 | r[type.numeric.float] 30 | ## Floating-point types 31 | 32 | The IEEE 754-2008 "binary32" and "binary64" floating-point types are `f32` and 33 | `f64`, respectively. 34 | 35 | r[type.numeric.int.size] 36 | ## Machine-dependent integer types 37 | 38 | r[type.numeric.int.size.usize] 39 | The `usize` type is an unsigned integer type with the same number of bits as the 40 | platform's pointer type. It can represent every memory address in the process. 41 | 42 | > [!NOTE] 43 | > While a `usize` can represent every *address*, converting a *pointer* to a `usize` is not necessarily a reversible operation. 44 | > For more information, see the documentation for [type cast expressions], [`std::ptr`], and [provenance][std::ptr#provenance] in particular. 45 | 46 | r[type.numeric.int.size.isize] 47 | The `isize` type is a signed two's complement integer type with the same number of bits as the 48 | platform's pointer type. The theoretical upper bound on object and array size 49 | is the maximum `isize` value. This ensures that `isize` can be used to calculate 50 | differences between pointers into an object or array and can address every byte 51 | within an object along with one byte past the end. 52 | 53 | r[type.numeric.int.size.minimum] 54 | `usize` and `isize` are at least 16-bits wide. 55 | 56 | > [!NOTE] 57 | > Many pieces of Rust code may assume that pointers, `usize`, and `isize` are either 32-bit or 64-bit. As a consequence, 16-bit pointer support is limited and may require explicit care and acknowledgment from a library to support. 58 | 59 | r[type.numeric.validity] 60 | ## Bit validity 61 | 62 | For every numeric type, `T`, the bit validity of `T` is equivalent to the bit 63 | validity of `[u8; size_of::()]`. An uninitialized byte is not a valid `u8`. 64 | 65 | [type cast expressions]: ../expressions/operator-expr.md#type-cast-expressions 66 | -------------------------------------------------------------------------------- /src/attributes/limits.md: -------------------------------------------------------------------------------- 1 | r[attributes.limits] 2 | # Limits 3 | 4 | The following [attributes] affect compile-time limits. 5 | 6 | r[attributes.limits.recursion_limit] 7 | ## The `recursion_limit` attribute 8 | 9 | r[attributes.limits.recursion_limit.intro] 10 | The *`recursion_limit` attribute* may be applied at the [crate] level to set the 11 | maximum depth for potentially infinitely-recursive compile-time operations 12 | like macro expansion or auto-dereference. 13 | 14 | r[attributes.limits.recursion_limit.syntax] 15 | It uses the [MetaNameValueStr] 16 | syntax to specify the recursion depth. 17 | 18 | > [!NOTE] 19 | > The default in `rustc` is 128. 20 | 21 | ```rust,compile_fail 22 | #![recursion_limit = "4"] 23 | 24 | macro_rules! a { 25 | () => { a!(1); }; 26 | (1) => { a!(2); }; 27 | (2) => { a!(3); }; 28 | (3) => { a!(4); }; 29 | (4) => { }; 30 | } 31 | 32 | // This fails to expand because it requires a recursion depth greater than 4. 33 | a!{} 34 | ``` 35 | 36 | ```rust,compile_fail 37 | #![recursion_limit = "1"] 38 | 39 | // This fails because it requires two recursive steps to auto-dereference. 40 | (|_: &u8| {})(&&&1); 41 | ``` 42 | 43 | 44 | r[attributes.limits.type_length_limit] 45 | ## The `type_length_limit` attribute 46 | 47 | r[attributes.limits.type_length_limit.intro] 48 | The *`type_length_limit` [attribute][attributes]* sets the maximum number of type substitutions allowed when constructing a concrete type during monomorphization. 49 | 50 | > [!NOTE] 51 | > `rustc` only enforces the limit when the nightly `-Zenforce-type-length-limit` flag is active. 52 | > 53 | > For more information, see [Rust PR #127670](https://github.com/rust-lang/rust/pull/127670). 54 | 55 | > [!EXAMPLE] 56 | > 57 | > ```rust,ignore 58 | > #![type_length_limit = "4"] 59 | > 60 | > fn f(x: T) {} 61 | > 62 | > // This fails to compile because monomorphizing to 63 | > // `f::<((((i32,), i32), i32), i32)>` requires more 64 | > // than 4 type elements. 65 | > f(((((1,), 2), 3), 4)); 66 | > ``` 67 | 68 | > [!NOTE] 69 | > The default value in `rustc` is `1048576`. 70 | 71 | r[attributes.limits.type_length_limit.syntax] 72 | The `type_length_limit` attribute uses the [MetaNameValueStr] syntax. The value in the string must be a non-negative number. 73 | 74 | r[attributes.limits.type_length_limit.allowed-positions] 75 | The `type_length_limit` attribute may only be applied to the crate root. 76 | 77 | > [!NOTE] 78 | > `rustc` ignores use in other positions but lints against it. This may become an error in the future. 79 | 80 | r[attributes.limits.type_length_limit.duplicates] 81 | Only the first use of `type_length_limit` on an item has effect. 82 | 83 | > [!NOTE] 84 | > `rustc` lints against any use following the first. This may become an error in the future. 85 | 86 | [attributes]: ../attributes.md 87 | [crate]: ../crates-and-source-files.md 88 | -------------------------------------------------------------------------------- /src/items.md: -------------------------------------------------------------------------------- 1 | r[items] 2 | # Items 3 | 4 | r[items.syntax] 5 | ```grammar,items 6 | Item -> 7 | OuterAttribute* ( VisItem | MacroItem ) 8 | 9 | VisItem -> 10 | Visibility? 11 | ( 12 | Module 13 | | ExternCrate 14 | | UseDeclaration 15 | | Function 16 | | TypeAlias 17 | | Struct 18 | | Enumeration 19 | | Union 20 | | ConstantItem 21 | | StaticItem 22 | | Trait 23 | | Implementation 24 | | ExternBlock 25 | ) 26 | 27 | MacroItem -> 28 | MacroInvocationSemi 29 | | MacroRulesDefinition 30 | ``` 31 | 32 | r[items.intro] 33 | An _item_ is a component of a crate. Items are organized within a crate by a 34 | nested set of [modules]. Every crate has a single "outermost" anonymous module; 35 | all further items within the crate have [paths] within the module tree of the 36 | crate. 37 | 38 | r[items.static-def] 39 | Items are entirely determined at compile-time, generally remain fixed during 40 | execution, and may reside in read-only memory. 41 | 42 | r[items.kinds] 43 | There are several kinds of items: 44 | 45 | * [modules] 46 | * [`extern crate` declarations] 47 | * [`use` declarations] 48 | * [function definitions] 49 | * [type alias definitions] 50 | * [struct definitions] 51 | * [enumeration definitions] 52 | * [union definitions] 53 | * [constant items] 54 | * [static items] 55 | * [trait definitions] 56 | * [implementations] 57 | * [`extern` blocks] 58 | 59 | r[items.locations] 60 | Items may be declared in the [root of the crate], a [module][modules], or a [block expression]. 61 | 62 | r[items.associated-locations] 63 | A subset of items, called [associated items], may be declared in [traits] and [implementations]. 64 | 65 | r[items.extern-locations] 66 | A subset of items, called external items, may be declared in [`extern` blocks]. 67 | 68 | r[items.decl-order] 69 | Items may be defined in any order, with the exception of [`macro_rules`] which has its own scoping behavior. 70 | 71 | r[items.name-resolution] 72 | [Name resolution] of item names allows items to be defined before or after where the item is referred to in the module or block. 73 | 74 | See [item scopes] for information on the scoping rules of items. 75 | 76 | [`extern crate` declarations]: items/extern-crates.md 77 | [`extern` blocks]: items/external-blocks.md 78 | [`macro_rules`]: macros-by-example.md 79 | [`use` declarations]: items/use-declarations.md 80 | [associated items]: items/associated-items.md 81 | [block expression]: expressions/block-expr.md 82 | [constant items]: items/constant-items.md 83 | [enumeration definitions]: items/enumerations.md 84 | [function definitions]: items/functions.md 85 | [implementations]: items/implementations.md 86 | [item scopes]: names/scopes.md#item-scopes 87 | [modules]: items/modules.md 88 | [name resolution]: names/name-resolution.md 89 | [paths]: paths.md 90 | [root of the crate]: crates-and-source-files.md 91 | [statement]: statements.md 92 | [static items]: items/static-items.md 93 | [struct definitions]: items/structs.md 94 | [trait definitions]: items/traits.md 95 | [traits]: items/traits.md 96 | [type alias definitions]: items/type-aliases.md 97 | [union definitions]: items/unions.md 98 | -------------------------------------------------------------------------------- /src/expressions/field-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.field] 2 | # Field access expressions 3 | 4 | r[expr.field.syntax] 5 | ```grammar,expressions 6 | FieldExpression -> Expression `.` IDENTIFIER 7 | ``` 8 | 9 | r[expr.field.intro] 10 | A *field expression* is a [place expression] that evaluates to the location of a field of a [struct] or [union]. 11 | 12 | r[expr.field.mut] 13 | When the operand is [mutable], the field expression is also mutable. 14 | 15 | r[expr.field.form] 16 | The syntax for a field expression is an expression, called the *container operand*, then a `.`, and finally an [identifier]. 17 | 18 | r[expr.field.not-method-call] 19 | Field expressions cannot be followed by a parenthetical comma-separated list of expressions, as that is instead parsed as a [method call expression]. 20 | That is, they cannot be the function operand of a [call expression]. 21 | 22 | > [!NOTE] 23 | > Wrap the field expression in a [parenthesized expression] to use it in a call expression. 24 | > 25 | > ```rust 26 | > # struct HoldsCallable { callable: F } 27 | > let holds_callable = HoldsCallable { callable: || () }; 28 | > 29 | > // Invalid: Parsed as calling the method "callable" 30 | > // holds_callable.callable(); 31 | > 32 | > // Valid 33 | > (holds_callable.callable)(); 34 | > ``` 35 | 36 | Examples: 37 | 38 | 39 | ```rust,ignore 40 | mystruct.myfield; 41 | foo().x; 42 | (Struct {a: 10, b: 20}).a; 43 | (mystruct.function_field)() // Call expression containing a field expression 44 | ``` 45 | 46 | r[expr.field.autoref-deref] 47 | ## Automatic dereferencing 48 | 49 | If the type of the container operand implements [`Deref`] or [`DerefMut`][`Deref`] depending on whether the operand is [mutable], it is *automatically dereferenced* as many times as necessary to make the field access possible. 50 | This process is also called *autoderef* for short. 51 | 52 | r[expr.field.borrow] 53 | ## Borrowing 54 | 55 | The fields of a struct or a reference to a struct are treated as separate entities when borrowing. 56 | If the struct does not implement [`Drop`] and is stored in a local variable, this also applies to moving out of each of its fields. 57 | This also does not apply if automatic dereferencing is done through user-defined types other than [`Box`]. 58 | 59 | ```rust 60 | struct A { f1: String, f2: String, f3: String } 61 | let mut x: A; 62 | # x = A { 63 | # f1: "f1".to_string(), 64 | # f2: "f2".to_string(), 65 | # f3: "f3".to_string() 66 | # }; 67 | let a: &mut String = &mut x.f1; // x.f1 borrowed mutably 68 | let b: &String = &x.f2; // x.f2 borrowed immutably 69 | let c: &String = &x.f2; // Can borrow again 70 | let d: String = x.f3; // Move out of x.f3 71 | ``` 72 | 73 | [`Box`]: ../special-types-and-traits.md#boxt 74 | [`Deref`]: ../special-types-and-traits.md#deref-and-derefmut 75 | [`drop`]: ../special-types-and-traits.md#drop 76 | [identifier]: ../identifiers.md 77 | [call expression]: call-expr.md 78 | [method call expression]: method-call-expr.md 79 | [mutable]: ../expressions.md#mutability 80 | [parenthesized expression]: grouped-expr.md 81 | [place expression]: ../expressions.md#place-expressions-and-value-expressions 82 | [struct]: ../items/structs.md 83 | [union]: ../items/unions.md 84 | -------------------------------------------------------------------------------- /src/runtime.md: -------------------------------------------------------------------------------- 1 | r[runtime] 2 | # The Rust runtime 3 | 4 | This section documents features that define some aspects of the Rust runtime. 5 | 6 | 7 | r[runtime.global_allocator] 8 | ## The `global_allocator` attribute 9 | 10 | r[runtime.global_allocator.intro] 11 | The *`global_allocator` [attribute][attributes]* selects a [memory allocator][std::alloc]. 12 | 13 | > [!EXAMPLE] 14 | > ```rust 15 | > use core::alloc::{GlobalAlloc, Layout}; 16 | > use std::alloc::System; 17 | > 18 | > struct MyAllocator; 19 | > 20 | > unsafe impl GlobalAlloc for MyAllocator { 21 | > unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 22 | > unsafe { System.alloc(layout) } 23 | > } 24 | > unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 25 | > unsafe { System.dealloc(ptr, layout) } 26 | > } 27 | > } 28 | > 29 | > #[global_allocator] 30 | > static GLOBAL: MyAllocator = MyAllocator; 31 | > ``` 32 | 33 | r[runtime.global_allocator.syntax] 34 | The `global_allocator` attribute uses the [MetaWord] syntax. 35 | 36 | r[runtime.global_allocator.allowed-positions] 37 | The `global_allocator` attribute may only be applied to a [static item] whose type implements the [`GlobalAlloc`] trait. 38 | 39 | r[runtime.global_allocator.duplicates] 40 | The `global_allocator` attribute may only be used once on an item. 41 | 42 | r[runtime.global_allocator.single] 43 | The `global_allocator` attribute may only be used once in the crate graph. 44 | 45 | r[runtime.global_allocator.stdlib] 46 | The `global_allocator` attribute is exported from the [standard library prelude][core::prelude::v1]. 47 | 48 | 49 | r[runtime.windows_subsystem] 50 | ## The `windows_subsystem` attribute 51 | 52 | r[runtime.windows_subsystem.intro] 53 | The *`windows_subsystem` [attribute][attributes]* sets the [subsystem] when linking on a Windows target. 54 | 55 | > [!EXAMPLE] 56 | > ```rust 57 | > #![windows_subsystem = "windows"] 58 | > ``` 59 | 60 | r[runtime.windows_subsystem.syntax] 61 | The `windows_subsystem` attribute uses the [MetaNameValueStr] syntax. Accepted values are `"console"` and `"windows"`. 62 | 63 | r[runtime.windows_subsystem.allowed-positions] 64 | The `windows_subsystem` attribute may only be applied to the crate root. 65 | 66 | r[runtime.windows_subsystem.duplicates] 67 | Only the first use of `windows_subsystem` has effect. 68 | 69 | > [!NOTE] 70 | > `rustc` lints against any use following the first. This may become an error in the future. 71 | 72 | r[runtime.windows_subsystem.ignored] 73 | The `windows_subsystem` attribute is ignored on non-Windows targets and non-`bin` [crate types]. 74 | 75 | r[runtime.windows_subsystem.console] 76 | 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. 77 | 78 | r[runtime.windows_subsystem.windows] 79 | The `"windows"` subsystem will run detached from any existing console. 80 | 81 | > [!NOTE] 82 | > The `"windows"` subsystem is commonly used by GUI applications that do not want to display a console window on startup. 83 | 84 | [`GlobalAlloc`]: alloc::alloc::GlobalAlloc 85 | [crate types]: linkage.md 86 | [static item]: items/static-items.md 87 | [subsystem]: https://msdn.microsoft.com/en-us/library/fcc1zstk.aspx 88 | -------------------------------------------------------------------------------- /src/expressions/await-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.await] 2 | # Await expressions 3 | 4 | r[expr.await.syntax] 5 | ```grammar,expressions 6 | AwaitExpression -> Expression `.` `await` 7 | ``` 8 | 9 | r[expr.await.intro] 10 | An `await` expression is a syntactic construct for suspending a computation 11 | provided by an implementation of `std::future::IntoFuture` until the given 12 | future is ready to produce a value. 13 | 14 | r[expr.await.construct] 15 | 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. 16 | 17 | r[expr.await.allowed-positions] 18 | Await expressions are legal only within an [async context], like an [`async fn`], [`async` closure], or [`async` block]. 19 | 20 | r[expr.await.effects] 21 | More specifically, an await expression has the following effect. 22 | 23 | 1. Create a future by calling [`IntoFuture::into_future`] on the future operand. 24 | 2. Evaluate the future to a [future] `tmp`; 25 | 3. Pin `tmp` using [`Pin::new_unchecked`]; 26 | 4. This pinned future is then polled by calling the [`Future::poll`] method and passing it the current [task context](#task-context); 27 | 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; 28 | 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. 29 | 30 | r[expr.await.edition2018] 31 | > [!EDITION-2018] 32 | > Await expressions are only available beginning with Rust 2018. 33 | 34 | r[expr.await.task] 35 | ## Task context 36 | 37 | The task context refers to the [`Context`] which was supplied to the current [async context] when the async context itself was polled. 38 | Because `await` expressions are only legal in an async context, there must be some task context available. 39 | 40 | r[expr.await.desugar] 41 | ## Approximate desugaring 42 | 43 | Effectively, an await expression is roughly equivalent to the following non-normative desugaring: 44 | 45 | 46 | ```rust,ignore 47 | match operand.into_future() { 48 | mut pinned => loop { 49 | let mut pin = unsafe { Pin::new_unchecked(&mut pinned) }; 50 | match Pin::future::poll(Pin::borrow(&mut pin), &mut current_context) { 51 | Poll::Ready(r) => break r, 52 | Poll::Pending => yield Poll::Pending, 53 | } 54 | } 55 | } 56 | ``` 57 | 58 | where the `yield` pseudo-code returns `Poll::Pending` and, when re-invoked, resumes execution from that point. 59 | The variable `current_context` refers to the context taken from the async environment. 60 | 61 | [`async fn`]: ../items/functions.md#async-functions 62 | [`async` closure]: closure-expr.md#async-closures 63 | [`async` block]: block-expr.md#async-blocks 64 | [`Context`]: std::task::Context 65 | [`future::poll`]: std::future::Future::poll 66 | [`pin::new_unchecked`]: std::pin::Pin::new_unchecked 67 | [`poll::Pending`]: std::task::Poll::Pending 68 | [`poll::Ready`]: std::task::Poll::Ready 69 | [async context]: ../expressions/block-expr.md#async-context 70 | [future]: std::future::Future 71 | [`IntoFuture`]: std::future::IntoFuture 72 | [`IntoFuture::into_future`]: std::future::IntoFuture::into_future 73 | -------------------------------------------------------------------------------- /src/notation.md: -------------------------------------------------------------------------------- 1 | r[notation] 2 | # Notation 3 | 4 | r[notation.grammar] 5 | ## Grammar 6 | 7 | r[notation.grammar.syntax] 8 | 9 | The following notations are used by the *Lexer* and *Syntax* grammar snippets: 10 | 11 | | Notation | Examples | Meaning | 12 | |-------------------|-------------------------------|-------------------------------------------| 13 | | CAPITAL | KW_IF, INTEGER_LITERAL | A token produced by the lexer | 14 | | _ItalicCamelCase_ | _LetStatement_, _Item_ | A syntactical production | 15 | | `string` | `x`, `while`, `*` | The exact character(s) | 16 | | x? | `pub`? | An optional item | 17 | | x\* | _OuterAttribute_\* | 0 or more of x | 18 | | x+ | _MacroMatch_+ | 1 or more of x | 19 | | xa..b | HEX_DIGIT1..6 | a to b repetitions of x | 20 | | Rule1 Rule2 | `fn` _Name_ _Parameters_ | Sequence of rules in order | 21 | | \| | `u8` \| `u16`, Block \| Item | Either one or another | 22 | | \[ ] | \[`b` `B`] | Any of the characters listed | 23 | | \[ - ] | \[`a`-`z`] | Any of the characters in the range | 24 | | ~\[ ] | ~\[`b` `B`] | Any characters, except those listed | 25 | | ~`string` | ~`\n`, ~`*/` | Any characters, except this sequence | 26 | | ( ) | (`,` _Parameter_)? | Groups items | 27 | | U+xxxx | U+0060 | A single unicode character | 28 | | \ | \ | An English description of what should be matched | 29 | | Rule suffix | IDENTIFIER_OR_KEYWORD _except `crate`_ | A modification to the previous rule | 30 | | // Comment. | // Single line comment. | A comment extending to the end of the line. | 31 | 32 | Sequences have a higher precedence than `|` alternation. 33 | 34 | r[notation.grammar.string-tables] 35 | ### String table productions 36 | 37 | Some rules in the grammar — notably [unary operators], [binary 38 | operators], and [keywords] — are given in a simplified form: as a listing 39 | of printable strings. These cases form a subset of the rules regarding the 40 | [token][tokens] rule, and are assumed to be the result of a lexical-analysis 41 | phase feeding the parser, driven by a DFA, operating over the disjunction of all such string table 43 | entries. 44 | 45 | When such a string in `monospace` font occurs inside the grammar, 46 | it is an implicit reference to a single member of such a string table 47 | production. See [tokens] for more information. 48 | 49 | r[notation.grammar.visualizations] 50 | ### Grammar visualizations 51 | 52 | Below each grammar block is a button to toggle the display of a [syntax diagram]. A square element is a non-terminal rule, and a rounded rectangle is a terminal. 53 | 54 | [binary operators]: expressions/operator-expr.md#arithmetic-and-logical-binary-operators 55 | [keywords]: keywords.md 56 | [syntax diagram]: https://en.wikipedia.org/wiki/Syntax_diagram 57 | [tokens]: tokens.md 58 | [unary operators]: expressions/operator-expr.md#borrow-operators 59 | -------------------------------------------------------------------------------- /xtask/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::process::Command; 3 | use std::process::exit; 4 | 5 | type Result = std::result::Result>; 6 | 7 | fn main() -> Result<()> { 8 | let mut args = std::env::args().skip(1); 9 | let cmd = args.next(); 10 | const OPTIONS: &str = "linkcheck, style-check, test-all"; 11 | match cmd.as_deref() { 12 | Some("test-all") => { 13 | mdbook_test()?; 14 | style_check()?; 15 | fmt()?; 16 | linkcheck(args)?; 17 | cargo_test()?; 18 | eprintln!("all tests passed!"); 19 | } 20 | Some("linkcheck") => linkcheck(args)?, 21 | Some("style-check") => style_check()?, 22 | Some("-h" | "--help") => eprintln!("valid options: {OPTIONS}"), 23 | Some(x) => { 24 | eprintln!("error: unknown command `{x}` (valid options: {OPTIONS})"); 25 | exit(1); 26 | } 27 | None => { 28 | eprintln!("error: specify a command (valid options: {OPTIONS})"); 29 | exit(1); 30 | } 31 | } 32 | Ok(()) 33 | } 34 | 35 | fn mdbook_test() -> Result<()> { 36 | eprintln!("Testing inline code tests..."); 37 | let status = Command::new("mdbook") 38 | .arg("test") 39 | .status() 40 | .expect("mdbook should be installed"); 41 | if !status.success() { 42 | return Err("inline code tests failed".into()); 43 | } 44 | Ok(()) 45 | } 46 | 47 | fn style_check() -> Result<()> { 48 | eprintln!("Running style checks..."); 49 | let status = Command::new("cargo") 50 | .args(["run", "--manifest-path=style-check/Cargo.toml", "--", "src"]) 51 | .status() 52 | .expect("cargo should be installed"); 53 | if !status.success() { 54 | return Err("style check failed".into()); 55 | } 56 | Ok(()) 57 | } 58 | 59 | fn fmt() -> Result<()> { 60 | eprintln!("Checking code formatting..."); 61 | for dir in ["style-check", "mdbook-spec", "xtask"] { 62 | let status = Command::new("cargo") 63 | .args(["fmt", "--check"]) 64 | .current_dir(dir) 65 | .status() 66 | .expect("cargo should be installed"); 67 | if !status.success() { 68 | return Err(format!("fmt check failed for {dir}").into()); 69 | } 70 | } 71 | Ok(()) 72 | } 73 | 74 | fn cargo_test() -> Result<()> { 75 | eprintln!("Running cargo tests..."); 76 | let status = Command::new("cargo") 77 | .arg("test") 78 | .current_dir("mdbook-spec") 79 | .status() 80 | .expect("cargo should be installed"); 81 | if !status.success() { 82 | return Err("mdbook-spec test failed".into()); 83 | } 84 | Ok(()) 85 | } 86 | 87 | fn linkcheck(args: impl Iterator) -> Result<()> { 88 | eprintln!("Running linkcheck..."); 89 | let status = Command::new("curl") 90 | .args(["-sSLo", "linkcheck.sh", "https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh"]) 91 | .status() 92 | .expect("curl should be installed"); 93 | if !status.success() { 94 | return Err("failed to fetch script from GitHub".into()); 95 | } 96 | 97 | let status = Command::new("sh") 98 | .args(["linkcheck.sh", "--all", "reference"]) 99 | .args(args) 100 | .status() 101 | .expect("sh should be installed"); 102 | if !status.success() { 103 | return Err("linkcheck failed".into()); 104 | } 105 | Ok(()) 106 | } 107 | -------------------------------------------------------------------------------- /src/identifiers.md: -------------------------------------------------------------------------------- 1 | r[ident] 2 | # Identifiers 3 | 4 | r[ident.syntax] 5 | ```grammar,lexer 6 | IDENTIFIER_OR_KEYWORD -> ( XID_Start | `_` ) XID_Continue* 7 | 8 | XID_Start -> <`XID_Start` defined by Unicode> 9 | 10 | XID_Continue -> <`XID_Continue` defined by Unicode> 11 | 12 | RAW_IDENTIFIER -> `r#` IDENTIFIER_OR_KEYWORD 13 | 14 | NON_KEYWORD_IDENTIFIER -> IDENTIFIER_OR_KEYWORD _except a [strict][lex.keywords.strict] or [reserved][lex.keywords.reserved] keyword_ 15 | 16 | IDENTIFIER -> NON_KEYWORD_IDENTIFIER | RAW_IDENTIFIER 17 | 18 | RESERVED_RAW_IDENTIFIER -> `r#` (`_` | `crate` | `self` | `Self` | `super`) 19 | ``` 20 | 21 | 22 | r[ident.unicode] 23 | Identifiers follow the specification in [Unicode Standard Annex #31][UAX31] for Unicode version 16.0, with the additions described below. Some examples of identifiers: 24 | 25 | * `foo` 26 | * `_identifier` 27 | * `r#true` 28 | * `Москва` 29 | * `東京` 30 | 31 | r[ident.profile] 32 | The profile used from UAX #31 is: 33 | 34 | * Start := [`XID_Start`], plus the underscore character (U+005F) 35 | * Continue := [`XID_Continue`] 36 | * Medial := empty 37 | 38 | > [!NOTE] 39 | > Identifiers starting with an underscore are typically used to indicate an identifier that is intentionally unused, and will silence the unused warning in `rustc`. 40 | 41 | r[ident.keyword] 42 | Identifiers may not be a [strict] or [reserved] keyword without the `r#` prefix described below in [raw identifiers](#raw-identifiers). 43 | 44 | r[ident.zero-width-chars] 45 | Zero width non-joiner (ZWNJ U+200C) and zero width joiner (ZWJ U+200D) characters are not allowed in identifiers. 46 | 47 | r[ident.ascii-limitations] 48 | Identifiers are restricted to the ASCII subset of [`XID_Start`] and [`XID_Continue`] in the following situations: 49 | 50 | * [`extern crate`] declarations (except the [AsClause] identifier) 51 | * External crate names referenced in a [path] 52 | * [Module] names loaded from the filesystem without a [`path` attribute] 53 | * [`no_mangle`] attributed items 54 | * Item names in [external blocks] 55 | 56 | r[ident.normalization] 57 | ## Normalization 58 | 59 | Identifiers are normalized using Normalization Form C (NFC) as defined in [Unicode Standard Annex #15][UAX15]. Two identifiers are equal if their NFC forms are equal. 60 | 61 | [Procedural][proc-macro] and [declarative][mbe] macros receive normalized identifiers in their input. 62 | 63 | r[ident.raw] 64 | ## Raw identifiers 65 | 66 | r[ident.raw.intro] 67 | A raw identifier is like a normal identifier, but prefixed by `r#`. (Note that the `r#` prefix is not included as part of the actual identifier.) 68 | 69 | r[ident.raw.allowed] 70 | Unlike a normal identifier, a raw identifier may be any strict or reserved keyword except the ones listed above for `RAW_IDENTIFIER`. 71 | 72 | r[ident.raw.reserved] 73 | It is an error to use the [RESERVED_RAW_IDENTIFIER] token. 74 | 75 | [`extern crate`]: items/extern-crates.md 76 | [`no_mangle`]: abi.md#the-no_mangle-attribute 77 | [`path` attribute]: items/modules.md#the-path-attribute 78 | [`XID_Continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i= 79 | [`XID_Start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i= 80 | [external blocks]: items/external-blocks.md 81 | [mbe]: macros-by-example.md 82 | [module]: items/modules.md 83 | [path]: paths.md 84 | [proc-macro]: procedural-macros.md 85 | [reserved]: keywords.md#reserved-keywords 86 | [strict]: keywords.md#strict-keywords 87 | [UAX15]: https://www.unicode.org/reports/tr15/tr15-56.html 88 | [UAX31]: https://www.unicode.org/reports/tr31/tr31-41.html 89 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Thank you for your interest in contributing to the Rust Reference! 2 | 3 | There are a few ways of helping with the reference: critiquing the reference, 4 | editing the reference, fixing incorrect information, adding examples and 5 | glossary entries, and documenting new or otherwise undocumented features in 6 | Rust. 7 | 8 | For a while, the Reference was basically ignored, and Rust continued gaining new 9 | features or changing old ones. It was also basically the introduction document 10 | before the first edition of the Rust book, and constantly in flux from the huge 11 | churn of the language design before v1.0.0. So there's a lot that's wrong, too 12 | teachy for people who should have basic understanding of Rust, or is too shallow 13 | for the Reference. As such, we have the warning saying there's work that needs 14 | to be done. Eventually, we plan to make sure everything is well documented 15 | enough that we can remove the warning. 16 | 17 | It is encouraged for you to read the [introduction] to familiarize yourself with 18 | the kind of content the reference is expected to contain and the conventions it 19 | uses. Also, the [Authoring Guide] provides more detailed guidelines for 20 | formatting and content. 21 | 22 | ## Critiquing the Reference 23 | 24 | This is the easiest way to contribute. Basically, as you read the reference, if 25 | you find something confusing, incorrect, or missing, then you can file an issue 26 | against the reference explaining your concerns. 27 | 28 | ## Editing the Reference 29 | 30 | Typos and incorrect links get through from time to time. Should you find them, 31 | we welcome PRs to fix them. Additionally, larger editing jobs that help remove 32 | the number of parentheticals, remove comma splices, italicize term definitions 33 | and other similar tasks are helpful. 34 | 35 | ## Adding examples and glossary entries 36 | 37 | Examples are great. Many people will only read examples and ignore the prose. 38 | Ideally, every facet of every feature will have an example. 39 | 40 | Likewise, the reference has a glossary. It doesn't need to explain every facet 41 | of every feature nor contain every definition, but it does need to be expanded 42 | upon. Ideally entries in the glossary link to the associated documentation. 43 | 44 | ## Adding documentation 45 | 46 | There are a lot of features that are not documented at all or are documented 47 | poorly. This is the hardest, but definitely most valuable. Pick an unassigned 48 | issue from the [issue tracker], and write about it. 49 | 50 | While writing, you may find it handy to have a [playpen] open to test out what 51 | you are documenting. 52 | 53 | Feel free to take information from the standard library and Rustonomicon as 54 | appropriate. 55 | 56 | Note that we don't write documentation for purely library features such as 57 | threads and IO and we don't write about Rust in the future. Documentation is 58 | written as if the current stable release of Rust is the last release. The 59 | `master` branch of the reference corresponds to what is **stable** on the 60 | `master` branch ("nightly") of [rust-lang/rust]. If you want to write about 61 | Rust in the future, you want [the Unstable book][unstable]. 62 | 63 | ## Stabilization 64 | 65 | When something that alters the language is stabilized, an issue should be 66 | opened on the reference [issue tracker] to track the documentation process. 67 | This should include links to any relevant information, such as the 68 | stabilization PR, the RFC, the tracking issue, and anything else that would be 69 | helpful for writing the documentation. 70 | 71 | [Authoring Guide]: docs/authoring.md 72 | [introduction]: src/introduction.md 73 | [issue tracker]: https://github.com/rust-lang/reference/issues 74 | [playpen]: https://play.rust-lang.org/ 75 | [rust-lang/rust]: https://github.com/rust-lang/rust/ 76 | [unstable]: https://doc.rust-lang.org/nightly/unstable-book/ 77 | -------------------------------------------------------------------------------- /src/macros.md: -------------------------------------------------------------------------------- 1 | r[macro] 2 | # Macros 3 | 4 | r[macro.intro] 5 | The functionality and syntax of Rust can be extended with custom definitions 6 | called macros. They are given names, and invoked through a consistent 7 | syntax: `some_extension!(...)`. 8 | 9 | There are two ways to define new macros: 10 | 11 | * [Macros by Example] define new syntax in a higher-level, declarative way. 12 | * [Procedural Macros] define function-like macros, custom derives, and custom 13 | attributes using functions that operate on input tokens. 14 | 15 | r[macro.invocation] 16 | ## Macro invocation 17 | 18 | r[macro.invocation.syntax] 19 | ```grammar,macros 20 | MacroInvocation -> 21 | SimplePath `!` DelimTokenTree 22 | 23 | DelimTokenTree -> 24 | `(` TokenTree* `)` 25 | | `[` TokenTree* `]` 26 | | `{` TokenTree* `}` 27 | 28 | TokenTree -> 29 | Token _except [delimiters][lex.token.delim]_ | DelimTokenTree 30 | 31 | MacroInvocationSemi -> 32 | SimplePath `!` `(` TokenTree* `)` `;` 33 | | SimplePath `!` `[` TokenTree* `]` `;` 34 | | SimplePath `!` `{` TokenTree* `}` 35 | ``` 36 | 37 | r[macro.invocation.intro] 38 | A macro invocation expands a macro at compile time and replaces the 39 | invocation with the result of the macro. Macros may be invoked in the 40 | following situations: 41 | 42 | r[macro.invocation.expr] 43 | * [Expressions] and [statements] 44 | 45 | r[macro.invocation.pattern] 46 | * [Patterns] 47 | 48 | r[macro.invocation.type] 49 | * [Types] 50 | 51 | r[macro.invocation.item] 52 | * [Items] including [associated items] 53 | 54 | r[macro.invocation.nested] 55 | * [`macro_rules`] transcribers 56 | 57 | r[macro.invocation.extern] 58 | * [External blocks] 59 | 60 | r[macro.invocation.item-statement] 61 | When used as an item or a statement, the [MacroInvocationSemi] form is used 62 | where a semicolon is required at the end when not using curly braces. 63 | [Visibility qualifiers] are never allowed before a macro invocation or 64 | [`macro_rules`] definition. 65 | 66 | ```rust 67 | // Used as an expression. 68 | let x = vec![1,2,3]; 69 | 70 | // Used as a statement. 71 | println!("Hello!"); 72 | 73 | // Used in a pattern. 74 | macro_rules! pat { 75 | ($i:ident) => (Some($i)) 76 | } 77 | 78 | if let pat!(x) = Some(1) { 79 | assert_eq!(x, 1); 80 | } 81 | 82 | // Used in a type. 83 | macro_rules! Tuple { 84 | { $A:ty, $B:ty } => { ($A, $B) }; 85 | } 86 | 87 | type N2 = Tuple!(i32, i32); 88 | 89 | // Used as an item. 90 | # use std::cell::RefCell; 91 | thread_local!(static FOO: RefCell = RefCell::new(1)); 92 | 93 | // Used as an associated item. 94 | macro_rules! const_maker { 95 | ($t:ty, $v:tt) => { const CONST: $t = $v; }; 96 | } 97 | trait T { 98 | const_maker!{i32, 7} 99 | } 100 | 101 | // Macro calls within macros. 102 | macro_rules! example { 103 | () => { println!("Macro call in a macro!") }; 104 | } 105 | // Outer macro `example` is expanded, then inner macro `println` is expanded. 106 | example!(); 107 | ``` 108 | 109 | r[macro.invocation.name-resolution] 110 | 111 | Macros invocations can be resolved via two kinds of scopes: 112 | 113 | - Textual Scope 114 | - [Textual scope `macro_rules`](macros-by-example.md#r-macro.decl.scope.textual) 115 | - Path-based scope 116 | - [Path-based scope `macro_rules`](macros-by-example.md#r-macro.decl.scope.path-based) 117 | - [Procedural macros] 118 | 119 | [External blocks]: items/external-blocks.md 120 | [Macros by Example]: macros-by-example.md 121 | [Procedural Macros]: procedural-macros.md 122 | [`macro_rules`]: macros-by-example.md 123 | [associated items]: items/associated-items.md 124 | [delimiters]: tokens.md#delimiters 125 | [expressions]: expressions.md 126 | [items]: items.md 127 | [patterns]: patterns.md 128 | [statements]: statements.md 129 | [types]: types.md 130 | [visibility qualifiers]: visibility-and-privacy.md 131 | -------------------------------------------------------------------------------- /src/expressions/call-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.call] 2 | # Call expressions 3 | 4 | r[expr.call.syntax] 5 | ```grammar,expressions 6 | CallExpression -> Expression `(` CallParams? `)` 7 | 8 | CallParams -> Expression ( `,` Expression )* `,`? 9 | ``` 10 | 11 | r[expr.call.intro] 12 | A *call expression* calls a function. 13 | The syntax of a call expression is an expression, called the *function operand*, followed by a parenthesized comma-separated list of expression, called the *argument operands*. 14 | 15 | r[expr.call.convergence] 16 | If the function eventually returns, then the expression completes. 17 | 18 | r[expr.call.trait] 19 | For [non-function types], the expression `f(...)` uses the method on one of the following traits based on the function operand: 20 | 21 | - [`Fn`] or [`AsyncFn`] --- shared reference. 22 | - [`FnMut`] or [`AsyncFnMut`] --- mutable reference. 23 | - [`FnOnce`] or [`AsyncFnOnce`] --- value. 24 | 25 | r[expr.call.autoref-deref] 26 | An automatic borrow will be taken if needed. 27 | The function operand will also be [automatically dereferenced] as required. 28 | 29 | Some examples of call expressions: 30 | 31 | ```rust 32 | # fn add(x: i32, y: i32) -> i32 { 0 } 33 | let three: i32 = add(1i32, 2i32); 34 | let name: &'static str = (|| "Rust")(); 35 | ``` 36 | 37 | r[expr.call.desugar] 38 | ## Disambiguating function calls 39 | 40 | r[expr.call.desugar.fully-qualified] 41 | All function calls are sugar for a more explicit [fully-qualified syntax]. 42 | 43 | r[expr.call.desugar.ambiguity] 44 | Function calls may need to be fully qualified, depending on the ambiguity of a call in light of in-scope items. 45 | 46 | > [!NOTE] 47 | > In the past, the terms "Unambiguous Function Call Syntax", "Universal Function Call Syntax", or "UFCS", have been used in documentation, issues, RFCs, and other community writings. However, these terms lack descriptive power and potentially confuse the issue at hand. We mention them here for searchability's sake. 48 | 49 | r[expr.call.desugar.limits] 50 | Several situations often occur which result in ambiguities about the receiver or referent of method or associated function calls. 51 | These situations may include: 52 | 53 | * Multiple in-scope traits define methods with the same name for the same types 54 | * Auto-`deref` is undesirable; for example, distinguishing between methods on a smart pointer itself and the pointer's referent 55 | * Methods which take no arguments, like [`default()`], and return properties of a type, like [`size_of()`] 56 | 57 | r[expr.call.desugar.explicit-path] 58 | To resolve the ambiguity, the programmer may refer to their desired method or function using more specific paths, types, or traits. 59 | 60 | For example, 61 | 62 | ```rust 63 | trait Pretty { 64 | fn print(&self); 65 | } 66 | 67 | trait Ugly { 68 | fn print(&self); 69 | } 70 | 71 | struct Foo; 72 | impl Pretty for Foo { 73 | fn print(&self) {} 74 | } 75 | 76 | struct Bar; 77 | impl Pretty for Bar { 78 | fn print(&self) {} 79 | } 80 | impl Ugly for Bar { 81 | fn print(&self) {} 82 | } 83 | 84 | fn main() { 85 | let f = Foo; 86 | let b = Bar; 87 | 88 | // we can do this because we only have one item called `print` for `Foo`s 89 | f.print(); 90 | // more explicit, and, in the case of `Foo`, not necessary 91 | Foo::print(&f); 92 | // if you're not into the whole brevity thing 93 | ::print(&f); 94 | 95 | // b.print(); // Error: multiple 'print' found 96 | // Bar::print(&b); // Still an error: multiple `print` found 97 | 98 | // necessary because of in-scope items defining `print` 99 | ::print(&b); 100 | } 101 | ``` 102 | 103 | Refer to [RFC 132] for further details and motivations. 104 | 105 | [RFC 132]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md 106 | [`default()`]: std::default::Default::default 107 | [`size_of()`]: std::mem::size_of 108 | [automatically dereferenced]: field-expr.md#automatic-dereferencing 109 | [fully-qualified syntax]: ../paths.md#qualified-paths 110 | [non-function types]: ../types/function-item.md 111 | -------------------------------------------------------------------------------- /src/types/pointer.md: -------------------------------------------------------------------------------- 1 | r[type.pointer] 2 | # Pointer types 3 | 4 | r[type.pointer.intro] 5 | All pointers are explicit first-class values. 6 | They can be moved or copied, stored into data structs, and returned from functions. 7 | 8 | r[type.pointer.reference] 9 | ## References (`&` and `&mut`) 10 | 11 | r[type.pointer.reference.syntax] 12 | ```grammar,types 13 | ReferenceType -> `&` Lifetime? `mut`? TypeNoBounds 14 | ``` 15 | 16 | r[type.pointer.reference.shared] 17 | ### Shared references (`&`) 18 | 19 | r[type.pointer.reference.shared.intro] 20 | Shared references point to memory which is owned by some other value. 21 | 22 | r[type.pointer.reference.shared.constraint-mutation] 23 | When a shared reference to a value is created, it prevents direct mutation of the value. 24 | [Interior mutability] provides an exception for this in certain circumstances. 25 | As the name suggests, any number of shared references to a value may exist. 26 | A shared reference type is written `&type`, or `&'a type` when you need to specify an explicit lifetime. 27 | 28 | r[type.pointer.reference.shared.copy] 29 | Copying a reference is a "shallow" operation: 30 | it involves only copying the pointer itself, that is, pointers are `Copy`. 31 | Releasing a reference has no effect on the value it points to, but referencing of a [temporary value] will keep it alive during the scope of the reference itself. 32 | 33 | r[type.pointer.reference.mut] 34 | ### Mutable references (`&mut`) 35 | 36 | r[type.pointer.reference.mut.intro] 37 | Mutable references point to memory which is owned by some other value. 38 | A mutable reference type is written `&mut type` or `&'a mut type`. 39 | 40 | r[type.pointer.reference.mut.copy] 41 | A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`. 42 | 43 | r[type.pointer.raw] 44 | ## Raw pointers (`*const` and `*mut`) 45 | 46 | r[type.pointer.raw.syntax] 47 | ```grammar,types 48 | RawPointerType -> `*` ( `mut` | `const` ) TypeNoBounds 49 | ``` 50 | 51 | r[type.pointer.raw.intro] 52 | Raw pointers are pointers without safety or liveness guarantees. 53 | Raw pointers are written as `*const T` or `*mut T`. 54 | For example `*const i32` means a raw pointer to a 32-bit integer. 55 | 56 | r[type.pointer.raw.copy] 57 | Copying or dropping a raw pointer has no effect on the lifecycle of any other value. 58 | 59 | r[type.pointer.raw.safety] 60 | Dereferencing a raw pointer is an [`unsafe` operation]. 61 | 62 | This can also be used to convert a raw pointer to a reference by reborrowing it (`&*` or `&mut *`). 63 | Raw pointers are generally discouraged; 64 | they exist to support interoperability with foreign code, and writing performance-critical or low-level functions. 65 | 66 | r[type.pointer.raw.cmp] 67 | When comparing raw pointers they are compared by their address, rather than by what they point to. 68 | When comparing raw pointers to [dynamically sized types] they also have their additional data compared. 69 | 70 | r[type.pointer.raw.constructor] 71 | Raw pointers can be created directly using `&raw const` for `*const` pointers and `&raw mut` for `*mut` pointers. 72 | 73 | r[type.pointer.smart] 74 | ## Smart pointers 75 | 76 | The standard library contains additional 'smart pointer' types beyond references and raw pointers. 77 | 78 | r[type.pointer.validity] 79 | ## Bit validity 80 | 81 | r[type.pointer.validity.pointer-fragment] 82 | Despite pointers and references being similar to `usize`s in the machine code emitted on most platforms, 83 | the semantics of transmuting a reference or pointer type to a non-pointer type is currently undecided. 84 | Thus, it may not be valid to transmute a pointer or reference type, `P`, to a `[u8; size_of::

()]`. 85 | 86 | r[type.pointer.validity.raw] 87 | For thin raw pointers (i.e., for `P = *const T` or `P = *mut T` for `T: Sized`), 88 | the inverse direction (transmuting from an integer or array of integers to `P`) is always valid. 89 | However, the pointer produced via such a transmutation may not be dereferenced (not even if `T` has size zero). 90 | 91 | [Interior mutability]: ../interior-mutability.md 92 | [`unsafe` operation]: ../unsafety.md 93 | [dynamically sized types]: ../dynamically-sized-types.md 94 | [temporary value]: ../expressions.md#temporaries 95 | -------------------------------------------------------------------------------- /src/attributes/derive.md: -------------------------------------------------------------------------------- 1 | 2 | r[attributes.derive] 3 | # Derive 4 | 5 | r[attributes.derive.intro] 6 | The *`derive` [attribute][attributes]* invokes one or more [derive macros], allowing new [items] to be automatically generated for data structures. You can create `derive` macros with [procedural macros]. 7 | 8 | > [!EXAMPLE] 9 | > The [`PartialEq`][macro@PartialEq] derive macro emits an [implementation] of [`PartialEq`] for `Foo where T: PartialEq`. The [`Clone`][macro@Clone] derive macro does likewise for [`Clone`]. 10 | > 11 | > ```rust 12 | > #[derive(PartialEq, Clone)] 13 | > struct Foo { 14 | > a: i32, 15 | > b: T, 16 | > } 17 | > ``` 18 | > 19 | > The generated `impl` items are equivalent to: 20 | > 21 | > ```rust 22 | > # struct Foo { a: i32, b: T } 23 | > impl PartialEq for Foo { 24 | > fn eq(&self, other: &Foo) -> bool { 25 | > self.a == other.a && self.b == other.b 26 | > } 27 | > } 28 | > 29 | > impl Clone for Foo { 30 | > fn clone(&self) -> Self { 31 | > Foo { a: self.a.clone(), b: self.b.clone() } 32 | > } 33 | > } 34 | > ``` 35 | 36 | r[attributes.derive.syntax] 37 | The `derive` attribute uses the [MetaListPaths] syntax to specify a list of paths to [derive macros] to invoke. 38 | 39 | r[attributes.derive.allowed-positions] 40 | The `derive` attribute may only be applied to [structs][items.struct], [enums][items.enum], and [unions][items.union]. 41 | 42 | r[attributes.derive.duplicates] 43 | The `derive` attribute may be used any number of times on an item. All derive macros listed in all attributes are invoked. 44 | 45 | r[attributes.derive.stdlib] 46 | The `derive` attribute is exported in the standard library prelude as [`core::prelude::v1::derive`]. 47 | 48 | r[attributes.derive.built-in] 49 | Built-in derives are defined in the [language prelude][names.preludes.lang]. The list of built-in derives are: 50 | 51 | - [`Clone`] 52 | - [`Copy`] 53 | - [`Debug`] 54 | - [`Default`] 55 | - [`Eq`] 56 | - [`Hash`] 57 | - [`Ord`] 58 | - [`PartialEq`] 59 | - [`PartialOrd`] 60 | 61 | r[attributes.derive.built-in-automatically_derived] 62 | The built-in derives include the [`automatically_derived` attribute][attributes.derive.automatically_derived] on the implementations they generate. 63 | 64 | r[attributes.derive.behavior] 65 | During macro expansion, for each element in the list of derives, the corresponding derive macro expands to zero or more [items]. 66 | 67 | 68 | r[attributes.derive.automatically_derived] 69 | ## The `automatically_derived` attribute 70 | 71 | r[attributes.derive.automatically_derived.intro] 72 | The *`automatically_derived` [attribute][attributes]* is used to annotate an [implementation] to indicate that it was automatically created by a [derive macro]. It has no direct effect, but it may be used by tools and diagnostic lints to detect these automatically generated implementations. 73 | 74 | > [!EXAMPLE] 75 | > Given [`#[derive(Clone)]`][macro@Clone] on `struct Example`, the [derive macro] may produce: 76 | > 77 | > ```rust 78 | > # struct Example; 79 | > #[automatically_derived] 80 | > impl ::core::clone::Clone for Example { 81 | > #[inline] 82 | > fn clone(&self) -> Self { 83 | > Example 84 | > } 85 | > } 86 | > ``` 87 | 88 | r[attributes.derive.automatically_derived.syntax] 89 | The `automatically_derived` attribute uses the [MetaWord] syntax. 90 | 91 | r[attributes.derive.automatically_derived.allowed-positions] 92 | The `automatically_derived` attribute may only be applied to an [implementation]. 93 | 94 | > [!NOTE] 95 | > `rustc` ignores use in other positions but lints against it. This may become an error in the future. 96 | 97 | r[attributes.derive.automatically_derived.duplicates] 98 | Using `automatically_derived` more than once on an implementation has the same effect as using it once. 99 | 100 | > [!NOTE] 101 | > `rustc` lints against any use following the first. 102 | 103 | r[attributes.derive.automatically_derived.behavior] 104 | The `automatically_derived` attribute has no behavior. 105 | 106 | [items]: ../items.md 107 | [derive macro]: macro.proc.derive 108 | [derive macros]: macro.proc.derive 109 | [implementation]: ../items/implementations.md 110 | [items]: ../items.md 111 | [procedural macros]: macro.proc.derive 112 | -------------------------------------------------------------------------------- /src/expressions/tuple-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.tuple] 2 | # Tuple and tuple indexing expressions 3 | 4 | ## Tuple expressions 5 | 6 | r[expr.tuple.syntax] 7 | ```grammar,expressions 8 | TupleExpression -> `(` TupleElements? `)` 9 | 10 | TupleElements -> ( Expression `,` )+ Expression? 11 | ``` 12 | 13 | r[expr.tuple.result] 14 | A *tuple expression* constructs [tuple values][tuple type]. 15 | 16 | r[expr.tuple.intro] 17 | The syntax for tuple expressions is a parenthesized, comma separated list of expressions, called the *tuple initializer operands*. 18 | 19 | r[expr.tuple.unary-tuple-restriction] 20 | 1-ary tuple expressions require a comma after their tuple initializer operand to be disambiguated with a [parenthetical expression]. 21 | 22 | r[expr.tuple.value] 23 | Tuple expressions are a [value expression] that evaluate into a newly constructed value of a tuple type. 24 | 25 | r[expr.tuple.type] 26 | The number of tuple initializer operands is the arity of the constructed tuple. 27 | 28 | r[expr.tuple.unit] 29 | Tuple expressions without any tuple initializer operands produce the unit tuple. 30 | 31 | r[expr.tuple.fields] 32 | For other tuple expressions, the first written tuple initializer operand initializes the field `0` and subsequent operands initializes the next highest field. 33 | For example, in the tuple expression `('a', 'b', 'c')`, `'a'` initializes the value of the field `0`, `'b'` field `1`, and `'c'` field `2`. 34 | 35 | Examples of tuple expressions and their types: 36 | 37 | | Expression | Type | 38 | | -------------------- | ------------ | 39 | | `()` | `()` (unit) | 40 | | `(0.0, 4.5)` | `(f64, f64)` | 41 | | `("x".to_string(), )` | `(String, )` | 42 | | `("a", 4usize, true)`| `(&'static str, usize, bool)` | 43 | 44 | r[expr.tuple-index] 45 | ## Tuple indexing expressions 46 | 47 | r[expr.tuple-index.syntax] 48 | ```grammar,expressions 49 | TupleIndexingExpression -> Expression `.` TUPLE_INDEX 50 | ``` 51 | 52 | r[expr.tuple-index.intro] 53 | A *tuple indexing expression* accesses fields of [tuples][tuple type] and [tuple structs][tuple struct]. 54 | 55 | The syntax for a tuple index expression is an expression, called the *tuple operand*, then a `.`, then finally a tuple index. 56 | 57 | r[expr.tuple-index.index-syntax] 58 | The syntax for the *tuple index* is a [decimal literal] with no leading zeros, underscores, or suffix. 59 | For example `0` and `2` are valid tuple indices but not `01`, `0_`, nor `0i32`. 60 | 61 | r[expr.tuple-index.required-type] 62 | The type of the tuple operand must be a [tuple type] or a [tuple struct]. 63 | 64 | r[expr.tuple-index.index-name-operand] 65 | The tuple index must be a name of a field of the type of the tuple operand. 66 | 67 | r[expr.tuple-index.result] 68 | Evaluation of tuple index expressions has no side effects beyond evaluation of its tuple operand. 69 | As a [place expression], it evaluates to the location of the field of the tuple operand with the same name as the tuple index. 70 | 71 | Examples of tuple indexing expressions: 72 | 73 | ```rust 74 | // Indexing a tuple 75 | let pair = ("a string", 2); 76 | assert_eq!(pair.1, 2); 77 | 78 | // Indexing a tuple struct 79 | # struct Point(f32, f32); 80 | let point = Point(1.0, 0.0); 81 | assert_eq!(point.0, 1.0); 82 | assert_eq!(point.1, 0.0); 83 | ``` 84 | 85 | > [!NOTE] 86 | > Unlike field access expressions, tuple index expressions can be the function operand of a [call expression] as it cannot be confused with a method call since method names cannot be numbers. 87 | 88 | > [!NOTE] 89 | > Although arrays and slices also have elements, you must use an [array or slice indexing expression] or a [slice pattern] to access their elements. 90 | 91 | [array or slice indexing expression]: array-expr.md#array-and-slice-indexing-expressions 92 | [call expression]: ./call-expr.md 93 | [decimal literal]: ../tokens.md#integer-literals 94 | [field access expressions]: ./field-expr.html#field-access-expressions 95 | [operands]: ../expressions.md 96 | [parenthetical expression]: grouped-expr.md 97 | [place expression]: ../expressions.md#place-expressions-and-value-expressions 98 | [slice pattern]: ../patterns.md#slice-patterns 99 | [tuple type]: ../types/tuple.md 100 | [tuple struct]: ../types/struct.md 101 | [value expression]: ../expressions.md#place-expressions-and-value-expressions 102 | -------------------------------------------------------------------------------- /src/items/constant-items.md: -------------------------------------------------------------------------------- 1 | r[items.const] 2 | # Constant items 3 | 4 | r[items.const.syntax] 5 | ```grammar,items 6 | ConstantItem -> 7 | `const` ( IDENTIFIER | `_` ) `:` Type ( `=` Expression )? `;` 8 | ``` 9 | 10 | r[items.const.intro] 11 | A *constant item* is an optionally named _[constant value]_ which is not associated 12 | with a specific memory location in the program. 13 | 14 | r[items.const.behavior] 15 | Constants are essentially inlined wherever they are used, meaning that they are copied directly into the relevant 16 | context when used. This includes usage of constants from external crates, and 17 | non-[`Copy`] types. References to the same constant are not necessarily 18 | guaranteed to refer to the same memory address. 19 | 20 | r[items.const.namespace] 21 | The constant declaration defines the constant value in the [value namespace] of the module or block where it is located. 22 | 23 | r[items.const.static] 24 | Constants must be explicitly typed. The type must have a `'static` lifetime: any 25 | references in the initializer must have `'static` lifetimes. References 26 | in the type of a constant default to `'static` lifetime; see [static lifetime 27 | elision]. 28 | 29 | r[items.const.static-temporary] 30 | A reference to a constant will have `'static` lifetime if the constant value is eligible for 31 | [promotion]; otherwise, a temporary will be created. 32 | 33 | ```rust 34 | const BIT1: u32 = 1 << 0; 35 | const BIT2: u32 = 1 << 1; 36 | 37 | const BITS: [u32; 2] = [BIT1, BIT2]; 38 | const STRING: &'static str = "bitstring"; 39 | 40 | struct BitsNStrings<'a> { 41 | mybits: [u32; 2], 42 | mystring: &'a str, 43 | } 44 | 45 | const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings { 46 | mybits: BITS, 47 | mystring: STRING, 48 | }; 49 | ``` 50 | 51 | r[items.const.expr-omission] 52 | The constant expression may only be omitted in a [trait definition]. 53 | 54 | r[items.const.destructor] 55 | ## Constants with destructors 56 | 57 | Constants can contain destructors. Destructors are run when the value goes out 58 | of scope. 59 | 60 | ```rust 61 | struct TypeWithDestructor(i32); 62 | 63 | impl Drop for TypeWithDestructor { 64 | fn drop(&mut self) { 65 | println!("Dropped. Held {}.", self.0); 66 | } 67 | } 68 | 69 | const ZERO_WITH_DESTRUCTOR: TypeWithDestructor = TypeWithDestructor(0); 70 | 71 | fn create_and_drop_zero_with_destructor() { 72 | let x = ZERO_WITH_DESTRUCTOR; 73 | // x gets dropped at end of function, calling drop. 74 | // prints "Dropped. Held 0.". 75 | } 76 | ``` 77 | 78 | r[items.const.unnamed] 79 | ## Unnamed constant 80 | 81 | r[items.const.unnamed.intro] 82 | Unlike an [associated constant], a [free] constant may be unnamed by using 83 | an underscore instead of the name. For example: 84 | 85 | ```rust 86 | const _: () = { struct _SameNameTwice; }; 87 | 88 | // OK although it is the same name as above: 89 | const _: () = { struct _SameNameTwice; }; 90 | ``` 91 | 92 | r[items.const.unnamed.repetition] 93 | As with [underscore imports], macros may safely emit the same unnamed constant in 94 | the same scope more than once. For example, the following should not produce an error: 95 | 96 | ```rust 97 | macro_rules! m { 98 | ($item: item) => { $item $item } 99 | } 100 | 101 | m!(const _: () = ();); 102 | // This expands to: 103 | // const _: () = (); 104 | // const _: () = (); 105 | ``` 106 | 107 | r[items.const.eval] 108 | ## Evaluation 109 | 110 | [Free][free] constants are always [evaluated][const_eval] at compile-time to surface 111 | panics. This happens even within an unused function: 112 | 113 | ```rust,compile_fail 114 | // Compile-time panic 115 | const PANIC: () = std::unimplemented!(); 116 | 117 | fn unused_generic_function() { 118 | // A failing compile-time assertion 119 | const _: () = assert!(usize::BITS == 0); 120 | } 121 | ``` 122 | 123 | [const_eval]: ../const_eval.md 124 | [associated constant]: ../items/associated-items.md#associated-constants 125 | [constant value]: ../const_eval.md#constant-expressions 126 | [free]: ../glossary.md#free-item 127 | [static lifetime elision]: ../lifetime-elision.md#const-and-static-elision 128 | [trait definition]: traits.md 129 | [underscore imports]: use-declarations.md#underscore-imports 130 | [`Copy`]: ../special-types-and-traits.md#copy 131 | [value namespace]: ../names/namespaces.md 132 | [promotion]: destructors.scope.const-promotion 133 | -------------------------------------------------------------------------------- /src/types/trait-object.md: -------------------------------------------------------------------------------- 1 | r[type.trait-object] 2 | # Trait objects 3 | 4 | r[type.trait-object.syntax] 5 | ```grammar,types 6 | TraitObjectType -> `dyn`? TypeParamBounds 7 | 8 | TraitObjectTypeOneBound -> `dyn`? TraitBound 9 | ``` 10 | 11 | r[type.trait-object.intro] 12 | A *trait object* is an opaque value of another type that implements a set of 13 | traits. The set of traits is made up of a [dyn compatible] *base trait* plus any 14 | number of [auto traits]. 15 | 16 | r[type.trait-object.impls] 17 | Trait objects implement the base trait, its auto traits, and any [supertraits] 18 | of the base trait. 19 | 20 | r[type.trait-object.name] 21 | Trait objects are written as the keyword `dyn` followed by a set of trait 22 | bounds, but with the following restrictions on the trait bounds. 23 | 24 | r[type.trait-object.constraint] 25 | There may not be more than one non-auto trait, no more than one 26 | lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore, 27 | paths to traits may be parenthesized. 28 | 29 | For example, given a trait `Trait`, the following are all trait objects: 30 | 31 | * `dyn Trait` 32 | * `dyn Trait + Send` 33 | * `dyn Trait + Send + Sync` 34 | * `dyn Trait + 'static` 35 | * `dyn Trait + Send + 'static` 36 | * `dyn Trait +` 37 | * `dyn 'static + Trait`. 38 | * `dyn (Trait)` 39 | 40 | r[type.trait-object.syntax-edition2021] 41 | > [!EDITION-2021] 42 | > Before the 2021 edition, the `dyn` keyword may be omitted. 43 | 44 | r[type.trait-object.syntax-edition2018] 45 | > [!EDITION-2018] 46 | > In the 2015 edition, if the first bound of the trait object is a path that starts with `::`, then the `dyn` will be treated as a part of the path. The first path can be put in parenthesis to get around this. As such, if you want a trait object with the trait `::your_module::Trait`, you should write it as `dyn (::your_module::Trait)`. 47 | > 48 | > Beginning in the 2018 edition, `dyn` is a true keyword and is not allowed in paths, so the parentheses are not necessary. 49 | 50 | r[type.trait-object.alias] 51 | Two trait object types alias each other if the base traits alias each other and 52 | if the sets of auto traits are the same and the lifetime bounds are the same. 53 | For example, `dyn Trait + Send + UnwindSafe` is the same as 54 | `dyn Trait + UnwindSafe + Send`. 55 | 56 | r[type.trait-object.unsized] 57 | Due to the opaqueness of which concrete type the value is of, trait objects are 58 | [dynamically sized types]. Like all 59 | DSTs, trait objects are used 60 | behind some type of pointer; for example `&dyn SomeTrait` or 61 | `Box`. Each instance of a pointer to a trait object includes: 62 | 63 | - a pointer to an instance of a type `T` that implements `SomeTrait` 64 | - a _virtual method table_, often just called a _vtable_, which contains, for 65 | each method of `SomeTrait` and its [supertraits] that `T` implements, a 66 | pointer to `T`'s implementation (i.e. a function pointer). 67 | 68 | The purpose of trait objects is to permit "late binding" of methods. Calling a 69 | method on a trait object results in virtual dispatch at runtime: that is, a 70 | function pointer is loaded from the trait object vtable and invoked indirectly. 71 | The actual implementation for each vtable entry can vary on an object-by-object 72 | basis. 73 | 74 | An example of a trait object: 75 | 76 | ```rust 77 | trait Printable { 78 | fn stringify(&self) -> String; 79 | } 80 | 81 | impl Printable for i32 { 82 | fn stringify(&self) -> String { self.to_string() } 83 | } 84 | 85 | fn print(a: Box) { 86 | println!("{}", a.stringify()); 87 | } 88 | 89 | fn main() { 90 | print(Box::new(10) as Box); 91 | } 92 | ``` 93 | 94 | In this example, the trait `Printable` occurs as a trait object in both the 95 | type signature of `print`, and the cast expression in `main`. 96 | 97 | r[type.trait-object.lifetime-bounds] 98 | ## Trait object lifetime bounds 99 | 100 | Since a trait object can contain references, the lifetimes of those references 101 | need to be expressed as part of the trait object. This lifetime is written as 102 | `Trait + 'a`. There are [defaults] that allow this lifetime to usually be 103 | inferred with a sensible choice. 104 | 105 | [auto traits]: ../special-types-and-traits.md#auto-traits 106 | [defaults]: ../lifetime-elision.md#default-trait-object-lifetimes 107 | [dyn compatible]: ../items/traits.md#dyn-compatibility 108 | [dynamically sized types]: ../dynamically-sized-types.md 109 | [supertraits]: ../items/traits.md#supertraits 110 | -------------------------------------------------------------------------------- /src/comments.md: -------------------------------------------------------------------------------- 1 | r[comments] 2 | # Comments 3 | 4 | r[comments.syntax] 5 | ```grammar,lexer 6 | @root LINE_COMMENT -> 7 | `//` (~[`/` `!` LF] | `//`) ~LF* 8 | | `//` 9 | 10 | BLOCK_COMMENT -> 11 | `/*` 12 | ( ~[`*` `!`] | `**` | BLOCK_COMMENT_OR_DOC ) 13 | ( BLOCK_COMMENT_OR_DOC | ~`*/` )* 14 | `*/` 15 | | `/**/` 16 | | `/***/` 17 | 18 | @root INNER_LINE_DOC -> 19 | `//!` ~[LF CR]* 20 | 21 | INNER_BLOCK_DOC -> 22 | `/*!` ( BLOCK_COMMENT_OR_DOC | ~[`*/` CR] )* `*/` 23 | 24 | @root OUTER_LINE_DOC -> 25 | `///` (~`/` ~[LF CR]*)? 26 | 27 | OUTER_BLOCK_DOC -> 28 | `/**` 29 | ( ~`*` | BLOCK_COMMENT_OR_DOC ) 30 | ( BLOCK_COMMENT_OR_DOC | ~[`*/` CR] )* 31 | `*/` 32 | 33 | @root BLOCK_COMMENT_OR_DOC -> 34 | BLOCK_COMMENT 35 | | OUTER_BLOCK_DOC 36 | | INNER_BLOCK_DOC 37 | ``` 38 | 39 | r[comments.normal] 40 | ## Non-doc comments 41 | 42 | Comments follow the general C++ style of line (`//`) and block (`/* ... */`) comment forms. Nested block comments are supported. 43 | 44 | r[comments.normal.tokenization] 45 | Non-doc comments are interpreted as a form of whitespace. 46 | 47 | r[comments.doc] 48 | ## Doc comments 49 | 50 | r[comments.doc.syntax] 51 | Line doc comments beginning with exactly _three_ slashes (`///`), and block doc comments (`/** ... */`), both outer doc comments, are interpreted as a special syntax for [`doc` attributes]. 52 | 53 | r[comments.doc.attributes] 54 | That is, they are equivalent to writing `#[doc="..."]` around the body of the comment, i.e., `/// Foo` turns into `#[doc="Foo"]` and `/** Bar */` turns into `#[doc="Bar"]`. They must therefore appear before something that accepts an outer attribute. 55 | 56 | r[comments.doc.inner-syntax] 57 | Line comments beginning with `//!` and block comments `/*! ... */` are doc comments that apply to the parent of the comment, rather than the item that follows. 58 | 59 | r[comments.doc.inner-attributes] 60 | That is, they are equivalent to writing `#![doc="..."]` around the body of the comment. `//!` comments are usually used to document modules that occupy a source file. 61 | 62 | r[comments.doc.bare-crs] 63 | The character `U+000D` (CR) is not allowed in doc comments. 64 | 65 | > [!NOTE] 66 | > It is conventional for doc comments to contain Markdown, as expected by `rustdoc`. However, the comment syntax does not respect any internal Markdown. ``/** `glob = "*/*.rs";` */`` terminates the comment at the first `*/`, and the remaining code would cause a syntax error. This slightly limits the content of block doc comments compared to line doc comments. 67 | 68 | > [!NOTE] 69 | > The sequence `U+000D` (CR) immediately followed by `U+000A` (LF) would have been previously transformed into a single `U+000A` (LF). 70 | 71 | ## Examples 72 | 73 | ```rust 74 | //! A doc comment that applies to the implicit anonymous module of this crate 75 | 76 | pub mod outer_module { 77 | 78 | //! - Inner line doc 79 | //!! - Still an inner line doc (but with a bang at the beginning) 80 | 81 | /*! - Inner block doc */ 82 | /*!! - Still an inner block doc (but with a bang at the beginning) */ 83 | 84 | // - Only a comment 85 | /// - Outer line doc (exactly 3 slashes) 86 | //// - Only a comment 87 | 88 | /* - Only a comment */ 89 | /** - Outer block doc (exactly) 2 asterisks */ 90 | /*** - Only a comment */ 91 | 92 | pub mod inner_module {} 93 | 94 | pub mod nested_comments { 95 | /* In Rust /* we can /* nest comments */ */ */ 96 | 97 | // All three types of block comments can contain or be nested inside 98 | // any other type: 99 | 100 | /* /* */ /** */ /*! */ */ 101 | /*! /* */ /** */ /*! */ */ 102 | /** /* */ /** */ /*! */ */ 103 | pub mod dummy_item {} 104 | } 105 | 106 | pub mod degenerate_cases { 107 | // empty inner line doc 108 | //! 109 | 110 | // empty inner block doc 111 | /*!*/ 112 | 113 | // empty line comment 114 | // 115 | 116 | // empty outer line doc 117 | /// 118 | 119 | // empty block comment 120 | /**/ 121 | 122 | pub mod dummy_item {} 123 | 124 | // empty 2-asterisk block isn't a doc block, it is a block comment 125 | /***/ 126 | 127 | } 128 | 129 | /* The next one isn't allowed because outer doc comments 130 | require an item that will receive the doc */ 131 | 132 | /// Where is my item? 133 | # mod boo {} 134 | } 135 | ``` 136 | 137 | [`doc` attributes]: ../rustdoc/the-doc-attribute.html 138 | -------------------------------------------------------------------------------- /src/keywords.md: -------------------------------------------------------------------------------- 1 | r[lex.keywords] 2 | # Keywords 3 | 4 | Rust divides keywords into three categories: 5 | 6 | * [strict](#strict-keywords) 7 | * [reserved](#reserved-keywords) 8 | * [weak](#weak-keywords) 9 | 10 | r[lex.keywords.strict] 11 | ## Strict keywords 12 | 13 | r[lex.keywords.strict.intro] 14 | These keywords can only be used in their correct contexts. They cannot be used as the names of: 15 | 16 | * [Items] 17 | * [Variables] and function parameters 18 | * Fields and [variants] 19 | * [Type parameters] 20 | * Lifetime parameters or [loop labels] 21 | * [Macros] or [attributes] 22 | * [Macro placeholders] 23 | * [Crates] 24 | 25 | r[lex.keywords.strict.list] 26 | The following keywords are in all editions: 27 | 28 | - `_` 29 | - `as` 30 | - `async` 31 | - `await` 32 | - `break` 33 | - `const` 34 | - `continue` 35 | - `crate` 36 | - `dyn` 37 | - `else` 38 | - `enum` 39 | - `extern` 40 | - `false` 41 | - `fn` 42 | - `for` 43 | - `if` 44 | - `impl` 45 | - `in` 46 | - `let` 47 | - `loop` 48 | - `match` 49 | - `mod` 50 | - `move` 51 | - `mut` 52 | - `pub` 53 | - `ref` 54 | - `return` 55 | - `self` 56 | - `Self` 57 | - `static` 58 | - `struct` 59 | - `super` 60 | - `trait` 61 | - `true` 62 | - `type` 63 | - `unsafe` 64 | - `use` 65 | - `where` 66 | - `while` 67 | 68 | r[lex.keywords.strict.edition2018] 69 | > [!EDITION-2018] 70 | > The following keywords were added in the 2018 edition: 71 | > 72 | > - `async` 73 | > - `await` 74 | > - `dyn` 75 | 76 | r[lex.keywords.reserved] 77 | ## Reserved keywords 78 | 79 | r[lex.keywords.reserved.intro] 80 | These keywords aren't used yet, but they are reserved for future use. They have the same restrictions as strict keywords. The reasoning behind this is to make current programs forward compatible with future versions of Rust by forbidding them to use these keywords. 81 | 82 | r[lex.keywords.reserved.list] 83 | - `abstract` 84 | - `become` 85 | - `box` 86 | - `do` 87 | - `final` 88 | - `gen` 89 | - `macro` 90 | - `override` 91 | - `priv` 92 | - `try` 93 | - `typeof` 94 | - `unsized` 95 | - `virtual` 96 | - `yield` 97 | 98 | r[lex.keywords.reserved.edition2018] 99 | > [!EDITION-2018] 100 | > The `try` keyword was added as a reserved keyword in the 2018 edition. 101 | 102 | r[lex.keywords.reserved.edition2024] 103 | > [!EDITION-2024] 104 | > The `gen` keyword was added as a reserved keyword in the 2024 edition. 105 | 106 | r[lex.keywords.weak] 107 | ## Weak keywords 108 | 109 | r[lex.keywords.weak.intro] 110 | These keywords have special meaning only in certain contexts. For example, it is possible to declare a variable or method with the name `union`. 111 | 112 | - `'static` 113 | - `macro_rules` 114 | - `raw` 115 | - `safe` 116 | - `union` 117 | 118 | r[lex.keywords.weak.macro_rules] 119 | * `macro_rules` is used to create custom [macros]. 120 | 121 | r[lex.keywords.weak.union] 122 | * `union` is used to declare a [union] and is only a keyword when used in a union declaration. 123 | 124 | r[lex.keywords.weak.lifetime-static] 125 | * `'static` is used for the static lifetime and cannot be used as a [generic lifetime parameter] or [loop label] 126 | 127 | ```compile_fail 128 | // error[E0262]: invalid lifetime parameter name: `'static` 129 | fn invalid_lifetime_parameter<'static>(s: &'static str) -> &'static str { s } 130 | ``` 131 | 132 | r[lex.keywords.weak.safe] 133 | * `safe` is used for functions and statics, which has meaning in [external blocks]. 134 | 135 | r[lex.keywords.weak.raw] 136 | * `raw` is used for [raw borrow operators], and is only a keyword when matching a raw borrow operator form (such as `&raw const expr` or `&raw mut expr`). 137 | 138 | r[lex.keywords.weak.dyn.edition2018] 139 | > [!EDITION-2018] 140 | > In the 2015 edition, [`dyn`] is a keyword when used in a type position followed by a path that does not start with `::` or `<`, a lifetime, a question mark, a `for` keyword or an opening parenthesis. 141 | > 142 | > Beginning in the 2018 edition, `dyn` has been promoted to a strict keyword. 143 | 144 | [items]: items.md 145 | [Variables]: variables.md 146 | [Type parameters]: types/parameters.md 147 | [loop labels]: expressions/loop-expr.md#loop-labels 148 | [Macros]: macros.md 149 | [attributes]: attributes.md 150 | [Macro placeholders]: macros-by-example.md 151 | [Crates]: crates-and-source-files.md 152 | [union]: items/unions.md 153 | [variants]: items/enumerations.md 154 | [`dyn`]: types/trait-object.md 155 | [loop label]: expressions/loop-expr.md#loop-labels 156 | [generic lifetime parameter]: items/generics.md 157 | [external blocks]: items/external-blocks.md 158 | [raw borrow operators]: expressions/operator-expr.md#raw-borrow-operators 159 | -------------------------------------------------------------------------------- /docs/review-policy.md: -------------------------------------------------------------------------------- 1 | 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: 2 | 3 | ## Review principles 4 | 5 | Reviewers and authors should focus on a few key principles during the review process: 6 | 7 | * **Understandability**: Language within the Reference should be understandable to most members of the Project. Contributions should assumes that readers are familiar with the rest of the content of the Reference, but, wherever possible, sections should facilitate that understanding by linking to related content. 8 | * **Defensibility**: When the lang-docs team merges a change to the Reference, they are agreeing to take responsibility for it going forward. Team members need to feel confident defending and explaining the correctness of content within the Reference. Whenever possible, changes to the Reference should back up any claims with concise examples to verify correctness. 9 | * **Voice**: Authors are not expected to have competence as a specification writer when drafting new contributions to the Reference. So long as claims are understandable and defensible, it is fine for PRs to be written in a casual tone or with the voice of the author instead of the voice of the Reference. Team members will bring editorial experience as part of their reviews and will revise the phrasing, organization, style, etc. to fit the Reference before merging if necessary. 10 | 11 | ## Policy changes 12 | 13 | - 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. 14 | - 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. 15 | 16 | ## Meaningful content addition or changes 17 | 18 | - 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. 19 | - Content should always follow the guidelines from the [authoring guide]. 20 | 21 | ## Minor content changes 22 | - Minor content changes, such as small cleanups or wording fixes, can be made with the review from a team member without further consultation. 23 | 24 | ## Tooling changes 25 | - 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. 26 | - 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. 27 | 28 | ## Review process flowchart 29 | 30 | When reviewing a pull request, ask yourself the following questions: 31 | 32 | ### Are the proposed changes true? 33 | 34 | If we're not sure and can't easily verify it ourselves, we ask someone who would know. 35 | 36 | ### Does this make any new guarantees about the language? 37 | 38 | 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. 39 | 40 | ### Would we have added this to the Reference ourselves? 41 | 42 | 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. 43 | 44 | ### Is this editorially sound? 45 | 46 | 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. 47 | 48 | ### Is this well written? 49 | 50 | 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. 51 | 52 | 53 | This policy does not yet cover the process for getting final approval from the relevant teams. 54 | 55 | [authoring guide]: authoring.md 56 | -------------------------------------------------------------------------------- /style-check/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::error::Error; 3 | use std::fs; 4 | use std::path::Path; 5 | 6 | macro_rules! style_error { 7 | ($bad:expr, $path:expr, $($arg:tt)*) => { 8 | *$bad = true; 9 | eprint!("error in {}: ", $path.display()); 10 | eprintln!("{}", format_args!($($arg)*)); 11 | }; 12 | } 13 | 14 | fn main() { 15 | let arg = env::args().nth(1).unwrap_or_else(|| { 16 | eprintln!("Please pass a src directory as the first argument"); 17 | std::process::exit(1); 18 | }); 19 | 20 | let mut bad = false; 21 | if let Err(e) = check_directory(&Path::new(&arg), &mut bad) { 22 | eprintln!("error: {}", e); 23 | std::process::exit(1); 24 | } 25 | if bad { 26 | eprintln!("some style checks failed"); 27 | std::process::exit(1); 28 | } 29 | eprintln!("passed!"); 30 | } 31 | 32 | fn check_directory(dir: &Path, bad: &mut bool) -> Result<(), Box> { 33 | for entry in fs::read_dir(dir)? { 34 | let entry = entry?; 35 | let path = entry.path(); 36 | 37 | if path.is_dir() { 38 | check_directory(&path, bad)?; 39 | continue; 40 | } 41 | 42 | if !matches!( 43 | path.extension().and_then(|p| p.to_str()), 44 | Some("md") | Some("html") 45 | ) { 46 | // This may be extended in the future if other file types are needed. 47 | style_error!(bad, path, "expected only md or html in src"); 48 | } 49 | 50 | let contents = fs::read_to_string(&path)?; 51 | if contents.contains("#![feature") { 52 | style_error!(bad, path, "#![feature] attributes are not allowed"); 53 | } 54 | if !cfg!(windows) && contents.contains('\r') { 55 | style_error!( 56 | bad, 57 | path, 58 | "CR characters not allowed, must use LF line endings" 59 | ); 60 | } 61 | if contents.contains('\t') { 62 | style_error!(bad, path, "tab characters not allowed, use spaces"); 63 | } 64 | if !contents.ends_with('\n') { 65 | style_error!(bad, path, "file must end with a newline"); 66 | } 67 | if contents.contains('\u{2013}') { 68 | style_error!(bad, path, "en-dash not allowed, use two dashes like --"); 69 | } 70 | if contents.contains('\u{2014}') { 71 | style_error!(bad, path, "em-dash not allowed, use three dashes like ---"); 72 | } 73 | if contents.contains('\u{a0}') { 74 | style_error!( 75 | bad, 76 | path, 77 | "don't use 0xa0 no-break-space, use   instead" 78 | ); 79 | } 80 | for line in contents.lines() { 81 | if line.ends_with(' ') { 82 | style_error!(bad, path, "lines must not end with spaces"); 83 | } 84 | } 85 | cmark_check(&path, bad, &contents)?; 86 | } 87 | Ok(()) 88 | } 89 | 90 | fn cmark_check(path: &Path, bad: &mut bool, contents: &str) -> Result<(), Box> { 91 | use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag}; 92 | 93 | macro_rules! cmark_error { 94 | ($bad:expr, $path:expr, $range:expr, $($arg:tt)*) => { 95 | *$bad = true; 96 | let lineno = contents[..$range.start].chars().filter(|&ch| ch == '\n').count() + 1; 97 | eprint!("error in {} (line {}): ", $path.display(), lineno); 98 | eprintln!("{}", format_args!($($arg)*)); 99 | } 100 | } 101 | 102 | let options = Options::all(); 103 | let parser = Parser::new_ext(contents, options); 104 | 105 | for (event, range) in parser.into_offset_iter() { 106 | match event { 107 | Event::Start(Tag::CodeBlock(CodeBlockKind::Indented)) => { 108 | cmark_error!( 109 | bad, 110 | path, 111 | range, 112 | "indented code blocks should use triple backtick-style \ 113 | with a language identifier" 114 | ); 115 | } 116 | Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(languages))) => { 117 | if languages.is_empty() { 118 | cmark_error!( 119 | bad, 120 | path, 121 | range, 122 | "code block should include an explicit language", 123 | ); 124 | } 125 | } 126 | _ => {} 127 | } 128 | } 129 | Ok(()) 130 | } 131 | -------------------------------------------------------------------------------- /src/items/extern-crates.md: -------------------------------------------------------------------------------- 1 | r[items.extern-crate] 2 | # Extern crate declarations 3 | 4 | r[items.extern-crate.syntax] 5 | ```grammar,items 6 | ExternCrate -> `extern` `crate` CrateRef AsClause? `;` 7 | 8 | CrateRef -> IDENTIFIER | `self` 9 | 10 | AsClause -> `as` ( IDENTIFIER | `_` ) 11 | ``` 12 | 13 | r[items.extern-crate.intro] 14 | An _`extern crate` declaration_ specifies a dependency on an external crate. 15 | 16 | r[items.extern-crate.namespace] 17 | The external crate is then bound into the declaring scope as the given [identifier] in the [type namespace]. 18 | 19 | r[items.extern-crate.extern-prelude] 20 | Additionally, if the `extern crate` appears in the crate root, then the crate name is also added to the [extern prelude], making it automatically in scope in all modules. 21 | 22 | r[items.extern-crate.as] 23 | The `as` clause can be used to bind the imported crate to a different name. 24 | 25 | r[items.extern-crate.lookup] 26 | The external crate is resolved to a specific `soname` at compile time, and a 27 | runtime linkage requirement to that `soname` is passed to the linker for 28 | loading at runtime. The `soname` is resolved at compile time by scanning the 29 | compiler's library path and matching the optional `crate_name` provided against 30 | the [`crate_name` attributes] that were declared on the external crate when it was 31 | compiled. If no `crate_name` is provided, a default `name` attribute is assumed, 32 | equal to the [identifier] given in the `extern crate` declaration. 33 | 34 | r[items.extern-crate.self] 35 | The `self` crate may be imported which creates a binding to the current crate. 36 | In this case the `as` clause must be used to specify the name to bind it to. 37 | 38 | Three examples of `extern crate` declarations: 39 | 40 | 41 | ```rust,ignore 42 | extern crate pcre; 43 | 44 | extern crate std; // equivalent to: extern crate std as std; 45 | 46 | extern crate std as ruststd; // linking to 'std' under another name 47 | ``` 48 | 49 | r[items.extern-crate.name-restrictions] 50 | When naming Rust crates, hyphens are disallowed. However, Cargo packages may 51 | make use of them. In such case, when `Cargo.toml` doesn't specify a crate name, 52 | Cargo will transparently replace `-` with `_` (Refer to [RFC 940] for more 53 | details). 54 | 55 | Here is an example: 56 | 57 | 58 | ```rust,ignore 59 | // Importing the Cargo package hello-world 60 | extern crate hello_world; // hyphen replaced with an underscore 61 | ``` 62 | 63 | r[items.extern-crate.underscore] 64 | ## Underscore imports 65 | 66 | r[items.extern-crate.underscore.intro] 67 | An external crate dependency can be declared without binding its name in scope 68 | by using an underscore with the form `extern crate foo as _`. This may be 69 | useful for crates that only need to be linked, but are never referenced, and 70 | will avoid being reported as unused. 71 | 72 | r[items.extern-crate.underscore.macro_use] 73 | The [`macro_use` attribute] works as usual and imports the macro names 74 | into the [`macro_use` prelude]. 75 | 76 | 77 | r[items.extern-crate.no_link] 78 | ## The `no_link` attribute 79 | 80 | r[items.extern-crate.no_link.intro] 81 | The *`no_link` [attribute][attributes]* may be applied to an `extern crate` item to prevent linking the crate. 82 | 83 | > [!NOTE] 84 | > This is helpful, e.g., when only the macros of a crate are needed. 85 | 86 | > [!EXAMPLE] 87 | > 88 | > ```rust,ignore 89 | > #[no_link] 90 | > extern crate other_crate; 91 | > 92 | > other_crate::some_macro!(); 93 | > ``` 94 | 95 | r[items.extern-crate.no_link.syntax] 96 | The `no_link` attribute uses the [MetaWord] syntax. 97 | 98 | r[items.extern-crate.no_link.allowed-positions] 99 | The `no_link` attribute may only be applied to an `extern crate` declaration. 100 | 101 | > [!NOTE] 102 | > `rustc` ignores use in other positions but lints against it. This may become an error in the future. 103 | 104 | r[items.extern-crate.no_link.duplicates] 105 | Only the first use of `no_link` on an `extern crate` declaration has effect. 106 | 107 | > [!NOTE] 108 | > `rustc` lints against any use following the first. This may become an error in the future. 109 | 110 | [identifier]: ../identifiers.md 111 | [RFC 940]: https://github.com/rust-lang/rfcs/blob/master/text/0940-hyphens-considered-harmful.md 112 | [`macro_use` attribute]: ../macros-by-example.md#the-macro_use-attribute 113 | [extern prelude]: ../names/preludes.md#extern-prelude 114 | [`macro_use` prelude]: ../names/preludes.md#macro_use-prelude 115 | [`crate_name` attributes]: ../crates-and-source-files.md#the-crate_name-attribute 116 | [type namespace]: ../names/namespaces.md 117 | -------------------------------------------------------------------------------- /src/abi.md: -------------------------------------------------------------------------------- 1 | r[abi] 2 | # Application binary interface (ABI) 3 | 4 | r[abi.intro] 5 | This section documents features that affect the ABI of the compiled output of 6 | a crate. 7 | 8 | See *[extern functions]* for information on specifying the ABI for exporting 9 | functions. See *[external blocks]* for information on specifying the ABI for 10 | linking external libraries. 11 | 12 | r[abi.used] 13 | ## The `used` attribute 14 | 15 | r[abi.used.intro] 16 | The *`used` attribute* can only be applied to [`static` items]. This [attribute] forces the 17 | compiler to keep the variable in the output object file (.o, .rlib, etc. excluding final binaries) 18 | even if the variable is not used, or referenced, by any other item in the crate. 19 | However, the linker is still free to remove such an item. 20 | 21 | Below is an example that shows under what conditions the compiler keeps a `static` item in the 22 | output object file. 23 | 24 | ``` rust 25 | // foo.rs 26 | 27 | // This is kept because of `#[used]`: 28 | #[used] 29 | static FOO: u32 = 0; 30 | 31 | // This is removable because it is unused: 32 | #[allow(dead_code)] 33 | static BAR: u32 = 0; 34 | 35 | // This is kept because it is publicly reachable: 36 | pub static BAZ: u32 = 0; 37 | 38 | // This is kept because it is referenced by a public, reachable function: 39 | static QUUX: u32 = 0; 40 | 41 | pub fn quux() -> &'static u32 { 42 | &QUUX 43 | } 44 | 45 | // This is removable because it is referenced by a private, unused (dead) function: 46 | static CORGE: u32 = 0; 47 | 48 | #[allow(dead_code)] 49 | fn corge() -> &'static u32 { 50 | &CORGE 51 | } 52 | ``` 53 | 54 | ``` console 55 | $ rustc -O --emit=obj --crate-type=rlib foo.rs 56 | 57 | $ nm -C foo.o 58 | 0000000000000000 R foo::BAZ 59 | 0000000000000000 r foo::FOO 60 | 0000000000000000 R foo::QUUX 61 | 0000000000000000 T foo::quux 62 | ``` 63 | 64 | r[abi.no_mangle] 65 | ## The `no_mangle` attribute 66 | 67 | r[abi.no_mangle.intro] 68 | The *`no_mangle` attribute* may be used on any [item] to disable standard 69 | symbol name mangling. The symbol for the item will be the identifier of the 70 | item's name. 71 | 72 | r[abi.no_mangle.publicly-exported] 73 | Additionally, the item will be publicly exported from the produced library or 74 | object file, similar to the [`used` attribute](#the-used-attribute). 75 | 76 | r[abi.no_mangle.unsafe] 77 | This attribute is unsafe as an unmangled symbol may collide with another symbol 78 | with the same name (or with a well-known symbol), leading to undefined behavior. 79 | 80 | ```rust 81 | #[unsafe(no_mangle)] 82 | extern "C" fn foo() {} 83 | ``` 84 | 85 | r[abi.no_mangle.edition2024] 86 | > [!EDITION-2024] 87 | > Before the 2024 edition it is allowed to use the `no_mangle` attribute without the `unsafe` qualification. 88 | 89 | r[abi.link_section] 90 | ## The `link_section` attribute 91 | 92 | r[abi.link_section.intro] 93 | The *`link_section` attribute* specifies the section of the object file that a 94 | [function] or [static]'s content will be placed into. 95 | 96 | r[abi.link_section.syntax] 97 | The `link_section` attribute uses the [MetaNameValueStr] syntax to specify the section name. 98 | 99 | 100 | ```rust,no_run 101 | #[unsafe(no_mangle)] 102 | #[unsafe(link_section = ".example_section")] 103 | pub static VAR1: u32 = 1; 104 | ``` 105 | 106 | r[abi.link_section.unsafe] 107 | This attribute is unsafe as it allows users to place data and code into sections 108 | of memory not expecting them, such as mutable data into read-only areas. 109 | 110 | r[abi.link_section.edition2024] 111 | > [!EDITION-2024] 112 | > Before the 2024 edition it is allowed to use the `link_section` attribute without the `unsafe` qualification. 113 | 114 | r[abi.export_name] 115 | ## The `export_name` attribute 116 | 117 | r[abi.export_name.intro] 118 | The *`export_name` attribute* specifies the name of the symbol that will be 119 | exported on a [function] or [static]. 120 | 121 | r[abi.export_name.syntax] 122 | The `export_name `attribute uses the [MetaNameValueStr] syntax to specify the symbol name. 123 | 124 | ```rust 125 | #[unsafe(export_name = "exported_symbol_name")] 126 | pub fn name_in_rust() { } 127 | ``` 128 | 129 | r[abi.export_name.unsafe] 130 | This attribute is unsafe as a symbol with a custom name may collide with another 131 | symbol with the same name (or with a well-known symbol), leading to undefined 132 | behavior. 133 | 134 | r[abi.export_name.edition2024] 135 | > [!EDITION-2024] 136 | > Before the 2024 edition it is allowed to use the `export_name` attribute without the `unsafe` qualification. 137 | 138 | [`static` items]: items/static-items.md 139 | [attribute]: attributes.md 140 | [extern functions]: items/functions.md#extern-function-qualifier 141 | [external blocks]: items/external-blocks.md 142 | [function]: items/functions.md 143 | [item]: items.md 144 | [static]: items/static-items.md 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Rust Language Reference 2 | 3 | This document is the primary reference for the Rust programming language. 4 | 5 | ## Contributor docs 6 | 7 | There are several pages for those working on the reference: 8 | 9 | * [Authoring guide](https://github.com/rust-lang/reference/blob/master/docs/authoring.md): Guidelines for writing content. 10 | * [Review policy](https://github.com/rust-lang/reference/blob/master/docs/review-policy.md): Guidelines for reviewers. 11 | * [Grammar](https://github.com/rust-lang/reference/blob/master/docs/grammar.md): How the grammar syntax works. 12 | * [Attribute template](https://github.com/rust-lang/reference/blob/master/docs/attribute-template.md): The standard template for documenting an attribute. 13 | 14 | ## Building 15 | 16 | To build the Reference, first clone the project: 17 | 18 | ```sh 19 | git clone https://github.com/rust-lang/reference.git 20 | cd reference 21 | ``` 22 | 23 | (Alternatively, if you don't want to use `git`, [download][] a ZIP file 24 | of the project, extract it using your preferred tool, and rename the 25 | top-level directory to `reference`.) 26 | 27 | [download]: https://github.com/rust-lang/reference/archive/refs/heads/master.zip 28 | 29 | ### Installing mdbook 30 | 31 | The Reference is built using [mdbook]. 32 | 33 | First, ensure that you have a recent copy of the nightly Rust compiler installed, as this is needed in order to run the tests: 34 | 35 | ```sh 36 | rustup toolchain install nightly 37 | rustup override set nightly 38 | ``` 39 | 40 | Now, ensure you have `mdbook` installed, as this is needed in order to build the Reference: 41 | 42 | ```sh 43 | cargo install --locked mdbook 44 | ``` 45 | 46 | [mdbook]: https://rust-lang.github.io/mdBook/ 47 | 48 | ### Running mdbook 49 | 50 | `mdbook` provides a variety of different commands and options to help you work on the book: 51 | 52 | * `mdbook build --open`: Build the book and open it in a web browser. 53 | * `mdbook serve --open`: Launches a web server on localhost. It also automatically rebuilds the book whenever any file changes and automatically reloads your web browser. 54 | 55 | The book contents are driven by a `SUMMARY.md` file, and every file must be linked there. See for its usage. 56 | 57 | ### `SPEC_RELATIVE` 58 | 59 | The `SPEC_RELATIVE=0` environment variable makes links to the standard library go to instead of being relative, which is useful when viewing locally since you normally don't have a copy of the standard library. 60 | 61 | ```sh 62 | SPEC_RELATIVE=0 mdbook serve --open 63 | ``` 64 | 65 | The published site at (or local docs using `rustup doc`) does not set this, which means it will use relative links which supports offline viewing and links to the correct version (for example, links in will stay within the 1.81.0 directory). 66 | 67 | ### `SPEC_DENY_WARNINGS` 68 | 69 | The `SPEC_DENY_WARNINGS=1` environment variable will turn all warnings generated by `mdbook-spec` to errors. This is used in CI to ensure that there aren't any problems with the book content. 70 | 71 | ### `SPEC_RUST_ROOT` 72 | 73 | The `SPEC_RUST_ROOT` can be used to point to the directory of a checkout of . This is used by the test-linking feature so that it can find tests linked to reference rules. If this is not set, then the tests won't be linked. 74 | 75 | ## Running tests 76 | 77 | There are several different kinds of tests you can run (these are enforced on CI): 78 | 79 | * `mdbook test`: This will run the inline Rust codeblocks (internally it uses `rustdoc` to do this). 80 | * `cargo xtask style-check`: This will validate some style checks (see [authoring guide](docs/authoring.md)). 81 | * `cargo xtask linkcheck`: This will validate that markdown links aren't broken. 82 | * `cargo xtask test-all`: Runs all tests. 83 | 84 | ## How is this published? 85 | 86 | The process for getting the reference content into a [Rust release](https://doc.rust-lang.org/reference/#rust-releases) and on the website is: 87 | 88 | 1. Changes are merged to this repository. 89 | 2. [Triagebot](https://forge.rust-lang.org/triagebot/doc-updates.html) will automatically synchronize this repository to [rust-lang/rust]. This happens every other week. The reference is tracked in [rust-lang/rust] as a [submodule](https://github.com/rust-lang/rust/tree/master/src/doc). 90 | - This will open a PR on [rust-lang/rust] which needs to be merged, and that can take up to several days. 91 | 3. At midnight UTC, whatever is on the default branch of [rust-lang/rust] will be a part of that nightly release, and will be published after a few hours to . 92 | 4. Following Rust's [release process](https://doc.rust-lang.org/book/appendix-07-nightly-rust.html), every 6 weeks, nightly will be promoted to beta (), and then 6 weeks after that it will be promoted to stable (). 93 | 94 | [rust-lang/rust]: https://github.com/rust-lang/rust/ 95 | -------------------------------------------------------------------------------- /mdbook-spec/src/admonitions.rs: -------------------------------------------------------------------------------- 1 | //! Support for admonitions using markdown blockquotes. 2 | //! 3 | //! To add support for a new admonition: 4 | //! 5 | //! 1. Modify the [`admonitions`] function below to include an icon. 6 | //! 2. Modify `theme/reference.css` to set the color for the different themes. 7 | //! Look at one of the other admonitions as a guide. 8 | //! 3. Update `src/introduction.md` and describe what this new block is for 9 | //! with an example. 10 | //! 4. Update `docs/authoring.md` to show an example of your new admonition. 11 | 12 | use crate::{Diagnostics, warn_or_err}; 13 | use mdbook_preprocessor::book::Chapter; 14 | use regex::{Captures, Regex}; 15 | use std::sync::LazyLock; 16 | 17 | /// The Regex for the syntax for blockquotes that have a specific CSS class, 18 | /// like `> [!WARNING]`. 19 | static ADMONITION_RE: LazyLock = LazyLock::new(|| { 20 | Regex::new(r"(?m)^ *> \[!(?[^]]+)\]\n(?

(?: *>.*\n)+)").unwrap() 21 | }); 22 | 23 | // This icon is from GitHub, MIT License, see https://github.com/primer/octicons 24 | const ICON_NOTE: &str = r#""#; 25 | 26 | // This icon is from GitHub, MIT License, see https://github.com/primer/octicons 27 | const ICON_WARNING: &str = r#""#; 28 | 29 | // This icon is from GitHub, MIT License, see https://github.com/primer/octicons 30 | const ICON_EXAMPLE: &str = r#""#; 31 | 32 | /// Converts blockquotes with special headers into admonitions. 33 | /// 34 | /// The blockquote should look something like: 35 | /// 36 | /// ```markdown 37 | /// > [!WARNING] 38 | /// > ... 39 | /// ``` 40 | /// 41 | /// This will add a `
` around the 42 | /// blockquote so that it can be styled differently, and injects an icon. 43 | /// The actual styling needs to be added in the `reference.css` CSS file. 44 | pub fn admonitions(chapter: &Chapter, diag: &mut Diagnostics) -> String { 45 | ADMONITION_RE 46 | .replace_all(&chapter.content, |caps: &Captures<'_>| { 47 | let lower = caps["admon"].to_lowercase(); 48 | let term = to_initial_case(&caps["admon"]); 49 | let blockquote = &caps["blockquote"]; 50 | let initial_spaces = blockquote.chars().position(|ch| ch != ' ').unwrap_or(0); 51 | let space = &blockquote[..initial_spaces]; 52 | 53 | let format_div = |class, content| { 54 | format!( 55 | "{space}
\n\ 56 | \n\ 57 | {space}>

\ 58 | {content}

\n\ 59 | {space} >\n\ 60 | {blockquote}\n\ 61 | \n\ 62 | {space}
\n", 63 | ) 64 | }; 65 | 66 | if lower.starts_with("edition-") { 67 | let edition = &lower[8..]; 68 | return format_div( 69 | "edition", 70 | format!( 71 | "{edition} Edition differences" 72 | ), 73 | ); 74 | } 75 | 76 | let svg = match lower.as_str() { 77 | "note" => ICON_NOTE, 78 | "warning" => ICON_WARNING, 79 | "example" => ICON_EXAMPLE, 80 | _ => { 81 | warn_or_err!( 82 | diag, 83 | "admonition `{lower}` in {:?} is incorrect or not yet supported", 84 | chapter.path.as_ref().unwrap() 85 | ); 86 | "" 87 | } 88 | }; 89 | format_div( 90 | &lower, 91 | format!( 92 | "\ 93 | {svg}\ 94 | {term}" 95 | ), 96 | ) 97 | }) 98 | .to_string() 99 | } 100 | 101 | fn to_initial_case(s: &str) -> String { 102 | let mut chars = s.chars(); 103 | let first = chars.next().expect("not empty").to_uppercase(); 104 | let rest = chars.as_str().to_lowercase(); 105 | format!("{first}{rest}") 106 | } 107 | -------------------------------------------------------------------------------- /mdbook-spec/src/rules.rs: -------------------------------------------------------------------------------- 1 | //! Handling for rule identifiers. 2 | 3 | use crate::test_links::RuleToTests; 4 | use crate::{Diagnostics, Spec, warn_or_err}; 5 | use mdbook_preprocessor::book::{Book, BookItem}; 6 | use once_cell::sync::Lazy; 7 | use regex::{Captures, Regex}; 8 | use std::collections::{BTreeMap, HashSet}; 9 | use std::fmt::Write; 10 | use std::path::PathBuf; 11 | 12 | /// The Regex for rules like `r[foo]`. 13 | static RULE_RE: Lazy = Lazy::new(|| Regex::new(r"(?m)^r\[([^]]+)]$").unwrap()); 14 | 15 | /// The set of rules defined in the reference. 16 | #[derive(Default)] 17 | pub struct Rules { 18 | /// A mapping from a rule identifier to a tuple of `(source_path, path)`. 19 | /// 20 | /// `source_path` is the path to the markdown source file relative to the 21 | /// `SUMMARY.md`. 22 | /// 23 | /// `path` is the same as `source_path`, except filenames like `README.md` 24 | /// are translated to `index.md`. Which to use depends on if you are 25 | /// trying to access the source files (`source_path`), or creating links 26 | /// in the output (`path`). 27 | pub def_paths: BTreeMap, 28 | /// Set of rule name prefixes that have more specific rules within. 29 | /// 30 | /// For example, `asm.ts-args` is an interior prefix of `asm.ts-args.syntax`. 31 | pub interior_prefixes: HashSet, 32 | } 33 | 34 | impl Spec { 35 | /// Collects all rule definitions in the book. 36 | pub fn collect_rules(&self, book: &Book, diag: &mut Diagnostics) -> Rules { 37 | let mut rules = Rules::default(); 38 | for item in book.iter() { 39 | let BookItem::Chapter(ch) = item else { 40 | continue; 41 | }; 42 | if ch.is_draft_chapter() { 43 | continue; 44 | } 45 | RULE_RE 46 | .captures_iter(&ch.content) 47 | .for_each(|caps: Captures<'_>| { 48 | let rule_id = &caps[1]; 49 | let source_path = ch.source_path.clone().unwrap_or_default(); 50 | let path = ch.path.clone().unwrap_or_default(); 51 | if let Some((old, _)) = rules 52 | .def_paths 53 | .insert(rule_id.to_string(), (source_path.clone(), path.clone())) 54 | { 55 | warn_or_err!( 56 | diag, 57 | "rule `{rule_id}` defined multiple times\n\ 58 | First location: {old:?}\n\ 59 | Second location: {source_path:?}" 60 | ); 61 | } 62 | let mut parts: Vec<_> = rule_id.split('.').collect(); 63 | while !parts.is_empty() { 64 | parts.pop(); 65 | let prefix = parts.join("."); 66 | rules.interior_prefixes.insert(prefix); 67 | } 68 | }); 69 | } 70 | 71 | rules 72 | } 73 | 74 | /// Converts lines that start with `r[…]` into a "rule" which has special 75 | /// styling and can be linked to. 76 | pub fn render_rule_definitions( 77 | &self, 78 | content: &str, 79 | tests: &RuleToTests, 80 | git_ref: &str, 81 | ) -> String { 82 | RULE_RE 83 | .replace_all(content, |caps: &Captures<'_>| { 84 | let rule_id = &caps[1]; 85 | let mut test_link = String::new(); 86 | let mut test_popup = String::new(); 87 | if let Some(tests) = tests.get(rule_id) { 88 | test_link = format!( 89 | "
\n"); 92 | test_popup = format!( 93 | "
\n\ 94 | Tests with this rule:\n\ 95 |
    "); 96 | for test in tests { 97 | writeln!( 98 | test_popup, 99 | "
  • {test_path}
  • ", 100 | test_path = test.path, 101 | ) 102 | .unwrap(); 103 | } 104 | 105 | test_popup.push_str("
"); 106 | } 107 | format!( 108 | "
\ 109 | [{rule_id_broken}]\n\ 110 | {test_link}\ 111 |
\n\ 112 | {test_popup}\n", 113 | rule_id_broken = rule_id.replace(".", "."), 114 | ) 115 | }) 116 | .to_string() 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/expressions/closure-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.closure] 2 | # Closure expressions 3 | 4 | r[expr.closure.syntax] 5 | ```grammar,expressions 6 | ClosureExpression -> 7 | `async`?[^cl-async-edition] 8 | `move`? 9 | ( `||` | `|` ClosureParameters? `|` ) 10 | (Expression | `->` TypeNoBounds BlockExpression) 11 | 12 | ClosureParameters -> ClosureParam (`,` ClosureParam)* `,`? 13 | 14 | ClosureParam -> OuterAttribute* PatternNoTopAlt ( `:` Type )? 15 | ``` 16 | 17 | [^cl-async-edition]: The `async` qualifier is not allowed in the 2015 edition. 18 | 19 | r[expr.closure.intro] 20 | A *closure expression*, also known as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type. 21 | The syntax for a closure expression is an optional `async` keyword, an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], called the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, called the *return type*, and then an expression, called the *closure body operand*. 22 | 23 | r[expr.closure.param-type] 24 | The optional type after each pattern is a type annotation for the pattern. 25 | 26 | r[expr.closure.explicit-type-body] 27 | If there is a return type, the closure body must be a [block]. 28 | 29 | r[expr.closure.parameter-restriction] 30 | A closure expression denotes a function that maps a list of parameters onto the expression that follows the parameters. 31 | Just like a [`let` binding], the closure parameters are irrefutable [patterns], whose type annotation is optional and will be inferred from context if not given. 32 | 33 | r[expr.closure.unique-type] 34 | Each closure expression has a unique, anonymous type. 35 | 36 | r[expr.closure.captures] 37 | Significantly, closure expressions _capture their environment_, which regular [function definitions] do not. 38 | 39 | r[expr.closure.capture-inference] 40 | Without the `move` keyword, the closure expression [infers how it captures each variable from its environment](../types/closure.md#capture-modes), preferring to capture by shared reference, effectively borrowing all outer variables mentioned inside the closure's body. 41 | 42 | r[expr.closure.capture-mut-ref] 43 | If needed the compiler will infer that instead mutable references should be taken, or that the values should be moved or copied (depending on their type) from the environment. 44 | 45 | r[expr.closure.capture-move] 46 | A closure can be forced to capture its environment by copying or moving values by prefixing it with the `move` keyword. 47 | This is often used to ensure that the closure's lifetime is `'static`. 48 | 49 | r[expr.closure.trait-impl] 50 | ## Closure trait implementations 51 | 52 | Which traits the closure type implement depends on how variables are captured, the types of the captured variables, and the presence of `async`. 53 | See the [call traits and coercions] chapter for how and when a closure implements `Fn`, `FnMut`, and `FnOnce`. 54 | The closure type implements [`Send`] and [`Sync`] if the type of every captured variable also implements the trait. 55 | 56 | r[expr.closure.async] 57 | ## Async closures 58 | 59 | r[expr.closure.async.intro] 60 | Closures marked with the `async` keyword indicate that they are asynchronous in an analogous way to an [async function][items.fn.async]. 61 | 62 | r[expr.closure.async.future] 63 | Calling the async closure does not perform any work, but instead evaluates to a value that implements [`Future`] that corresponds to the computation of the body of the closure. 64 | 65 | ```rust 66 | async fn takes_async_callback(f: impl AsyncFn(u64)) { 67 | f(0).await; 68 | f(1).await; 69 | } 70 | 71 | async fn example() { 72 | takes_async_callback(async |i| { 73 | core::future::ready(i).await; 74 | println!("done with {i}."); 75 | }).await; 76 | } 77 | ``` 78 | 79 | r[expr.closure.async.edition2018] 80 | > [!EDITION-2018] 81 | > Async closures are only available beginning with Rust 2018. 82 | 83 | ## Example 84 | 85 | In this example, we define a function `ten_times` that takes a higher-order function argument, and we then call it with a closure expression as an argument, followed by a closure expression that moves values from its environment. 86 | 87 | ```rust 88 | fn ten_times(f: F) where F: Fn(i32) { 89 | for index in 0..10 { 90 | f(index); 91 | } 92 | } 93 | 94 | ten_times(|j| println!("hello, {}", j)); 95 | // With type annotations 96 | ten_times(|j: i32| -> () { println!("hello, {}", j) }); 97 | 98 | let word = "konnichiwa".to_owned(); 99 | ten_times(move |j| println!("{}, {}", word, j)); 100 | ``` 101 | 102 | ## Attributes on closure parameters 103 | 104 | r[expr.closure.param-attributes] 105 | Attributes on closure parameters follow the same rules and restrictions as [regular function parameters]. 106 | 107 | [`let` binding]: ../statements.md#let-statements 108 | [`Send`]: ../special-types-and-traits.md#send 109 | [`Sync`]: ../special-types-and-traits.md#sync 110 | [block]: block-expr.md 111 | [call traits and coercions]: ../types/closure.md#call-traits-and-coercions 112 | [closure type]: ../types/closure.md 113 | [function definitions]: ../items/functions.md 114 | [patterns]: ../patterns.md 115 | [regular function parameters]: ../items/functions.md#attributes-on-function-parameters 116 | -------------------------------------------------------------------------------- /src/types/boolean.md: -------------------------------------------------------------------------------- 1 | r[type.bool] 2 | # Boolean type 3 | 4 | ```rust 5 | let b: bool = true; 6 | ``` 7 | 8 | r[type.bool.intro] 9 | The *boolean type* or *bool* is a primitive data type that can take on one of 10 | two values, called *true* and *false*. 11 | 12 | r[type.bool.literal] 13 | Values of this type may be created using a [literal expression] using the 14 | keywords `true` and `false` corresponding to the value of the same name. 15 | 16 | r[type.bool.namespace] 17 | This type is a part of the [language prelude] with the [name] `bool`. 18 | 19 | r[type.bool.layout] 20 | An object with the boolean type has a [size and alignment] of 1 each. 21 | 22 | r[type.bool.repr] 23 | The value false has the bit pattern `0x00` and the value true has the bit pattern 24 | `0x01`. It is [undefined behavior] for an object with the boolean type to have 25 | any other bit pattern. 26 | 27 | r[type.bool.usage] 28 | The boolean type is the type of many operands in various [expressions]: 29 | 30 | r[type.bool.usage-condition] 31 | * The condition operand in [if expressions] and [while expressions] 32 | 33 | r[type.bool.usage-lazy-operator] 34 | * The operands in [lazy boolean operator expressions][lazy] 35 | 36 | > [!NOTE] 37 | > The boolean type acts similarly to but is not an [enumerated type]. In practice, this mostly means that constructors are not associated to the type (e.g. `bool::true`). 38 | 39 | r[type.bool.traits] 40 | Like all primitives, the boolean type [implements][p-impl] the 41 | [traits][p-traits] [`Clone`][p-clone], [`Copy`][p-copy], [`Sized`][p-sized], 42 | [`Send`][p-send], and [`Sync`][p-sync]. 43 | 44 | > [!NOTE] 45 | > See the [standard library docs](bool) for library operations. 46 | 47 | r[type.bool.expr] 48 | ## Operations on boolean values 49 | 50 | When using certain operator expressions with a boolean type for its operands, 51 | they evaluate using the rules of [boolean logic]. 52 | 53 | r[type.bool.expr.not] 54 | ### Logical not 55 | 56 | | `b` | [`!b`][op-not] | 57 | |- | - | 58 | | `true` | `false` | 59 | | `false` | `true` | 60 | 61 | r[type.bool.expr.or] 62 | ### Logical or 63 | 64 | | `a` | `b` | [`a \| b`][op-or] | 65 | |- | - | - | 66 | | `true` | `true` | `true` | 67 | | `true` | `false` | `true` | 68 | | `false` | `true` | `true` | 69 | | `false` | `false` | `false` | 70 | 71 | r[type.bool.expr.and] 72 | ### Logical and 73 | 74 | | `a` | `b` | [`a & b`][op-and] | 75 | |- | - | - | 76 | | `true` | `true` | `true` | 77 | | `true` | `false` | `false` | 78 | | `false` | `true` | `false` | 79 | | `false` | `false` | `false` | 80 | 81 | r[type.bool.expr.xor] 82 | ### Logical xor 83 | 84 | | `a` | `b` | [`a ^ b`][op-xor] | 85 | |- | - | - | 86 | | `true` | `true` | `false` | 87 | | `true` | `false` | `true` | 88 | | `false` | `true` | `true` | 89 | | `false` | `false` | `false` | 90 | 91 | r[type.bool.expr.cmp] 92 | ### Comparisons 93 | 94 | r[type.bool.expr.cmp.eq] 95 | | `a` | `b` | [`a == b`][op-compare] | 96 | |- | - | - | 97 | | `true` | `true` | `true` | 98 | | `true` | `false` | `false` | 99 | | `false` | `true` | `false` | 100 | | `false` | `false` | `true` | 101 | 102 | r[type.bool.expr.cmp.greater] 103 | | `a` | `b` | [`a > b`][op-compare] | 104 | |- | - | - | 105 | | `true` | `true` | `false` | 106 | | `true` | `false` | `true` | 107 | | `false` | `true` | `false` | 108 | | `false` | `false` | `false` | 109 | 110 | r[type.bool.expr.cmp.not-eq] 111 | * `a != b` is the same as `!(a == b)` 112 | 113 | r[type.bool.expr.cmp.greater-eq] 114 | * `a >= b` is the same as `a == b | a > b` 115 | 116 | r[type.bool.expr.cmp.less] 117 | * `a < b` is the same as `!(a >= b)` 118 | 119 | r[type.bool.expr.cmp.less-eq] 120 | * `a <= b` is the same as `a == b | a < b` 121 | 122 | r[type.bool.validity] 123 | ## Bit validity 124 | 125 | The single byte of a `bool` is guaranteed to be initialized (in other words, 126 | `transmute::(...)` is always sound -- but since some bit patterns 127 | are invalid `bool`s, the inverse is not always sound). 128 | 129 | [boolean logic]: https://en.wikipedia.org/wiki/Boolean_algebra 130 | [enumerated type]: enum.md 131 | [expressions]: ../expressions.md 132 | [if expressions]: ../expressions/if-expr.md#if-expressions 133 | [language prelude]: ../names/preludes.md#language-prelude 134 | [lazy]: ../expressions/operator-expr.md#lazy-boolean-operators 135 | [literal expression]: ../expressions/literal-expr.md 136 | [name]: ../names.md 137 | [op-and]: ../expressions/operator-expr.md#arithmetic-and-logical-binary-operators 138 | [op-compare]: ../expressions/operator-expr.md#comparison-operators 139 | [op-not]: ../expressions/operator-expr.md#negation-operators 140 | [op-or]: ../expressions/operator-expr.md#arithmetic-and-logical-binary-operators 141 | [op-xor]: ../expressions/operator-expr.md#arithmetic-and-logical-binary-operators 142 | [p-clone]: ../special-types-and-traits.md#clone 143 | [p-copy]: ../special-types-and-traits.md#copy 144 | [p-impl]: ../items/implementations.md 145 | [p-send]: ../special-types-and-traits.md#send 146 | [p-sized]: ../special-types-and-traits.md#sized 147 | [p-sync]: ../special-types-and-traits.md#sync 148 | [p-traits]: ../items/traits.md 149 | [size and alignment]: ../type-layout.md#size-and-alignment 150 | [undefined behavior]: ../behavior-considered-undefined.md 151 | [while expressions]: ../expressions/loop-expr.md#predicate-loops 152 | -------------------------------------------------------------------------------- /src/expressions/method-call-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.method] 2 | # Method-call expressions 3 | 4 | r[expr.method.syntax] 5 | ```grammar,expressions 6 | MethodCallExpression -> Expression `.` PathExprSegment `(`CallParams? `)` 7 | ``` 8 | 9 | r[expr.method.intro] 10 | A _method call_ consists of an expression (the *receiver*) followed by a single dot, an expression path segment, and a parenthesized expression-list. 11 | 12 | r[expr.method.target] 13 | Method calls are resolved to associated [methods] on specific traits, either statically dispatching to a method if the exact `self`-type of the left-hand-side is known, or dynamically dispatching if the left-hand-side expression is an indirect [trait object](../types/trait-object.md). 14 | 15 | ```rust 16 | let pi: Result = "3.14".parse(); 17 | let log_pi = pi.unwrap_or(1.0).log(2.72); 18 | # assert!(1.14 < log_pi && log_pi < 1.15) 19 | ``` 20 | 21 | r[expr.method.autoref-deref] 22 | When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method. 23 | This requires a more complex lookup process than for other functions, since there may be a number of possible methods to call. 24 | The following procedure is used: 25 | 26 | r[expr.method.candidate-receivers] 27 | The first step is to build a list of candidate receiver types. 28 | Obtain these by repeatedly [dereferencing][dereference] the receiver expression's type, adding each type encountered to the list, then finally attempting an [unsized coercion] at the end, and adding the result type if that is successful. 29 | 30 | r[expr.method.candidate-receivers-refs] 31 | Then, for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`. 32 | 33 | For instance, if the receiver has type `Box<[i32;2]>`, then the candidate types will be `Box<[i32;2]>`, `&Box<[i32;2]>`, `&mut Box<[i32;2]>`, `[i32; 2]` (by dereferencing), `&[i32; 2]`, `&mut [i32; 2]`, `[i32]` (by unsized coercion), `&[i32]`, and finally `&mut [i32]`. 34 | 35 | r[expr.method.candidate-search] 36 | Then, for each candidate type `T`, search for a [visible] method with a receiver of that type in the following places: 37 | 38 | 1. `T`'s inherent methods (methods implemented directly on `T`). 39 | 1. Any of the methods provided by a [visible] trait implemented by `T`. 40 | If `T` is a type parameter, methods provided by trait bounds on `T` are looked up first. 41 | Then all remaining methods in scope are looked up. 42 | 43 | > [!NOTE] 44 | > The lookup is done for each type in order, which can occasionally lead to surprising results. The below code will print "In trait impl!", because `&self` methods are looked up first, the trait method is found before the struct's `&mut self` method is found. 45 | > 46 | > ```rust 47 | > struct Foo {} 48 | > 49 | > trait Bar { 50 | > fn bar(&self); 51 | > } 52 | > 53 | > impl Foo { 54 | > fn bar(&mut self) { 55 | > println!("In struct impl!") 56 | > } 57 | > } 58 | > 59 | > impl Bar for Foo { 60 | > fn bar(&self) { 61 | > println!("In trait impl!") 62 | > } 63 | > } 64 | > 65 | > fn main() { 66 | > let mut f = Foo{}; 67 | > f.bar(); 68 | > } 69 | > ``` 70 | 71 | r[expr.method.ambiguous-target] 72 | If this results in multiple possible candidates, then it is an error, and the receiver must be [converted][disambiguate call] to an appropriate receiver type to make the method call. 73 | 74 | r[expr.method.receiver-constraints] 75 | This process does not take into account the mutability or lifetime of the receiver, or whether a method is `unsafe`. 76 | Once a method is looked up, if it can't be called for one (or more) of those reasons, the result is a compiler error. 77 | 78 | r[expr.method.ambiguous-search] 79 | If a step is reached where there is more than one possible method, such as where generic methods or traits are considered the same, then it is a compiler error. 80 | These cases require a [disambiguating function call syntax] for method and function invocation. 81 | 82 | r[expr.method.edition2021] 83 | > [!EDITION-2021] 84 | > Before the 2021 edition, during the search for visible methods, if the candidate receiver type is an [array type], methods provided by the standard library [`IntoIterator`] trait are ignored. 85 | > 86 | > The edition used for this purpose is determined by the token representing the method name. 87 | > 88 | > This special case may be removed in the future. 89 | 90 | > [!WARNING] 91 | > For [trait objects], if there is an inherent method of the same name as a trait method, it will give a compiler error when trying to call the method in a method call expression. 92 | > Instead, you can call the method using [disambiguating function call syntax], in which case it calls the trait method, not the inherent method. 93 | > There is no way to call the inherent method. 94 | > Just don't define inherent methods on trait objects with the same name as a trait method and you'll be fine. 95 | 96 | [visible]: ../visibility-and-privacy.md 97 | [array type]: ../types/array.md 98 | [trait objects]: ../types/trait-object.md 99 | [disambiguate call]: call-expr.md#disambiguating-function-calls 100 | [disambiguating function call syntax]: call-expr.md#disambiguating-function-calls 101 | [dereference]: operator-expr.md#the-dereference-operator 102 | [methods]: ../items/associated-items.md#methods 103 | [unsized coercion]: ../type-coercions.md#unsized-coercions 104 | [`IntoIterator`]: std::iter::IntoIterator 105 | -------------------------------------------------------------------------------- /src/expressions/array-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.array] 2 | # Array and array index expressions 3 | 4 | ## Array expressions 5 | 6 | r[expr.array.syntax] 7 | ```grammar,expressions 8 | ArrayExpression -> `[` ArrayElements? `]` 9 | 10 | ArrayElements -> 11 | Expression ( `,` Expression )* `,`? 12 | | Expression `;` Expression 13 | ``` 14 | 15 | r[expr.array.constructor] 16 | *Array expressions* construct [arrays][array]. 17 | Array expressions come in two forms. 18 | 19 | r[expr.array.array] 20 | The first form lists out every value in the array. 21 | 22 | r[expr.array.array-syntax] 23 | The syntax for this form is a comma-separated list of expressions of uniform type enclosed in square brackets. 24 | 25 | r[expr.array.array-behavior] 26 | This produces an array containing each of these values in the order they are written. 27 | 28 | r[expr.array.repeat] 29 | The syntax for the second form is two expressions separated by a semicolon (`;`) enclosed in square brackets. 30 | 31 | r[expr.array.repeat-operand] 32 | The expression before the `;` is called the *repeat operand*. 33 | 34 | r[expr.array.length-operand] 35 | The expression after the `;` is called the *length operand*. 36 | 37 | r[expr.array.length-restriction] 38 | The length operand must either be an [inferred const] or be a [constant expression] of type `usize` (e.g. a [literal] or a [constant item]). 39 | 40 | ```rust 41 | const C: usize = 1; 42 | let _: [u8; C] = [0; 1]; // Literal. 43 | let _: [u8; C] = [0; C]; // Constant item. 44 | let _: [u8; C] = [0; _]; // Inferred const. 45 | let _: [u8; C] = [0; (((_)))]; // Inferred const. 46 | ``` 47 | 48 | > [!NOTE] 49 | > In an array expression, an [inferred const] is parsed as an [expression][Expression] but then semantically treated as a separate kind of [const generic argument]. 50 | 51 | r[expr.array.repeat-behavior] 52 | An array expression of this form creates an array with the length of the value of the length operand with each element being a copy of the repeat operand. 53 | That is, `[a; b]` creates an array containing `b` copies of the value of `a`. 54 | 55 | r[expr.array.repeat-copy] 56 | If the length operand has a value greater than 1 then this requires the repeat operand to have a type that implements [`Copy`], to be a [const block expression], or to be a [path] to a constant item. 57 | 58 | r[expr.array.repeat-const-item] 59 | When the repeat operand is a const block or a path to a constant item, it is evaluated the number of times specified in the length operand. 60 | 61 | r[expr.array.repeat-evaluation-zero] 62 | If that value is `0`, then the const block or constant item is not evaluated at all. 63 | 64 | r[expr.array.repeat-non-const] 65 | For expressions that are neither a const block nor a path to a constant item, it is evaluated exactly once, and then the result is copied the length operand's value times. 66 | 67 | ```rust 68 | [1, 2, 3, 4]; 69 | ["a", "b", "c", "d"]; 70 | [0; 128]; // array with 128 zeros 71 | [0u8, 0u8, 0u8, 0u8,]; 72 | [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; // 2D array 73 | const EMPTY: Vec = Vec::new(); 74 | [EMPTY; 2]; 75 | ``` 76 | 77 | r[expr.array.index] 78 | ## Array and slice indexing expressions 79 | 80 | r[expr.array.index.syntax] 81 | ```grammar,expressions 82 | IndexExpression -> Expression `[` Expression `]` 83 | ``` 84 | 85 | r[expr.array.index.array] 86 | [Array] and [slice]-typed values can be indexed by writing a square-bracket-enclosed expression of type `usize` (the index) after them. 87 | When the array is mutable, the resulting [memory location] can be assigned to. 88 | 89 | r[expr.array.index.trait] 90 | For other types an index expression `a[b]` is equivalent to `*std::ops::Index::index(&a, b)`, or `*std::ops::IndexMut::index_mut(&mut a, b)` in a mutable place expression context. 91 | Just as with methods, Rust will also insert dereference operations on `a` repeatedly to find an implementation. 92 | 93 | r[expr.array.index.zero-index] 94 | Indices are zero-based for arrays and slices. 95 | 96 | r[expr.array.index.const] 97 | Array access is a [constant expression], so bounds can be checked at compile-time with a constant index value. 98 | Otherwise a check will be performed at run-time that will put the thread in a [_panicked state_][panic] if it fails. 99 | 100 | ```rust,should_panic 101 | // lint is deny by default. 102 | #![warn(unconditional_panic)] 103 | 104 | ([1, 2, 3, 4])[2]; // Evaluates to 3 105 | 106 | let b = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; 107 | b[1][2]; // multidimensional array indexing 108 | 109 | let x = (["a", "b"])[10]; // warning: index out of bounds 110 | 111 | let n = 10; 112 | let y = (["a", "b"])[n]; // panics 113 | 114 | let arr = ["a", "b"]; 115 | arr[10]; // warning: index out of bounds 116 | ``` 117 | 118 | r[expr.array.index.trait-impl] 119 | The array index expression can be implemented for types other than arrays and slices by implementing the [Index] and [IndexMut] traits. 120 | 121 | [`Copy`]: ../special-types-and-traits.md#copy 122 | [IndexMut]: std::ops::IndexMut 123 | [Index]: std::ops::Index 124 | [array]: ../types/array.md 125 | [const generic argument]: items.generics.const.argument 126 | [const block expression]: expr.block.const 127 | [constant expression]: ../const_eval.md#constant-expressions 128 | [constant item]: ../items/constant-items.md 129 | [inferred const]: items.generics.const.inferred 130 | [literal]: ../tokens.md#literals 131 | [memory location]: ../expressions.md#place-expressions-and-value-expressions 132 | [panic]: ../panic.md 133 | [path]: path-expr.md 134 | [slice]: ../types/slice.md 135 | -------------------------------------------------------------------------------- /src/subtyping.md: -------------------------------------------------------------------------------- 1 | r[subtype] 2 | # Subtyping and variance 3 | 4 | r[subtype.intro] 5 | Subtyping is implicit and can occur at any stage in type checking or 6 | inference. 7 | 8 | r[subtype.kinds] 9 | Subtyping is restricted to two cases: 10 | variance with respect to lifetimes and between types with higher ranked 11 | lifetimes. If we were to erase lifetimes from types, then the only subtyping 12 | would be due to type equality. 13 | 14 | Consider the following example: string literals always have `'static` 15 | lifetime. Nevertheless, we can assign `s` to `t`: 16 | 17 | ```rust 18 | fn bar<'a>() { 19 | let s: &'static str = "hi"; 20 | let t: &'a str = s; 21 | } 22 | ``` 23 | 24 | Since `'static` outlives the lifetime parameter `'a`, `&'static str` is a 25 | subtype of `&'a str`. 26 | 27 | r[subtype.higher-ranked] 28 | [Higher-ranked] [function pointers] and [trait objects] have another 29 | subtype relation. They are subtypes of types that are given by substitutions of 30 | the higher-ranked lifetimes. Some examples: 31 | 32 | ```rust 33 | // Here 'a is substituted for 'static 34 | let subtype: &(for<'a> fn(&'a i32) -> &'a i32) = &((|x| x) as fn(&_) -> &_); 35 | let supertype: &(fn(&'static i32) -> &'static i32) = subtype; 36 | 37 | // This works similarly for trait objects 38 | let subtype: &(dyn for<'a> Fn(&'a i32) -> &'a i32) = &|x| x; 39 | let supertype: &(dyn Fn(&'static i32) -> &'static i32) = subtype; 40 | 41 | // We can also substitute one higher-ranked lifetime for another 42 | let subtype: &(for<'a, 'b> fn(&'a i32, &'b i32)) = &((|x, y| {}) as fn(&_, &_)); 43 | let supertype: &for<'c> fn(&'c i32, &'c i32) = subtype; 44 | ``` 45 | 46 | r[subtyping.variance] 47 | ## Variance 48 | 49 | r[subtyping.variance.intro] 50 | Variance is a property that generic types have with respect to their arguments. 51 | A generic type's *variance* in a parameter is how the subtyping of the 52 | parameter affects the subtyping of the type. 53 | 54 | r[subtyping.variance.covariant] 55 | * `F` is *covariant* over `T` if `T` being a subtype of `U` implies that 56 | `F` is a subtype of `F` (subtyping "passes through") 57 | 58 | r[subtyping.variance.contravariant] 59 | * `F` is *contravariant* over `T` if `T` being a subtype of `U` implies that 60 | `F` is a subtype of `F` 61 | 62 | r[subtyping.variance.invariant] 63 | * `F` is *invariant* over `T` otherwise (no subtyping relation can be 64 | derived) 65 | 66 | r[subtyping.variance.builtin-types] 67 | Variance of types is automatically determined as follows 68 | 69 | | Type | Variance in `'a` | Variance in `T` | 70 | |-------------------------------|-------------------|-------------------| 71 | | `&'a T` | covariant | covariant | 72 | | `&'a mut T` | covariant | invariant | 73 | | `*const T` | | covariant | 74 | | `*mut T` | | invariant | 75 | | `[T]` and `[T; n]` | | covariant | 76 | | `fn() -> T` | | covariant | 77 | | `fn(T) -> ()` | | contravariant | 78 | | `std::cell::UnsafeCell` | | invariant | 79 | | `std::marker::PhantomData` | | covariant | 80 | | `dyn Trait + 'a` | covariant | invariant | 81 | 82 | r[subtyping.variance.user-composite-types] 83 | The variance of other `struct`, `enum`, and `union` types is decided by 84 | looking at the variance of the types of their fields. If the parameter is used 85 | in positions with different variances then the parameter is invariant. For 86 | example the following struct is covariant in `'a` and `T` and invariant in `'b`, `'c`, 87 | and `U`. 88 | 89 | ```rust 90 | use std::cell::UnsafeCell; 91 | struct Variance<'a, 'b, 'c, T, U: 'a> { 92 | x: &'a U, // This makes `Variance` covariant in 'a, and would 93 | // make it covariant in U, but U is used later 94 | y: *const T, // Covariant in T 95 | z: UnsafeCell<&'b f64>, // Invariant in 'b 96 | w: *mut U, // Invariant in U, makes the whole struct invariant 97 | 98 | f: fn(&'c ()) -> &'c () // Both co- and contravariant, makes 'c invariant 99 | // in the struct. 100 | } 101 | ``` 102 | 103 | r[subtyping.variance.builtin-composite-types] 104 | When used outside of an `struct`, `enum`, or `union`, the variance for parameters is checked at each location separately. 105 | 106 | ```rust 107 | # use std::cell::UnsafeCell; 108 | fn generic_tuple<'short, 'long: 'short>( 109 | // 'long is used inside of a tuple in both a co- and invariant position. 110 | x: (&'long u32, UnsafeCell<&'long u32>), 111 | ) { 112 | // As the variance at these positions is computed separately, 113 | // we can freely shrink 'long in the covariant position. 114 | let _: (&'short u32, UnsafeCell<&'long u32>) = x; 115 | } 116 | 117 | fn takes_fn_ptr<'short, 'middle: 'short>( 118 | // 'middle is used in both a co- and contravariant position. 119 | f: fn(&'middle ()) -> &'middle (), 120 | ) { 121 | // As the variance at these positions is computed separately, 122 | // we can freely shrink 'middle in the covariant position 123 | // and extend it in the contravariant position. 124 | let _: fn(&'static ()) -> &'short () = f; 125 | } 126 | ``` 127 | 128 | [function pointers]: types/function-pointer.md 129 | [Higher-ranked]: ../nomicon/hrtb.html 130 | [trait objects]: types/trait-object.md 131 | -------------------------------------------------------------------------------- /docs/grammar.md: -------------------------------------------------------------------------------- 1 | # Grammar 2 | 3 | The Reference grammar is written in markdown code blocks using a modified BNF-like syntax (with a blend of regex and other arbitrary things). The `mdbook-spec` extension parses these rules and converts them to a renderable format, including railroad diagrams. 4 | 5 | The code block should have a lang string with the word "grammar", a comma, and the category of the grammar, like this: 6 | 7 | ~~~ 8 | ```grammar,items 9 | ProductionName -> SomeExpression 10 | ``` 11 | ~~~ 12 | 13 | The category is used to group similar productions on the grammar summary page in the appendix. 14 | 15 | ## Grammar syntax 16 | 17 | The syntax for the grammar itself is pretty close to what is described in the [Notation chapter](../src/notation.md), though there are some rendering differences. 18 | 19 | A "root" production, marked with `@root`, is one that is not used in any other production. 20 | 21 | The syntax for the grammar itself (written in itself, hopefully that's not too confusing) is: 22 | 23 | ``` 24 | Grammar -> Production+ 25 | 26 | BACKTICK -> U+0060 27 | 28 | LF -> U+000A 29 | 30 | Production -> 31 | ( Comment LF )* 32 | `@root`? Name ` ->` Expression 33 | 34 | Name -> + 35 | 36 | Expression -> Sequence (` `* `|` ` `* Sequence)* 37 | 38 | Sequence -> (` `* AdornedExpr)+ 39 | 40 | AdornedExpr -> ExprRepeat Suffix? Footnote? 41 | 42 | Suffix -> ` _` * `_` 43 | 44 | Footnote -> `[^` ~[`]` LF]+ `]` 45 | 46 | ExprRepeat -> 47 | Expr1 `?` 48 | | Expr1 `*?` 49 | | Expr1 `*` 50 | | Expr1 `+?` 51 | | Expr1 `+` 52 | | Expr1 `{` Range? `..` Range? `}` 53 | 54 | Range -> [0-9]+ 55 | 56 | Expr1 -> 57 | Unicode 58 | | NonTerminal 59 | | Break 60 | | Comment 61 | | Terminal 62 | | Charset 63 | | Prose 64 | | Group 65 | | NegativeExpression 66 | 67 | Unicode -> `U+` [`A`-`Z` `0`-`9`]4..4 68 | 69 | NonTerminal -> Name 70 | 71 | Break -> LF ` `+ 72 | 73 | Comment -> `//` ~[LF]+ 74 | 75 | Terminal -> BACKTICK ~[LF]+ BACKTICK 76 | 77 | Charset -> `[` (` `* Characters)+ ` `* `]` 78 | 79 | Characters -> 80 | CharacterRange 81 | | CharacterTerminal 82 | | CharacterName 83 | 84 | CharacterRange -> BACKTICK BACKTICK `-` BACKTICK BACKTICK 85 | 86 | CharacterTerminal -> Terminal 87 | 88 | CharacterName -> Name 89 | 90 | Prose -> `<` ~[`>` LF]+ `>` 91 | 92 | Group -> `(` ` `* Expression ` `* `)` 93 | 94 | NegativeExpression -> `~` ( Charset | Terminal | NonTerminal ) 95 | ``` 96 | 97 | The general format is a series of productions separated by blank lines. The expressions are: 98 | 99 | | Expression | Example | Description | 100 | |------------|---------|-------------| 101 | | Unicode | U+0060 | A single unicode character. | 102 | | NonTerminal | FunctionParameters | A reference to another production by name. | 103 | | Break | | This is used internally by the renderer to detect line breaks and indentation. | 104 | | Comment | // Single line comment. | A comment extending to the end of the line. | 105 | | Terminal | \`example\` | This is a sequence of exact characters, surrounded by backticks | 106 | | Charset | [ \`A\`-\`Z\` \`0\`-\`9\` \`_\` ] | A choice from a set of characters, space separated. There are three different forms. | 107 | | CharacterRange | [ \`A\`-\`Z\` ] | A range of characters, each character should be in backticks. 108 | | CharacterTerminal | [ \`x\` ] | A single character, surrounded by backticks. | 109 | | CharacterName | [ LF ] | A nonterminal, referring to another production. | 110 | | Prose | \ | This is an English description of what should be matched, surrounded in angle brackets. | 111 | | Group | (\`,\` Parameter)+ | This groups an expression for the purpose of precedence, such as applying a repetition operator to a sequence of other expressions. 112 | | NegativeExpression | ~[\` \` LF] | Matches anything except the given Charset, Terminal, or Nonterminal. | 113 | | Sequence | \`fn\` Name Parameters | A sequence of expressions, where they must match in order. | 114 | | Alternation | Expr1 \| Expr2 | Matches only one of the given expressions, separated by the vertical pipe character. | 115 | | Suffix | \_except \[LazyBooleanExpression\]\_ | This adds a suffix to the previous expression to provide an additional English description to it, rendered in subscript. This can have limited markdown, but try to avoid anything except basics like links. | 116 | | Footnote | \[^extern-safe\] | This adds a footnote, which can supply some extra information that may be helpful to the user. The footnote itself should be defined outside of the code block like a normal markdown footnote. | 117 | | Optional | Expr? | The preceding expression is optional. | 118 | | Repeat | Expr* | The preceding expression is repeated 0 or more times. | 119 | | Repeat (non-greedy) | Expr*? | The preceding expression is repeated 0 or more times without being greedy. | 120 | | RepeatPlus | Expr+ | The preceding expression is repeated 1 or more times. | 121 | | RepeatPlus (non-greedy) | Expr+? | The preceding expression is repeated 1 or more times without being greedy. | 122 | | RepeatRange | Expr{2..4} | The preceding expression is repeated between the range of times specified. Either bounds can be excluded, which works just like Rust ranges. | 123 | 124 | ## Automatic linking 125 | 126 | The plugin automatically adds markdown link definitions for all the production names on every page. If you want to link directly to a production name, all you need to do is surround it in square brackets, like `[ArrayExpression]`. 127 | 128 | In some cases there might be name collisions with the automatic linking of rule names. In that case, disambiguate with the `grammar-` prefix, such as `[Type][grammar-Type]`. You can also do that if you just feel like being more explicit. 129 | -------------------------------------------------------------------------------- /src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # The Rust Reference 2 | 3 | [Introduction](introduction.md) 4 | 5 | - [Notation](notation.md) 6 | 7 | - [Lexical structure](lexical-structure.md) 8 | - [Input format](input-format.md) 9 | - [Keywords](keywords.md) 10 | - [Identifiers](identifiers.md) 11 | - [Comments](comments.md) 12 | - [Whitespace](whitespace.md) 13 | - [Tokens](tokens.md) 14 | 15 | - [Macros](macros.md) 16 | - [Macros by example](macros-by-example.md) 17 | - [Procedural macros](procedural-macros.md) 18 | 19 | - [Crates and source files](crates-and-source-files.md) 20 | 21 | - [Conditional compilation](conditional-compilation.md) 22 | 23 | - [Items](items.md) 24 | - [Modules](items/modules.md) 25 | - [Extern crates](items/extern-crates.md) 26 | - [Use declarations](items/use-declarations.md) 27 | - [Functions](items/functions.md) 28 | - [Type aliases](items/type-aliases.md) 29 | - [Structs](items/structs.md) 30 | - [Enumerations](items/enumerations.md) 31 | - [Unions](items/unions.md) 32 | - [Constant items](items/constant-items.md) 33 | - [Static items](items/static-items.md) 34 | - [Traits](items/traits.md) 35 | - [Implementations](items/implementations.md) 36 | - [External blocks](items/external-blocks.md) 37 | - [Generic parameters](items/generics.md) 38 | - [Associated items](items/associated-items.md) 39 | 40 | - [Attributes](attributes.md) 41 | - [Testing](attributes/testing.md) 42 | - [Derive](attributes/derive.md) 43 | - [Diagnostics](attributes/diagnostics.md) 44 | - [Code generation](attributes/codegen.md) 45 | - [Limits](attributes/limits.md) 46 | - [Type system](attributes/type_system.md) 47 | - [Debugger](attributes/debugger.md) 48 | 49 | - [Statements and expressions](statements-and-expressions.md) 50 | - [Statements](statements.md) 51 | - [Expressions](expressions.md) 52 | - [Literal expressions](expressions/literal-expr.md) 53 | - [Path expressions](expressions/path-expr.md) 54 | - [Block expressions](expressions/block-expr.md) 55 | - [Operator expressions](expressions/operator-expr.md) 56 | - [Grouped expressions](expressions/grouped-expr.md) 57 | - [Array and index expressions](expressions/array-expr.md) 58 | - [Tuple and index expressions](expressions/tuple-expr.md) 59 | - [Struct expressions](expressions/struct-expr.md) 60 | - [Call expressions](expressions/call-expr.md) 61 | - [Method call expressions](expressions/method-call-expr.md) 62 | - [Field access expressions](expressions/field-expr.md) 63 | - [Closure expressions](expressions/closure-expr.md) 64 | - [Loop expressions](expressions/loop-expr.md) 65 | - [Range expressions](expressions/range-expr.md) 66 | - [If expressions](expressions/if-expr.md) 67 | - [Match expressions](expressions/match-expr.md) 68 | - [Return expressions](expressions/return-expr.md) 69 | - [Await expressions](expressions/await-expr.md) 70 | - [Underscore expressions](expressions/underscore-expr.md) 71 | 72 | - [Patterns](patterns.md) 73 | 74 | - [Type system](type-system.md) 75 | - [Types](types.md) 76 | - [Boolean type](types/boolean.md) 77 | - [Numeric types](types/numeric.md) 78 | - [Textual types](types/textual.md) 79 | - [Never type](types/never.md) 80 | - [Tuple types](types/tuple.md) 81 | - [Array types](types/array.md) 82 | - [Slice types](types/slice.md) 83 | - [Struct types](types/struct.md) 84 | - [Enumerated types](types/enum.md) 85 | - [Union types](types/union.md) 86 | - [Function item types](types/function-item.md) 87 | - [Closure types](types/closure.md) 88 | - [Pointer types](types/pointer.md) 89 | - [Function pointer types](types/function-pointer.md) 90 | - [Trait object types](types/trait-object.md) 91 | - [Impl trait type](types/impl-trait.md) 92 | - [Type parameters](types/parameters.md) 93 | - [Inferred type](types/inferred.md) 94 | - [Dynamically sized types](dynamically-sized-types.md) 95 | - [Type layout](type-layout.md) 96 | - [Interior mutability](interior-mutability.md) 97 | - [Subtyping and variance](subtyping.md) 98 | - [Trait and lifetime bounds](trait-bounds.md) 99 | - [Type coercions](type-coercions.md) 100 | - [Destructors](destructors.md) 101 | - [Lifetime elision](lifetime-elision.md) 102 | 103 | - [Special types and traits](special-types-and-traits.md) 104 | 105 | - [Names](names.md) 106 | - [Namespaces](names/namespaces.md) 107 | - [Scopes](names/scopes.md) 108 | - [Preludes](names/preludes.md) 109 | - [Paths](paths.md) 110 | - [Name resolution](names/name-resolution.md) 111 | - [Visibility and privacy](visibility-and-privacy.md) 112 | 113 | - [Memory model](memory-model.md) 114 | - [Memory allocation and lifetime](memory-allocation-and-lifetime.md) 115 | - [Variables](variables.md) 116 | 117 | - [Panic](panic.md) 118 | 119 | - [Linkage](linkage.md) 120 | 121 | - [Inline assembly](inline-assembly.md) 122 | 123 | - [Unsafety](unsafety.md) 124 | - [The `unsafe` keyword](unsafe-keyword.md) 125 | - [Behavior considered undefined](behavior-considered-undefined.md) 126 | - [Behavior not considered unsafe](behavior-not-considered-unsafe.md) 127 | 128 | - [Constant evaluation](const_eval.md) 129 | 130 | - [Application binary interface](abi.md) 131 | 132 | - [The Rust runtime](runtime.md) 133 | 134 | - [Appendices](appendices.md) 135 | - [Grammar summary](grammar.md) 136 | - [Syntax index](syntax-index.md) 137 | - [Macro follow-set ambiguity formal specification](macro-ambiguity.md) 138 | - [Influences](influences.md) 139 | - [Test summary](test-summary.md) 140 | - [Glossary](glossary.md) 141 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | merge_group: 5 | 6 | env: 7 | MDBOOK_VERSION: 0.5.1 8 | 9 | jobs: 10 | code-tests: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@master 14 | - name: Update rustup 15 | run: rustup self update 16 | - name: Install Rust 17 | run: | 18 | rustup set profile minimal 19 | rustup toolchain install nightly 20 | rustup default nightly 21 | - name: Install mdbook 22 | run: | 23 | mkdir bin 24 | 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 25 | echo "$(pwd)/bin" >> $GITHUB_PATH 26 | - name: Report versions 27 | run: | 28 | rustup --version 29 | rustc -Vv 30 | mdbook --version 31 | - name: Run tests 32 | run: mdbook test 33 | 34 | style-tests: 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions/checkout@master 38 | - name: Checkout rust-lang/rust 39 | uses: actions/checkout@master 40 | with: 41 | repository: rust-lang/rust 42 | path: rust 43 | - name: Update rustup 44 | run: rustup self update 45 | - name: Install Rust 46 | run: | 47 | rustup set profile minimal 48 | rustup toolchain install nightly -c rust-docs,rustfmt 49 | rustup default nightly 50 | - name: Install mdbook 51 | run: | 52 | mkdir bin 53 | 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 54 | echo "$(pwd)/bin" >> $GITHUB_PATH 55 | - name: Report versions 56 | run: | 57 | rustup --version 58 | rustc -Vv 59 | mdbook --version 60 | - name: Style checks 61 | working-directory: style-check 62 | run: cargo run --locked -- ../src 63 | - name: Style fmt 64 | working-directory: style-check 65 | run: cargo fmt --check 66 | - name: Verify the book builds 67 | env: 68 | SPEC_DENY_WARNINGS: 1 69 | SPEC_RUST_ROOT: ${{ github.workspace }}/rust 70 | run: mdbook build 71 | - name: Check for broken links 72 | run: | 73 | curl -sSLo linkcheck.sh \ 74 | https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh 75 | sh linkcheck.sh --all reference 76 | 77 | mdbook-spec: 78 | runs-on: ubuntu-latest 79 | steps: 80 | - uses: actions/checkout@master 81 | - name: Update rustup 82 | run: rustup self update 83 | - name: Install Rust 84 | run: | 85 | rustup set profile minimal 86 | rustup toolchain install nightly -c rustfmt 87 | rustup default nightly 88 | - name: Install mdbook 89 | run: | 90 | mkdir bin 91 | 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 92 | echo "$(pwd)/bin" >> $GITHUB_PATH 93 | - name: Report versions 94 | run: | 95 | rustup --version 96 | rustc -Vv 97 | - name: Verify mdbook-spec lockfile is current 98 | working-directory: ./mdbook-spec 99 | run: cargo update -p mdbook-spec --locked 100 | - name: Test mdbook-spec 101 | working-directory: ./mdbook-spec 102 | run: cargo test 103 | - name: Rustfmt check 104 | working-directory: ./mdbook-spec 105 | run: cargo fmt --check 106 | - name: Xtask rustfmt check 107 | working-directory: ./xtask 108 | run: cargo fmt --check 109 | 110 | preview: 111 | if: github.event_name == 'pull_request' 112 | runs-on: ubuntu-latest 113 | steps: 114 | - uses: actions/checkout@master 115 | - name: Checkout rust-lang/rust 116 | uses: actions/checkout@master 117 | with: 118 | repository: rust-lang/rust 119 | path: rust 120 | - name: Update rustup 121 | run: rustup self update 122 | - name: Install Rust 123 | run: | 124 | rustup set profile minimal 125 | rustup toolchain install nightly 126 | rustup default nightly 127 | - name: Install mdbook 128 | run: | 129 | mkdir bin 130 | 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 131 | echo "$(pwd)/bin" >> $GITHUB_PATH 132 | - name: Build the book 133 | env: 134 | SPEC_RELATIVE: 0 135 | SPEC_RUST_ROOT: ${{ github.workspace }}/rust 136 | run: mdbook build --dest-dir dist/preview-${{ github.event.pull_request.number }} 137 | - name: Upload artifact 138 | uses: actions/upload-artifact@v4 139 | with: 140 | name: preview-${{ github.event.pull_request.number }} 141 | overwrite: true 142 | path: dist 143 | 144 | # The success job is here to consolidate the total success/failure state of 145 | # all other jobs. This job is then included in the GitHub branch protection 146 | # rule which prevents merges unless all other jobs are passing. This makes 147 | # it easier to manage the list of jobs via this yml file and to prevent 148 | # accidentally adding new jobs without also updating the branch protections. 149 | success: 150 | name: Success gate 151 | if: always() 152 | needs: 153 | - code-tests 154 | - style-tests 155 | - mdbook-spec 156 | # preview is explicitly excluded here since it doesn't run on merge 157 | runs-on: ubuntu-latest 158 | steps: 159 | - run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}' 160 | - name: Done 161 | run: exit 0 162 | -------------------------------------------------------------------------------- /src/types.md: -------------------------------------------------------------------------------- 1 | r[type] 2 | # Types 3 | 4 | r[type.intro] 5 | Every variable, item, and value in a Rust program has a type. The _type_ of a 6 | *value* defines the interpretation of the memory holding it and the operations 7 | that may be performed on the value. 8 | 9 | r[type.builtin] 10 | Built-in types are tightly integrated into the language, in nontrivial ways 11 | that are not possible to emulate in user-defined types. 12 | 13 | r[type.user-defined] 14 | User-defined types have limited capabilities. 15 | 16 | r[type.kinds] 17 | The list of types is: 18 | 19 | * Primitive types: 20 | * [Boolean] --- `bool` 21 | * [Numeric] --- integer and float 22 | * [Textual] --- `char` and `str` 23 | * [Never] --- `!` --- a type with no values 24 | * Sequence types: 25 | * [Tuple] 26 | * [Array] 27 | * [Slice] 28 | * User-defined types: 29 | * [Struct] 30 | * [Enum] 31 | * [Union] 32 | * Function types: 33 | * [Functions] 34 | * [Closures] 35 | * Pointer types: 36 | * [References] 37 | * [Raw pointers] 38 | * [Function pointers] 39 | * Trait types: 40 | * [Trait objects] 41 | * [Impl trait] 42 | 43 | r[type.name] 44 | ## Type expressions 45 | 46 | r[type.name.syntax] 47 | ```grammar,types 48 | Type -> 49 | TypeNoBounds 50 | | ImplTraitType 51 | | TraitObjectType 52 | 53 | TypeNoBounds -> 54 | ParenthesizedType 55 | | ImplTraitTypeOneBound 56 | | TraitObjectTypeOneBound 57 | | TypePath 58 | | TupleType 59 | | NeverType 60 | | RawPointerType 61 | | ReferenceType 62 | | ArrayType 63 | | SliceType 64 | | InferredType 65 | | QualifiedPathInType 66 | | BareFunctionType 67 | | MacroInvocation 68 | ``` 69 | 70 | r[type.name.intro] 71 | A _type expression_ as defined in the [Type] grammar rule above is the syntax 72 | for referring to a type. It may refer to: 73 | 74 | r[type.name.sequence] 75 | * Sequence types ([tuple], [array], [slice]). 76 | 77 | r[type.name.path] 78 | * [Type paths] which can reference: 79 | * Primitive types ([boolean], [numeric], [textual]). 80 | * Paths to an [item] ([struct], [enum], [union], [type alias], [trait]). 81 | * [`Self` path] where `Self` is the implementing type. 82 | * Generic [type parameters]. 83 | 84 | r[type.name.pointer] 85 | * Pointer types ([reference], [raw pointer], [function pointer]). 86 | 87 | r[type.name.inference] 88 | * The [inferred type] which asks the compiler to determine the type. 89 | 90 | r[type.name.grouped] 91 | * [Parentheses] which are used for disambiguation. 92 | 93 | r[type.name.trait] 94 | * Trait types: [Trait objects] and [impl trait]. 95 | 96 | r[type.name.never] 97 | * The [never] type. 98 | 99 | r[type.name.macro-expansion] 100 | * [Macros] which expand to a type expression. 101 | 102 | r[type.name.parenthesized] 103 | ### Parenthesized types 104 | 105 | r[type.name.parenthesized.syntax] 106 | ```grammar,types 107 | ParenthesizedType -> `(` Type `)` 108 | ``` 109 | 110 | r[type.name.parenthesized.intro] 111 | In some situations the combination of types may be ambiguous. Use parentheses 112 | around a type to avoid ambiguity. For example, the `+` operator for [type 113 | boundaries] within a [reference type] is unclear where the 114 | boundary applies, so the use of parentheses is required. Grammar rules that 115 | require this disambiguation use the [TypeNoBounds] rule instead of 116 | [Type][grammar-Type]. 117 | 118 | ```rust 119 | # use std::any::Any; 120 | type T<'a> = &'a (dyn Any + Send); 121 | ``` 122 | 123 | r[type.recursive] 124 | ## Recursive types 125 | 126 | r[type.recursive.intro] 127 | Nominal types — [structs], [enumerations], and [unions] — may be 128 | recursive. That is, each `enum` variant or `struct` or `union` field may 129 | refer, directly or indirectly, to the enclosing `enum` or `struct` type 130 | itself. 131 | 132 | r[type.recursive.constraint] 133 | Such recursion has restrictions: 134 | 135 | * Recursive types must include a nominal type in the recursion (not mere [type 136 | aliases], or other structural types such as [arrays] or [tuples]). So `type 137 | Rec = &'static [Rec]` is not allowed. 138 | * The size of a recursive type must be finite; in other words the recursive 139 | fields of the type must be [pointer types]. 140 | 141 | An example of a *recursive* type and its use: 142 | 143 | ```rust 144 | enum List { 145 | Nil, 146 | Cons(T, Box>) 147 | } 148 | 149 | let a: List = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil)))); 150 | ``` 151 | 152 | [Array]: types/array.md 153 | [Boolean]: types/boolean.md 154 | [Closures]: types/closure.md 155 | [Enum]: types/enum.md 156 | [Function pointers]: types/function-pointer.md 157 | [Functions]: types/function-item.md 158 | [Impl trait]: types/impl-trait.md 159 | [Macros]: macros.md 160 | [Numeric]: types/numeric.md 161 | [Parentheses]: #parenthesized-types 162 | [Raw pointers]: types/pointer.md#raw-pointers-const-and-mut 163 | [References]: types/pointer.md#shared-references- 164 | [Slice]: types/slice.md 165 | [Struct]: types/struct.md 166 | [Textual]: types/textual.md 167 | [Trait objects]: types/trait-object.md 168 | [Tuple]: types/tuple.md 169 | [Type paths]: paths.md#paths-in-types 170 | [Union]: types/union.md 171 | [`Self` path]: paths.md#self-1 172 | [arrays]: types/array.md 173 | [enumerations]: types/enum.md 174 | [function pointer]: types/function-pointer.md 175 | [inferred type]: types/inferred.md 176 | [item]: items.md 177 | [never]: types/never.md 178 | [pointer types]: types/pointer.md 179 | [raw pointer]: types/pointer.md#raw-pointers-const-and-mut 180 | [reference type]: types/pointer.md#shared-references- 181 | [reference]: types/pointer.md#shared-references- 182 | [structs]: types/struct.md 183 | [trait]: types/trait-object.md 184 | [tuples]: types/tuple.md 185 | [type alias]: items/type-aliases.md 186 | [type aliases]: items/type-aliases.md 187 | [type boundaries]: trait-bounds.md 188 | [type parameters]: types/parameters.md 189 | [unions]: types/union.md 190 | -------------------------------------------------------------------------------- /src/expressions/struct-expr.md: -------------------------------------------------------------------------------- 1 | r[expr.struct] 2 | # Struct expressions 3 | 4 | r[expr.struct.syntax] 5 | ```grammar,expressions 6 | StructExpression -> 7 | PathInExpression `{` (StructExprFields | StructBase)? `}` 8 | 9 | StructExprFields -> 10 | StructExprField (`,` StructExprField)* (`,` StructBase | `,`?) 11 | 12 | StructExprField -> 13 | OuterAttribute* 14 | ( 15 | IDENTIFIER 16 | | (IDENTIFIER | TUPLE_INDEX) `:` Expression 17 | ) 18 | 19 | StructBase -> `..` Expression 20 | ``` 21 | 22 | r[expr.struct.intro] 23 | A *struct expression* creates a struct, enum, or union value. 24 | It consists of a path to a [struct], [enum variant], or [union] item followed by the values for the fields of the item. 25 | 26 | The following are examples of struct expressions: 27 | 28 | ```rust 29 | # struct Point { x: f64, y: f64 } 30 | # struct NothingInMe { } 31 | # mod game { pub struct User<'a> { pub name: &'a str, pub age: u32, pub score: usize } } 32 | # enum Enum { Variant {} } 33 | Point {x: 10.0, y: 20.0}; 34 | NothingInMe {}; 35 | let u = game::User {name: "Joe", age: 35, score: 100_000}; 36 | Enum::Variant {}; 37 | ``` 38 | 39 | > [!NOTE] 40 | > Tuple structs and tuple enum variants are typically instantiated using a [call expression][expr.call] referring to the [constructor in the value namespace][items.struct.tuple]. These are distinct from a struct expression using curly braces referring to the constructor in the type namespace. 41 | > 42 | > ```rust 43 | > struct Position(i32, i32, i32); 44 | > Position(0, 0, 0); // Typical way of creating a tuple struct. 45 | > let c = Position; // `c` is a function that takes 3 arguments. 46 | > let pos = c(8, 6, 7); // Creates a `Position` value. 47 | > 48 | > enum Version { Triple(i32, i32, i32) }; 49 | > Version::Triple(0, 0, 0); 50 | > let f = Version::Triple; 51 | > let ver = f(8, 6, 7); 52 | > ``` 53 | > 54 | > The last segment of the call path cannot refer to a type alias: 55 | > 56 | > ```rust 57 | > trait Tr { type T; } 58 | > impl Tr for T { type T = T; } 59 | > 60 | > struct Tuple(); 61 | > enum Enum { Tuple() } 62 | > 63 | > // ::T(); // causes an error -- `::T` is a type, not a value 64 | > ::T::Tuple(); // OK 65 | > ``` 66 | > 67 | > ---- 68 | > 69 | > Unit structs and unit enum variants are typically instantiated using a [path expression][expr.path] referring to the [constant in the value namespace][items.struct.unit]. 70 | > 71 | > ```rust 72 | > struct Gamma; 73 | > // Gamma unit value, referring to the const in the value namespace. 74 | > let a = Gamma; 75 | > // Exact same value as `a`, but constructed using a struct expression 76 | > // referring to the type namespace. 77 | > let b = Gamma {}; 78 | > 79 | > enum ColorSpace { Oklch } 80 | > let c = ColorSpace::Oklch; 81 | > let d = ColorSpace::Oklch {}; 82 | > ``` 83 | 84 | r[expr.struct.field] 85 | ## Field struct expression 86 | 87 | r[expr.struct.field.intro] 88 | A struct expression with fields enclosed in curly braces allows you to specify the value for each individual field in any order. 89 | The field name is separated from its value with a colon. 90 | 91 | r[expr.struct.field.union-constraint] 92 | A value of a [union] type can only be created using this syntax, and it must specify exactly one field. 93 | 94 | r[expr.struct.update] 95 | ## Functional update syntax 96 | 97 | r[expr.struct.update.intro] 98 | A struct expression that constructs a value of a struct type can terminate with the syntax `..` followed by an expression to denote a functional update. 99 | 100 | r[expr.struct.update.base-same-type] 101 | The expression following `..` (the base) must have the same struct type as the new struct type being formed. 102 | 103 | r[expr.struct.update.fields] 104 | The entire expression uses the given values for the fields that were specified and moves or copies the remaining fields from the base expression. 105 | 106 | r[expr.struct.update.visibility-constraint] 107 | As with all struct expressions, all of the fields of the struct must be [visible], even those not explicitly named. 108 | 109 | ```rust 110 | # struct Point3d { x: i32, y: i32, z: i32 } 111 | let mut base = Point3d {x: 1, y: 2, z: 3}; 112 | let y_ref = &mut base.y; 113 | Point3d {y: 0, z: 10, .. base}; // OK, only base.x is accessed 114 | drop(y_ref); 115 | ``` 116 | 117 | r[expr.struct.brace-restricted-positions] 118 | Struct expressions can't be used directly in a [loop] or [if] expression's head, or in the [scrutinee] of an [if let] or [match] expression. 119 | However, struct expressions can be used in these situations if they are within another expression, for example inside [parentheses]. 120 | 121 | r[expr.struct.tuple-field] 122 | The field names can be decimal integer values to specify indices for constructing tuple structs. 123 | This can be used with base structs to fill out the remaining indices not specified: 124 | 125 | ```rust 126 | struct Color(u8, u8, u8); 127 | let c1 = Color(0, 0, 0); // Typical way of creating a tuple struct. 128 | let c2 = Color{0: 255, 1: 127, 2: 0}; // Specifying fields by index. 129 | let c3 = Color{1: 0, ..c2}; // Fill out all other fields using a base struct. 130 | ``` 131 | 132 | r[expr.struct.field.named] 133 | ### Struct field init shorthand 134 | 135 | When initializing a data structure (struct, enum, union) with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`. 136 | This allows a compact syntax with less duplication. 137 | For example: 138 | 139 | ```rust 140 | # struct Point3d { x: i32, y: i32, z: i32 } 141 | # let x = 0; 142 | # let y_value = 0; 143 | # let z = 0; 144 | Point3d { x: x, y: y_value, z: z }; 145 | Point3d { x, y: y_value, z }; 146 | ``` 147 | 148 | [enum variant]: ../items/enumerations.md 149 | [if let]: if-expr.md#if-let-patterns 150 | [if]: if-expr.md#if-expressions 151 | [loop]: loop-expr.md 152 | [match]: match-expr.md 153 | [parentheses]: grouped-expr.md 154 | [struct]: ../items/structs.md 155 | [union]: ../items/unions.md 156 | [visible]: ../visibility-and-privacy.md 157 | [scrutinee]: ../glossary.md#scrutinee 158 | --------------------------------------------------------------------------------