diff options
Diffstat (limited to 'src/doc')
139 files changed, 4340 insertions, 1370 deletions
diff --git a/src/doc/book/redirects/using-rust-without-the-standard-library.md b/src/doc/book/redirects/using-rust-without-the-standard-library.md index 75145429d..0fbdfebdd 100644 --- a/src/doc/book/redirects/using-rust-without-the-standard-library.md +++ b/src/doc/book/redirects/using-rust-without-the-standard-library.md @@ -7,11 +7,11 @@ --- -This particular chapter has moved to [the Unstable Book][2]. +This particular chapter has moved to [the Rustonomicon][2]. -* **[In the Unstable Rust Book: `lang_items` — Writing an executable without stdlib][2]** +* **[In the Rustonomicon: Beneath std][2]** * <small>[In the first edition: Ch 4.12 — Using Rust without the Standard Library][1]</small> [1]: https://doc.rust-lang.org/1.30.0/book/first-edition/using-rust-without-the-standard-library.html -[2]: ../unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib +[2]: ../nomicon/beneath-std.html diff --git a/src/doc/book/src/ch08-02-strings.md b/src/doc/book/src/ch08-02-strings.md index 9663d36ab..f38803ee3 100644 --- a/src/doc/book/src/ch08-02-strings.md +++ b/src/doc/book/src/ch08-02-strings.md @@ -244,7 +244,7 @@ encoded UTF-8 example strings from Listing 8-14. First, this one: In this case, `len` will be 4, which means the vector storing the string “Hola” is 4 bytes long. Each of these letters takes 1 byte when encoded in UTF-8. The following line, however, may surprise you. (Note that this string begins with -the capital Cyrillic letter Ze, not the Arabic number 3.) +the capital Cyrillic letter Ze, not the number 3.) ```rust {{#rustdoc_include ../listings/ch08-common-collections/listing-08-14/src/main.rs:russian}} diff --git a/src/doc/book/src/ch10-03-lifetime-syntax.md b/src/doc/book/src/ch10-03-lifetime-syntax.md index 5229ab74b..498f01f0b 100644 --- a/src/doc/book/src/ch10-03-lifetime-syntax.md +++ b/src/doc/book/src/ch10-03-lifetime-syntax.md @@ -8,13 +8,13 @@ One detail we didn’t discuss in the [“References and Borrowing”][references-and-borrowing]<!-- ignore --> section in Chapter 4 is that every reference in Rust has a *lifetime*, which is the scope for which that reference is valid. Most of the time, lifetimes are implicit and inferred, -just like most of the time, types are inferred. We only must annotate types +just like most of the time, types are inferred. We must only annotate types when multiple types are possible. In a similar way, we must annotate lifetimes when the lifetimes of references could be related in a few different ways. Rust requires us to annotate the relationships using generic lifetime parameters to ensure the actual references used at runtime will definitely be valid. -Annotating lifetimes is not even a concept most other programming languages +Annotating lifetimes is not a concept most other programming languages have, so this is going to feel unfamiliar. Although we won’t cover lifetimes in their entirety in this chapter, we’ll discuss common ways you might encounter lifetime syntax so you can get comfortable with the concept. @@ -44,7 +44,7 @@ The outer scope declares a variable named `r` with no initial value, and the inner scope declares a variable named `x` with the initial value of 5. Inside the inner scope, we attempt to set the value of `r` as a reference to `x`. Then the inner scope ends, and we attempt to print the value in `r`. This code won’t -compile because the value `r` is referring to has gone out of scope before we +compile because what the value `r` is referring to has gone out of scope before we try to use it. Here is the error message: ```console diff --git a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md index 9abc5a608..5f6653dcd 100644 --- a/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md +++ b/src/doc/edition-guide/src/rust-2021/default-cargo-resolver.md @@ -24,7 +24,7 @@ See [the announcement of Rust 1.51][5] for details. [4]: ../../cargo/reference/resolver.html#feature-resolver-version-2 [5]: https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver [workspace]: ../../cargo/reference/workspaces.html -[virtual workspace]: ../../cargo/reference/workspaces.html#virtual-manifest +[virtual workspace]: ../../cargo/reference/workspaces.html#virtual-workspace [`resolver` field]: ../../cargo/reference/resolver.html#resolver-versions ## Migration diff --git a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md index db711a7d1..a4a7114a6 100644 --- a/src/doc/edition-guide/src/rust-2021/reserving-syntax.md +++ b/src/doc/edition-guide/src/rust-2021/reserving-syntax.md @@ -17,7 +17,7 @@ we've decided to reserve syntax for prefixed identifiers and literals: `prefix#identifier`, `prefix"string"`, `prefix'c'`, and `prefix#123`, where `prefix` can be any identifier. (Except those prefixes that already have a meaning, such as `b'...'` (byte -strings) and `r"..."` (raw strings).) +chars) and `r"..."` (raw strings).) This provides syntax we can expand into in the future without requiring an edition boundary. We may use this for temporary syntax until the next edition, @@ -82,4 +82,4 @@ This `z` prefix is no longer allowed in Rust 2021, so in order to call this macr ```rust,ignore my_macro!(z "hey"); -```
\ No newline at end of file +``` diff --git a/src/doc/embedded-book/.github/bors.toml b/src/doc/embedded-book/.github/bors.toml deleted file mode 100644 index c3cfa378d..000000000 --- a/src/doc/embedded-book/.github/bors.toml +++ /dev/null @@ -1,4 +0,0 @@ -block_labels = ["needs-decision"] -delete_merged_branches = true -required_approvals = 1 -status = ["build"] diff --git a/src/doc/embedded-book/.github/workflows/ci.yml b/src/doc/embedded-book/.github/workflows/ci.yml index b1e3d552e..9018d1146 100644 --- a/src/doc/embedded-book/.github/workflows/ci.yml +++ b/src/doc/embedded-book/.github/workflows/ci.yml @@ -1,9 +1,11 @@ name: CI on: - push: - branches: [ staging, trying, master ] - pull_request: + push: # Run CI for all branches except GitHub merge queue tmp branches + branches-ignore: + - "gh-readonly-queue/**" + pull_request: # Run CI for PRs on any branch + merge_group: # Run CI for the GitHub merge queue jobs: build: diff --git a/src/doc/embedded-book/src/start/qemu.md b/src/doc/embedded-book/src/start/qemu.md index d4dfc361d..f7241b873 100644 --- a/src/doc/embedded-book/src/start/qemu.md +++ b/src/doc/embedded-book/src/start/qemu.md @@ -388,7 +388,7 @@ Let's break down that QEMU command: program compiled for the Cortex-M4F, which has a hardware FPU, will make QEMU error during its execution. -- `-machine lm3s6965evb`. This tells QEMU to emulate the LM3S6965EVB, a +- `-machine lm3s6965evb`. This tells QEMU to emulate the LM3S6965EVB, an evaluation board that contains a LM3S6965 microcontroller. - `-nographic`. This tells QEMU to not launch its GUI. diff --git a/src/doc/embedded-book/src/unsorted/math.md b/src/doc/embedded-book/src/unsorted/math.md index 91271710e..4367b867b 100644 --- a/src/doc/embedded-book/src/unsorted/math.md +++ b/src/doc/embedded-book/src/unsorted/math.md @@ -70,6 +70,7 @@ If you need to perform more complex operations like DSP signal processing or adv algebra on your MCU, the following crates might help you - [CMSIS DSP library binding](https://github.com/jacobrosenthal/cmsis-dsp-sys) +- [`constgebra`](https://crates.io/crates/constgebra) - [`micromath`](https://github.com/tarcieri/micromath) - [`microfft`](https://crates.io/crates/microfft) - [`nalgebra`](https://github.com/dimforge/nalgebra) diff --git a/src/doc/nomicon/src/atomics.md b/src/doc/nomicon/src/atomics.md index 6aef6aee6..72a2d56fd 100644 --- a/src/doc/nomicon/src/atomics.md +++ b/src/doc/nomicon/src/atomics.md @@ -76,7 +76,7 @@ For instance, say we convince the compiler to emit this logic: ```text initial state: x = 0, y = 1 -THREAD 1 THREAD2 +THREAD 1 THREAD 2 y = 3; if x == 1 { x = 1; y *= 2; } diff --git a/src/doc/nomicon/src/exception-safety.md b/src/doc/nomicon/src/exception-safety.md index ca1a39416..8404bb859 100644 --- a/src/doc/nomicon/src/exception-safety.md +++ b/src/doc/nomicon/src/exception-safety.md @@ -161,9 +161,9 @@ impl<'a, T> Hole<'a, T> { unsafe { let elt = ptr::read(&data[pos]); Hole { - data: data, + data, elt: Some(elt), - pos: pos, + pos, } } } diff --git a/src/doc/nomicon/src/ffi.md b/src/doc/nomicon/src/ffi.md index 55be225de..b76f0b2ac 100644 --- a/src/doc/nomicon/src/ffi.md +++ b/src/doc/nomicon/src/ffi.md @@ -586,6 +586,7 @@ are: * `aapcs` * `cdecl` * `fastcall` +* `thiscall` * `vectorcall` This is currently hidden behind the `abi_vectorcall` gate and is subject to change. * `Rust` diff --git a/src/doc/nomicon/src/leaking.md b/src/doc/nomicon/src/leaking.md index ea29595f4..d90fed571 100644 --- a/src/doc/nomicon/src/leaking.md +++ b/src/doc/nomicon/src/leaking.md @@ -134,10 +134,10 @@ impl<T> Rc<T> { // Wouldn't it be nice if heap::allocate worked like this? let ptr = heap::allocate::<RcBox<T>>(); ptr::write(ptr, RcBox { - data: data, + data, ref_count: 1, }); - Rc { ptr: ptr } + Rc { ptr } } } @@ -194,7 +194,7 @@ pub fn scoped<'a, F>(f: F) -> JoinGuard<'a> ``` Here `f` is some closure for the other thread to execute. Saying that -`F: Send +'a` is saying that it closes over data that lives for `'a`, and it +`F: Send + 'a` is saying that it closes over data that lives for `'a`, and it either owns that data or the data was Sync (implying `&data` is Send). Because JoinGuard has a lifetime, it keeps all the data it closes over diff --git a/src/doc/nomicon/src/vec/vec-final.md b/src/doc/nomicon/src/vec/vec-final.md index 696391d10..e680e0d65 100644 --- a/src/doc/nomicon/src/vec/vec-final.md +++ b/src/doc/nomicon/src/vec/vec-final.md @@ -23,7 +23,7 @@ impl<T> RawVec<T> { // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: NonNull::dangling(), - cap: cap, + cap, } } diff --git a/src/doc/nomicon/src/vec/vec-zsts.md b/src/doc/nomicon/src/vec/vec-zsts.md index 8f2529727..6715f9478 100644 --- a/src/doc/nomicon/src/vec/vec-zsts.md +++ b/src/doc/nomicon/src/vec/vec-zsts.md @@ -39,7 +39,7 @@ impl<T> RawVec<T> { // `NonNull::dangling()` doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: NonNull::dangling(), - cap: cap, + cap, } } diff --git a/src/doc/reference/.github/workflows/main.yml b/src/doc/reference/.github/workflows/main.yml index 4456c3c9c..aff208478 100644 --- a/src/doc/reference/.github/workflows/main.yml +++ b/src/doc/reference/.github/workflows/main.yml @@ -1,5 +1,7 @@ name: CI -on: [push, pull_request] +on: + pull_request: + merge_group: jobs: test: diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md index 8629e835d..c929f979c 100644 --- a/src/doc/reference/src/attributes/codegen.md +++ b/src/doc/reference/src/attributes/codegen.md @@ -361,15 +361,20 @@ trait object whose methods are attributed. ## The `instruction_set` attribute -The *`instruction_set` attribute* may be applied to a function to enable code generation for a specific -instruction set supported by the target architecture. It uses the [_MetaListPath_] syntax and a path -comprised of the architecture and instruction set to specify how to generate the code for -architectures where a single program may utilize multiple instruction sets. +The *`instruction_set` [attribute]* may be applied to a function to control which instruction set the function will be generated for. +This allows mixing more than one instruction set in a single program on CPU architectures that support it. +It uses the [_MetaListPath_] syntax, and a path comprised of the architecture family name and instruction set name. -The following values are available on targets for the `ARMv4` and `ARMv5te` architectures: +[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax + +It is a compilation error to use the `instruction_set` attribute on a target that does not support it. + +### On ARM -* `arm::a32` - Uses ARM code. -* `arm::t32` - Uses Thumb code. +For the `ARMv4T` and `ARMv5te` architectures, the following are supported: + +* `arm::a32` - Generate the function as A32 "ARM" code. +* `arm::t32` - Generate the function as T32 "Thumb" code. <!-- ignore: arm-only --> ```rust,ignore @@ -380,4 +385,7 @@ fn foo_arm_code() {} fn bar_thumb_code() {} ``` -[_MetaListPath_]: ../attributes.md#meta-item-attribute-syntax +Using the `instruction_set` attribute has the following effects: + +* If the address of the function is taken as a function pointer, the low bit of the address will be set to 0 (arm) or 1 (thumb) depending on the instruction set. +* Any inline assembly in the function must use the specified instruction set instead of the target default. diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index 31963d1e5..9d1732d07 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -42,9 +42,12 @@ code. All this also applies when values of these types are passed in a (nested) field of a compound type, but not behind pointer indirections. -* Mutating immutable data. All data inside a [`const`] item is immutable. Moreover, all - data reached through a shared reference or data owned by an immutable binding - is immutable, unless that data is contained within an [`UnsafeCell<U>`]. +* Mutating immutable bytes. All bytes inside a [`const`] item are immutable. + The bytes owned by an immutable binding are immutable, unless those bytes are part of an [`UnsafeCell<U>`]. + + Moreover, the bytes [pointed to] by a shared reference, including transitively through other references (both shared and mutable) and `Box`es, are immutable; transitivity includes those references stored in fields of compound types. + + A mutation is any write of more than 0 bytes which overlaps with any of the relevant bytes (even if that write does not change the memory contents). * Invoking undefined behavior via compiler intrinsics. * Executing code compiled with platform features that the current platform does not support (see [`target_feature`]), *except* if the platform explicitly documents this to be safe. @@ -74,6 +77,11 @@ code. > `rustc_layout_scalar_valid_range_*` attributes. * Incorrect use of inline assembly. For more details, refer to the [rules] to follow when writing code that uses inline assembly. +* **In [const context](const_eval.md#const-context)**: transmuting or otherwise + reinterpreting a pointer (reference, raw pointer, or function pointer) into + some allocated object as a non-pointer type (such as integers). + 'Reinterpreting' refers to loading the pointer value at integer type without a + cast, e.g. by doing raw pointer casts or using a union. **Note:** Uninitialized memory is also implicitly invalid for any type that has a restricted set of valid values. In other words, the only cases in which @@ -86,13 +94,16 @@ reading uninitialized memory is permitted are inside `union`s and in "padding" > vice versa, undefined behavior in Rust can cause adverse affects on code > executed by any FFI calls to other languages. +### Pointed-to bytes + +The span of bytes a pointer or reference "points to" is determined by the pointer value and the size of the pointee type (using `size_of_val`). + ### Dangling pointers [dangling]: #dangling-pointers A reference/pointer is "dangling" if it is null or not all of the bytes it -points to are part of the same live allocation (so in particular they all have to be -part of *some* allocation). The span of bytes it points to is determined by the -pointer value and the size of the pointee type (using `size_of_val`). +[points to] are part of the same live allocation (so in particular they all have to be +part of *some* allocation). If the size is 0, then the pointer must either point inside of a live allocation (including pointing just after the last byte of the allocation), or it must be @@ -116,3 +127,5 @@ must never exceed `isize::MAX`. [dereference expression]: expressions/operator-expr.md#the-dereference-operator [place expression context]: expressions.md#place-expressions-and-value-expressions [rules]: inline-assembly.md#rules-for-inline-assembly +[points to]: #pointed-to-bytes +[pointed to]: #pointed-to-bytes diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md index 84aac89d3..17afc3676 100644 --- a/src/doc/reference/src/destructors.md +++ b/src/doc/reference/src/destructors.md @@ -284,7 +284,7 @@ An *extending pattern* is either * An [identifier pattern] that binds by reference or mutable reference. * A [struct][struct pattern], [tuple][tuple pattern], [tuple struct][tuple struct pattern], or [slice][slice pattern] pattern where at least one of the - direct subpatterns is a extending pattern. + direct subpatterns is an extending pattern. So `ref x`, `V(ref x)` and `[ref x, y]` are all extending patterns, but `x`, `&ref x` and `&(ref x,)` are not. diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md index b2411cd8e..ad4cc5f54 100644 --- a/src/doc/reference/src/expressions.md +++ b/src/doc/reference/src/expressions.md @@ -162,7 +162,7 @@ Explicitly, the assignee expressions are: - Place expressions. - [Underscores][_UnderscoreExpression_]. - [Tuples][_TupleExpression_] of assignee expressions. -- [Slices][_ArrayExpression_] of assingee expressions. +- [Slices][_ArrayExpression_] of assignee expressions. - [Tuple structs][_StructExpression_] of assignee expressions. - [Structs][_StructExpression_] of assignee expressions (with optionally named fields). diff --git a/src/doc/reference/src/expressions/operator-expr.md b/src/doc/reference/src/expressions/operator-expr.md index 691f801e8..8b6429636 100644 --- a/src/doc/reference/src/expressions/operator-expr.md +++ b/src/doc/reference/src/expressions/operator-expr.md @@ -243,8 +243,8 @@ The operands of all of these operators are evaluated in [value expression contex | `+` | Addition | | Addition | `std::ops::Add` | `std::ops::AddAssign` | | `-` | Subtraction | | Subtraction | `std::ops::Sub` | `std::ops::SubAssign` | | `*` | Multiplication | | Multiplication | `std::ops::Mul` | `std::ops::MulAssign` | -| `/` | Division* | | Division | `std::ops::Div` | `std::ops::DivAssign` | -| `%` | Remainder** | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | +| `/` | Division*† | | Division | `std::ops::Div` | `std::ops::DivAssign` | +| `%` | Remainder**† | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | | `&` | Bitwise AND | [Logical AND] | | `std::ops::BitAnd` | `std::ops::BitAndAssign` | | <code>|</code> | Bitwise OR | [Logical OR] | | `std::ops::BitOr` | `std::ops::BitOrAssign` | | `^` | Bitwise XOR | [Logical XOR] | | `std::ops::BitXor` | `std::ops::BitXorAssign` | @@ -258,6 +258,8 @@ The operands of all of these operators are evaluated in [value expression contex \*\*\* Arithmetic right shift on signed integer types, logical right shift on unsigned integer types. +† For integer types, division by zero panics. + Here are examples of these operators being used. ```rust diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md index 25ae37bc3..982f57ba7 100644 --- a/src/doc/reference/src/items/external-blocks.md +++ b/src/doc/reference/src/items/external-blocks.md @@ -90,6 +90,8 @@ There are also some platform-specific ABI strings: `__fastcall` and GCC and clang's `__attribute__((fastcall))` * `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's `__vectorcall` and clang's `__attribute__((vectorcall))` +* `extern "thiscall"` -- The default for C++ member functions on MSVC -- corresponds to MSVC's + `__thiscall` and GCC and clang's `__attribute__((thiscall))` * `extern "efiapi"` -- The ABI used for [UEFI] functions. ## Variadic functions diff --git a/src/doc/reference/src/trait-bounds.md b/src/doc/reference/src/trait-bounds.md index 0a6731288..a7cd5a7d9 100644 --- a/src/doc/reference/src/trait-bounds.md +++ b/src/doc/reference/src/trait-bounds.md @@ -156,6 +156,79 @@ fn call_on_ref_zero<F>(f: F) where F: for<'a> Fn(&'a i32) { } ``` +## Implied bounds + +Lifetime bounds required for types to be well-formed are sometimes inferred. + +```rust +fn requires_t_outlives_a<'a, T>(x: &'a T) {} +``` +The type parameter `T` is required to outlive `'a` for the type `&'a T` to be well-formed. +This is inferred because the function signature contains the type `&'a T` which is +only valid if `T: 'a` holds. + +Implied bounds are added for all parameters and outputs of functions. Inside of `requires_t_outlives_a` +you can assume `T: 'a` to hold even if you don't explicitly specify this: + +```rust +fn requires_t_outlives_a_not_implied<'a, T: 'a>() {} + +fn requires_t_outlives_a<'a, T>(x: &'a T) { + // This compiles, because `T: 'a` is implied by + // the reference type `&'a T`. + requires_t_outlives_a_not_implied::<'a, T>(); +} +``` + +```rust,compile_fail,E0309 +# fn requires_t_outlives_a_not_implied<'a, T: 'a>() {} +fn not_implied<'a, T>() { + // This errors, because `T: 'a` is not implied by + // the function signature. + requires_t_outlives_a_not_implied::<'a, T>(); +} +``` + +Only lifetime bounds are implied, trait bounds still have to be explicitly added. +The following example therefore causes an error: + +```rust,compile_fail,E0277 +use std::fmt::Debug; +struct IsDebug<T: Debug>(T); +// error[E0277]: `T` doesn't implement `Debug` +fn doesnt_specify_t_debug<T>(x: IsDebug<T>) {} +``` + +Lifetime bounds are also inferred for type definitions and impl blocks for any type: + +```rust +struct Struct<'a, T> { + // This requires `T: 'a` to be well-formed + // which is inferred by the compiler. + field: &'a T, +} + +enum Enum<'a, T> { + // This requires `T: 'a` to be well-formed, + // which is inferred by the compiler. + // + // Note that `T: 'a` is required even when only + // using `Enum::OtherVariant`. + SomeVariant(&'a T), + OtherVariant, +} + +trait Trait<'a, T: 'a> {} + +// This would error because `T: 'a` is not implied by any type +// in the impl header. +// impl<'a, T> Trait<'a, T> for () {} + +// This compiles as `T: 'a` is implied by the self type `&'a T`. +impl<'a, T> Trait<'a, T> for &'a T {} +``` + + [LIFETIME_OR_LABEL]: tokens.md#lifetimes-and-loop-labels [_GenericParams_]: items/generics.md [_TypePath_]: paths.md#paths-in-types diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md index 191567a42..4c87954f3 100644 --- a/src/doc/reference/src/type-layout.md +++ b/src/doc/reference/src/type-layout.md @@ -549,13 +549,28 @@ The `align` modifier can also be applied on an `enum`. When it is, the effect on the `enum`'s alignment is the same as if the `enum` was wrapped in a newtype `struct` with the same `align` modifier. -<div class="warning"> - -***Warning:*** Dereferencing an unaligned pointer is [undefined behavior] and -it is possible to [safely create unaligned pointers to `packed` fields][27060]. -Like all ways to create undefined behavior in safe Rust, this is a bug. - -</div> +> Note: References to unaligned fields are not allowed because it is [undefined behavior]. +> When fields are unaligned due to an alignment modifier, consider the following options for using references and dereferences: +> +> ```rust +> #[repr(packed)] +> struct Packed { +> f1: u8, +> f2: u16, +> } +> let mut e = Packed { f1: 1, f2: 2 }; +> // Instead of creating a reference to a field, copy the value to a local variable. +> let x = e.f2; +> // Or in situations like `println!` which creates a reference, use braces +> // to change it to a copy of the value. +> println!("{}", {e.f2}); +> // Or if you need a pointer, use the unaligned methods for reading and writing +> // instead of dereferencing the pointer directly. +> let ptr: *const u16 = std::ptr::addr_of!(e.f2); +> let value = unsafe { ptr.read_unaligned() }; +> let mut_ptr: *mut u16 = std::ptr::addr_of_mut!(e.f2); +> unsafe { mut_ptr.write_unaligned(3) } +> ``` ### The `transparent` Representation @@ -587,7 +602,6 @@ used with any other representation. [enumerations]: items/enumerations.md [zero-variant enums]: items/enumerations.md#zero-variant-enums [undefined behavior]: behavior-considered-undefined.md -[27060]: https://github.com/rust-lang/rust/issues/27060 [55149]: https://github.com/rust-lang/rust/issues/55149 [`PhantomData<T>`]: special-types-and-traits.md#phantomdatat [Default]: #the-default-representation diff --git a/src/doc/reference/src/types/never.md b/src/doc/reference/src/types/never.md index e32674272..3fbd2ad5c 100644 --- a/src/doc/reference/src/types/never.md +++ b/src/doc/reference/src/types/never.md @@ -7,16 +7,17 @@ The never type `!` is a type with no values, representing the result of computations that never complete. Expressions of type `!` can be coerced into any other type. -<!-- ignore: unstable --> -```rust,ignore -let x: ! = panic!(); -// Can be coerced into any type. -let y: u32 = x; +The `!` type can **only** appear in function return types presently, +indicating it is a diverging function that never returns. + +```rust +fn foo() -> ! { + panic!("This call never returns."); +} ``` -**NB.** The never type was expected to be stabilized in 1.41, but due -to some last minute regressions detected the stabilization was -temporarily reverted. The `!` type can only appear in function return -types presently. See [the tracking -issue](https://github.com/rust-lang/rust/issues/35121) for more -details. +```rust +extern "C" { + pub fn no_return_extern_func() -> !; +} +``` diff --git a/src/doc/reference/src/types/textual.md b/src/doc/reference/src/types/textual.md index 7f3899d70..65d563312 100644 --- a/src/doc/reference/src/types/textual.md +++ b/src/doc/reference/src/types/textual.md @@ -8,7 +8,7 @@ or 0xE000 to 0x10FFFF range. It is immediate [Undefined Behavior] to create a `char` that falls outside this range. A `[char]` is effectively a UCS-4 / UTF-32 string of length 1. -A value of type `str` is represented the same way as `[u8]`, it is a slice of +A value of type `str` is represented the same way as `[u8]`, a slice of 8-bit unsigned bytes. However, the Rust standard library makes extra assumptions about `str`: methods working on `str` assume and ensure that the data in there is valid UTF-8. Calling a `str` method with a non-UTF-8 buffer can cause diff --git a/src/doc/reference/src/unsafe-keyword.md b/src/doc/reference/src/unsafe-keyword.md index 5fa5deea6..a29fc9432 100644 --- a/src/doc/reference/src/unsafe-keyword.md +++ b/src/doc/reference/src/unsafe-keyword.md @@ -27,9 +27,9 @@ this can be changed by enabling the [`unsafe_op_in_unsafe_fn`] lint. By putting operations into an unsafe block, the programmer states that they have taken care of satisfying the extra safety conditions of all operations inside that block. Unsafe blocks are the logical dual to unsafe functions: -where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations have been discharged. +where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations of functions or operations called inside the block have been discharged. There are many ways to discharge proof obligations; -for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn` and use its own proof obligations to discharge the proof obligations of its callees. +for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn`, in which case the block can use the proof obligations of that function to discharge the proof obligations arising inside the block. Unsafe blocks are used to wrap foreign libraries, make direct use of hardware or implement features not directly present in the language. For example, Rust provides the language features necessary to implement memory-safe concurrency in the language but the implementation of threads and message passing in the standard library uses unsafe blocks. diff --git a/src/doc/rust-by-example/README.md b/src/doc/rust-by-example/README.md index e43b044c8..2529a3fad 100644 --- a/src/doc/rust-by-example/README.md +++ b/src/doc/rust-by-example/README.md @@ -40,6 +40,7 @@ Please see the [CONTRIBUTING.md] file for more details. * [French](https://github.com/Songbird0/FR_RBE) * [Russian](https://github.com/ruRust/rust-by-example) * [Vietnamese](https://github.com/EyesCrypto-Insights/rust-by-example-vn) +* [Portuguese](https://github.com/nazarepiedady/rust-com-exemplos) ## License diff --git a/src/doc/rust-by-example/src/error/panic.md b/src/doc/rust-by-example/src/error/panic.md index 5524dbf6f..8e3f10109 100644 --- a/src/doc/rust-by-example/src/error/panic.md +++ b/src/doc/rust-by-example/src/error/panic.md @@ -15,5 +15,8 @@ fn drink(beverage: &str) { fn main() { drink("water"); drink("lemonade"); + drink("still water"); } ``` + +The first call to `drink` works. The second panics and thus the third is never called. diff --git a/src/doc/rust-by-example/src/flow_control/loop/nested.md b/src/doc/rust-by-example/src/flow_control/loop/nested.md index 01c55a559..01e8f3971 100644 --- a/src/doc/rust-by-example/src/flow_control/loop/nested.md +++ b/src/doc/rust-by-example/src/flow_control/loop/nested.md @@ -5,7 +5,7 @@ loops. In these cases, the loops must be annotated with some `'label`, and the label must be passed to the `break`/`continue` statement. ```rust,editable -#![allow(unreachable_code)] +#![allow(unreachable_code, unused_labels)] fn main() { 'outer: loop { @@ -26,4 +26,4 @@ fn main() { println!("Exited the outer loop"); } -```
\ No newline at end of file +``` diff --git a/src/doc/rust-by-example/src/hello/print/fmt.md b/src/doc/rust-by-example/src/hello/print/fmt.md index c3c78f6b1..b6f676061 100644 --- a/src/doc/rust-by-example/src/hello/print/fmt.md +++ b/src/doc/rust-by-example/src/hello/print/fmt.md @@ -78,8 +78,11 @@ RGB (0, 3, 254) 0x0003FE RGB (0, 0, 0) 0x000000 ``` -Two hints if you get stuck: +Three hints if you get stuck: +* The formula for calculating a color in the RGB color space is: +`RGB = (R*65536)+(G*256)+B , (when R is RED, G is GREEN and B is BLUE)`. +For more see [RGB color format & calculation][rgb_color]. * You [may need to list each color more than once][named_parameters]. * You can [pad with zeros to a width of 2][fmt_width] with `:0>2`. @@ -87,6 +90,7 @@ Two hints if you get stuck: [`std::fmt`][fmt] +[rgb_color]: https://www.rapidtables.com/web/color/RGB_Color.html#rgb-format [named_parameters]: https://doc.rust-lang.org/std/fmt/#named-parameters [deadbeef]: https://en.wikipedia.org/wiki/Deadbeef#Magic_debug_values [fmt]: https://doc.rust-lang.org/std/fmt/ diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index fdf6c5050..131651e38 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -118,7 +118,7 @@ git submodule update --remote src/doc/rustc-dev-guide git add -u git commit -m "Update rustc-dev-guide" # Note that you can use -i, which is short for --incremental, in the following command -./x.py test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway +./x test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway # Open a PR in rust-lang/rust ``` diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 9f7c9cf1b..97f3503ae 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -40,12 +40,12 @@ - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) - [Walkthrough: a typical contribution](./walkthrough.md) -- [Procedures for Breaking Changes](./bug-fix-procedure.md) -- [Implementing new features](./implementing_new_features.md) +- [Implementing new language features](./implementing_new_features.md) - [Stability attributes](./stability.md) - [Stabilizing Features](./stabilization_guide.md) - [Feature Gates](./feature-gates.md) - [Coding conventions](./conventions.md) +- [Procedures for Breaking Changes](./bug-fix-procedure.md) - [Using external repositories](./external-repos.md) - [Fuzzing](./fuzzing.md) - [Notification groups](notification-groups/about.md) @@ -109,9 +109,10 @@ - [`TypeFolder` and `TypeFoldable`](./ty-fold.md) - [Generic arguments](./generic_arguments.md) - [Constants in the type system](./constants.md) + - [Bound vars and Parameters](./bound-vars-and-params.md) - [Type inference](./type-inference.md) - [Trait solving](./traits/resolution.md) - - [Early and Late Bound Parameters](./early-late-bound.md) + - [Early and Late Bound Parameter Definitions](./early-late-bound.md) - [Higher-ranked trait bounds](./traits/hrtb.md) - [Caching subtleties](./traits/caching.md) - [Specialization](./traits/specialization.md) @@ -124,11 +125,13 @@ - [Canonicalization](./solve/canonicalization.md) - [Coinduction](./solve/coinduction.md) - [Proof trees](./solve/proof-trees.md) + - [Normalization](./solve/normalization.md) - [Type checking](./type-checking.md) - [Method Lookup](./method-lookup.md) - [Variance](./variance.md) - [Opaque Types](./opaque-types-type-alias-impl-trait.md) - [Inference details](./opaque-types-impl-trait-inference.md) + - [Return Position Impl Trait In Trait](./return-position-impl-trait-in-trait.md) - [Pattern and Exhaustiveness Checking](./pat-exhaustive-checking.md) - [MIR dataflow](./mir/dataflow.md) - [Drop elaboration](./mir/drop-elaboration.md) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 944ebf5a8..f43f86e5f 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -66,7 +66,6 @@ You might also find the following sites useful: of the team procedures, active working groups, and the team calendar. - [std-dev-guide] -- a similar guide for developing the standard library. - [The t-compiler zulip][z] -- [The Forge](https://forge.rust-lang.org/) has more documentation about various procedures. - `#contribute` and `#wg-rustup` on [Discord](https://discord.gg/rust-lang). - The [Rust Internals forum][rif], a place to ask questions and discuss Rust's internals diff --git a/src/doc/rustc-dev-guide/src/appendix/background.md b/src/doc/rustc-dev-guide/src/appendix/background.md index 0b83b010f..05d01be0f 100644 --- a/src/doc/rustc-dev-guide/src/appendix/background.md +++ b/src/doc/rustc-dev-guide/src/appendix/background.md @@ -300,7 +300,7 @@ does not. > Thanks to `mem`, `scottmcm`, and `Levi` on the official Discord for the > recommendations, and to `tinaun` for posting a link to a [twitter thread from -> Graydon Hoare](https://twitter.com/graydon_pub/status/1039615569132118016) +> Graydon Hoare](https://web.archive.org/web/20181230012554/https://twitter.com/graydon_pub/status/1039615569132118016) > which had some more recommendations! > > Other sources: https://gcc.gnu.org/wiki/ListOfCompilerBooks diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index a02011149..08af10f89 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -90,16 +90,16 @@ so let's go through each in detail. `src/llvm-project` to ensure submodule updates aren't reverted. Some commands you should execute are: - * `./x.py build src/llvm` - test that LLVM still builds - * `./x.py build src/tools/lld` - same for LLD - * `./x.py build` - build the rest of rustc + * `./x build src/llvm` - test that LLVM still builds + * `./x build src/tools/lld` - same for LLD + * `./x build` - build the rest of rustc You'll likely need to update [`llvm-wrapper/*.cpp`][`llvm-wrapper`] to compile with updated LLVM bindings. Note that you should use `#ifdef` and such to ensure that the bindings still compile on older LLVM versions. - Note that `profile = "compiler"` and other defaults set by `./x.py setup` + Note that `profile = "compiler"` and other defaults set by `./x setup` download LLVM from CI instead of building it from source. You should disable this temporarily to make sure your changes are being used. This is done by having the following setting in `config.toml`: diff --git a/src/doc/rustc-dev-guide/src/bound-vars-and-params.md b/src/doc/rustc-dev-guide/src/bound-vars-and-params.md new file mode 100644 index 000000000..50d5cefb1 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/bound-vars-and-params.md @@ -0,0 +1,59 @@ +# Bound vars and parameters + +## Early-bound parameters + +Early-bound parameters in rustc are identified by an index, stored in the +[`ParamTy`] struct for types or the [`EarlyBoundRegion`] struct for lifetimes. +The index counts from the outermost declaration in scope. This means that as you +add more binders inside, the index doesn't change. + +For example, + +```rust,ignore +trait Foo<T> { + type Bar<U> = (Self, T, U); +} +``` + +Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a +[`ParamTy`] with the index of `N`. + +In rustc, the [`Generics`] structure carries this information. So the +[`Generics`] for `Bar` above would be just like for `U` and would indicate the +'parent' generics of `Foo`, which declares `Self` and `T`. You can read more +in [this chapter](./generics.md). + +[`ParamTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamTy.html +[`EarlyBoundRegion`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.EarlyBoundRegion.html +[`Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html + +## Late-bound parameters + +Late-bound parameters in `rustc` are handled differently. We indicate their +presence by a [`Binder`] type. The [`Binder`] doesn't know how many variables +there are at that binding level. This can only be determined by walking the +type itself and collecting them. So a type like `for<'a, 'b> ('a, 'b)` would be +`for (^0.a, ^0.b)`. Here, we just write `for` because we don't know the names +of the things bound within. + +Moreover, a reference to a late-bound lifetime is written `^0.a`: + +- The `0` is the index; it identifies that this lifetime is bound in the + innermost binder (the `for`). +- The `a` is the "name"; late-bound lifetimes in rustc are identified by a + "name" -- the [`BoundRegionKind`] enum. This enum can contain a + [`DefId`][defid] or it might have various "anonymous" numbered names. The + latter arise from types like `fn(&u32, &u32)`, which are equivalent to + something like `for<'a, 'b> fn(&'a u32, &'b u32)`, but the names of those + lifetimes must be generated. + +This setup of not knowing the full set of variables at a binding level has some +advantages and some disadvantages. The disadvantage is that you must walk the +type to find out what is bound at the given level and so forth. The advantage +is primarily that, when constructing types from Rust syntax, if we encounter +anonymous regions like in `fn(&u32)`, we just create a fresh index and don't have +to update the binder. + +[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html +[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html +[defid]: ./hir.html#identifiers-in-the-hir diff --git a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md index e69ce48f9..388e39b93 100644 --- a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md +++ b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md @@ -304,7 +304,7 @@ self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, We want to convert this into an error. In some cases, there may be an existing error for this scenario. In others, we will need to allocate a fresh diagnostic code. [Instructions for allocating a fresh diagnostic -code can be found here.](./diagnostics/diagnostic-codes.md) You may want +code can be found here.](./diagnostics/error-codes.md) You may want to mention in the extended description that the compiler behavior changed on this point, and include a reference to the tracking issue for the change. @@ -325,7 +325,7 @@ general, if the test used to have `#[deny(overlapping_inherent_impls)]`, that can just be removed. ``` -./x.py test +./x test ``` #### All done! diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index d53896f81..936c75f36 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -96,7 +96,7 @@ However, it takes a very long time to build because one must first build the new compiler with an older compiler and then use that to build the new compiler with itself. For development, you usually only want the `stage1` compiler, -which you can build with `./x.py build library`. +which you can build with `./x build library`. See [Building the compiler](./how-to-build-and-run.html#building-the-compiler). ### Stage 3: the same-result test @@ -107,7 +107,7 @@ to be identical to before, unless something has broken. ### Building the stages -`x.py` tries to be helpful and pick the stage you most likely meant for each subcommand. +`x` tries to be helpful and pick the stage you most likely meant for each subcommand. These defaults are as follows: - `check`: `--stage 0` @@ -152,7 +152,7 @@ bootstrapping the compiler. This is a detailed look into the separate bootstrap stages. -The convention `x.py` uses is that: +The convention `x` uses is that: - A `--stage N` flag means to run the stage N compiler (`stageN/rustc`). - A "stage N artifact" is a build artifact that is _produced_ by the stage N compiler. @@ -161,7 +161,7 @@ The convention `x.py` uses is that: #### Build artifacts -Anything you can build with `x.py` is a _build artifact_. +Anything you can build with `x` is a _build artifact_. Build artifacts include, but are not limited to: - binaries, like `stage0-rustc/rustc-main` @@ -173,27 +173,27 @@ Build artifacts include, but are not limited to: #### Examples -- `./x.py build --stage 0` means to build with the beta `rustc`. -- `./x.py doc --stage 0` means to document using the beta `rustdoc`. -- `./x.py test --stage 0 library/std` means to run tests on the standard library - without building `rustc` from source ('build with stage 0, then test the +- `./x build --stage 0` means to build with the beta `rustc`. +- `./x doc --stage 0` means to document using the beta `rustdoc`. +- `./x test --stage 0 library/std` means to run tests on the standard library + without building `rustc` from source ('build with stage 0, then test the artifacts'). If you're working on the standard library, this is normally the test command you want. -- `./x.py test tests/ui` means to build the stage 1 compiler and run +- `./x test tests/ui` means to build the stage 1 compiler and run `compiletest` on it. If you're working on the compiler, this is normally the test command you want. #### Examples of what *not* to do -- `./x.py test --stage 0 tests/ui` is not useful: it runs tests on the +- `./x test --stage 0 tests/ui` is not useful: it runs tests on the _beta_ compiler and doesn't build `rustc` from source. Use `test tests/ui` instead, which builds stage 1 from source. -- `./x.py test --stage 0 compiler/rustc` builds the compiler but runs no tests: +- `./x test --stage 0 compiler/rustc` builds the compiler but runs no tests: it's running `cargo test -p rustc`, but cargo doesn't understand Rust's tests. You shouldn't need to use this, use `test` instead (without arguments). -- `./x.py build --stage 0 compiler/rustc` builds the compiler, but does not build - libstd or even libcore. Most of the time, you'll want `./x.py build - library` instead, which allows compiling programs without needing to define +- `./x build --stage 0 compiler/rustc` builds the compiler, but does not build + libstd or even libcore. Most of the time, you'll want `./x build +library` instead, which allows compiling programs without needing to define lang items. ### Building vs. running @@ -243,7 +243,7 @@ artifacts into the appropriate place, skipping the cargo invocation. For instance, you might want to build an ARM version of rustc using an x86 machine. Building stage2 `std` is different when you are cross-compiling. -This is because `x.py` uses a trick: if `HOST` and `TARGET` are the same, +This is because `x` uses a trick: if `HOST` and `TARGET` are the same, it will reuse stage1 `std` for stage2! This is sound because stage1 `std` was compiled with the stage1 compiler, i.e. a compiler using the source code you currently have checked out. So it should be identical (and therefore ABI-compatible) @@ -362,7 +362,7 @@ You can find more discussion about sysroots in: ## Passing flags to commands invoked by `bootstrap` -`x.py` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping. +`x` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping. The `RUSTFLAGS_BOOTSTRAP` environment variable is passed as `RUSTFLAGS` to the bootstrap stage (stage0), and `RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages. `RUSTFLAGS` will work, but also affects the build of `bootstrap` itself, so it will be rare to want @@ -395,7 +395,7 @@ If `./stageN/bin/rustc` gives an error about environment variables, that usually means something is quite wrong -- or you're trying to compile e.g. `rustc` or `std` or something that depends on environment variables. In the unlikely case that you actually need to invoke rustc in such a situation, -you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x.py` command. +you can tell the bootstrap shim to print all env variables by adding `-vvv` to your `x` command. Finally, bootstrap makes use of the [cc-rs crate] which has [its own method][env-vars] of configuring C compilers and C flags via environment @@ -408,7 +408,7 @@ variables. In this part, we will investigate the build command's stdout in an action (similar, but more detailed and complete documentation compare to topic above). -When you execute `x.py build --dry-run` command, the build output will be something +When you execute `x build --dry-run` command, the build output will be something like the following: ```text diff --git a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md index 4ec3f958a..df3037469 100644 --- a/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md +++ b/src/doc/rustc-dev-guide/src/building/build-install-distribution-artifacts.md @@ -3,22 +3,22 @@ You might want to build and package up the compiler for distribution. You’ll want to run this command to do it: - ```bash - ./x.py dist - ``` +```bash +./x dist +``` # Install distribution artifacts If you’ve built a distribution artifact you might want to install it and test that it works on your target system. You’ll want to run this command: - ```bash - ./x.py install - ``` +```bash +./x install +``` Note: If you are testing out a modification to a compiler, you might want to use it to compile some project. - Usually, you do not want to use `./x.py install` for testing. + Usually, you do not want to use `./x install` for testing. Rather, you should create a toolchain as discussed in [here][create-rustup-toolchain]. diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index 4e72bf994..948571ce8 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -10,13 +10,13 @@ like the standard library (std) or the compiler (rustc). as rustdoc is under active development: ```bash - ./x.py doc + ./x doc ``` If you want to be sure the documentation looks the same as on CI: ```bash - ./x.py doc --stage 1 + ./x doc --stage 1 ``` This ensures that (current) rustdoc gets built, @@ -26,9 +26,9 @@ like the standard library (std) or the compiler (rustc). you can build just the documentation you want: ```bash - ./x.py doc src/doc/book - ./x.py doc src/doc/nomicon - ./x.py doc compiler library + ./x doc src/doc/book + ./x doc src/doc/nomicon + ./x doc compiler library ``` See [the nightly docs index page](https://doc.rust-lang.org/nightly/) for a full list of books. @@ -36,7 +36,7 @@ like the standard library (std) or the compiler (rustc). - Document internal rustc items Compiler documentation is not built by default. - To create it by default with `x.py doc`, modify `config.toml`: + To create it by default with `x doc`, modify `config.toml`: ```toml [build] diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 6444aab5f..0865f1955 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -5,9 +5,6 @@ The compiler is built using a tool called `x.py`. You will need to have Python installed to run it. -For instructions on how to install Python and other prerequisites, -see [the `rust-lang/rust` README][readme]. - ## Get the source code The main repository is [`rust-lang/rust`][repo]. This contains the compiler, @@ -15,7 +12,6 @@ the standard library (including `core`, `alloc`, `test`, `proc_macro`, etc), and a bunch of tools (e.g. `rustdoc`, the bootstrapping infrastructure, etc). [repo]: https://github.com/rust-lang/rust -[readme]: https://github.com/rust-lang/rust#building-on-a-unix-like-system The very first step to work on `rustc` is to clone the repository: @@ -57,7 +53,75 @@ if you want to learn more about `x.py`, [read this chapter][bootstrap]. [bootstrap]: ./bootstrapping.md -### Running `x.py` slightly more conveniently +Also, using `x` rather than `x.py` is recommended as: + +> `./x` is the most likely to work on every system (on Unix it runs the shell script +> that does python version detection, on Windows it will probably run the +> powershell script - certainly less likely to break than `./x.py` which often just +> opens the file in an editor).[^1] + +(You can find the platform related scripts around the `x.py`, like `x.ps1`) + +Notice that this is not absolute, for instance, using Nushell in VSCode on Win10, +typing `x` or `./x` still open the `x.py` in editor rather invoke the program :) + +In the rest of documents, we use `x` to represent the straightly usage of `x.py`, which +means the following command: + +```bash +./x check +``` + +could be replaced by: + +```bash +./x.py check +``` + +### Running `x.py` + +The `x.py` command can be run directly on most Unix systems in the following format: + +```sh +./x <subcommand> [flags] +``` + +This is how the documentation and examples assume you are running `x.py`. +Some alternative ways are: + +```sh +# On a Unix shell if you don't have the necessary `python3` command +./x <subcommand> [flags] + +# In Windows Powershell (if powershell is configured to run scripts) +./x <subcommand> [flags] +./x.ps1 <subcommand> [flags] + +# On the Windows Command Prompt (if .py files are configured to run Python) +x.py <subcommand> [flags] + +# You can also run Python yourself, e.g.: +python x.py <subcommand> [flags] +``` + +On Windows, the Powershell commands may give you an error that looks like this: +``` +PS C:\Users\vboxuser\rust> ./x +./x : File C:\Users\vboxuser\rust\x.ps1 cannot be loaded because running scripts is disabled on this system. For more +information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170. +At line:1 char:1 ++ ./x ++ ~~~ + + CategoryInfo : SecurityError: (:) [], PSSecurityException + + FullyQualifiedErrorId : UnauthorizedAccess +``` + +You can avoid this error by allowing powershell to run local scripts: +``` +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +``` + +#### Running `x.py` slightly more conveniently There is a binary that wraps `x.py` called `x` in `src/tools/x`. All it does is run `x.py`, but it can be installed system-wide and run from any subdirectory @@ -65,9 +129,14 @@ of a checkout. It also looks up the appropriate version of `python` to use. You can install it with `cargo install --path src/tools/x`. +To clarify that this is another global installed binary util, which is +similar to the one declared in section [What is `x.py`](#what-is-xpy), but +it works as an independent process to execute the `x.py` rather than calling the +shell to run the platform related scripts. + ## Create a `config.toml` -To start, run `./x.py setup` and select the `compiler` defaults. This will do some initialization +To start, run `./x setup` and select the `compiler` defaults. This will do some initialization and create a `config.toml` for you with reasonable defaults. If you use a different default (which you'll likely want to do if you want to contribute to an area of rust other than the compiler, such as rustdoc), make sure to read information about that default (located in `src/bootstrap/defaults`) @@ -77,35 +146,35 @@ Alternatively, you can write `config.toml` by hand. See `config.example.toml` fo settings and explanations of them. See `src/bootstrap/defaults` for common settings to change. If you have already built `rustc` and you change settings related to LLVM, then you may have to -execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x.py +execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x clean` will not cause a rebuild of LLVM. -## Common `x.py` commands +## Common `x` commands -Here are the basic invocations of the `x.py` commands most commonly used when +Here are the basic invocations of the `x` commands most commonly used when working on `rustc`, `std`, `rustdoc`, and other tools. -| Command | When to use it | -| --- | --- | -| `./x.py check` | Quick check to see if most things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | -| `./x.py build` | Builds `rustc`, `std`, and `rustdoc` | -| `./x.py test` | Runs all tests | -| `./x.py fmt` | Formats all code | +| Command | When to use it | +| ----------- | ------------------------------------------------------------------------------------------------------------ | +| `./x check` | Quick check to see if most things compile; [rust-analyzer can run this automatically for you][rust-analyzer] | +| `./x build` | Builds `rustc`, `std`, and `rustdoc` | +| `./x test` | Runs all tests | +| `./x fmt` | Formats all code | As written, these commands are reasonable starting points. However, there are additional options and arguments for each of them that are worth learning for -serious development work. In particular, `./x.py build` and `./x.py test` +serious development work. In particular, `./x build` and `./x test` provide many ways to compile or test a subset of the code, which can save a lot of time. -Also, note that `x.py` supports all kinds of path suffixes for `compiler`, `library`, -and `src/tools` directories. So, you can simply run `x.py test tidy` instead of -`x.py test src/tools/tidy`. Or, `x.py build std` instead of `x.py build library/std`. +Also, note that `x` supports all kinds of path suffixes for `compiler`, `library`, +and `src/tools` directories. So, you can simply run `x test tidy` instead of +`x test src/tools/tidy`. Or, `x build std` instead of `x build library/std`. [rust-analyzer]: suggested.html#configuring-rust-analyzer-for-rustc -See the chapters on [building](how-to-build-and-run), -[testing](../tests/intro), and [rustdoc](../rustdoc) for more details. +See the chapters on +[testing](../tests/running.md) and [rustdoc](../rustdoc.md) for more details. ### Building the compiler @@ -113,11 +182,11 @@ Note that building will require a relatively large amount of storage space. You may want to have upwards of 10 or 15 gigabytes available to build the compiler. Once you've created a `config.toml`, you are now ready to run -`x.py`. There are a lot of options here, but let's start with what is +`x`. There are a lot of options here, but let's start with what is probably the best "go to" command for building a local compiler: ```bash -./x.py build library +./x build library ``` This may *look* like it only builds the standard library, but that is not the case. @@ -140,10 +209,10 @@ see [the section on avoiding rebuilds for std][keep-stage]. Sometimes you don't need a full build. When doing some kind of "type-based refactoring", like renaming a method, or changing the -signature of some function, you can use `./x.py check` instead for a much faster build. +signature of some function, you can use `./x check` instead for a much faster build. Note that this whole command just gives you a subset of the full `rustc` -build. The **full** `rustc` build (what you get with `./x.py build +build. The **full** `rustc` build (what you get with `./x build --stage 2 compiler/rustc`) has quite a few more steps: - Build `rustc` with the stage1 compiler. @@ -160,10 +229,10 @@ the compiler unless you are planning to use a recently added nightly feature. Instead, you can just build using the bootstrap compiler. ```bash -./x.py build --stage 0 library +./x build --stage 0 library ``` -If you choose the `library` profile when running `x.py setup`, you can omit `--stage 0` (it's the +If you choose the `library` profile when running `x setup`, you can omit `--stage 0` (it's the default). ## Creating a rustup toolchain @@ -198,7 +267,7 @@ LLVM version: 11.0 ``` The rustup toolchain points to the specified toolchain compiled in your `build` directory, -so the rustup toolchain will be updated whenever `x.py build` or `x.py test` are run for +so the rustup toolchain will be updated whenever `x build` or `x test` are run for that toolchain/stage. **Note:** the toolchain we've built does not include `cargo`. In this case, `rustup` will @@ -213,25 +282,25 @@ custom toolchain for a project (e.g. via `rustup override set stage1`) you may want to build this component: ```bash -./x.py build proc-macro-srv-cli +./x build proc-macro-srv-cli ``` ## Building targets for cross-compilation To produce a compiler that can cross-compile for other targets, -pass any number of `target` flags to `x.py build`. +pass any number of `target` flags to `x build`. For example, if your host platform is `x86_64-unknown-linux-gnu` and your cross-compilation target is `wasm32-wasi`, you can build with: ```bash -./x.py build --target x86_64-unknown-linux-gnu --target wasm32-wasi +./x build --target x86_64-unknown-linux-gnu --target wasm32-wasi ``` Note that if you want the resulting compiler to be able to build crates that involve proc macros or build scripts, you must be sure to explicitly build target support for the host platform (in this case, `x86_64-unknown-linux-gnu`). -If you want to always build for other targets without needing to pass flags to `x.py build`, +If you want to always build for other targets without needing to pass flags to `x build`, you can configure this in the `[build]` section of your `config.toml` like so: ```toml @@ -260,24 +329,24 @@ then once you have built your compiler you will be able to use it to cross-compi cargo +stage1 build --target wasm32-wasi ``` -## Other `x.py` commands +## Other `x` commands -Here are a few other useful `x.py` commands. We'll cover some of them in detail +Here are a few other useful `x` commands. We'll cover some of them in detail in other sections: - Building things: - - `./x.py build` – builds everything using the stage 1 compiler, + - `./x build` – builds everything using the stage 1 compiler, not just up to `std` - - `./x.py build --stage 2` – builds everything with the stage 2 compiler including + - `./x build --stage 2` – builds everything with the stage 2 compiler including `rustdoc` - Running tests (see the [section on running tests](../tests/running.html) for more details): - - `./x.py test library/std` – runs the unit tests and integration tests from `std` - - `./x.py test tests/ui` – runs the `ui` test suite - - `./x.py test tests/ui/const-generics` - runs all the tests in - the `const-generics/` subdirectory of the `ui` test suite - - `./x.py test tests/ui/const-generics/const-types.rs` - runs - the single test `const-types.rs` from the `ui` test suite + - `./x test library/std` – runs the unit tests and integration tests from `std` + - `./x test tests/ui` – runs the `ui` test suite + - `./x test tests/ui/const-generics` - runs all the tests in + the `const-generics/` subdirectory of the `ui` test suite + - `./x test tests/ui/const-generics/const-types.rs` - runs + the single test `const-types.rs` from the `ui` test suite ### Cleaning out build directories @@ -287,8 +356,10 @@ you should file a bug as to what is going wrong. If you do need to clean everything up then you only need to run one command! ```bash -./x.py clean +./x clean ``` `rm -rf build` works too, but then you have to rebuild LLVM, which can take a long time even on fast computers. + +[^1]: issue[#1707](https://github.com/rust-lang/rustc-dev-guide/issues/1707) diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index 629445be6..83973f2c9 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -10,7 +10,7 @@ relevant to your desired goal. For very new targets, you may need to use a different fork of LLVM than what is currently shipped with Rust. In that case, navigate to -the `src/llvm-project` git submodule (you might need to run `./x.py +the `src/llvm-project` git submodule (you might need to run `./x check` at least once so the submodule is updated), check out the appropriate commit for your fork, then commit that new submodule reference in the main Rust repository. @@ -135,7 +135,7 @@ cross-compile `rustc`: ``` DESTDIR=/path/to/install/in \ -./x.py install -i --stage 1 --host aarch64-apple-darwin.json --target aarch64-apple-darwin \ +./x install -i --stage 1 --host aarch64-apple-darwin.json --target aarch64-apple-darwin \ compiler/rustc library/std ``` diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index 3dc2ea934..c511c7c81 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -20,7 +20,7 @@ recommend trying to build on a Raspberry Pi! We recommend the following. * 2+ cores. Having more cores really helps. 10 or 20 or more is not too many! Beefier machines will lead to much faster builds. If your machine is not very -powerful, a common strategy is to only use `./x.py check` on your local machine +powerful, a common strategy is to only use `./x check` on your local machine and let the CI build test your changes when you push to a PR branch. Building the compiler takes more than half an hour on my moderately powerful diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 9dcc795f2..0da3f60cf 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -10,14 +10,14 @@ to make your life easier. CI will automatically fail your build if it doesn't pass `tidy`, our internal tool for ensuring code quality. If you'd like, you can install a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -that will automatically run `./x.py test tidy` on each push, to ensure -your code is up to par. If the hook fails then run `./x.py test tidy --bless` +that will automatically run `./x test tidy` on each push, to ensure +your code is up to par. If the hook fails then run `./x test tidy --bless` and commit the changes. If you decide later that the pre-push behavior is undesirable, you can delete the `pre-push` file in `.git/hooks`. A prebuilt git hook lives at [`src/etc/pre-push.sh`](https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh) which can be copied into your `.git/hooks` folder as `pre-push` (without the `.sh` extension!). -You can also install the hook as a step of running `./x.py setup`! +You can also install the hook as a step of running `./x setup`! ## Configuring `rust-analyzer` for `rustc` @@ -26,22 +26,19 @@ You can also install the hook as a step of running `./x.py setup`! `rust-analyzer` can help you check and format your code whenever you save a file. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, but you can override these commands to use more adapted versions -of these tools when hacking on `rustc`. For example, `x.py setup vscode` will prompt +of these tools when hacking on `rustc`. For example, `x setup vscode` will prompt you to create a `.vscode/settings.json` file which will configure Visual Studio code. -This will ask `rust-analyzer` to use `./x.py check` to check the sources, and the +This will ask `rust-analyzer` to use `./x check` to check the sources, and the stage 0 rustfmt to format them. The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`]. -If you have enough free disk space and you would like to be able to run `x.py` commands while +If you have enough free disk space and you would like to be able to run `x` commands while rust-analyzer runs in the background, you can also add `--build-dir build-rust-analyzer` to the -`overrideCommand` to avoid x.py locking. - -If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a -`.vim/coc-settings.json` and copy the settings from [`src/etc/rust_analyzer_settings.json`]. +`overrideCommand` to avoid x locking. [`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json -If running `./x.py check` on save is inconvenient, in VS Code you can use a [Build +If running `./x check` on save is inconvenient, in VS Code you can use a [Build Task] instead: ```JSON @@ -50,8 +47,8 @@ Task] instead: "version": "2.0.0", "tasks": [ { - "label": "./x.py check", - "command": "./x.py check", + "label": "./x check", + "command": "./x check", "type": "shell", "problemMatcher": "$rustc", "presentation": { "clear": true }, @@ -73,13 +70,13 @@ Rust-Analyzer to already be configured with Neovim. Steps for this can be [found here](https://rust-analyzer.github.io/manual.html#nvim-lsp). 1. First install the plugin. This can be done by following the steps in the README. -2. Run `x.py setup`, which will have a prompt for it to create a `.vscode/settings.json` file. -`neoconf` is able to read and update Rust-Analyzer settings automatically when the project is -opened when this file is detected. +2. Run `x setup`, which will have a prompt for it to create a `.vscode/settings.json` file. + `neoconf` is able to read and update Rust-Analyzer settings automatically when the project is + opened when this file is detected. If you're running `coc.nvim`, you can use `:CocLocalConfig` to create a `.vim/coc-settings.json` and copy the settings from -[this file](https://github.com/rust-lang/rust/blob/master/src/etc/vscode_settings.json). +[this file](https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json). Another way is without a plugin, and creating your own logic in your configuration. To do this you must translate the JSON to Lua yourself. The translation is 1:1 and fairly straight-forward. It @@ -94,11 +91,11 @@ follow the same instructions as above. ## Check, check, and check again -When doing simple refactorings, it can be useful to run `./x.py check` +When doing simple refactorings, it can be useful to run `./x check` continuously. If you set up `rust-analyzer` as described above, this will be done for you every time you save a file. Here you are just checking that the compiler can **build**, but often that is all you need (e.g., when renaming a -method). You can then run `./x.py build` when you actually need to +method). You can then run `./x build` when you actually need to run tests. In fact, it is sometimes useful to put off tests even when you are not @@ -141,11 +138,11 @@ directories you have [setup a worktree for]. You may need to use the pinned nightly version from `src/stage0.json`, but often the normal `nightly` channel will work. -**Note** see [the section on vscode] for how to configure it with this real rustfmt `x.py` uses, +**Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses, and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler **Note** This does _not_ allow you to build `rustc` with cargo directly. You -still have to use `x.py` to work on the compiler or standard library, this just +still have to use `x` to work on the compiler or standard library, this just lets you use `cargo fmt`. [installing a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust @@ -166,13 +163,13 @@ don't work (but that is easily detected and fixed). The sequence of commands you want is as follows: -- Initial build: `./x.py build library` +- Initial build: `./x build library` - As [documented previously], this will build a functional stage1 compiler as part of running all stage0 commands (which include building a `std` compatible with the stage1 compiler) as well as the first few steps of the "stage 1 actions" up to "stage1 (sysroot stage1) builds std". -- Subsequent builds: `./x.py build library --keep-stage 1` +- Subsequent builds: `./x build library --keep-stage 1` - Note that we added the `--keep-stage 1` flag here [documented previously]: ./how-to-build-and-run.md#building-the-compiler @@ -194,8 +191,8 @@ rebuild. That ought to fix the problem. You can also use `--keep-stage 1` when running tests. Something like this: -- Initial test run: `./x.py test tests/ui` -- Subsequent test run: `./x.py test tests/ui --keep-stage 1` +- Initial test run: `./x test tests/ui` +- Subsequent test run: `./x test tests/ui --keep-stage 1` ## Using incremental compilation @@ -203,7 +200,7 @@ You can further enable the `--incremental` flag to save additional time in subsequent rebuilds: ```bash -./x.py test tests/ui --incremental --test-args issue-1234 +./x test tests/ui --incremental --test-args issue-1234 ``` If you don't want to include the flag with every command, you can @@ -348,4 +345,4 @@ Zsh support will also be included once issues with [`clap_complete`](https://cra You can use `source ./src/etc/completions/x.py.<extension>` to load completions for your shell of choice, or `source .\src\etc\completions\x.py.ps1` for PowerShell. -Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion.
\ No newline at end of file +Adding this to your shell's startup script (e.g. `.bashrc`) will automatically load this completion. diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index e356f415d..786c831ee 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -115,10 +115,10 @@ Let's start with defining a term that we will be using quite a bit in the rest o *upvar*. An **upvar** is a variable that is local to the function where the closure is defined. So, in the above examples, **x** will be an upvar to the closure. They are also sometimes referred to as the *free variables* meaning they are not bound to the context of the closure. -[`compiler/rustc_middle/src/ty/query/mod.rs`][upvars] defines a query called *upvars_mentioned* +[`compiler/rustc_passes/src/upvars.rs`][upvars] defines a query called *upvars_mentioned* for this purpose. -[upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_query_impl/queries/struct.upvars_mentioned.html +[upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_passes/upvars/index.html Other than lazy invocation, one other thing that distinguishes a closure from a normal function is that it can use the upvars. It borrows these upvars from its surrounding diff --git a/src/doc/rustc-dev-guide/src/compiler-src.md b/src/doc/rustc-dev-guide/src/compiler-src.md index 9c7d0bb2e..6090c6787 100644 --- a/src/doc/rustc-dev-guide/src/compiler-src.md +++ b/src/doc/rustc-dev-guide/src/compiler-src.md @@ -195,11 +195,8 @@ These include: run a lot of tests on a lot of platforms. - [`src/doc`]: Various documentation, including submodules for a few books. - [`src/etc`]: Miscellaneous utilities. -- [`src/tools/rustc-workspace-hack`], and others: Various workarounds to make - cargo work with bootstrapping. - And more... [`src/ci`]: https://github.com/rust-lang/rust/tree/master/src/ci [`src/doc`]: https://github.com/rust-lang/rust/tree/master/src/doc [`src/etc`]: https://github.com/rust-lang/rust/tree/master/src/etc -[`src/tools/rustc-workspace-hack`]: https://github.com/rust-lang/rust/tree/master/src/tools/rustc-workspace-hack diff --git a/src/doc/rustc-dev-guide/src/constants.md b/src/doc/rustc-dev-guide/src/constants.md index 91d21bd32..56d01cc79 100644 --- a/src/doc/rustc-dev-guide/src/constants.md +++ b/src/doc/rustc-dev-guide/src/constants.md @@ -77,6 +77,6 @@ the constant doesn't use them in any way. This can cause [some interesting errors][pcg-unused-substs] and breaks some already stable code. [`ty::Const`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Const.html -[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.ConstKind.html +[`ty::ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.ConstKind.html [`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html [pcg-unused-substs]: https://github.com/rust-lang/project-const-generics/issues/33 diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index d6037c7f1..d6b9fc84d 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -2,7 +2,7 @@ <!-- toc --> -## Bug Reports +## Bug reports While bugs are unfortunate, they're a reality in software. We can't fix what we don't know about, so please report liberally. If you're not sure if something @@ -16,8 +16,7 @@ please follow our [instructions for reporting security vulnerabilities][vuln]**. If you're using the nightly channel, please check if the bug exists in the latest toolchain before filing your bug. It might be fixed already. -If you have the chance, before reporting a bug, please [search existing -issues](https://github.com/rust-lang/rust/issues?q=is%3Aissue), +If you have the chance, before reporting a bug, please [search existing issues], as it's possible that someone else has already reported your error. This doesn't always work, and sometimes it's hard to know what to search for, so consider this extra credit. We won't mind if you accidentally file a duplicate report. @@ -33,22 +32,22 @@ Opening an issue is as easy as following [this link](https://github.com/rust-lang/rust/issues/new/choose) and filling out the fields in the appropriate provided template. -## Bug Fixes or "Normal" code changes +## Bug fixes or "normal" code changes -For most PRs, no special procedures are needed. You can just [open a PR][prs], and it +For most PRs, no special procedures are needed. You can just [open a PR], and it will be reviewed, approved, and merged. This includes most bug fixes, refactorings, and other user-invisible changes. The next few sections talk about exceptions to this rule. -Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft -PRs][draft]. Some people prefer to do this so they can get feedback along the +Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft PRs]. +Some people prefer to do this so they can get feedback along the way or share their code with a collaborator. Others do this so they can utilize -the CI to build and test their PR (e.g. if you are developing on a laptop). +the CI to build and test their PR (e.g. when developing on a slow machine). -[prs]: #pull-requests -[draft]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ +[open a PR]: #pull-requests +[Draft PRs]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ -## New Features +## New features Rust has strong backwards-compatibility guarantees. Thus, new features can't just be implemented directly in stable Rust. Instead, we have 3 release @@ -63,13 +62,11 @@ channels: stable, beta, and nightly. See [this chapter on implementing new features](./implementing_new_features.md) for more information. -### Breaking Changes +### Breaking changes -Breaking changes have a [dedicated section][breaking-changes] in the dev-guide. +Breaking changes have a [dedicated section][Breaking Changes] in the dev-guide. -[breaking-changes]: ./bug-fix-procedure.md - -### Major Changes +### Major changes The compiler team has a special process for large changes, whether or not they cause breakage. This process is called a Major Change Proposal (MCP). MCP is a @@ -80,12 +77,12 @@ Example of things that might require MCPs include major refactorings, changes to important types, or important changes to how the compiler does something, or smaller user-facing changes. -**When in doubt, ask on [zulip][z]. It would be a shame to put a lot of work +**When in doubt, ask on [zulip]. It would be a shame to put a lot of work into a PR that ends up not getting merged!** [See this document][mcpinfo] for more info on MCPs. [mcpinfo]: https://forge.rust-lang.org/compiler/mcp.html -[z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler +[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler ### Performance @@ -95,19 +92,19 @@ few years into [gradually improving it][perfdash]. [perfdash]: https://perf.rust-lang.org/dashboard.html If you suspect that your change may cause a performance regression (or -improvement), you can request a "perf run" (your reviewer may also request one +improvement), you can request a "perf run" (and your reviewer may also request one before approving). This is yet another bot that will compile a collection of benchmarks on a compiler with your changes. The numbers are reported [here][perf], and you can see a comparison of your changes against the latest master. -For an introduction to the performance of Rust code in general -which would also be useful in rustc development, see [The Rust Performance Book]. +> For an introduction to the performance of Rust code in general +> which would also be useful in rustc development, see [The Rust Performance Book]. [perf]: https://perf.rust-lang.org [The Rust Performance Book]: https://nnethercote.github.io/perf-book/ -## Pull Requests +## Pull requests Pull requests (or PRs for short) are the primary mechanism we use to change Rust. GitHub itself has some [great documentation][about-pull-requests] on using the @@ -135,15 +132,15 @@ to the end of the pull request description, and [@rustbot] will assign them instead of a random person. This is entirely optional. You can also assign a random reviewer from a specific team by writing `r? rust-lang/groupname`. -So if you were making a diagnostics change, then you could get a reviewer from the diagnostics -team by adding: +As an example, +if you were making a diagnostics change, +then you could get a reviewer from the diagnostics team by adding: r? rust-lang/diagnostics -For a full list of possible `groupname` check the `adhoc_groups` section at the -[triagebot.toml config file](https://github.com/rust-lang/rust/blob/master/triagebot.toml) -or the list of teams in the [rust-lang teams -database](https://github.com/rust-lang/team/tree/master/teams). +For a full list of possible `groupname`s, +check the `adhoc_groups` section at the [triagebot.toml config file], +or the list of teams in the [rust-lang teams database]. ### Waiting for reviews @@ -175,22 +172,21 @@ Zulip ([#t-release/triage]). They have knowledge of when to ping, who might be on vacation, etc. The reviewer may request some changes using the GitHub code review interface. -They may also request special procedures (such as a [crater] run; [see -below][break]) for some PRs. +They may also request special procedures for some PRs. +See [Crater] and [Breaking Changes] chapters for some examples of such procedures. [r?]: https://github.com/rust-lang/rust/pull/78133#issuecomment-712692371 [#t-release/triage]: https://rust-lang.zulipchat.com/#narrow/stream/242269-t-release.2Ftriage -[break]: #breaking-changes +[Crater]: tests/crater.md + ### CI -In addition to being reviewed by a human, pull requests are automatically tested +In addition to being reviewed by a human, pull requests are automatically tested, thanks to continuous integration (CI). Basically, every time you open and update a pull request, CI builds the compiler and tests it against the -[compiler test suite][rctd], and also performs other tests such as checking that +[compiler test suite], and also performs other tests such as checking that your pull request is in compliance with Rust's style guidelines. -[rctd]: tests/intro.md - Running continuous integration tests allows PR authors to catch mistakes early without going through a first review cycle, and also helps reviewers stay aware of the status of a particular pull request. @@ -198,7 +194,7 @@ of the status of a particular pull request. Rust has plenty of CI capacity, and you should never have to worry about wasting computational resources each time you push a change. It is also perfectly fine (and even encouraged!) to use the CI to test your changes if it can help your -productivity. In particular, we don't recommend running the full `./x.py test` suite locally, +productivity. In particular, we don't recommend running the full `./x test` suite locally, since it takes a very long time to execute. ### r+ @@ -209,7 +205,7 @@ on the pull request with an `r+`. It will look something like this: @bors r+ This tells [@bors], our lovable integration bot, that your pull request has -been approved. The PR then enters the [merge queue][merge-queue], where [@bors] +been approved. The PR then enters the [merge queue], where [@bors] will run *all* the tests on *every* platform we support. If it all works out, [@bors] will merge your code into `master` and close the pull request. @@ -226,25 +222,23 @@ Be patient; this can take a while and the queue can sometimes be long. PRs are n [@rustbot]: https://github.com/rustbot [@bors]: https://github.com/bors -[merge-queue]: https://bors.rust-lang.org/queue/rust ### Opening a PR You are now ready to file a pull request? Great! Here are a few points you should be aware of. -All pull requests should be filed against the `master` branch, except in very -particular scenarios. Unless you know for sure that you should target another -branch, `master` will be the right choice (it's also the default). +All pull requests should be filed against the `master` branch, +unless you know for sure that you should target a different branch. Make sure your pull request is in compliance with Rust's style guidelines by running - $ ./x.py test tidy --bless + $ ./x test tidy --bless We recommend to make this check before every pull request (and every new commit -in a pull request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) -before every push to make sure you never forget to make this check. The -CI will also run tidy and will fail if tidy fails. +in a pull request); you can add [git hooks] +before every push to make sure you never forget to make this check. +The CI will also run tidy and will fail if tidy fails. Rust follows a _no merge-commit policy_, meaning, when you encounter merge conflicts you are expected to always rebase instead of merging. E.g. always use @@ -268,11 +262,11 @@ the issue in question. [labeling]: ./rustbot.md#issue-relabeling [closing-keywords]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue -## External Dependencies +## External dependencies This section has moved to ["Using External Repositories"](./external-repos.md). -## Writing Documentation +## Writing documentation Documentation improvements are very welcome. The source of `doc.rust-lang.org` is located in [`src/doc`] in the tree, and standard API documentation is generated @@ -282,13 +276,9 @@ function in the same way as other pull requests. [`src/doc`]: https://github.com/rust-lang/rust/tree/master/src/doc [std-root]: https://github.com/rust-lang/rust/blob/master/library/std/src/lib.rs#L1 -To find documentation-related issues, sort by the [A-docs label][adocs]. - -[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs - -You can find documentation style guidelines in [RFC 1574][rfc1574]. +To find documentation-related issues, sort by the [A-docs label]. -[rfc1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text +You can find documentation style guidelines in [RFC 1574]. To build the standard library documentation, use `x doc --stage 0 library --open`. To build the documentation for a book (e.g. the unstable book), use `x doc src/doc/unstable-book.` @@ -302,22 +292,23 @@ The CSS might be messed up, but you can verify that the HTML is right. ### Contributing to rustc-dev-guide -Contributions to the [rustc-dev-guide][rdg] are always welcome, and can be made directly at +Contributions to the [rustc-dev-guide] are always welcome, and can be made directly at [the rust-lang/rustc-dev-guide repo][rdgrepo]. The issue tracker in that repo is also a great way to find things that need doing. There are issues for beginners and advanced compiler devs alike! Just a few things to keep in mind: -- Please limit line length to 100 characters. This is enforced by CI, and you can run the checks - locally with `ci/lengthcheck.sh`. +- Please limit line length to 100 characters. + This is enforced by CI, + and you can run the checks locally with `ci/lengthcheck.sh`. - When contributing text to the guide, please contextualize the information with some time period and/or a reason so that the reader knows how much to trust or mistrust the information. Aim to provide a reasonable amount of context, possibly including but not limited to: - - A reason for why the data may be out of date other than "change", as change is a constant across - the project. + - A reason for why the data may be out of date other than "change", + as change is a constant across the project. - The date the comment was added, e.g. instead of writing _"Currently, ..."_ or _"As of now, ..."_, @@ -358,19 +349,15 @@ Just a few things to keep in mind: subsections) it might benefit from having a Table of Contents at the beginning, which you can auto-generate by including the `<!-- toc -->` marker. -[rdg]: https://rustc-dev-guide.rust-lang.org/ -[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide - -## Issue Triage +## Issue triage -Sometimes, an issue will stay open, even though the bug has been fixed. And -sometimes, the original bug may go stale because something has changed in the -meantime. +Sometimes, an issue will stay open, even though the bug has been fixed. +And sometimes, the original bug may go stale because something has changed in the meantime. -It can be helpful to go through older bug reports and make sure that they are -still valid. Load up an older issue, double check that it's still true, and -leave a comment letting us know if it is or is not. The [least recently -updated sort][lru] is good for finding issues like this. +It can be helpful to go through older bug reports and make sure that they are still valid. +Load up an older issue, double check that it's still true, +and leave a comment letting us know if it is or is not. +The [least recently updated sort][lru] is good for finding issues like this. [Thanks to `@rustbot`][rustbot], anyone can help triage issues by adding appropriate labels to issues that haven't been triaged yet: @@ -466,8 +453,19 @@ This is used for [RFCs], issues, and pull requests. [rfcbot]: https://github.com/anp/rfcbot-rs/ [RFCs]: https://github.com/rust-lang/rfcs -## Helpful Links and Information - -This section has moved to the ["About this guide"][more-links] chapter. - -[more-links]: ./about-this-guide.md#other-places-to-find-information +## Helpful links and information + +This section has moved to the ["About this guide"] chapter. + +["About this guide"]: about-this-guide.md#other-places-to-find-information +[search existing issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue +[Breaking Changes]: bug-fix-procedure.md +[triagebot.toml config file]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml +[rust-lang teams database]: https://github.com/rust-lang/team/tree/HEAD/teams +[compiler test suite]: tests/intro.md +[merge queue]: https://bors.rust-lang.org/queue/rust +[git hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks +[A-docs label]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs +[RFC 1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ +[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide diff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md index 521aeb4a5..1c963c669 100644 --- a/src/doc/rustc-dev-guide/src/conventions.md +++ b/src/doc/rustc-dev-guide/src/conventions.md @@ -13,11 +13,11 @@ However, for now we don't use stable `rustfmt`; we use a pinned version with a special config, so this may result in different style from normal [`rustfmt`]. Therefore, formatting this repository using `cargo fmt` is not recommended. -Instead, formatting should be done using `./x.py fmt`. It's a good habit to run -`./x.py fmt` before every commit, as this reduces conflicts later. +Instead, formatting should be done using `./x fmt`. It's a good habit to run +`./x fmt` before every commit, as this reduces conflicts later. Formatting is checked by the `tidy` script. It runs automatically when you do -`./x.py test` and can be run in isolation with `./x.py fmt --check`. +`./x test` and can be run in isolation with `./x fmt --check`. If you want to use format-on-save in your editor, the pinned version of `rustfmt` is built under `build/<target>/stage0/bin/rustfmt`. You'll have to @@ -126,7 +126,7 @@ dramatically (versus adding to it) in a later commit, that **Format liberally.** While only the final commit of a PR must be correctly formatted, it is both easier to review and less noisy to format each commit -individually using `./x.py fmt`. +individually using `./x fmt`. **No merges.** We do not allow merge commits into our history, other than those by bors. If you get a merge conflict, rebase instead via a diff --git a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md index 932b23b92..ac629934e 100644 --- a/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md +++ b/src/doc/rustc-dev-guide/src/debugging-support-in-rustc.md @@ -133,8 +133,7 @@ or `symbols`. Rust has support for embedding Natvis files for crates outside of the standard libraries by using the `#[debugger_visualizer]` attribute. For more details on how to embed debugger visualizers, -please refer to the `#[debugger_visualizer]` attribute in -[the unstable book](https://doc.rust-lang.org/unstable-book/language-features/debugger-visualizer.html). +please refer to the section on the [`debugger_visualizer` attribute]. ## DWARF and `rustc` @@ -352,3 +351,4 @@ but may have to add some mode to let the compiler understand some extensions. [symbol records]: https://llvm.org/docs/PDB/CodeViewSymbols.html [type records]: https://llvm.org/docs/PDB/CodeViewTypes.html [Windows Debugging Tools]: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/ +[`debugger_visualizer` attribute]: https://doc.rust-lang.org/nightly/reference/attributes/debugger.html#the-debugger_visualizer-attribute diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index daaffba7b..9f4245f28 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -507,6 +507,83 @@ module. [rlint]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/index.html +### When do lints run? + +Different lints will run at different times based on what information the lint +needs to do its job. Some lints get grouped into *passes* where the lints +within a pass are processed together via a single visitor. Some of the passes +are: + +- Pre-expansion pass: Works on [AST nodes] before [macro expansion]. This + should generally be avoided. + - Example: [`keyword_idents`] checks for identifiers that will become + keywords in future editions, but is sensitive to identifiers used in + macros. + +- Early lint pass: Works on [AST nodes] after [macro expansion] and name + resolution, just before [HIR lowering]. These lints are for purely + syntactical lints. + - Example: The [`unsued_parens`] lint checks for parenthesized-expressions + in situations where they are not needed, like an `if` condition. + +- Late lint pass: Works on [HIR nodes], towards the end of [analysis] (after + borrow checking, etc.). These lints have full type information available. + Most lints are late. + - Example: The [`invalid_value`] lint (which checks for obviously invalid + uninitialized values) is a late lint because it needs type information to + figure out whether a type allows being left uninitialized. + +- MIR pass: Works on [MIR nodes]. This isn't quite the same as other passes; + lints that work on MIR nodes have their own methods for running. + - Example: The [`arithmetic_overflow`] lint is emitted when it detects a + constant value that may overflow. + +Most lints work well via the pass systems, and they have a fairly +straightforward interface and easy way to integrate (mostly just implementing +a specific `check` function). However, some lints are easier to write when +they live on a specific code path anywhere in the compiler. For example, the +[`unused_mut`] lint is implemented in the borrow checker as it requires some +information and state in the borrow checker. + +Some of these inline lints fire before the linting system is ready. Those +lints will be *buffered* where they are held until later phases of the +compiler when the linting system is ready. See [Linting early in the +compiler](#linting-early-in-the-compiler). + + +[AST nodes]: the-parser.md +[HIR lowering]: lowering.md +[HIR nodes]: hir.md +[MIR nodes]: mir/index.md +[macro expansion]: macro-expansion.md +[analysis]: part-4-intro.md +[`keyword_idents`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#keyword-idents +[`unsued_parens`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-parens +[`invalid_value`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#invalid-value +[`arithmetic_overflow`]: https://doc.rust-lang.org/rustc/lints/listing/deny-by-default.html#arithmetic-overflow +[`unused_mut`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#unused-mut + +### Lint definition terms + +Lints are managed via the [`LintStore`][LintStore] and get registered in +various ways. The following terms refer to the different classes of lints +generally based on how they are registered. + +- *Built-in* lints are defined inside the compiler source. +- *Driver-registered* lints are registered when the compiler driver is created + by an external driver. This is the mechanism used by Clippy, for example. +- *Plugin* lints are registered by the [deprecated plugin system]. +- *Tool* lints are lints with a path prefix like `clippy::` or `rustdoc::`. +- *Internal* lints are the `rustc::` scoped tool lints that only run on the + rustc source tree itself and are defined in the compiler source like a + regular built-in lint. + +More information about lint registration can be found in the [LintStore] +chapter. + +[deprecated plugin system]: https://doc.rust-lang.org/nightly/unstable-book/language-features/plugin.html +[LintStore]: diagnostics/lintstore.md + ### Declaring a lint The built-in compiler lints are defined in the [`rustc_lint`][builtin] diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index 790d74dcf..6d698e3f3 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -70,7 +70,7 @@ Diagnostics are more than just their primary message, they often include labels, notes, help messages and suggestions, all of which can also be specified on a `Diagnostic`. -`#[label]`, `#[help]` and `#[note]` can all be applied to fields which have the +`#[label]`, `#[help]`, `#[warning]` and `#[note]` can all be applied to fields which have the type `Span`. Applying any of these attributes will create the corresponding subdiagnostic with that `Span`. These attributes will look for their diagnostic message in a Fluent attribute attached to the primary Fluent @@ -87,11 +87,11 @@ Other types have special behavior when used in a `Diagnostic` derive: - Any attribute applied to a `Vec<T>` will be repeated for each element of the vector. -`#[help]` and `#[note]` can also be applied to the struct itself, in which case +`#[help]`, `#[warning]` and `#[note]` can also be applied to the struct itself, in which case they work exactly like when applied to fields except the subdiagnostic won't have a `Span`. These attributes can also be applied to fields of type `()` for the same effect, which when combined with the `Option` type can be used to -represent optional `#[note]`/`#[help]` subdiagnostics. +represent optional `#[note]`/`#[help]`/`#[warning]` subdiagnostics. Suggestions can be emitted using one of four field attributes: @@ -161,14 +161,14 @@ following attributes: - `code = "..."` (_Optional_) - Specifies the error code. - `#[note]` or `#[note(slug)]` (_Optional_) - - _Applied to struct or `Span`/`()` fields._ + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a note subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. - Defaults to equivalent of `.note`. - If applied to a `Span` field, creates a spanned note. - `#[help]` or `#[help(slug)]` (_Optional_) - - _Applied to struct or `Span`/`()` fields._ + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a help subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. @@ -180,8 +180,8 @@ following attributes: - Value is a path to an item in `rustc_errors::fluent` for the note's message. - Defaults to equivalent of `.label`. -- `#[warn_]` or `#[warn_(slug)]` (_Optional_) - - _Applied to `Span` fields._ +- `#[warning]` or `#[warning(slug)]` (_Optional_) + - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ - Adds a warning subdiagnostic. - Value is a path to an item in `rustc_errors::fluent` for the note's message. @@ -253,6 +253,7 @@ attribute applied to the struct or each variant, one of: - `#[label(..)]` for defining a label - `#[note(..)]` for defining a note - `#[help(..)]` for defining a help +- `#[warning(..)]` for defining a warning - `#[suggestion{,_hidden,_short,_verbose}(..)]` for defining a suggestion All of the above must provide a slug as the first positional argument (a path @@ -333,7 +334,7 @@ diagnostic struct. ### Reference `#[derive(Subdiagnostic)]` supports the following attributes: -- `#[label(slug)]`, `#[help(slug)]` or `#[note(slug)]` +- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]` - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._ - _Mandatory_ - Defines the type to be representing a label, help or note. diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md index 2dbdb53fe..7cdf5ebca 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md @@ -37,7 +37,7 @@ To create a new error, you first need to find the next available code. You can find it with `tidy`: ``` -./x.py test tidy +./x test tidy ``` This will invoke the tidy script, which generally checks that your code obeys diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md index e3ccec7d7..a42a15484 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md @@ -86,10 +86,10 @@ excellent examples of translating messages into different locales and the information that needs to be provided by the code to do so. ### Compile-time validation and typed identifiers -rustc's Fluent resources for the default locale (`en-US`) are in the -[`compiler/rustc_error_messages/locales/en-US`] directory. Currently, each crate -which defines translatable diagnostics has its own Fluent resource, such as -`parser.ftl` or `typeck.ftl`. +Currently, each crate which defines translatable diagnostics has its own +Fluent resource in a file named `messages.ftl`, such as +[`compiler/rustc_borrowck/messages.ftl`] and +[`compiler/rustc_parse/messages.ftl`]. rustc's `fluent_messages` macro performs compile-time validation of Fluent resources and generates code to make it easier to refer to Fluent messages in @@ -240,5 +240,6 @@ won't fail. Bundle loading can fail if a requested locale is missing, Fluent files are malformed, or a message is duplicated in multiple resources. [Fluent]: https://projectfluent.org -[`compiler/rustc_error_messages/locales/en-US`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_error_messages/locales/en-US +[`compiler/rustc_borrowck/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_borrowck/messages.ftl +[`compiler/rustc_parse/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_parse/messages.ftl [`rustc_error_messages::DiagnosticMessage`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_error_messages/enum.DiagnosticMessage.html diff --git a/src/doc/rustc-dev-guide/src/early-late-bound.md b/src/doc/rustc-dev-guide/src/early-late-bound.md index 29b2136b4..8fb856742 100644 --- a/src/doc/rustc-dev-guide/src/early-late-bound.md +++ b/src/doc/rustc-dev-guide/src/early-late-bound.md @@ -1,107 +1,199 @@ -# Early and Late Bound Variables +# Early and Late Bound Parameter Definitions -In Rust, item definitions (like `fn`) can often have generic parameters, which -are always [_universally_ quantified][quant]. That is, if you have a function -like +Understanding this page likely requires a rudimentary understanding of higher ranked +trait bounds/`for<'a>`and also what types such as `dyn for<'a> Trait<'a>` and +`for<'a> fn(&'a u32)` mean. Reading [the nomincon chapter](https://doc.rust-lang.org/nomicon/hrtb.html) +on HRTB may be useful for understanding this syntax. The meaning of `for<'a> fn(&'a u32)` +is incredibly similar to the meaning of `T: for<'a> Trait<'a>`. +If you are looking for information on the `RegionKind` variants `ReLateBound` and `ReEarlyBound` +you should look at the section on [bound vars and params](./bound-vars-and-params.md). This section +discusses what makes generic parameters on functions and closures late/early bound. Not the general +concept of bound vars and generic parameters which `RegionKind` has named somewhat confusingly +with this topic. + +## What does it mean for parameters to be early or late bound + +All function definitions conceptually have a ZST (this is represented by `TyKind::FnDef` in rustc). +The only generics on this ZST are the early bound parameters of the function definition. e.g. ```rust -fn foo<T>(x: T) { } +fn foo<'a>(_: &'a u32) {} + +fn main() { + let b = foo; + // ^ `b` has type `FnDef(foo, [])` (no substs because `'a` is late bound) + assert!(std::mem::size_of_val(&b) == 0); +} ``` -this function is defined "for all T" (not "for some specific T", which would be -[_existentially_ quantified][quant]). +In order to call `b` the late bound parameters do need to be provided, these are inferred at the +call site instead of when we refer to `foo`. +```rust +fn main() { + let b = foo; + let a: &'static u32 = &10; + foo(a); + // the lifetime argument for `'a` on `foo` is inferred at the callsite + // the generic parameter `'a` on `foo` is inferred to `'static` here +} +``` + +Because late bound parameters are not part of the `FnDef`'s substs this allows us to prove trait +bounds such as `F: for<'a> Fn(&'a u32)` where `F` is `foo`'s `FnDef`. e.g. +```rust +fn foo_early<'a, T: Trait<'a>>(_: &'a u32, _: T) {} +fn foo_late<'a, T>(_: &'a u32, _: T) {} + +fn accepts_hr_func<F: for<'a> Fn(&'a u32, u32)>(_: F) {} + +fn main() { + // doesnt work, the substituted bound is `for<'a> FnDef<'?0>: Fn(&'a u32, u32)` + // `foo_early` only implements `for<'a> FnDef<'a>: Fn(&'a u32, u32)`- the lifetime + // of the borrow in the function argument must be the same as the lifetime + // on the `FnDef`. + accepts_hr_func(foo_early); + + // works, the substituted bound is `for<'a> FnDef: Fn(&'a u32, u32)` + accepts_hr_func(foo_late); +} + +// the builtin `Fn` impls for `foo_early` and `foo_late` look something like: +// `foo_early` +impl<'a, T: Trait<'a>> Fn(&'a u32, T) for FooEarlyFnDef<'a, T> { ... } +// `foo_late` +impl<'a, T> Fn(&'a u32, T) for FooLateFnDef<T> { ... } + +``` + +Early bound parameters are present on the `FnDef`. Late bound generic parameters are not present +on the `FnDef` but are instead constrained by the builtin `Fn*` impl. + +The same distinction applies to closures. Instead of `FnDef` we are talking about the anonymous +closure type. Closures are [currently unsound](https://github.com/rust-lang/rust/issues/84366) in +ways that are closely related to the distinction between early/late bound +parameters (more on this later) + +The early/late boundness of generic parameters is only relevent for the desugaring of +functions/closures into types with builtin `Fn*` impls. It does not make sense to talk about +in other contexts. + +The `generics_of` query in rustc only contains early bound parameters. In this way it acts more +like `generics_of(my_func)` is the generics for the FnDef than the generics provided to the function +body although it's not clear to the author of this section if this was the actual justification for +making `generics_of` behave this way. -[quant]: ./appendix/background.md#quantified +## What parameters are currently late bound -While Rust *items* can be quantified over types, lifetimes, and constants, the -types of values in Rust are only ever quantified over lifetimes. So you can -have a type like `for<'a> fn(&'a u32)`, which represents a function pointer -that takes a reference with any lifetime, or `for<'a> dyn Trait<'a>`, which is -a `dyn` trait for a trait implemented for any lifetime; but we have no type -like `for<T> fn(T)`, which would be a function that takes a value of *any type* -as a parameter. This is a consequence of monomorphization -- to support a value -of type `for<T> fn(T)`, we would need a single function pointer that can be -used for a parameter of any type, but in Rust we generate customized code for -each parameter type. +Below are the current requirements for determining if a generic parameter is late bound. It is worth +keeping in mind that these are not necessarily set in stone and it is almost certainly possible to +be more flexible. -One consequence of this asymmetry is a weird split in how we represent some -generic types: _early-_ and _late-_ bound parameters. -Basically, if we cannot represent a type (e.g. a universally quantified type), -we have to bind it _early_ so that the unrepresentable type is never around. +### Must be a lifetime parameter -Consider the following example: +Rust can't support types such as `for<T> dyn Trait<T>` or `for<T> fn(T)`, this is a +fundamental limitation of the language as we are required to monomorphize type/const +parameters and cannot do so behind dynamic dispatch. (technically we could probably +support `for<T> dyn MarkerTrait<T>` as there is nothing to monomorphize) -```rust,ignore -fn foo<'a, 'b, T>(x: &'a u32, y: &'b T) where T: 'b { ... } +Not being able to support `for<T> dyn Trait<T>` resulted in making all type and const +parameters early bound. Only lifetime parameters can be late bound. + +### Must not appear in the where clauses + +In order for a generic parameter to be late bound it must not appear in any where clauses. +This is currently an incredibly simplistic check that causes lifetimes to be early bound even +if the where clause they appear in are always true, or implied by well formedness of function +arguments. e.g. +```rust +fn foo1<'a: 'a>(_: &'a u32) {} +// ^^ early bound parameter because it's in a `'a: 'a` clause +// even though the bound obviously holds all the time +fn foo2<'a, T: Trait<'a>(a: T, b: &'a u32) {} +// ^^ early bound parameter because it's used in the `T: Trait<'a>` clause +fn foo3<'a, T: 'a>(_: &'a T) {} +// ^^ early bound parameter because it's used in the `T: 'a` clause +// even though that bound is implied by wellformedness of `&'a T` +fn foo4<'a, 'b: 'a>(_: Inv<&'a ()>, _: Inv<&'b ()>) {} +// ^^ ^^ ^^^ note: +// ^^ ^^ `Inv` stands for `Invariant` and is used to +// ^^ ^^ make the the type parameter invariant. This +// ^^ ^^ is necessary for demonstration purposes as +// ^^ ^^ `for<'a, 'b> fn(&'a (), &'b ())` and +// ^^ ^^ `for<'a> fn(&'a u32, &'a u32)` are subtypes- +// ^^ ^^ of eachother which makes the bound trivially +// ^^ ^^ satisfiable when making the fnptr. `Inv` +// ^^ ^^ disables this subtyping. +// ^^ ^^ +// ^^^^^^ both early bound parameters because they are present in the +// `'b: 'a` clause ``` -We cannot treat `'a`, `'b`, and `T` in the same way. Types in Rust can't have -`for<T> { .. }`, only `for<'a> {...}`, so whenever you reference `foo` the type -you get back can't be `for<'a, 'b, T> fn(&'a u32, y: &'b T)`. Instead, the `T` -must be substituted early. In particular, you have: +The reason for this requirement is that we cannot represent the `T: Trait<'a>` or `'a: 'b` clauses +on a function pointer. `for<'a, 'b> fn(Inv<&'a ()>, Inv<&'b ()>)` is not a valid function pointer to +represent`foo4` as it would allow calling the function without `'b: 'a` holding. -```rust,ignore -let x = foo; // T, 'b have to be substituted here -x(...); // 'a substituted here, at the point of call -x(...); // 'a substituted here with a different value +### Must be constrained by where clauses or function argument types + +The builtin impls of the `Fn*` traits for closures and `FnDef`s cannot not have any unconstrained +parameters. For example the following impl is illegal: +```rust +impl<'a> Trait for u32 { type Assoc = &'a u32; } +``` +We must not end up with a similar impl for the `Fn*` traits e.g. +```rust +impl<'a> Fn<()> for FnDef { type Assoc = &'a u32 } ``` -## Early-bound parameters +Violating this rule can trivially lead to unsoundness as seen in [#84366](https://github.com/rust-lang/rust/issues/84366). +Additionally if we ever support late bound type params then an impl like: +```rust +impl<T> Fn<()> for FnDef { type Assoc = T; } +``` +would break the compiler in various ways. -Early-bound parameters in rustc are identified by an index, stored in the -[`ParamTy`] struct for types or the [`EarlyBoundRegion`] struct for lifetimes. -The index counts from the outermost declaration in scope. This means that as you -add more binders inside, the index doesn't change. +In order to ensure that everything functions correctly, we do not allow generic parameters to +be late bound if it would result in a builtin impl that does not constrain all of the generic +parameters on the builtin impl. Making a generic parameter be early bound trivially makes it be +constrained by the builtin impl as it ends up on the self type. -For example, +Because of the requirement that late bound parameters must not appear in where clauses, checking +this is simpler than the rules for checking impl headers constrain all the parameters on the impl. +We only have to ensure that all late bound parameters appear at least once in the function argument +types outside of an alias (e.g. an associated type). -```rust,ignore -trait Foo<T> { - type Bar<U> = (Self, T, U); -} +The requirement that they not indirectly be in the substs of an alias for it to count is the +same as why the follow code is forbidden: +```rust +impl<T: Trait> OtherTrait for <T as Trait>::Assoc { type Assoc = T } ``` +There is no guarantee that `<T as Trait>::Assoc` will normalize to different types for every +instantiation of `T`. If we were to allow this impl we could get overlapping impls and the +same is true of the builtin `Fn*` impls. + +## Making more generic parameters late bound + +It is generally considered desirable for more parameters to be late bound as it makes +the builtin `Fn*` impls more flexible. Right now many of the requirements for making +a parameter late bound are overly restrictive as they are tied to what we can currently +(or can ever) do with fn ptrs. + +It would be theoretically possible to support late bound params in `where`-clauses in the +language by introducing implication types which would allow us to express types such as: +`for<'a, 'b: 'a> fn(Inv<&'a u32>, Inv<&'b u32>)` which would ensure `'b: 'a` is upheld when +calling the function pointer. + +It would also be theoretically possible to support it by making the coercion to a fn ptr +instantiate the parameter with an infer var while still allowing the FnDef to not have the +generic parameter present as trait impls are perfectly capable of representing the where clauses +on the function on the impl itself. This would also allow us to support late bound type/const +vars allowing bounds like `F: for<T> Fn(T)` to hold. + +It is almost somewhat unclear if we can change the `Fn` traits to be structured differently +so that we never have to make a parameter early bound just to make the builtin impl have all +generics be constrained. Of all the possible causes of a generic parameter being early bound +this seems the most difficult to remove. + +Whether these would be good ideas to implement is a separate question- they are only brought +up to illustrate that the current rules are not necessarily set in stone and a result of +"its the only way of doing this". -Here, the type `(Self, T, U)` would be `($0, $1, $2)`, where `$N` means a -[`ParamTy`] with the index of `N`. - -In rustc, the [`Generics`] structure carries this information. So the -[`Generics`] for `Bar` above would be just like for `U` and would indicate the -'parent' generics of `Foo`, which declares `Self` and `T`. You can read more -in [this chapter](./generics.md). - -[`ParamTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamTy.html -[`EarlyBoundRegion`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.EarlyBoundRegion.html -[`Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html - -## Late-bound parameters - -Late-bound parameters in `rustc` are handled quite differently (they are also -specialized to lifetimes since, right now, only late-bound lifetimes are -supported, though with GATs that has to change). We indicate their potential -presence by a [`Binder`] type. The [`Binder`] doesn't know how many variables -there are at that binding level. This can only be determined by walking the -type itself and collecting them. So a type like `for<'a, 'b> ('a, 'b)` would be -`for (^0.a, ^0.b)`. Here, we just write `for` because we don't know the names -of the things bound within. - -Moreover, a reference to a late-bound lifetime is written `^0.a`: - -- The `0` is the index; it identifies that this lifetime is bound in the - innermost binder (the `for`). -- The `a` is the "name"; late-bound lifetimes in rustc are identified by a - "name" -- the [`BoundRegionKind`] enum. This enum can contain a - [`DefId`][defid] or it might have various "anonymous" numbered names. The - latter arise from types like `fn(&u32, &u32)`, which are equivalent to - something like `for<'a, 'b> fn(&'a u32, &'b u32)`, but the names of those - lifetimes must be generated. - -This setup of not knowing the full set of variables at a binding level has some -advantages and some disadvantages. The disadvantage is that you must walk the -type to find out what is bound at the given level and so forth. The advantage -is primarily that, when constructing types from Rust syntax, if we encounter -anonymous regions like in `fn(&u32)`, we just create a fresh index and don't have -to update the binder. - -[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Binder.html -[`BoundRegionKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BoundRegionKind.html -[defid]: ./hir.html#identifiers-in-the-hir diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md index 9e9a83ea6..8ad4fea1f 100644 --- a/src/doc/rustc-dev-guide/src/feature-gates.md +++ b/src/doc/rustc-dev-guide/src/feature-gates.md @@ -3,44 +3,16 @@ This chapter is intended to provide basic help for adding, removing, and modifying feature gates. +Note that this is specific to *language* feature gates; *library* feature gates use [a different +mechanism][libs-gate]. -## Adding a feature gate - -See ["Stability in code"] for help with adding a new feature; this section just -covers how to add the feature gate *declaration*. - -First, add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block. - -Then, add a feature gate declaration to `rustc_feature/src/active.rs` in the active -`declare_features` block: - -```rust,ignore -/// description of feature -(active, $feature_name, "$current_nightly_version", Some($tracking_issue_number), $edition) -``` +[libs-gate]: ./stability.md -where `$edition` has the type `Option<Edition>`, and is typically -just `None`. - -For example: - -```rust,ignore -/// Allows defining identifiers beyond ASCII. -(active, non_ascii_idents, "1.0.0", Some(55467), None), -``` - -Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` lint] -by setting their type to `incomplete`: - -```rust,ignore -/// Allows unsized rvalues at arguments and parameters. -(incomplete, unsized_locals, "1.30.0", Some(48055), None), -``` +## Adding a feature gate -When added, the current version should be the one for the current nightly. -Once the feature is moved to `accepted.rs`, the version is changed to that -nightly version. +See ["Stability in code"][adding] in the "Implementing new features" section for instructions. +[adding]: ./implementing_new_features.md#stability-in-code ## Removing a feature gate @@ -109,5 +81,4 @@ updating the declaration! ["Stability in code"]: ./implementing_new_features.md#stability-in-code -[`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features ["Updating the feature-gate listing"]: ./stabilization_guide.md#updating-the-feature-gate-listing diff --git a/src/doc/rustc-dev-guide/src/fuzzing.md b/src/doc/rustc-dev-guide/src/fuzzing.md index 3fb1add01..869fc2f71 100644 --- a/src/doc/rustc-dev-guide/src/fuzzing.md +++ b/src/doc/rustc-dev-guide/src/fuzzing.md @@ -36,7 +36,7 @@ project, please read this guide before reporting fuzzer-generated bugs! If you're not sure whether or not an ICE is a duplicate of one that's already been reported, please go ahead and report it and link to issues you think might be related. In general, ICEs on the same line but with different *query stacks* -are usually distinct bugs. For example, [#109020][#109202] and [#109129][#109129] +are usually distinct bugs. For example, [#109020][#109020] and [#109129][#109129] had similar error messages: ``` @@ -100,7 +100,7 @@ to avoid introducing syntax, type-, and borrow-checking errors while using these tools, post both the complete and minimized test cases. Generally, *syntax-aware* tools give the best results in the least amount of time. [`treereduce-rust`][treereduce] and [picireny][picireny] are syntax-aware. -`halfempty` is not, but is generally a high-quality tool. +[`halfempty`][halfempty] is not, but is generally a high-quality tool. [halfempty]: https://github.com/googleprojectzero/halfempty [picireny]: https://github.com/renatahodovan/picireny @@ -146,4 +146,4 @@ ICEs that require debug assertions to reproduce should be tagged [glacier]: https://github.com/rust-lang/glacier [fuzz-rustc]: https://github.com/dwrensha/fuzz-rustc [icemaker]: https://github.com/matthiaskrgr/icemaker/ -[tree-splicer]: https://github.com/langston-barrett/tree-splicer/
\ No newline at end of file +[tree-splicer]: https://github.com/langston-barrett/tree-splicer/ diff --git a/src/doc/rustc-dev-guide/src/generic_arguments.md b/src/doc/rustc-dev-guide/src/generic_arguments.md index c9911acf5..6e09e8620 100644 --- a/src/doc/rustc-dev-guide/src/generic_arguments.md +++ b/src/doc/rustc-dev-guide/src/generic_arguments.md @@ -1,28 +1,28 @@ # Generic arguments -A `ty::subst::GenericArg<'tcx>` represents some entity in the type system: a type +A `ty::GenericArg<'tcx>` represents some entity in the type system: a type (`Ty<'tcx>`), lifetime (`ty::Region<'tcx>`) or constant (`ty::Const<'tcx>`). -`GenericArg` is used to perform substitutions of generic parameters for concrete +`GenericArg` is used to perform instantiation of generic parameters to concrete arguments, such as when calling a function with generic parameters explicitly -with type arguments. Substitutions are represented using the -[`Subst` type](#subst) as described below. +with type arguments. Instantiations are represented using the +[`GenericArgs` type](#genericargs) as described below. -## `Subst` -`ty::subst::Subst<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, -acting as an ordered list of substitutions from generic parameters to +## `GenericArgs` +`ty::GenericArgs<'tcx>` is intuitively simply a slice of `GenericArg<'tcx>`s, +acting as an ordered list of generic parameters instantiated to concrete arguments (such as types, lifetimes and consts). For example, given a `HashMap<K, V>` with two type parameters, `K` and `V`, an instantiation of the parameters, for example `HashMap<i32, u32>`, would be -represented by the substitution `&'tcx [tcx.types.i32, tcx.types.u32]`. +represented by `&'tcx [tcx.types.i32, tcx.types.u32]`. -`Subst` provides various convenience methods to instantiate substitutions +`GenericArgs` provides various convenience methods to instantiate generic arguments given item definitions, which should generally be used rather than explicitly -constructing such substitution slices. +instantiating such slices. ## `GenericArg` The actual `GenericArg` struct is optimised for space, storing the type, lifetime or const as an interned pointer containing a tag identifying its kind (in the -lowest 2 bits). Unless you are working with the `Subst` implementation +lowest 2 bits). Unless you are working with the `GenericArgs` implementation specifically, you should generally not have to deal with `GenericArg` and instead make use of the safe [`GenericArgKind`](#genericargkind) abstraction. @@ -30,7 +30,7 @@ make use of the safe [`GenericArgKind`](#genericargkind) abstraction. As `GenericArg` itself is not type-safe, the `GenericArgKind` enum provides a more convenient and safe interface for dealing with generic arguments. An `GenericArgKind` can be converted to a raw `GenericArg` using `GenericArg::from()` -(or simply `.into()` when the context is clear). As mentioned earlier, substitution +(or simply `.into()` when the context is clear). As mentioned earlier, instantiation lists store raw `GenericArg`s, so before dealing with them, it is preferable to convert them to `GenericArgKind`s first. This is done by calling the `.unpack()` method. @@ -44,7 +44,7 @@ fn deal_with_generic_arg<'tcx>(generic_arg: GenericArg<'tcx>) -> GenericArg<'tcx GenericArgKind::Lifetime(lt) => { /* ... */ } GenericArgKind::Const(ct) => { /* ... */ } }; - // Pack the `GenericArgKind` to store it in a substitution list. + // Pack the `GenericArgKind` to store it in a generic args list. new_generic_arg.into() } ``` diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 297873d98..80c3d3793 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -57,7 +57,7 @@ even if you can't figure out who to ping. Another way to find experts for a given part of the compiler is to see who has made recent commits. For example, to find people who have recently worked on name resolution since the 1.68.2 release, you could run `git shortlog -n 1.68.2.. compiler/rustc_resolve/`. Ignore any commits starting with -"Rollup merge" or commits by `@bors` (see [CI contribution prodcedures](./contributing.md#ci) for +"Rollup merge" or commits by `@bors` (see [CI contribution procedures](./contributing.md#ci) for more information about these commits). [map]: https://github.com/rust-lang/compiler-team/blob/master/content/experts/map.toml @@ -90,7 +90,7 @@ filtering the search to areas you're interested in. For example: Not all important or beginner work has issue labels. See below for how to find work that isn't labelled. -[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+ +[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+ [Triage]: ./contributing.md#issue-triage ### Recurring work diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 34f2f101e..6c5c64685 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -10,7 +10,7 @@ can be incorporated into the compiler. The goal of this page is to cover some of the more common questions and problems new contributors face. Although some Git basics will be covered here, -if you find that this is still a little too fast for you, it might make sense +if you find that this is still a little too fast for you, it might make sense to first read some introductions to Git, such as the Beginner and Getting started sections of [this tutorial from Atlassian][atlassian-git]. GitHub also provides [documentation] and [guides] for beginners, or you can consult the @@ -139,7 +139,7 @@ You might also notice conflicts in the web UI: ![conflict in src/tools/cargo](./img/submodule-conflicts.png) The most common cause is that you rebased after a change and ran `git add .` without first running -`x.py` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` +`x` to update the submodules. Alternatively, you might have run `cargo fmt` instead of `x fmt` and modified files in a submodule, then committed the changes. To fix it, do the following things: @@ -167,7 +167,7 @@ error: cannot rebase: You have unstaged changes. error: Please commit or stash them. ``` -(See https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#_the_three_states for the difference between the two.) +(See <https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#_the_three_states> for the difference between the two.) This means you have made changes since the last time you made a commit. To be able to rebase, either commit your changes, or make a temporary commit called a "stash" to have them still not be commited @@ -178,7 +178,7 @@ will prevent the "cannot rebase" error in nearly all cases: git config --global rebase.autostash true ``` -See https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning for more info about stashing. +See <https://git-scm.com/book/en/v2/Git-Tools-Stashing-and-Cleaning> for more info about stashing. ### I see 'Untracked Files: src/stdarch'? @@ -239,31 +239,13 @@ no changes added to commit (use "git add" and/or "git commit -a") ``` These changes are not changes to files: they are changes to submodules (more on this -[later](#git-submodules)). To get rid of those, run `./x.py --help`, which will automatically update +[later](#git-submodules)). To get rid of those, run `./x --help`, which will automatically update the submodules. Some submodules are not actually needed; for example, `src/llvm-project` doesn't need to be checked out if you're using `download-ci-llvm`. To avoid having to keep fetching its history, you can use `git submodule deinit -f src/llvm-project`, which will also avoid it showing as modified again. -Note that, as of <!-- date-check --> Aug 2022, -there is a [bug][#77620] if you use worktrees, -submodules, and `x.py` in a commit hook. -If you run into an error like the following, -it's not anything you did wrong: - -``` -error: failed to read `/home/jyn/rustc-worktree/src/tools/cargo/Cargo.toml` - -Caused by: - No such file or directory (os error 2) -``` - -There is a workaround in [the issue][#77620-workaround]. - -[#77620]: https://github.com/rust-lang/rust/issues/77620 -[#77620-workaround]: https://github.com/rust-lang/rust/issues/77620#issuecomment-705228229 - ## Rebasing and Conflicts When you edit your code locally, you are making changes to the version of @@ -314,7 +296,7 @@ Generally, resolving the conflict consists of two steps: First, fix the particular conflict. Edit the file to make the changes you want and remove the `<<<<<<<`, `=======` and `>>>>>>>` lines in the process. Second, check the surrounding code. If there was a conflict, its likely there are some logical -errors lying around too! It's a good idea to run `x.py check` here to make sure +errors lying around too! It's a good idea to run `x check` here to make sure there are no glaring errors. Once you're all done fixing the conflicts, you need to stage the files that had @@ -461,7 +443,7 @@ that merge commits in PRs are not accepted. As a result, if you are running course, this is not always true; if your merge will just be a fast-forward, like the merges that `git pull` usually performs, then no merge commit is created and you have nothing to worry about. Running `git config merge.ff only` -(this will apply the config to the local repo). +(this will apply the config to the local repo) once will ensure that all the merges you perform are of this type, so that you cannot make a mistake. @@ -558,7 +540,7 @@ commit, which doesn't change unless modified manually. If you use `git checkout in the `llvm-project` directory and go back to the `rust` directory, you can stage this change like any other, e.g. by running `git add src/llvm-project`. (Note that if you *don't* stage the change to commit, then you run the risk that running -`x.py` will just undo your change by switching back to the previous commit when +`x` will just undo your change by switching back to the previous commit when it automatically "updates" the submodules.) This version selection is usually done by the maintainers of the project, and diff --git a/src/doc/rustc-dev-guide/src/identifiers.md b/src/doc/rustc-dev-guide/src/identifiers.md index 09e85c019..c7e32d04c 100644 --- a/src/doc/rustc-dev-guide/src/identifiers.md +++ b/src/doc/rustc-dev-guide/src/identifiers.md @@ -70,7 +70,7 @@ See the [HIR chapter][hir-map] for more detailed information. - [`Local`] identifies a local variable in a function. Its associated data is in [`LocalDecl`], which can be retrieved by indexing into [`Body.local_decls`]. -- [`Field`] identifies a struct's, union's, or enum variant's field. It is used +- [`FieldIdx`] identifies a struct's, union's, or enum variant's field. It is used as a "projection" in [`Place`]. - [`SourceScope`] identifies a name scope in the original source code. Used for @@ -96,7 +96,7 @@ See the [HIR chapter][hir-map] for more detailed information. [`Local`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Local.html [`LocalDecl`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.LocalDecl.html [`Body.local_decls`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Body.html#structfield.local_decls -[`Field`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Field.html +[`FieldIdx`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_abi/struct.FieldIdx.html [`Place`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Place.html [`SourceScope`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.SourceScope.html [`SourceScopeData`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.SourceScopeData.html diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index 946637d29..01508889f 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -1,4 +1,4 @@ -# Implementing new features +# Implementing new language features <!-- toc --> @@ -6,6 +6,11 @@ When you want to implement a new significant feature in the compiler, you need to go through this process to make sure everything goes smoothly. +**NOTE: this section is for *language* features, not *library* features, +which use [a different process].** + +[a different process]: ./stability.md + ## The @rfcbot FCP process When the change is small and uncontroversial, then it can be done @@ -91,31 +96,16 @@ by being unstable and unchanged for a year. To keep track of the status of an unstable feature, the experience we get while using it on nightly, and of the concerns that block its stabilization, every feature-gate -needs a tracking issue. - -General discussions about the feature should be done on -the tracking issue. +needs a tracking issue. General discussions about the feature should be done on the tracking issue. For features that have an RFC, you should use the RFC's tracking issue for the feature. For other features, you'll have to make a tracking issue for that feature. The issue title should be "Tracking issue -for YOUR FEATURE". - -For tracking issues for features (as opposed to future-compat -warnings), I don't think the description has to contain -anything specific. Generally we put the list of items required -for stabilization in a checklist, e.g., +for YOUR FEATURE". Use the ["Tracking Issue" issue template][template]. -```txt -**Steps:** - -- [ ] Implement the RFC. (CC @rust-lang/compiler -- can anyone write - up mentoring instructions?) -- [ ] Adjust the documentation. ([See instructions on rustc-dev-guide.](stabilization_guide.md#documentation-prs)) -- [ ] Stabilize the feature. ([See instructions on rustc-dev-guide.](stabilization_guide.md#stabilization-pr)) -``` +[template]: https://github.com/rust-lang/rust/issues/new?template=tracking_issue.md ## Stability in code @@ -128,14 +118,48 @@ a new unstable feature: The tracking issue should be labeled with at least `C-tracking-issue`. For a language feature, a label `F-feature_name` should be added as well. -2. Pick a name for the feature gate (for RFCs, use the name +1. Pick a name for the feature gate (for RFCs, use the name in the RFC). -3. Add a feature gate declaration to `rustc_feature/src/active.rs` in the active - `declare_features` block, and add the feature gate keyword to - `rustc_span/src/symbol.rs`. See [here][add-feature-gate] for detailed instructions. +1. Add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block. + +1. Add a feature gate declaration to `rustc_feature/src/active.rs` in the active + `declare_features` block. + + ```rust ignore + /// description of feature + (active, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number), $edition) + ``` + + where `$edition` has the type `Option<Edition>`, and is typically just `None`. If you haven't yet + opened a tracking issue (e.g. because you want initial feedback on whether the feature is likely + to be accepted), you can temporarily use `None` - but make sure to update it before the PR is + merged! + + For example: + + ```rust ignore + /// Allows defining identifiers beyond ASCII. + (active, non_ascii_idents, "CURRENT_RUSTC_VERSION", Some(55467), None), + ``` + + Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` + lint] + by setting their type to `incomplete`: + + [`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features + + ```rust ignore + /// Allows unsized rvalues at arguments and parameters. + (incomplete, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), None), + ``` + + To avoid [semantic merge conflicts], please use `CURRENT_RUSTC_VERSION` instead of `1.70` or + another explicit version number. + + [semantic merge conflicts]: https://bors.tech/essay/2017/02/02/pitch/ -4. Prevent usage of the new feature unless the feature gate is set. +1. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the expression `tcx.features().$feature_name` (or `sess.features_untracked().$feature_name` if the @@ -151,18 +175,18 @@ a new unstable feature: and then finally feature-gate all the spans in [`rustc_ast_passes::feature_gate::check_crate`]. -5. Add a test to ensure the feature cannot be used without - a feature gate, by creating `feature-gate-$feature_name.rs` - and `feature-gate-$feature_name.stderr` files under the - directory where the other tests for your feature reside. +1. Add a test to ensure the feature cannot be used without + a feature gate, by creating `tests/ui/feature-gates/feature-gate-$feature_name.rs`. + You can generate the corresponding `.stderr` file by running `./x test +tests/ui/feature-gates/ --bless`. -6. Add a section to the unstable book, in +1. Add a section to the unstable book, in `src/doc/unstable-book/src/language-features/$feature_name.md`. -7. Write a lot of tests for the new feature. +1. Write a lot of tests for the new feature, preferably in `tests/ui/$feature_name/`. PRs without tests will not be accepted! -8. Get your PR reviewed and land it. You have now successfully +1. Get your PR reviewed and land it. You have now successfully implemented a feature in Rust! [`GatedSpans`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.GatedSpans.html @@ -172,5 +196,5 @@ a new unstable feature: [value the stability of Rust]: https://github.com/rust-lang/rfcs/blob/master/text/1122-language-semver.md [stability in code]: #stability-in-code [here]: ./stabilization_guide.md -[tracking issue]: #tracking-issue +[tracking issue]: #tracking-issues [add-feature-gate]: ./feature-gates.md#adding-a-feature-gate diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 8cd765011..2b1677ef4 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -199,7 +199,7 @@ statements is only implemented for LLVM, at this time. [backend-lowering-mir]: backend/lowering-mir.md [codegen-statement]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_statement [codegen-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/mir/struct.FunctionCx.html#method.codegen_coverage -[function-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/coverageinfo/map/struct.FunctionCoverage.html +[function-coverage]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_llvm/coverageinfo/map_data/struct.FunctionCoverage.html [instrprof-increment]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/trait.BuilderMethods.html#tymethod.instrprof_increment ### Coverage Map Generation @@ -279,8 +279,8 @@ Coverage instrumentation in the MIR is validated by a `mir-opt` test: More complete testing of end-to-end coverage instrumentation and reports are done in the `run-make-fulldeps` tests, with sample Rust programs (to be -instrumented) in the [`coverage`][coverage-test-samples] directory, and the -actual tests and expected results in [`coverage-reports`]. +instrumented) in the [`tests/run-coverage`] directory, +together with the actual tests and expected results. Finally, the [`coverage-llvmir`] test compares compiles a simple Rust program with `-C instrument-coverage` and compares the compiled program's LLVM IR to @@ -292,13 +292,12 @@ Expected results for both the `mir-opt` tests and the `coverage*` tests under `run-make-fulldeps` can be refreshed by running: ```shell -$ ./x.py test mir-opt --bless -$ ./x.py test tests/run-make-fulldeps/coverage --bless +$ ./x test mir-opt --bless +$ ./x test tests/run-make-fulldeps/coverage --bless ``` [mir-opt-test]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/instrument_coverage.rs -[coverage-test-samples]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage -[`coverage-reports`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-reports +[`tests/run-coverage`]: https://github.com/rust-lang/rust/tree/master/tests/run-coverage [spanview-debugging]: compiler-debugging.md#viewing-spanview-output [`coverage-llvmir`]: https://github.com/rust-lang/rust/tree/master/tests/run-make/coverage-llvmir @@ -466,7 +465,7 @@ function--[`bcb_from_bb()`][bcb-from-bb]--to look up a `BasicCoverageBlock` from [graph-traits]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/graph/index.html#traits [mir-dev-guide]: mir/index.md [compute-basic-coverage-blocks]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.compute_basic_coverage_blocks -[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/struct.SimplifyCfg.html +[simplify-cfg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/simplify/enum.SimplifyCfg.html [rust-lang/rust#78544]: https://github.com/rust-lang/rust/issues/78544 [mir-debugging]: mir/debugging.md [bcb-from-bb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/coverage/graph/struct.CoverageGraph.html#method.bcb_from_bb diff --git a/src/doc/rustc-dev-guide/src/macro-expansion.md b/src/doc/rustc-dev-guide/src/macro-expansion.md index 7f50f7f89..f3883223d 100644 --- a/src/doc/rustc-dev-guide/src/macro-expansion.md +++ b/src/doc/rustc-dev-guide/src/macro-expansion.md @@ -48,7 +48,7 @@ iteration, this represents a compile error. Here is the [algorithm][original]: [fef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/expand/struct.MacroExpander.html#method.fully_expand_fragment [original]: https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049 -1. Initialize an `queue` of unresolved macros. +1. Initialize a `queue` of unresolved macros. 2. Repeat until `queue` is empty (or we make no progress, which is an error): 1. [Resolve](./name-resolution.md) imports in our partially built crate as much as possible. diff --git a/src/doc/rustc-dev-guide/src/mir/optimizations.md b/src/doc/rustc-dev-guide/src/mir/optimizations.md index 293d2fe91..16cf2035b 100644 --- a/src/doc/rustc-dev-guide/src/mir/optimizations.md +++ b/src/doc/rustc-dev-guide/src/mir/optimizations.md @@ -34,7 +34,7 @@ optimizes it, and returns the improved MIR. `println!`, `format!`, etc. generate a lot of MIR that can make it harder to understand what the optimization does to the test. -2. Run `./x.py test --bless tests/mir-opt/<your-test>.rs` to generate a MIR +2. Run `./x test --bless tests/mir-opt/<your-test>.rs` to generate a MIR dump. Read [this README][mir-opt-test-readme] for instructions on how to dump things. @@ -45,16 +45,16 @@ optimizes it, and returns the improved MIR. 4. Implement a new optimization in [`compiler/rustc_mir_transform/src`]. The fastest and easiest way to do this is to - 1. pick a small optimization (such as [`no_landing_pads`]) and copy it + 1. pick a small optimization (such as [`remove_storage_markers`]) and copy it to a new file, 2. add your optimization to one of the lists in the [`run_optimization_passes()`] function, 3. and then start modifying the copied optimization. -5. Rerun `./x.py test --bless tests/mir-opt/<your-test>.rs` to regenerate the +5. Rerun `./x test --bless tests/mir-opt/<your-test>.rs` to regenerate the MIR dumps. Look at the diffs to see if they are what you expect. -6. Run `./x.py test tests/ui` to see if your optimization broke anything. +6. Run `./x test tests/ui` to see if your optimization broke anything. 7. If there are issues with your optimization, experiment with it a bit and repeat steps 5 and 6. @@ -72,8 +72,7 @@ If you have any questions along the way, feel free to ask in [mir-opt-test-readme]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/README.md [`compiler/rustc_mir_transform/src`]: https://github.com/rust-lang/rust/tree/master/compiler/rustc_mir_transform/src -<!--- TODO: Change NoLandingPads. [#1232](https://github.com/rust-lang/rustc-dev-guide/issues/1232) --> -[`no_landing_pads`]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_mir_transform/src/no_landing_pads.rs +[`remove_storage_markers`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_mir_transform/src/remove_storage_markers.rs [`run_optimization_passes()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/fn.run_optimization_passes.html ## Defining optimization passes diff --git a/src/doc/rustc-dev-guide/src/mir/visitor.md b/src/doc/rustc-dev-guide/src/mir/visitor.md index 17186fe75..c0c703a6b 100644 --- a/src/doc/rustc-dev-guide/src/mir/visitor.md +++ b/src/doc/rustc-dev-guide/src/mir/visitor.md @@ -23,7 +23,7 @@ struct MyVisitor<...> { and you then implement the `Visitor` or `MutVisitor` trait for that type: ```rust,ignore -impl<'tcx> MutVisitor<'tcx> for NoLandingPads { +impl<'tcx> MutVisitor<'tcx> for MyVisitor { fn visit_foo(&mut self, ...) { ... self.super_foo(...); diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md index 93c2a3eb7..fbeef19ff 100644 --- a/src/doc/rustc-dev-guide/src/name-resolution.md +++ b/src/doc/rustc-dev-guide/src/name-resolution.md @@ -117,7 +117,7 @@ fn do_something<T: Default>(val: T) { // <- New rib in both types and values (1) }; // End of (3) // `val` is accessible, `helper` variable shadows `helper` function fn helper() { // <- New rib in both types and values (4) - // `val` is not accessible here, (4) is not transparent for locals) + // `val` is not accessible here, (4) is not transparent for locals // `T` is not accessible here } // End of (4) let val = T::default(); // New rib (5) diff --git a/src/doc/rustc-dev-guide/src/notification-groups/about.md b/src/doc/rustc-dev-guide/src/notification-groups/about.md index a85c4a505..1307a50fc 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/about.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/about.md @@ -42,7 +42,7 @@ particularly those of **middle priority**: ## Joining a notification group -To join an notification group, you just have to open a PR adding your +To join a notification group, you just have to open a PR adding your Github username to the appropriate file in the Rust team repository. See the "example PRs" below to get a precise idea and to identify the file to edit. diff --git a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md index 2e7b1766c..707334304 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/cleanup-crew.md @@ -39,9 +39,9 @@ are a few: * The [rust-reduce](https://github.com/jethrogb/rust-reduce) tool can try to reduce code automatically. - * The [C-reduce](https://embed.cs.utah.edu/creduce/) tool also works + * The [C-reduce](https://github.com/csmith-project/creduce) tool also works on Rust code, though it requires that you start from a single - file. (XXX link to some post explaining how to do it?) + file. (A post explaining how to do it can be found [here](https://insaneinside.net/2017/09/12/whole-crate-bug-reduction-with-creduce.html).) * pnkfelix's [Rust Bug Minimization Patterns] blog post * This post focuses on "heavy bore" techniques, where you are starting with a large, complex cargo project that you wish to diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index de06c742b..797f4d8e2 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -286,7 +286,7 @@ of a crate.][passes] Then the codegen backend invokes the for that function and then creates codegen units. This kind of split will need to remain to ensure that unreachable functions still have their errors emitted. -[passes]: https://github.com/rust-lang/rust/blob/45ebd5808afd3df7ba842797c0fcd4447ddf30fb/src/librustc_interface/passes.rs#L824 +[passes]: https://github.com/rust-lang/rust/blob/e69c7306e2be08939d95f14229e3f96566fb206c/compiler/rustc_interface/src/passes.rs#L791 Moreover, the compiler wasn't originally built to use a query system; the query system has been retrofitted into the compiler, so parts of it are not query-fied diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md index e7cbbd7ee..9942f751a 100644 --- a/src/doc/rustc-dev-guide/src/parallel-rustc.md +++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md @@ -44,7 +44,6 @@ are implemented differently depending on whether `parallel-compiler` is true. | MappedWriteGuard | parking_lot::MappedRwLockWriteGuard | std::cell::RefMut | | LockGuard | parking_lot::MutexGuard | std::cell::RefMut | | MappedLockGuard | parking_lot::MappedMutexGuard | std::cell::RefMut | -| MetadataRef | [`OwningRef<Box<dyn Erased + Send + Sync>, [u8]>`][OwningRef] | [`OwningRef<Box<dyn Erased>, [u8]>`][OwningRef] | - These thread-safe data structures interspersed during compilation can cause a lot of lock contention, which actually degrades performance as the @@ -164,4 +163,3 @@ are a bit out of date): [parallel-rustdoc]: https://github.com/rust-lang/rust/issues/82741 [Arc]: https://doc.rust-lang.org/std/sync/struct.Arc.html [Rc]: https://doc.rust-lang.org/std/rc/struct.Rc.html -[OwningRef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/owning_ref/index.html diff --git a/src/doc/rustc-dev-guide/src/part-2-intro.md b/src/doc/rustc-dev-guide/src/part-2-intro.md index 5ea4d7b6b..aecab562b 100644 --- a/src/doc/rustc-dev-guide/src/part-2-intro.md +++ b/src/doc/rustc-dev-guide/src/part-2-intro.md @@ -1,4 +1,4 @@ -# Part 2: High-Level Compiler Architecture +# High-Level Compiler Architecture The remaining parts of this guide discuss how the compiler works. They go through everything from high-level structure of the compiler to how each stage diff --git a/src/doc/rustc-dev-guide/src/part-3-intro.md b/src/doc/rustc-dev-guide/src/part-3-intro.md index c10080632..59a1eeba7 100644 --- a/src/doc/rustc-dev-guide/src/part-3-intro.md +++ b/src/doc/rustc-dev-guide/src/part-3-intro.md @@ -1,4 +1,4 @@ -# Part 3: Source Code Representation +# Source Code Representation This part describes the process of taking raw source code from the user and transforming it into various forms that the compiler can work with easily. diff --git a/src/doc/rustc-dev-guide/src/part-4-intro.md b/src/doc/rustc-dev-guide/src/part-4-intro.md index 00a74f308..6a8433164 100644 --- a/src/doc/rustc-dev-guide/src/part-4-intro.md +++ b/src/doc/rustc-dev-guide/src/part-4-intro.md @@ -1,4 +1,4 @@ -# Part 4: Analysis +# Analysis This part discusses the many analyses that the compiler uses to check various properties of the code and to inform later stages. Typically, this is what people diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index e1666e237..df987e00a 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -19,7 +19,7 @@ Depending on what you're trying to measure, there are several different approach - If you want a nice visual representation of the compile times of your crate graph, you can use [cargo's `--timings` flag](https://doc.rust-lang.org/nightly/cargo/reference/timings.html), e.g. `cargo build --timings`. - You can use this flag on the compiler itself with `CARGOFLAGS="--timings" ./x.py build` + You can use this flag on the compiler itself with `CARGOFLAGS="--timings" ./x build` - If you want to profile memory usage, you can use various tools depending on what operating system you are using. @@ -41,11 +41,11 @@ extension in LLVM bitcode format. Example usage: ``` cargo install cargo-llvm-lines -# On a normal crate you could now run `cargo llvm-lines`, but `x.py` isn't normal :P +# On a normal crate you could now run `cargo llvm-lines`, but `x` isn't normal :P # Do a clean before every run, to not mix in the results from previous runs. -./x.py clean -env RUSTFLAGS=-Csave-temps ./x.py build --stage 0 compiler/rustc +./x clean +env RUSTFLAGS=-Csave-temps ./x build --stage 0 compiler/rustc # Single crate, e.g., rustc_middle. (Relies on the glob support of your shell.) # Convert unoptimized LLVM bitcode into a human readable LLVM assembly accepted by cargo-llvm-lines. @@ -85,7 +85,7 @@ Example output for the compiler: 326903 (0.7%) 642 (0.0%) rustc_query_system::query::plumbing::try_execute_query ``` -Since this doesn't seem to work with incremental compilation or `./x.py check`, +Since this doesn't seem to work with incremental compilation or `./x check`, you will be compiling rustc _a lot_. I recommend changing a few settings in `config.toml` to make it bearable: ``` diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md index c9bd88ecd..469e237b9 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md @@ -10,7 +10,7 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or - `debuginfo-level = 1` - enables line debuginfo - `jemalloc = false` - lets you do memory use profiling with valgrind - leave everything else the defaults -- Run `./x.py build` to get a full build +- Run `./x build` to get a full build - Make a rustup toolchain pointing to that result - see [the "build and run" section for instructions][b-a-r] @@ -282,7 +282,7 @@ Tree What happens with `--tree-callees` is that - we find each sample matching the regular expression -- we look at the code that is occurs *after* the regex match and try +- we look at the code that occurs *after* the regex match and try to build up a call tree The `--tree-min-percent 3` option says "only show me things that take diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md index e7cf9418c..a800c5717 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md @@ -47,11 +47,11 @@ we'll need to build a stage 1 compiler and then a stage 2 compiler ourselves. To do this, make sure you have set `debuginfo-level = 1` in your `config.toml` file. This tells rustc to generate debug information which includes stack frames when bootstrapping. -Now you can build the stage 1 compiler: `python x.py build --stage 1 -i library` or however +Now you can build the stage 1 compiler: `x build --stage 1 -i library` or however else you want to build the stage 1 compiler. Now that the stage 1 compiler is built, we can record the stage 2 build. Go back to WPR, click the -"start" button and build the stage 2 compiler (e.g., `python x build --stage=2 -i library`). +"start" button and build the stage 2 compiler (e.g., `x build --stage=2 -i library`). When this process finishes, stop the recording. Click the Save button and once that process is complete, click the "Open in WPA" button which diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index 5dbffac8d..782c5b4b3 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -103,7 +103,7 @@ When the tcx is created, it is given the providers by its creator using the [`Providers`][providers_struct] struct. This struct is generated by the macros here, but it is basically a big list of function pointers: -[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/query/struct.Providers.html +[providers_struct]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/struct.Providers.html ```rust,ignore struct Providers { diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md new file mode 100644 index 000000000..2ad9494e8 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md @@ -0,0 +1,419 @@ +# Return Position Impl Trait In Trait + +Return-position impl trait in trait (RPITIT) is conceptually (and as of +[#112988], literally) sugar that turns RPITs in trait methods into +generic associated types (GATs) without the user having to define that +GAT either on the trait side or impl side. + +RPITIT was originally implemented in [#101224], which added support for +async fn in trait (AFIT), since the implementation for RPITIT came for +free as a part of implementing AFIT which had been RFC'd previously. It +was then RFC'd independently in [RFC 3425], which was recently approved +by T-lang. + +## How does it work? + +This doc is ordered mostly via the compilation pipeline. AST -> HIR -> +astconv -> typeck. + +### AST and HIR + +AST -> HIR lowering for RPITITs is almost the same as lowering RPITs. We +still lower them as +[`hir::ItemKind::OpaqueTy`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html). +The two differences are that: + +We record `in_trait` for the opaque. This will signify that the opaque +is an RPITIT for astconv, diagnostics that deal with HIR, etc. + +We record `lifetime_mapping`s for the opaque type, described below. + +#### Aside: Opaque lifetime duplication + +*All opaques* (not just RPITITs) end up duplicating their captured +lifetimes into new lifetime parameters local to the opaque. The main +reason we do this is because RPITs need to be able to "reify"[^1] any +captured late-bound arguments, or make them into early-bound ones. This +is so they can be used as substs for the opaque, and later to +instantiate hidden types. Since we don't know which lifetimes are early- +or late-bound during AST lowering, we just do this for all lifetimes. + +[^1]: This is compiler-errors terminology, I'm not claiming it's accurate :^) + +The main addition for RPITITs is that during lowering we track the +relationship between the captured lifetimes and the corresponding +duplicated lifetimes in an additional field, +[`OpaqueTy::lifetime_mapping`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html#structfield.lifetime_mapping). +We use this lifetime mapping later on in `predicates_of` to install +bounds that enforce equality between these duplicated lifetimes and +their source lifetimes in order to properly typecheck these GATs, which +will be discussed below. + +##### note: + +It may be better if we were able to lower without duplicates and for +that I think we would need to stop distinguishing between early and late +bound lifetimes. So we would need a solution like [Account for +late-bound lifetimes in generics +#103448](https://github.com/rust-lang/rust/pull/103448) and then also a +PR similar to [Inherit function lifetimes for impl-trait +#103449](https://github.com/rust-lang/rust/pull/103449). + +### Astconv + +The main change to astconv is that we lower `hir::TyKind::OpaqueDef` for +an RPITIT to a projection instead of an opaque, using a newly +synthesized def-id for a new associated type in the trait. We'll +describe how exactly we get this def-id in the next section. + +This means that any time we call `ast_ty_to_ty` on the RPITIT, we end up +getting a projection back instead of an opaque. This projection can then +be normalized to the right value -- either the original opaque if we're +in the trait, or the inferred type of the RPITIT if we're in an impl. + +#### Lowering to synthetic associated types + +Using query feeding, we synthesize new associated types on both the +trait side and impl side for RPITITs that show up in methods. + +##### Lowering RPITITs in traits + +When `tcx.associated_item_def_ids(trait_def_id)` is called on a trait to +gather all of the trait's associated types, the query previously just +returned the def-ids of the HIR items that are children of the trait. +After [#112988], additionally, for each method in the trait, we add the +def-ids returned by +`tcx.associated_types_for_impl_traits_in_associated_fn(trait_method_def_id)`, +which walks through each trait method, gathers any RPITITs that show up +in the signature, and then calls +`associated_type_for_impl_trait_in_trait` for each RPITIT, which +synthesizes a new associated type. + +##### Lowering RPITITs in impls + +Similarly, along with the impl's HIR items, for each impl method, we +additionally add all of the +`associated_types_for_impl_traits_in_associated_fn` for the impl method. +This calls `associated_type_for_impl_trait_in_impl`, which will +synthesize an associated type definition for each RPITIT that comes from +the corresponding trait method. + +#### Synthesizing new associated types + +We use query feeding +([`TyCtxtAt::create_def`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/plumbing/struct.TyCtxtAt.html#method.create_def)) +to synthesize a new def-id for the synthetic GATs for each RPITIT. + +Locally, most of rustc's queries match on the HIR of an item to compute +their values. Since the RPITIT doesn't really have HIR associated with +it, or at least not HIR that corresponds to an associated type, we must +compute many queries eagerly and +[feed](https://github.com/rust-lang/rust/pull/104940) them, like +`opt_def_kind`, `associated_item`, `visibility`, and`defaultness`. + +The values for most of these queries is obvious, since the RPITIT +conceptually inherits most of its information from the parent function +(e.g. `visibility`), or because it's trivially knowable because it's an +associated type (`opt_def_kind`). + +Some other queries are more involved, or cannot be feeded, and we +document the interesting ones of those below: + +##### `generics_of` for the trait + +The GAT for an RPITIT conceptually inherits the same generics as the +RPIT it comes from. However, instead of having the method as the +generics' parent, the trait is the parent. + +Currently we get away with taking the RPIT's generics and method +generics and flattening them both into a new generics list, preserving +the def-id of each of the parameters. (This may cause issues with +def-ids having the wrong parents, but in the worst case this will cause +diagnostics issues. If this ends up being an issue, we can synthesize +new def-ids for generic params whose parent is the GAT.) + +<details> +<summary> <b>An illustrated example</b> </summary> + +```rust +trait Foo { + fn method<'early: 'early, 'late, T>() -> impl Sized + Captures<'early, 'late>; +} +``` + +Would desugar to... +```rust +trait Foo { + // vvvvvvvvv method's generics + // vvvvvvvvvvvvvvvvvvvvvvvv opaque's generics + type Gat<'early, T, 'early_duplicated, 'late>: Sized + Captures<'early_duplicated, 'late>; + + fn method<'early: 'early, 'late, T>() -> Self::Gat<'early, T, 'early, 'late>; +} +``` +</details> + +##### `generics_of` for the impl + +The generics for an impl's GAT are a bit more interesting. They are +composed of RPITIT's own generics (from the trait definition), appended +onto the impl's methods generics. This has the same issue as above, +where the generics for the GAT have parameters whose def-ids have the +wrong parent, but this should only cause issues in diagnostics. + +We could fix this similarly if we were to synthesize new generics +def-ids, but this can be done later in a forwards-compatible way, +perhaps by a interested new contributor. + +##### `opt_rpitit_info` + +Some queries rely on computing information that would result in cycles +if we were to feed them eagerly, like `explicit_predicates_of`. +Therefore we defer to the `predicates_of` provider to return the right +value for our RPITIT's GAT. We do this by detecting early on in the +query if the associated type is synthetic by using +[`opt_rpitit_info`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.opt_rpitit_info), +which returns `Some` if the associated type is synthetic. + +Then, during a query like `explicit_predicates_of`, we can detect if an +associated type is synthetic like: + +```rust +fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ... { + if let Some(rpitit_info) = tcx.opt_rpitit_info(def_id) { + // Do something special for RPITITs... + return ...; + } + + // The regular computation which relies on access to the HIR of `def_id`. +} +``` + +##### `explicit_predicates_of` + +RPITITs begin by copying the predicates of the method that defined it, +both on the trait and impl side. + +Additionally, we install "bidirectional outlives" predicates. +Specifically, we add region-outlives predicates in both directions for +each captured early-bound lifetime that constrains it to be equal to the +duplicated early-bound lifetime that results from lowering. This is best +illustrated in an example: + +```rust +trait Foo<'a> { + fn bar() -> impl Sized + 'a; +} + +// Desugars into... + +trait Foo<'a> { + type Gat<'a_duplicated>: Sized + 'a + where + 'a: 'a_duplicated, + 'a_duplicated: 'a; + //~^ Specifically, we should be able to assume that the + // duplicated `'a_duplicated` lifetime always stays in + // sync with the `'a` lifetime. + + fn bar() -> Self::Gat<'a>; +} +``` + +##### `assumed_wf_types` + +The GATs in both the trait and impl inherit the `assumed_wf_types` of +the trait method that defines the RPITIT. This is to make sure that the +following code is well formed when lowered. + +```rust +trait Foo { + fn iter<'a, T>(x: &'a [T]) -> impl Iterator<Item = &'a T>; +} + +// which is lowered to... + +trait FooDesugared { + type Iter<'a, T>: Iterator<Item = &'a T>; + //~^ assumed wf: `&'a [T]` + // Without assumed wf types, the GAT would not be well-formed on its own. + + fn iter<'a, T>(x: &'a [T]) -> Self::Iter<'a, T>; +} +``` + +Because `assumed_wf_types` is only defined for local def ids, in order +to properly implement `assumed_wf_types` for impls of foreign traits +with RPITs, we need to encode the assumed wf types of RPITITs in an +extern query +[`assumed_wf_types_for_rpitit`](https://github.com/rust-lang/rust/blob/a17c7968b727d8413801961fc4e89869b6ab00d3/compiler/rustc_ty_utils/src/implied_bounds.rs#L14). + +### Typechecking + +#### The RPITIT inference algorithm + +The RPITIT inference algorithm is implemented in +[`collect_return_position_impl_trait_in_trait_tys`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.collect_return_position_impl_trait_in_trait_tys.html). + +**High-level:** Given a impl method and a trait method, we take the +trait method and instantiate each RPITIT in the signature with an infer +var. We then equate this trait method signature with the impl method +signature, and process all obligations that fall out in order to infer +the type of all of the RPITITs in the method. + +The method is also responsible for making sure that the hidden types for +each RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that +if we infer `impl Trait = Foo`, that `Foo: Trait` holds. + +<details> + <summary><b>An example...</b></summary> + +```rust +#![feature(return_position_impl_trait_in_trait)] + +use std::ops::Deref; + +trait Foo { + fn bar() -> impl Deref<Target = impl Sized>; + // ^- RPITIT ?0 ^- RPITIT ?1 +} + +impl Foo for () { + fn bar() -> Box<String> { Box::new(String::new()) } +} +``` + +We end up with the trait signature that looks like `fn() -> ?0`, and +nested obligations `?0: Deref<Target = ?1>`, `?1: Sized`. The impl +signature is `fn() -> Box<String>`. + +Equating these signatures gives us `?0 = Box<String>`, which then after +processing the obligation `Box<String>: Deref<Target = ?1>` gives us `?1 += String`, and the other obligation `String: Sized` evaluates to true. + +By the end of the algorithm, we end up with a mapping between associated +type def-ids to concrete types inferred from the signature. We can then +use this mapping to implement `type_of` for the synthetic associated +types in the impl, since this mapping describes the type that should +come after the `=` in `type Assoc = ...` for each RPITIT. +</details> + +#### Default trait body + +Type-checking a default trait body, like: + +```rust +trait Foo { + fn bar() -> impl Sized { + 1i32 + } +} +``` + +requires one interesting hack. We need to install a projection predicate +into the param-env of `Foo::bar` allowing us to assume that the RPITIT's +GAT normalizes to the RPITIT's opaque type. This relies on the +observation that a trait method and RPITIT's GAT will always be "in +sync". That is, one will only ever be overridden if the other one is as +well. + +Compare this to a similar desugaring of the code above, which would fail +because we cannot rely on this same assumption: + +```rust +#![feature(impl_trait_in_assoc_type)] +#![feature(associated_type_defaults)] + +trait Foo { + type RPITIT = impl Sized; + + fn bar() -> Self::RPITIT { + 01i32 + } +} +``` + +Failing because a down-stream impl could theoretically provide an +implementation for `RPITIT` without providing an implementation of +`foo`: + +```text +error[E0308]: mismatched types +--> src/lib.rs:8:9 + | +5 | type RPITIT = impl Sized; + | ------------------------- associated type defaults can't be assumed inside the trait defining them +6 | +7 | fn bar() -> Self::RPITIT { + | ------------ expected `<Self as Foo>::RPITIT` because of return type +8 | 01i32 + | ^^^^^ expected associated type, found `i32` + | + = note: expected associated type `<Self as Foo>::RPITIT` + found type `i32` +``` + +#### Well-formedness checking + +We check well-formedness of RPITITs just like regular associated types. + +Since we added lifetime bounds in `predicates_of` that link the +duplicated early-bound lifetimes to their original lifetimes, and we +implemented `assumed_wf_types` which inherits the WF types of the method +from which the RPITIT originates ([#113704]), we have no issues +WF-checking the GAT as if it were a regular GAT. + +### What's broken, what's weird, etc. + +##### Specialization is super busted + +The "default trait methods" described above does not interact well with +specialization, because we only install those projection bounds in trait +default methods, and not in impl methods. Given that specialization is +already pretty busted, I won't go into detail, but it's currently a bug +tracked in: + * `tests/ui/impl-trait/in-trait/specialization-broken.rs` + +##### Projections don't have variances + +This code fails because projections don't have variances: +```rust +#![feature(return_position_impl_trait_in_trait)] + +trait Foo { + // Note that the RPITIT below does *not* capture `'lt`. + fn bar<'lt: 'lt>() -> impl Eq; +} + +fn test<'a, 'b, T: Foo>() -> bool { + <T as Foo>::bar::<'a>() == <T as Foo>::bar::<'b>() + //~^ ERROR + // (requires that `'a == 'b`) +} +``` + +This is because we can't relate `<T as Foo>::Rpitit<'a>` and `<T as +Foo>::Rpitit<'b>`, even if they don't capture their lifetime. If we were +using regular opaque types, this would work, because they would be +bivariant in that lifetime parameter: +```rust +#![feature(return_position_impl_trait_in_trait)] + +fn bar<'lt: 'lt>() -> impl Eq { + () +} + +fn test<'a, 'b>() -> bool { + bar::<'a>() == bar::<'b>() +} +``` + +This is probably okay though, since RPITITs will likely have their +captures behavior changed to capture all in-scope lifetimes anyways. +This could also be relaxed later in a forwards-compatible way if we were +to consider variances of RPITITs when relating projections. + +[#112988]: https://github.com/rust-lang/rust/pull/112988 +[RFC 3425]: https://github.com/rust-lang/rfcs/pull/3425 +[#101224]: https://github.com/rust-lang/rust/pull/101224 +[#113704]: https://github.com/rust-lang/rust/pull/113704 diff --git a/src/doc/rustc-dev-guide/src/rustc-driver.md b/src/doc/rustc-dev-guide/src/rustc-driver.md index 192811da1..bae98c746 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver.md @@ -32,7 +32,7 @@ as well as allowing some custom code run after different phases of the compilati [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html -[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html +[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-driver-example.rs [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index d58c2d280..e78c4bb25 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -173,6 +173,8 @@ running the Markdown parser. There's also a function in here (`find_testable_code`) that specifically scans for Rust code blocks so the test-runner code can find all the doctests in the crate. +[Askama]: https://docs.rs/askama/latest/askama/ + ### From soup to nuts (alternate title: ["An unbroken thread that stretches from those first `Cell`s @@ -279,7 +281,7 @@ server. To test these features locally, you can run a local HTTP server, like this: ```bash -$ ./x.py doc library +$ ./x doc library # The documentation has been generated into `build/[YOUR ARCH]/doc`. $ python3 -m http.server -d build/[YOUR ARCH]/doc ``` diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index cbe5e8b1f..02da8be81 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -41,24 +41,24 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) ## Cheat sheet -* Run `./x.py setup tools` before getting started. This will configure `x.py` +* Run `./x setup tools` before getting started. This will configure `x` with nice settings for developing rustdoc and other tools, including downloading a copy of rustc rather than building it. -* Use `./x.py check src/tools/rustdoc` to quickly check for compile errors. -* Use `./x.py build` to make a usable +* Use `./x check src/tools/rustdoc` to quickly check for compile errors. +* Use `./x build` to make a usable rustdoc you can run on other projects. * Add `library/test` to be able to use `rustdoc --test`. * Run `rustup toolchain link stage2 build/host/stage2` to add a custom toolchain called `stage2` to your rustup environment. After running that, `cargo +stage2 doc` in any directory will build with your locally-compiled rustdoc. -* Use `./x.py doc library` to use this rustdoc to generate the +* Use `./x doc library` to use this rustdoc to generate the standard library docs. * The completed docs will be available in `build/host/doc` (under `core`, `alloc`, and `std`). * If you want to copy those docs to a webserver, copy all of `build/host/doc`, since that's where the CSS, JS, fonts, and landing page are. -* Use `./x.py test tests/rustdoc*` to run the tests using a stage1 +* Use `./x test tests/rustdoc*` to run the tests using a stage1 rustdoc. * See [Rustdoc internals] for more information about tests. diff --git a/src/doc/rustc-dev-guide/src/salsa.md b/src/doc/rustc-dev-guide/src/salsa.md index 66f9d7479..47442ae14 100644 --- a/src/doc/rustc-dev-guide/src/salsa.md +++ b/src/doc/rustc-dev-guide/src/salsa.md @@ -148,9 +148,9 @@ this one depends on by specifying them as supertraits, as seen in the following example: ```rust,ignore -/// This query group is going to contain queries that depend on derived values a +/// This query group is going to contain queries that depend on derived values. A /// query group can access another query group's queries by specifying the -/// dependency as a super trait query groups can be stacked as much as needed using +/// dependency as a super trait. Query groups can be stacked as much as needed using /// that pattern. #[salsa::query_group(ParserStorage)] pub trait Parser: Inputs { @@ -168,7 +168,7 @@ belongs to, in addition to the other keys. ```rust,ignore ///This is going to be the definition of the `ast` query in the `Parser` trait. ///So, when the query `ast` is invoked, and it needs to be recomputed, Salsa is going to call this function -///and it's is going to give it the database as `impl Parser`. +///and it's going to give it the database as `impl Parser`. ///The function doesn't need to be aware of all the queries of all the query groups fn ast(db: &impl Parser, name: String) -> String { //! Note, `impl Parser` is used here but `dyn Parser` works just as well diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 21b07ec99..27d40a11a 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -98,7 +98,7 @@ To enable a sanitizer on a new target which is already supported by LLVM: 2. [Build the runtime for the target and include it in the libdir.][sanitizer-targets] 3. [Teach compiletest that your target now supports the sanitizer.][compiletest-definition] Tests marked with `needs-sanitizer-*` should now run on the target. -4. Run tests `./x.py test --force-rerun tests/ui/sanitize/` to verify. +4. Run tests `./x test --force-rerun tests/ui/sanitize/` to verify. 5. [--enable-sanitizers in the CI configuration][ci-configuration] to build and distribute the sanitizer runtime as part of the release process. diff --git a/src/doc/rustc-dev-guide/src/serialization.md b/src/doc/rustc-dev-guide/src/serialization.md index 691d21bc2..78b065311 100644 --- a/src/doc/rustc-dev-guide/src/serialization.md +++ b/src/doc/rustc-dev-guide/src/serialization.md @@ -109,7 +109,7 @@ and `Encodable`. only allow decoding by [`rustc_metadata::rmeta::encoder::EncodeContext`] and [`rustc_metadata::rmeta::decoder::DecodeContext`]. These are used for types that contain `rustc_metadata::rmeta::Lazy`. -- `TyEncodable` and `TyDecoder` generate implementation that apply to any +- `TyEncodable` and `TyDecodable` generate implementation that apply to any `TyEncoder` or `TyDecoder`. These should be used for types that are only serialized in crate metadata and/or the incremental cache, which is most serializable types in `rustc_middle`. @@ -130,7 +130,7 @@ some deserialization needs to be deferred from the initial loading of metadata. The [`LazyValue<T>`] type wraps the (relative) offset in the crate metadata where a `T` has been serialized. There are also some variants, [`LazyArray<T>`] and [`LazyTable<I, T>`]. -The `Lazy<[T]>` and `LazyTable<I, T>` type provide some functionality over +The `Lazy<[T]>` and `LazyTable<I, T>` types provide some functionality over `Lazy<Vec<T>>` and `Lazy<HashMap<I, T>>`: - It's possible to encode a `LazyArray<T>` directly from an iterator, without diff --git a/src/doc/rustc-dev-guide/src/solve/normalization.md b/src/doc/rustc-dev-guide/src/solve/normalization.md new file mode 100644 index 000000000..653c976a4 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/solve/normalization.md @@ -0,0 +1,80 @@ +# Normalization in the new solver + +With the new solver we've made some fairly significant changes to normalization when compared +to the existing implementation. + +We now differentiate between "shallow normalization" and "deep normalization". +"Shallow normalization" normalizes a type until it is no-longer a potentially normalizeable alias; +it does not recurse into the type. "deep normalization" replaces all normalizeable aliases in a +type with its underlying type. + +The old trait solver currently always deeply normalizes via `Projection` obligations. +This is the only way to normalize in the old solver. By replacing projections with a new +inference variable and then emitting `Projection(<T as Trait>::Assoc, ?new_infer)` the old +solver successfully deeply normalizes even in the case of ambiguity. This approach does not +work for projections referencing bound variables. + +## Inside of the trait solver + +Normalization in the new solver exclusively happens via `Projection`[^0] goals. +This only succeeds by first normalizing the alias by one level and then equating +it with the expected type. This differs from [the behavior of projection clauses] +which can also be proven by successfully equating the projection without normalizating. +This means that `Projection`[^0] goals must only be used in places where we +*have to normalize* to make progress. To normalize `<T as Trait>::Assoc`, we first create +a fresh inference variable `?normalized` and then prove +`Projection(<T as Trait>::Assoc, ?normalized)`[^0]. `?normalized` is then constrained to +the underlying type. + +Inside of the trait solver we never deeply normalize. we only apply shallow normalization +in [`assemble_candidates_after_normalizing_self_ty`] and inside for [`AliasRelate`] +goals for the [`normalizes-to` candidates]. + +## Outside of the trait solver + +The core type system - relating types and trait solving - will not need deep +normalization with the new solver. There are still some areas which depend on it. +For these areas there is the function `At::deeply_normalize`. Without additional +trait solver support deep normalization does not always work in case of ambiguity. +Luckily deep normalization is currently only necessary in places where there is no ambiguity. +`At::deeply_normalize` immediately fails if there's ambiguity. + +If we only care about the outermost layer of types, we instead use +`At::structurally_normalize` or `FnCtxt::(try_)structurally_resolve_type`. +Unlike `At::deeply_normalize`, shallow normalization is also used in cases where we +have to handle ambiguity. `At::structurally_normalize` normalizes until the self type +is either rigid or an inference variable and we're stuck with ambiguity. This means +that the self type may not be fully normalized after `At::structurally_normalize` was called. + +Because this may result in behavior changes depending on how the trait solver handles +ambiguity, it is safer to also require full normalization there. This happens in +`FnCtxt::structurally_resolve_type` which always emits a hard error if the self type ends +up as an inference variable. There are some existing places which have a fallback for +inference variables instead. These places use `try_structurally_resolve_type` instead. + +## Why deep normalization with ambiguity is hard + +Fully correct deep normalization is very challenging, especially with the new solver +given that we do not want to deeply normalize inside of the solver. Mostly deeply normalizing +but sometimes failing to do so is bound to cause very hard to minimize and understand bugs. +If possible, avoiding any reliance on deep normalization entirely therefore feels preferable. + +If the solver itself does not deeply normalize, any inference constraints returned by the +solver would require normalization. Handling this correctly is ugly. This also means that +we change goals we provide to the trait solver by "normalizing away" some projections. + +The way we (mostly) guarantee deep normalization with the old solver is by eagerly replacing +the projection with an inference variable and emitting a nested `Projection` goal. This works +as `Projection` goals in the old solver deeply normalize. Unless we add another `PredicateKind` +for deep normalization to the new solver we cannot emulate this behavior. This does not work +for projections with bound variables, sometimes leaving them unnormalized. An approach which +also supports projections with bound variables will be even more involved. + + +[`assemble_candidates_after_normalizing_self_ty`]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L330-L378 +[`AliasRelate`]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L16-L102 +[`normalizes-to` candidates]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L105-L151 +[the behavior of projection clauses]: https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 +[normalize-via-infer]: https://github.com/rust-lang/rust/blob/1b6d4cdc4d923c148198ad4df230af48cdaca59e/compiler/rustc_trait_selection/src/solve/assembly/mod.rs#L350-L358 + +[^0]: TODO: currently refactoring this to use `NormalizesTo` predicates instead.
\ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/solve/trait-solving.md b/src/doc/rustc-dev-guide/src/solve/trait-solving.md index b0cd9af6c..c3089f4a8 100644 --- a/src/doc/rustc-dev-guide/src/solve/trait-solving.md +++ b/src/doc/rustc-dev-guide/src/solve/trait-solving.md @@ -97,7 +97,7 @@ all free regions during codegen we must not rely on them during typeck. A notewo is special behavior for `'static`. We also have to be careful with relying on equality of regions in the trait solver. -This is fine for codegen, as we treat all erased regions are equal. We can however +This is fine for codegen, as we treat all erased regions as equal. We can however lose equality information from HIR to MIR typeck. ### 7. Removing ambiguity makes strictly more things compile @@ -111,8 +111,8 @@ Two types being equal in the type system must mean that they have the same `Type [solve]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/index.html -[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/struct.Goal.html +[`Goal`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/struct.Goal.html [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html [`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/struct.Candidate.html [`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/assembly/enum.CandidateSource.html -[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/solve/type.CanonicalResponse.html +[`CanonicalResponse`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/solve/type.CanonicalResponse.html diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index 85c75fadb..bf82d8517 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -1,12 +1,12 @@ # Stability attributes -<!-- toc --> - This section is about the stability attributes and schemes that allow stable APIs to use unstable APIs internally in the rustc standard library. -For instructions on stabilizing a language feature see [Stabilizing -Features](./stabilization_guide.md). +**NOTE**: this section is for *library* features, not *language* features. For instructions on +stabilizing a language feature see [Stabilizing Features](./stabilization_guide.md). + +<!-- toc --> ## unstable diff --git a/src/doc/rustc-dev-guide/src/stabilization_guide.md b/src/doc/rustc-dev-guide/src/stabilization_guide.md index 0ac19293b..001ed25a5 100644 --- a/src/doc/rustc-dev-guide/src/stabilization_guide.md +++ b/src/doc/rustc-dev-guide/src/stabilization_guide.md @@ -1,6 +1,6 @@ # Request for stabilization -**NOTE**: this page is about stabilizing language features. +**NOTE**: this page is about stabilizing *language* features. For stabilizing *library* features, see [Stabilizing a library feature]. [Stabilizing a library feature]: ./stability.md#stabilizing-a-library-feature diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index 632614539..fc0c4937e 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -84,7 +84,7 @@ The next step is to create the expected output from the compiler. This can be done with the `--bless` option: ```sh -./x.py test tests/ui/async-await/await-without-async.rs --bless +./x test tests/ui/async-await/await-without-async.rs --bless ``` This will build the compiler (if it hasn't already been built), compile the @@ -118,7 +118,7 @@ annotations](ui.md#error-annotations) section). Save that, and run the test again: ```sh -./x.py test tests/ui/async-await/await-without-async.rs +./x test tests/ui/async-await/await-without-async.rs ``` It should now pass, yay! @@ -166,7 +166,7 @@ The final step before posting a PR is to check if you have affected anything els Running the UI suite is usually a good start: ```sh -./x.py test tests/ui +./x test tests/ui ``` If other tests start failing, you may need to investigate what has changed diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index cca4973cb..bfdc2a45a 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -6,7 +6,7 @@ When a Pull Request is opened on GitHub, [GitHub Actions] will automatically launch a build that will run all tests on some configurations (x86_64-gnu-llvm-13 linux, x86_64-gnu-tools linux, and mingw-check linux). -In essence, each runs `./x.py test` with various different options. +In essence, each runs `./x test` with various different options. The integration bot [bors] is used for coordinating merges to the master branch. When a PR is approved, it goes into a [queue] where merges are tested one at a @@ -54,8 +54,8 @@ the other jobs. The comment at the top of `ci.yml` will tell you to run this command: ```sh -./x.py run src/tools/expand-yaml-anchors -```` +./x run src/tools/expand-yaml-anchors +``` This will generate the true [`.github/workflows/ci.yml`] which is what GitHub Actions uses. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index d4730c5b4..86ebe3a49 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -330,7 +330,7 @@ set a baseline for optimizations: The test should be annotated with `// EMIT_MIR` comments that specify files that will contain the expected MIR output. -You can use `x.py test --bless` to create the initial expected files. +You can use `x test --bless` to create the initial expected files. There are several forms the `EMIT_MIR` comment can take: @@ -380,7 +380,7 @@ There is a [`tools.mk`] Makefile which you can include which provides a bunch of utilities to make it easier to run commands and compare outputs. Take a look at some of the other tests for some examples on how to get started. -[`tools.mk`]: https://github.com/rust-lang/rust/blob/master/tests/run-make-fulldeps/tools.mk +[`tools.mk`]: https://github.com/rust-lang/rust/blob/master/tests/run-make/tools.mk [`tests/run-make`]: https://github.com/rust-lang/rust/tree/master/tests/run-make @@ -452,7 +452,7 @@ compiler, and `no-prefer-dynamic` is needed to tell compiletest to not use `prefer-dynamic` which is not compatible with proc-macros. The `#![crate_type]` attribute is needed to specify the correct crate-type. -Then in your test, you can build with with `aux-build`: +Then in your test, you can build with `aux-build`: ```rust,ignore // aux-build: my-proc-macro.rs @@ -503,10 +503,9 @@ currently only apply to the test as a whole, not to particular revisions. The only headers that are intended to really work when customized to a revision are error patterns and compiler flags. - ## Compare modes -Compiletest can be run in different modes, called *compare modes*, which can +Compiletest can be run in different modes, called _compare modes_, which can be used to compare the behavior of all tests with different compiler flags enabled. This can help highlight what differences might appear with certain flags, and @@ -516,7 +515,7 @@ To run the tests in a different mode, you need to pass the `--compare-mode` CLI flag: ```bash -./x.py test tests/ui --compare-mode=chalk +./x test tests/ui --compare-mode=chalk ``` The possible compare modes are: @@ -537,5 +536,5 @@ following settings: enabling split-DWARF. Note that compare modes are separate to [revisions](#revisions). -All revisions are tested when running `./x.py test tests/ui`, however +All revisions are tested when running `./x test tests/ui`, however compare-modes must be manually run individually via the `--compare-mode` flag. diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index 0d9e0a492..31e3825f5 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -21,7 +21,7 @@ directory. From there, you can run `../src/ci/run.sh` which will run the build as defined by the image. Alternatively, you can run individual commands to do specific tasks. For -example, you can run `python3 ../x.py test tests/ui` to just run UI tests. +example, you can run `../x test tests/ui` to just run UI tests. Note that there is some configuration in the [`src/ci/run.sh`] script that you may need to recreate. Particularly, set `submodules = false` in your `config.toml` so that it doesn't attempt to modify the read-only directory. diff --git a/src/doc/rustc-dev-guide/src/tests/headers.md b/src/doc/rustc-dev-guide/src/tests/headers.md index 682c96b44..f066dbbb5 100644 --- a/src/doc/rustc-dev-guide/src/tests/headers.md +++ b/src/doc/rustc-dev-guide/src/tests/headers.md @@ -28,7 +28,7 @@ Header commands can be standalone (like `// run-pass`) or take a value (like ## Header commands The following is a list of header commands. -Commands are linked to sections the describe the command in more detail if available. +Commands are linked to sections that describe the command in more detail if available. This list may not be exhaustive. Header commands can generally be found by browsing the `TestProps` structure found in [`header.rs`] from the compiletest source. @@ -70,7 +70,6 @@ found in [`header.rs`] from the compiletest source. * `min-llvm-versionX` * `min-system-llvm-version` * `ignore-llvm-version` - * `ignore-llvm-version` * [Environment variable headers](#environment-variable-headers) * `rustc-env` * `exec-env` @@ -145,7 +144,7 @@ The following header commands will check rustc build settings and target setting (AddressSanitizer, hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or ThreadSanitizer respectively) * `needs-run-enabled` — ignores if it is a test that gets executed, and - running has been disabled. Running tests can be disabled with the `x.py test + running has been disabled. Running tests can be disabled with the `x test --run=never` flag, or running on fuchsia. * `needs-unwind` — ignores if the target does not support unwinding * `needs-rust-lld` — ignores if the rust lld support is not enabled diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index adc5d58ec..647d1fbea 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -3,14 +3,14 @@ <!-- toc --> The Rust project runs a wide variety of different tests, orchestrated by -the build system (`./x.py test`). +the build system (`./x test`). This section gives a brief overview of the different testing tools. Subsequent chapters dive into [running tests](running.md) and [adding new tests](adding.md). ## Kinds of tests There are several kinds of tests to exercise things in the Rust distribution. -Almost all of them are driven by `./x.py test`, with some exceptions noted below. +Almost all of them are driven by `./x test`, with some exceptions noted below. ### Compiletest @@ -19,7 +19,7 @@ It supports running different styles of tests, called *test suites*. The tests are all located in the [`tests`] directory. The [Compiletest chapter][compiletest] goes into detail on how to use this tool. -> Example: `./x.py test tests/ui` +> Example: `./x test tests/ui` [compiletest]: compiletest.md [`tests`]: https://github.com/rust-lang/rust/tree/master/tests @@ -29,23 +29,23 @@ The [Compiletest chapter][compiletest] goes into detail on how to use this tool. The standard library and many of the compiler packages include typical Rust `#[test]` unit tests, integration tests, and documentation tests. You can pass a path to `x.py` to almost any package in the `library` or `compiler` directory, -and `x.py` will essentially run `cargo test` on that package. +and `x` will essentially run `cargo test` on that package. Examples: -| Command | Description | -|---------|-------------| -| `./x.py test library/std` | Runs tests on `std` only | -| `./x.py test library/core` | Runs tests on `core` only | -| `./x.py test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | +| Command | Description | +| ----------------------------------------- | ------------------------------------- | +| `./x test library/std` | Runs tests on `std` only | +| `./x test library/core` | Runs tests on `core` only | +| `./x test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | The standard library relies very heavily on documentation tests to cover its functionality. However, unit tests and integration tests can also be used as needed. Almost all of the compiler packages have doctests disabled. -The standard library and compiler always place all unit tests in a separate `tests` file -(this is enforced in [tidy][tidy-unit-tests]). -This approach ensures that when the test file is changed, the crate does not need to be recompiled. +All standard library and compiler unit tests are placed in separate `tests` file +(which is enforced in [tidy][tidy-unit-tests]). +This ensures that when the test file is changed, the crate does not need to be recompiled. For example: ```rust,ignore @@ -53,12 +53,11 @@ For example: mod tests; ``` -If it wasn't done this way, and the tests were placed in the same file as the source, -then changing or adding a test would cause the crate you are working on to be recompiled. -If you were working on something like `core`, -then that would require recompiling the entire standard library, and the entirety of `rustc`. +If it wasn't done this way, +and you were working on something like `core`, +that would require recompiling the entire standard library, and the entirety of `rustc`. -`./x.py test` includes some CLI options for controlling the behavior with these tests: +`./x test` includes some CLI options for controlling the behavior with these tests: * `--doc` — Only runs documentation tests in the package. * `--no-doc` — Run all tests *except* documentation tests. @@ -71,7 +70,7 @@ Tidy is a custom tool used for validating source code style and formatting conve such as rejecting long lines. There is more information in the [section on coding conventions](../conventions.md#formatting). -> Example: `./x.py test tidy` +> Example: `./x test tidy` ### Formatting @@ -80,28 +79,28 @@ The formatting check is automatically run by the Tidy tool mentioned above. Examples: -| Command | Description | -|---------|-------------| -| `./x.py fmt --check` | Checks formatting and exits with an error if formatting is needed. | -| `./x.py fmt` | Runs rustfmt across the entire codebase. | -| `./x.py test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | +| Command | Description | +| ----------------------- | ------------------------------------------------------------------ | +| `./x fmt --check` | Checks formatting and exits with an error if formatting is needed. | +| `./x fmt` | Runs rustfmt across the entire codebase. | +| `./x test tidy --bless` | First runs rustfmt to format the codebase, then runs tidy checks. | ### Book documentation tests All of the books that are published have their own tests, primarily for validating that the Rust code examples pass. Under the hood, these are essentially using `rustdoc --test` on the markdown files. -The tests can be run by passing a path to a book to `./x.py test`. +The tests can be run by passing a path to a book to `./x test`. -> Example: `./x.py test src/doc/book` +> Example: `./x test src/doc/book` ### Documentation link checker Links across all documentation is validated with a link checker tool. -> Example: `./x.py test src/tools/linkchecker` +> Example: `./x test src/tools/linkchecker` -> Example: `./x.py test linkchecker` +> Example: `./x test linkchecker` This requires building all of the documentation, which might take a while. @@ -110,7 +109,7 @@ This requires building all of the documentation, which might take a while. `distcheck` verifies that the source distribution tarball created by the build system will unpack, build, and run all tests. -> Example: `./x.py test distcheck` +> Example: `./x test distcheck` ### Tool tests @@ -119,9 +118,9 @@ This includes things such as cargo, clippy, rustfmt, miri, bootstrap (testing the Rust build system itself), etc. Most of the tools are located in the [`src/tools`] directory. -To run the tool's tests, just pass its path to `./x.py test`. +To run the tool's tests, just pass its path to `./x test`. -> Example: `./x.py test src/tools/cargo` +> Example: `./x test src/tools/cargo` Usually these tools involve running `cargo test` within the tool's directory. @@ -139,7 +138,7 @@ More information can be found in the [toolstate documentation]. (such as `servo`, `ripgrep`, `tokei`, etc.). This ensures there aren't any significant regressions. -> Example: `./x.py test src/tools/cargotest` +> Example: `./x test src/tools/cargotest` ### Crater diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 0a3de6f8b..71fb82b68 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -2,11 +2,11 @@ <!-- toc --> -You can run the tests using `x.py`. The most basic command – which +You can run the tests using `x`. The most basic command – which you will almost never want to use! – is as follows: ```bash -./x.py test +./x test ``` This will build the stage 1 compiler and then run the whole test @@ -37,7 +37,7 @@ modifying rustc to see if things are generally working correctly would be the following: ```bash -./x.py test tests/ui +./x test tests/ui ``` This will run the `ui` test suite. Of course, the choice @@ -46,32 +46,32 @@ doing. For example, if you are hacking on debuginfo, you may be better off with the debuginfo test suite: ```bash -./x.py test tests/debuginfo +./x test tests/debuginfo ``` If you only need to test a specific subdirectory of tests for any -given test suite, you can pass that directory to `./x.py test`: +given test suite, you can pass that directory to `./x test`: ```bash -./x.py test tests/ui/const-generics +./x test tests/ui/const-generics ``` Likewise, you can test a single file by passing its path: ```bash -./x.py test tests/ui/const-generics/const-test.rs +./x test tests/ui/const-generics/const-test.rs ``` ### Run only the tidy script ```bash -./x.py test tidy +./x test tidy ``` ### Run tests on the standard library ```bash -./x.py test --stage 0 library/std +./x test --stage 0 library/std ``` Note that this only runs tests on `std`; if you want to test `core` or other crates, @@ -80,13 +80,13 @@ you have to specify those explicitly. ### Run the tidy script and tests on the standard library ```bash -./x.py test --stage 0 tidy library/std +./x test --stage 0 tidy library/std ``` ### Run tests on the standard library using a stage 1 compiler ```bash -./x.py test --stage 1 library/std +./x test --stage 1 library/std ``` By listing which test suites you want to run you avoid having to run @@ -99,7 +99,7 @@ there are some limitations. ### Run all tests using a stage 2 compiler ```bash -./x.py test --stage 2 +./x test --stage 2 ``` You almost never need to do this; CI will run these tests for you. @@ -108,13 +108,13 @@ You almost never need to do this; CI will run these tests for you. You may want to run unit tests on a specific file with following: ```bash -./x.py test compiler/rustc_data_structures/src/thin_vec/tests.rs +./x test compiler/rustc_data_structures/src/thin_vec/tests.rs ``` But unfortunately, it's impossible. You should invoke following instead: ```bash -./x.py test compiler/rustc_data_structures/ --test-args thin_vec +./x test compiler/rustc_data_structures/ --test-args thin_vec ``` ## Running an individual test @@ -122,10 +122,10 @@ But unfortunately, it's impossible. You should invoke following instead: Another common thing that people want to do is to run an **individual test**, often the test they are trying to fix. As mentioned earlier, you may pass the full file path to achieve this, or alternatively one -may invoke `x.py` with the `--test-args` option: +may invoke `x` with the `--test-args` option: ```bash -./x.py test tests/ui --test-args issue-1234 +./x test tests/ui --test-args issue-1234 ``` Under the hood, the test runner invokes the standard Rust test runner @@ -133,6 +133,15 @@ Under the hood, the test runner invokes the standard Rust test runner filtering for tests that include "issue-1234" in the name. (Thus `--test-args` is a good way to run a collection of related tests.) +## Passing arguments to `rustc` when running tests + +It can sometimes be useful to run some tests with specific compiler arguments, +without using `RUSTFLAGS` (during development of unstable features, with `-Z` +flags, for example). + +This can be done with `./x test`'s `--rustc-args` option, to pass additional +arguments to the compiler when building the tests. + ## Editing and updating the reference files If you have changed the compiler's output intentionally, or you are @@ -140,7 +149,7 @@ making a new test, you can pass `--bless` to the test subcommand. E.g. if some tests in `tests/ui` are failing, you can run ```text -./x.py test tests/ui --bless +./x test tests/ui --bless ``` to automatically adjust the `.stderr`, `.stdout` or `.fixed` files of @@ -168,7 +177,7 @@ exists in the test file. For example, you can run all the tests in `tests/ui` as `check-pass`: ```bash -./x.py test tests/ui --pass check +./x test tests/ui --pass check ``` By passing `--pass $mode`, you can reduce the testing time. For each @@ -184,7 +193,7 @@ mode, a test `foo.rs` will first look for expected output in The following will run the UI test suite in Polonius mode: ```bash -./x.py test tests/ui --compare-mode=polonius +./x test tests/ui --compare-mode=polonius ``` See [Compare modes](compiletest.md#compare-modes) for more details. @@ -217,7 +226,7 @@ execution* so be careful where it is used. To do this, first build `remote-test-server` for the remote machine, e.g. for RISC-V ```sh -./x.py build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu +./x build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu ``` The binary will be created at @@ -247,11 +256,11 @@ pong ``` To run tests using the remote runner, set the `TEST_DEVICE_ADDR` environment -variable then use `x.py` as usual. For example, to run `ui` tests for a RISC-V +variable then use `x` as usual. For example, to run `ui` tests for a RISC-V machine with the IP address `1.2.3.4` use ```sh export TEST_DEVICE_ADDR="1.2.3.4:12345" -./x.py test tests/ui --target riscv64gc-unknown-linux-gnu +./x test tests/ui --target riscv64gc-unknown-linux-gnu ``` If `remote-test-server` was run with the verbose flag, output on the test machine @@ -273,7 +282,7 @@ run "/tmp/work/test1018/a" [...] ``` -Tests are built on the machine running `x.py` not on the remote machine. Tests +Tests are built on the machine running `x` not on the remote machine. Tests which fail to build unexpectedly (or `ui` tests producing incorrect build output) may fail without ever running on the remote machine. diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index d94d8cc4e..1f899f586 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -88,7 +88,7 @@ check for output files: contents of the stored output files by lines opposed to checking for strict equality. -UI tests run with with `-Zdeduplicate-diagnostics=no` flag which disables +UI tests run with `-Zdeduplicate-diagnostics=no` flag which disables rustc's built-in diagnostic deduplication mechanism. This means you may see some duplicate messages in the output. This helps illuminate situations where duplicate diagnostics are being @@ -390,7 +390,7 @@ Tests with the `*-pass` headers can be overridden with the `--pass` command-line option: ```sh -./x.py test tests/ui --pass check +./x test tests/ui --pass check ``` The `--pass` option only affects UI tests. @@ -485,7 +485,7 @@ Then, it applies the suggestion and compares against `.fixed` (they must match). Finally, the fixed source is compiled, and this compilation is required to succeed. Usually when creating a rustfix test you will generate the `.fixed` file -automatically with the `x.py test --bless` option. +automatically with the `x test --bless` option. The `run-rustfix` header will cause *all* suggestions to be applied, even if they are not [`MachineApplicable`](../diagnostics.md#suggestions). @@ -515,7 +515,7 @@ If in the rare case you encounter a test that has different behavior, you can run something like the following to generate the alternate stderr file: ```sh -./x.py test tests/ui --compare-mode=polonius --bless +./x test tests/ui --compare-mode=polonius --bless ``` Currently none of the compare modes are checked in CI for UI tests. diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 84cb1296f..5e22f10e4 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -163,7 +163,7 @@ Depending on the feature/change/bug fix/improvement, implementation may be relatively-straightforward or it may be a major undertaking. You can always ask for help or mentorship from more experienced compiler devs. Also, you don't have to be the one to implement your feature; but keep in mind that if you -don't it might be a while before someone else does. +don't, it might be a while before someone else does. For the `?` macro feature, I needed to go understand the relevant parts of macro expansion in the compiler. Personally, I find that [improving the diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml index cea6033ed..167aece0e 100644 --- a/src/doc/rustc/book.toml +++ b/src/doc/rustc/book.toml @@ -6,3 +6,9 @@ title = "The rustc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc" edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}" + +[output.html.search] +use-boolean-and = true + +[output.html.playground] +runnable = false diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index f8af26326..94605e2a2 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -28,21 +28,28 @@ - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - [\*-android and \*-androideabi](platform-support/android.md) - [\*-linux-ohos](platform-support/openharmony.md) + - [aarch64-unknown-teeos](platform-support/aarch64-unknown-teeos.md) - [\*-esp-espidf](platform-support/esp-idf.md) - [\*-unknown-fuchsia](platform-support/fuchsia.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) + - [csky-unknown-linux-gnuabiv2](platform-support/csky-unknown-linux-gnuabiv2.md) - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md) - [loongarch\*-unknown-none\*](platform-support/loongarch-none.md) - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md) - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md) - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md) + - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) + - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) + - [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) + - [*-unknown-hermit](platform-support/hermit.md) - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-uefi](platform-support/unknown-uefi.md) + - [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md) - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) @@ -55,4 +62,6 @@ - [Instrumentation-based Code Coverage](instrument-coverage.md) - [Linker-plugin-based LTO](linker-plugin-lto.md) - [Exploit Mitigations](exploit-mitigations.md) +- [Symbol Mangling](symbol-mangling/index.md) + - [v0 Symbol Format](symbol-mangling/v0.md) - [Contributing to `rustc`](contributing.md) diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 8de638dde..f882a31de 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -569,20 +569,22 @@ for the purpose of generating object code and linking. Supported values for this option are: -* `v0` — The "v0" mangling scheme. The specific format is not specified at - this time. +* `v0` — The "v0" mangling scheme. The default, if not specified, will use a compiler-chosen default which may change in the future. +See the [Symbol Mangling] chapter for details on symbol mangling and the mangling format. + [name mangling]: https://en.wikipedia.org/wiki/Name_mangling +[Symbol Mangling]: ../symbol-mangling/index.md ## target-cpu This instructs `rustc` to generate code specifically for a particular processor. You can run `rustc --print target-cpus` to see the valid options to pass -and the default target CPU for the current buid target. +and the default target CPU for the current build target. Each target has a default base CPU. Special values include: * `native` can be passed to use the processor of the host machine. diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d2a25e612..68b70a4f3 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -101,7 +101,7 @@ target | notes `x86_64-unknown-freebsd` | 64-bit FreeBSD `x86_64-unknown-illumos` | illumos `x86_64-unknown-linux-musl` | 64-bit Linux with MUSL -`x86_64-unknown-netbsd` | NetBSD/amd64 +[`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64 ## Tier 2 @@ -128,7 +128,7 @@ target | std | notes `aarch64-apple-ios` | ✓ | ARM64 iOS [`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64 `aarch64-fuchsia` | ✓ | Alias for `aarch64-unknown-fuchsia` -`aarch64-unknown-fuchsia` | ✓ | ARM64 Fuchsia +[`aarch64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | ARM64 Fuchsia [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat `aarch64-unknown-none` | * | Bare ARM64, hardfloat @@ -159,7 +159,7 @@ target | std | notes `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL `mipsel-unknown-linux-musl` | ✓ | MIPS (LE) Linux with MUSL -`nvptx64-nvidia-cuda` | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] +[`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs] `riscv32i-unknown-none-elf` | * | Bare RISC-V (RV32I ISA) `riscv32imac-unknown-none-elf` | * | Bare RISC-V (RV32IMAC ISA) `riscv32imc-unknown-none-elf` | * | Bare RISC-V (RV32IMC ISA) @@ -176,13 +176,15 @@ target | std | notes `thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline `thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat +[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+ `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI +[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads `x86_64-apple-ios` | ✓ | 64-bit x86 iOS [`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX `x86_64-fuchsia` | ✓ | Alias for `x86_64-unknown-fuchsia` -`x86_64-unknown-fuchsia` | ✓ | 64-bit Fuchsia +[`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia [`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android `x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) @@ -220,9 +222,10 @@ target | std | host | notes [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | [`aarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | ARM64 OpenHarmony | +[`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? | | ARM64 TEEOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD -`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore +[`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD @@ -257,6 +260,7 @@ target | std | host | notes `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) +`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux(little endian) `hexagon-unknown-linux-musl` | ? | | `i386-apple-ios` | ✓ | | 32-bit x86 iOS [`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS | @@ -277,10 +281,10 @@ target | std | host | notes [`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX) `mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc `mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat -`mipsisa32r6-unknown-linux-gnu` | ? | | -`mipsisa32r6el-unknown-linux-gnu` | ? | | -`mipsisa64r6-unknown-linux-gnuabi64` | ? | | -`mipsisa64r6el-unknown-linux-gnuabi64` | ? | | +[`mipsisa32r6-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Big Endian +[`mipsisa32r6el-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Little Endian +[`mipsisa64r6-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ? | | 64-bit MIPS Release 6 Big Endian +[`mipsisa64r6el-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ✓ | ✓ | 64-bit MIPS Release 6 Little Endian `msp430-none-elf` | * | | 16-bit MSP430 microcontrollers `powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux `powerpc-unknown-linux-musl` | ? | | @@ -302,11 +306,13 @@ target | std | host | notes [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF +[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit `riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) -[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ? | RISC-V NetBSD +[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 +[`riscv64-linux-android`](platform-support/android.md) | | | RISC-V 64-bit Android `s390x-unknown-linux-musl` | | | S390x Linux (kernel 3.2, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64 @@ -324,14 +330,16 @@ target | std | host | notes [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ | `x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support `x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos +[`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku -`x86_64-unknown-hermit` | ✓ | | HermitCore +[`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit `x86_64-unknown-l4re-uclibc` | ? | | +[`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | x86_64 OpenHarmony | [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD `x86_64-uwp-windows-gnu` | ✓ | | `x86_64-uwp-windows-msvc` | ✓ | | `x86_64-wrs-vxworks` | ? | | -`x86_64h-apple-darwin` | ✓ | ✓ | macOS with late-gen Intel (at least Haswell) +[`x86_64h-apple-darwin`](platform-support/x86_64h-apple-darwin.md) | ✓ | ✓ | macOS with late-gen Intel (at least Haswell) [runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md new file mode 100644 index 000000000..8bc938134 --- /dev/null +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -0,0 +1,100 @@ +# `aarch64-unknown-teeos` + +**Tier: 3** + +Target for the TEEOS operating system. + +TEEOS is a mini os run in TrustZone, for trusted/security apps. The kernel of TEEOS is HongMeng/ChCore micro kernel. The libc for TEEOS is a part of musl. +It's very small that there is no RwLock, no network, no stdin, and no file system for apps in TEEOS. + +Some abbreviation: +| Abbreviation | The full text | Description | +| ---- | ---- | ---- | +| TEE | Trusted Execution Environment | ARM TrustZone divides the system into two worlds/modes -- the secure world/mode and the normal world/mode. TEE is in the secure world/mode. | +| REE | Rich Execution Environment | The normal world. for example, Linux for Android phone is in REE side. | +| TA | Trusted Application | The app run in TEE side system. | +| CA | Client Application | The progress run in REE side system. | + +TEEOS is open source in progress. [MORE about](https://gitee.com/opentrustee-group) + +## Target maintainers + +- Petrochenkov Vadim +- Sword-Destiny + +## Setup +We use OpenHarmony SDK for TEEOS. + +The OpenHarmony SDK doesn't currently support Rust compilation directly, so +some setup is required. + +First, you must obtain the OpenHarmony SDK from [this page](https://gitee.com/openharmony/docs/tree/master/en/release-notes). +Select the version of OpenHarmony you are developing for and download the "Public SDK package for the standard system". + +Create the following shell scripts that wrap Clang from the OpenHarmony SDK: + +`aarch64-unknown-teeos-clang.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ + --target aarch64-linux-gnu \ + "$@" +``` + +`aarch64-unknown-teeos-clang++.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ + --target aarch64-linux-gnu \ + "$@" +``` + +## Building the target + +To build a rust toolchain, create a `config.toml` with the following contents: + +```toml +profile = "compiler" +changelog-seen = 2 + +[build] +sanitizers = true +profiler = true +target = ["x86_64-unknown-linux-gnu", "aarch64-unknown-teeos"] +submodules = false +compiler-docs = false +extended = true + +[install] +bindir = "bin" +libdir = "lib" + +[target.aarch64-unknown-teeos] +cc = "/path/to/scripts/aarch64-unknown-teeos-clang.sh" +cxx = "/path/to/scripts/aarch64-unknown-teeos-clang.sh" +linker = "/path/to/scripts/aarch64-unknown-teeos-clang.sh" +ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" +ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" +llvm-config = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-config" +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +You will need to configure the linker to use in `~/.cargo/config`: +```toml +[target.aarch64-unknown-teeos] +linker = "/path/to/aarch64-unknown-teeos-clang.sh" +``` + +## Testing + +Running the Rust testsuite is not possible now. + +More information about how to test CA/TA. [See here](https://gitee.com/openharmony-sig/tee_tee_dev_kit/tree/master/docs) diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md index e351cfaf8..4ef74295e 100644 --- a/src/doc/rustc/src/platform-support/android.md +++ b/src/doc/rustc/src/platform-support/android.md @@ -39,6 +39,8 @@ edition of the [Android NDK]. Supported Android targets are: * thumbv7neon-linux-androideabi * x86_64-linux-android +The riscv64-linux-android target is supported as a Tier 3 target. + [Android NDK]: https://developer.android.com/ndk/downloads A list of all supported targets can be found diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md new file mode 100644 index 000000000..e73598be0 --- /dev/null +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -0,0 +1,70 @@ +# `csky-unknown-linux-gnuabiv2` + +**Tier: 3** + +This target supports [C-SKY](https://github.com/c-sky) CPUs with `abi` v2 and `glibc`. + +https://c-sky.github.io/ +https://gitlab.com/c-sky/ + +## Target maintainers + +* [@Dirreke](https://github.com/Dirreke) + +## Requirements + + +## Building the target + +### Get a C toolchain + +Compiling rust for this target has been tested on `x86_64` linux hosts. Other host types have not been tested, but may work, if you can find a suitable cross compilation toolchain for them. + +If you don't already have a suitable toolchain, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource/1356021/1619528643136/csky-linux-gnuabiv2-tools-x86_64-glibc-linux-4.9.56-20210423.tar.gz), and unpack it into a directory. + +### Configure rust + +The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`: + +```toml +[build] +target = ["x86_64-unknown-linux-gnu", "csky-unknown-linux-gnuabiv2"] +stage = 2 + +[target.csky-unknown-linux-gnuabiv2] +# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN +cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc" + +### Build + +```sh +# in rust dir +./x.py build --stage 2 +``` + +## Building and Running Rust programs + +To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-cskyv2`. This avoids having a full emulated ARM system by doing dynamic binary translation and dynamic system call translation. It lets you run CSKY programs directly on your `x86_64` kernel. It's very convenient! + +To use: + +* Install `qemu-cskyv2` (If you don't already have a qemu, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1689324918932/xuantie-qemu-x86_64-Ubuntu-18.04-20230714-0202.tar.gz"), and unpack it into a directory.) +* Link your built toolchain via: + * `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2` +* Create a test program + +```sh +cargo new hello_world +cd hello_world +``` + +* Build and run + +```sh +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_RUNNER=${QEMU_PATH}/bin/qemu-cskyv2 -L ${TOOLCHAIN_PATH}/csky-linux-gnuabiv2/libc \ +CARGO_TARGET_CSKY_UNKNOWN_LINUX_GNUABIV2_LINKER=${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc \ +RUSTFLAGS="-C target-features=+crt-static" \ +cargo +stage2 run --target csky-unknown-linux-gnuabiv2 +``` + +Attention: The dynamic-linked program may nor be run by `qemu-cskyv2` but can be run on the target. diff --git a/src/doc/rustc/src/platform-support/hermit.md b/src/doc/rustc/src/platform-support/hermit.md new file mode 100644 index 000000000..146079e36 --- /dev/null +++ b/src/doc/rustc/src/platform-support/hermit.md @@ -0,0 +1,75 @@ +# `*-unknown-hermit` + +**Tier: 3** + +The [Hermit] unikernel target allows compiling your applications into self-contained, specialized unikernel images that can be run in small virtual machines. + +[Hermit]: https://github.com/hermitcore + +Target triplets available so far: + +- `x86_64-unknown-hermit` +- `aarch64-unknown-hermit` +- `riscv64gc-unknown-hermit` + +## Target maintainers + +- Stefan Lankes ([@stlankes](https://github.com/stlankes)) +- Martin Kröning ([@mkroening](https://github.com/mkroening)) + +## Requirements + +These targets only support cross-compilation. +The targets do support std. + +When building binaries for this target, the Hermit unikernel is built from scratch. +The application developer themselves specializes the target and sets corresponding expectations. + +The Hermit targets follow Linux's `extern "C"` calling convention. + +Hermit binaries have the ELF format. + +## Building the target + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. +To run the Hermit build scripts, you also have to enable your host target. +The build scripts rely on `llvm-tools` and binaries are linked using `rust-lld`, so those have to be enabled as well. + +```toml +[build] +build-stage = 1 +target = [ + "<HOST_TARGET>", + "x86_64-unknown-hermit", + "aarch64-unknown-hermit", + "riscv64gc-unknown-hermit", +] + +[rust] +lld = true +llvm-tools = true +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for these targets. +To compile for these targets, you will either need to build Rust with the targets enabled +(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar. + +Building Rust programs can be done by following the tutorial in our starter application [rusty-demo]. + +[rusty-demo]: https://github.com/hermitcore/rusty-demo + +## Testing + +The targets support running binaries in the form of self-contained unikernel images. +These images can be chainloaded by Hermit's [loader] or hypervisor ([Uhyve]). +QEMU can be used to boot Hermit binaries using the loader on any architecture. +The targets do not support running the Rust test suite. + +[loader]: https://github.com/hermitcore/rusty-loader +[Uhyve]: https://github.com/hermitcore/uhyve + +## Cross-compilation toolchains and C code + +The targets do not yet support C code and Rust code at the same time. diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md index 17e85590f..e8f55b8bf 100644 --- a/src/doc/rustc/src/platform-support/loongarch-linux.md +++ b/src/doc/rustc/src/platform-support/loongarch-linux.md @@ -71,7 +71,7 @@ CXX_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux- AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \ CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \ # SET TARGET SYSTEM LIBRARY PATH -CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRAY_PATH" \ +CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRARY_PATH" \ cargo run --target loongarch64-unknown-linux-gnu --release ``` Tested on x86 architecture, other architectures not tested. diff --git a/src/doc/rustc/src/platform-support/mips-release-6.md b/src/doc/rustc/src/platform-support/mips-release-6.md new file mode 100644 index 000000000..3f1912fc6 --- /dev/null +++ b/src/doc/rustc/src/platform-support/mips-release-6.md @@ -0,0 +1,181 @@ +# mipsisa\*r6\*-unknown-linux-gnu\* + +**Tier: 3** + +[MIPS Release 6](https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00083-2B-MIPS64INT-AFP-06.01.pdf), or simply MIPS R6, is the latest iteration of the MIPS instruction set architecture (ISA). + +MIPS R6 is experimental in nature, as there is not yet real hardware. However, Qemu emulation is available and we have two Linux distros maintained for development and evaluation purposes. This documentation describes the Rust support for MIPS R6 targets under `mipsisa*r6*-unknown-linux-gnu*`. + +The target name follow this format: `<machine>-<vendor>-<os><abi_suffix>`, where `<machine>` specifies the CPU family/model, `<vendor>` specifies the vendor and `<os>` the operating system name. The `<abi_suffix>` denotes the base ABI (32/n32/64/o64). + +| ABI suffix | Description | +|------------|------------------------------------| +| abi64 | Uses the 64-bit (64) ABI | +| abin32 | Uses the n32 ABI | +| N/A | Uses the (assumed) 32-bit (32) ABI | + +## Target Maintainers + +- [Xuan Chen](https://github.com/chenx97) <henry.chen@oss.cipunited.com> +- [Walter Ji](https://github.com/709924470) <walter.ji@oss.cipunited.com> +- [Xinhui Yang](https://github.com/Cyanoxygen) <cyan@oss.cipunited.com> +- [Lain Yang](https://github.com/Fearyncess) <lain.yang@oss.cipunited.com> + +## Requirements + +### C/C++ Toolchain + +A GNU toolchain for one of the MIPS R6 target is required. [AOSC OS](https://aosc.io/) provides working native and cross-compiling build environments. You may also supply your own a toolchain consisting of recent versions of GCC and Binutils. + +### Target libraries + +A minimum set of libraries is required to perform dynamic linking: + +- GNU glibc +- OpenSSL +- Zlib +- Linux API Headers + +This set of libraries should be installed to make up minimal target sysroot. + +For AOSC OS, You may install such a sysroot with the following commands: + +```sh +cd /tmp + +# linux+api, glibc, and file system structure are included in the toolchain. +sudo apt install gcc+cross-mips64r6el binutils+cross-mips64r6el + +# Download and extract required libraries. +wget https://repo.aosc.io/debs/pool/stable/main/z/zlib_1.2.13-0_mips64r6el.deb -O zlib.deb +wget https://repo.aosc.io/debs/pool/stable/main/o/openssl_1.1.1q-1_mips64r6el.deb -O openssl.deb + +# Extract them to your desired location. +for i in zlib openssl ; do + sudo dpkg-deb -vx $i.deb /var/ab/cross-root/mips64r6el +done + +# Workaround a possible ld bug when using -Wl,-Bdynamic. +sudo sed -i 's|/usr|=/usr|g' /var/ab/cross-root/mips64r6el/usr/lib/libc.so +``` + +For other distros, you may build them manually. + +## Building + +The following procedure outlines the build process for the MIPS64 R6 target with 64-bit (64) ABI (`mipsisa64r6el-unknown-linux-gnuabi64`). + +### Prerequisite: Disable debuginfo + +A LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this: + +```toml +[rust] +debug = false +debug-info-level = 0 +``` + +### Prerequisite: Enable rustix's libc backend + +The crate `rustix` may try to link itself against MIPS R2 assembly, resulting in linkage error. To avoid this, you may force `rustix` to use its fallback `libc` backend by setting relevant `RUSTFLAGS`: + +```sh +export RUSTFLAGS="--cfg rustix_use_libc" +``` + +This will trigger warnings during build, as `-D warnings` is enabled by default. Disable `-D warnings` by editing `config.toml` to append the following: + +```toml +[rust] +deny-warnings = false +``` + +### Prerequisite: Supplying OpenSSL + +As a Tier 3 target, `openssl_sys` lacks the vendored OpenSSL library for this target. You will need to provide a prebuilt OpenSSL library to link `cargo`. Since we have a pre-configured sysroot, we can point to it directly: + +```sh +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_NO_VENDOR=y +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_DIR="/var/ab/cross-root/mips64r6el/usr" +``` + +On Debian, you may need to provide library path and include path separately: + +```sh +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_NO_VENDOR=y +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_LIB_DIR="/usr/lib/mipsisa64r6el-linux-gnuabi64/" +export MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_OPENSSL_INCLUDE_DIR="/usr/include" +``` + +### Launching `x.py` + +```toml +[build] +target = ["mipsisa64r6el-unknown-linux-gnuabi64"] +``` + +Make sure that `mipsisa64r6el-unknown-linux-gnuabi64-gcc` is available from your executable search path (`$PATH`). + +Alternatively, you can specify the directories to all necessary toolchain executables in `config.toml`: + +```toml +[target.mipsisa64r6el-unknown-linux-gnuabi64] +# Adjust the paths below to point to your toolchain installation prefix. +cc = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-gcc" +cxx = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-g++" +ar = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-gcc-ar" +ranlib = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-ranlib" +linker = "/toolchain_prefix/bin/mipsisa64r6el-unknown-linux-gnuabi64-gcc" +``` + +Or, you can specify your cross compiler toolchain with an environment variable: + +```sh +export CROSS_COMPILE="/opt/abcross/mips64r6el/bin/mipsisa64r6el-aosc-linux-gnuabi64-" +``` + +Finally, launch the build script: + +```sh +./x.py build +``` + +### Tips + +- Avoid setting `cargo-native-static` to `false`, as this will result in a redundant artifact error while building clippy: + ```text + duplicate artifacts found when compiling a tool, this typically means that something was recompiled because a transitive dependency has different features activated than in a previous build: + + the following dependencies have different features: + syn 2.0.8 (registry+https://github.com/rust-lang/crates.io-index) + `clippy-driver` additionally enabled features {"full"} at ... + `cargo` additionally enabled features {} at ... + + to fix this you will probably want to edit the local src/tools/rustc-workspace-hack/Cargo.toml crate, as that will update the dependency graph to ensure that these crates all share the same feature set + thread 'main' panicked at 'tools should not compile multiple copies of the same crate', tool.rs:250:13 + note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + ``` + +## Building Rust programs + +To build Rust programs for MIPS R6 targets, for instance, the `mipsisa64r6el-unknown-linux-gnuabi64` target: + +```bash +cargo build --target mipsisa64r6el-unknown-linux-gnuabi64 +``` + +## Testing + +To test a cross-compiled binary on your build system, install the Qemu user emulator that support the MIPS R6 architecture (`qemu-user-mipsel` or `qemu-user-mips64el`). GCC runtime libraries (`libgcc_s`) for the target architecture should be present in target sysroot to run the program. + +```sh +env \ + CARGO_TARGET_MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_LINKER="/opt/abcross/mips64r6el/bin/mipsisa64r6el-aosc-linux-gnuabi64-gcc" \ + CARGO_TARGET_MIPSISA64R6EL_UNKNOWN_LINUX_GNUABI64_RUNNER="qemu-mips64el-static -L /var/ab/cross-root/mips64r6el" \ + cargo run --release \ + --target mipsisa64r6el-unknown-linux-gnuabi64 +``` + +## Tips for building Rust programs for MIPS R6 + +- Until we finalize a fix, please make sure the aforementioned workarounds for `rustix` crate and LLVM are always applied. This can be achieved by setting the relevant environment variables, and editing `Cargo.toml` before building. diff --git a/src/doc/rustc/src/platform-support/netbsd.md b/src/doc/rustc/src/platform-support/netbsd.md index 23f4488de..3891d6d31 100644 --- a/src/doc/rustc/src/platform-support/netbsd.md +++ b/src/doc/rustc/src/platform-support/netbsd.md @@ -86,7 +86,7 @@ The Rust testsuite could presumably be run natively. For the systems where the maintainer can build natively, the rust compiler itself is re-built natively. This involves the rust compiler -being re-built with the newly self-built rust compiler, so excercises +being re-built with the newly self-built rust compiler, so exercises the result quite extensively. Additionally, for some systems we build `librsvg`, and for the more diff --git a/src/doc/rustc/src/platform-support/openharmony.md b/src/doc/rustc/src/platform-support/openharmony.md index a8dcc6443..89539f388 100644 --- a/src/doc/rustc/src/platform-support/openharmony.md +++ b/src/doc/rustc/src/platform-support/openharmony.md @@ -71,6 +71,28 @@ exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ "$@" ``` +`x86_64-unknown-linux-ohos-clang.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang \ + -target x86_64-linux-ohos \ + --sysroot=/path/to/ohos-sdk/linux/native/sysroot \ + -D__MUSL__ \ + "$@" +``` + +`x86_64-unknown-linux-ohos-clang++.sh` + +```sh +#!/bin/sh +exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ + -target x86_64-linux-ohos \ + --sysroot=/path/to/ohos-sdk/linux/native/sysroot \ + -D__MUSL__ \ + "$@" +``` + Future versions of the OpenHarmony SDK will avoid the need for this process. ## Building the target @@ -98,6 +120,13 @@ cxx = "/path/to/armv7-unknown-linux-ohos-clang++.sh" ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" linker = "/path/to/armv7-unknown-linux-ohos-clang.sh" + +[target.x86_64-unknown-linux-ohos] +cc = "/path/to/x86_64-unknown-linux-ohos-clang.sh" +cxx = "/path/to/x86_64-unknown-linux-ohos-clang++.sh" +ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" +ranlib = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ranlib" +linker = "/path/to/x86_64-unknown-linux-ohos-clang.sh" ``` ## Building Rust programs @@ -116,6 +145,10 @@ linker = "/path/to/aarch64-unknown-linux-ohos-clang.sh" [target.armv7-unknown-linux-ohos] ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" linker = "/path/to/armv7-unknown-linux-ohos-clang.sh" + +[target.x86_64-unknown-linux-ohos] +ar = "/path/to/ohos-sdk/linux/native/llvm/bin/llvm-ar" +linker = "/path/to/x86_64-unknown-linux-ohos-clang.sh" ``` ## Testing diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md new file mode 100644 index 000000000..f579b1fb8 --- /dev/null +++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md @@ -0,0 +1,188 @@ +# `sparc-unknown-none-elf` + +**Tier: 3** + +Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3. + +| Target | Descriptions | +| ---------------------- | ----------------------------------------- | +| sparc-unknown-none-elf | SPARC V7 32-bit (freestanding, hardfloat) | + +## Target maintainers + +- Jonathan Pallant, <jonathan.pallant@ferrous-systems.com>, https://ferrous-systems.com + +## Requirements + +This target is cross-compiled. There is no support for `std`. There is no +default allocator, but it's possible to use `alloc` by supplying an allocator. + +By default, code generated with this target should run on any `SPARC` hardware; +enabling additional target features may raise this baseline. + +- `-Ctarget-cpu=v8` adds the extra SPARC V8 instructions. + +- `-Ctarget-cpu=leon3` adds the SPARC V8 instructions and sets up scheduling to + suit the Gaisler Leon3. + +Functions marked `extern "C"` use the [standard SPARC architecture calling +convention](https://sparc.org/technical-documents/). + +This target generates ELF binaries. Any alternate formats or special +considerations for binary layout will require linker options or linker scripts. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`: + +```toml +[build] +build-stage = 1 +host = ["<target for your host>"] +target = ["<target for your host>", "sparc-unknown-none-elf"] +``` + +Replace `<target for your host>` with `x86_64-unknown-linux-gnu` or whatever +else is appropriate for your host machine. + +## Building Rust programs + +To build with this target, pass it to the `--target` argument, like: + +```console +cargo build --target sparc-unknown-none-elf +``` + +This target uses GCC as a linker, and so you will need an appropriate GCC +compatible `sparc-unknown-none` toolchain. The default linker binary is +`sparc-elf-gcc`, but you can override this in your project configuration, as +follows: + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-custom-elf-gcc" +``` + +## Testing + +As `sparc-unknown-none-elf` supports a variety of different environments and does +not support `std`, this target does not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +This target was initially tested using [BCC2] from Gaisler, along with the TSIM +Leon3 processor simulator. Both [BCC2] GCC and [BCC2] Clang have been shown to +work. To work with these tools, your project configuration should contain +something like: + +[BCC2]: https://www.gaisler.com/index.php/downloads/compilers + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-gaisler-elf-gcc" +runner = "tsim-leon3" + +[build] +target = ["sparc-unknown-none-elf"] +rustflags = "-Ctarget-cpu=leon3" +``` + +With this configuration, running `cargo run` will compile your code for the +SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3` +simulator. The `libcore` was pre-compiled as part of the `rustc` compilation +process using the SPARC V7 baseline, but if you are using a nightly toolchain +you can use the +[`-Z build-std=core`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std) +option to rebuild `libcore` from source. This may be useful if you want to +compile it for SPARC V8 and take advantage of the extra instructions. + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-gaisler-elf-gcc" +runner = "tsim-leon3" + +[build] +target = ["sparc-unknown-none-elf"] +rustflags = "-Ctarget-cpu=leon3" + +[unstable] +build-std = ["core"] +``` + +Either way, once the simulator is running, simply enter the command `run` to +start the code executing in the simulator. + +The default C toolchain libraries are linked in, so with the Gaisler [BCC2] +toolchain, and using its default Leon3 BSP, you can use call the C `putchar` +function and friends to output to the simulator console. The default linker +script is also appropriate for the Leon3 simulator, so no linker script is +required. + +Here's a complete example using the above config file: + +```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions) +#![no_std] +#![no_main] + +extern "C" { + fn putchar(ch: i32); + fn _exit(code: i32) -> !; +} + +#[no_mangle] +extern "C" fn main() -> i32 { + let message = "Hello, this is Rust!"; + for b in message.bytes() { + unsafe { + putchar(b as i32); + } + } + 0 +} + +#[panic_handler] +fn panic(_panic: &core::panic::PanicInfo) -> ! { + unsafe { + _exit(1); + } +} +``` + +```console +$ cargo run --target=sparc-unknown-none-elf + Compiling sparc-demo-rust v0.1.0 (/work/sparc-demo-rust) + Finished dev [unoptimized + debuginfo] target(s) in 3.44s + Running `tsim-leon3 target/sparc-unknown-none-elf/debug/sparc-demo-rust` + + TSIM3 LEON3 SPARC simulator, version 3.1.9 (evaluation version) + + Copyright (C) 2023, Frontgrade Gaisler - all rights reserved. + This software may only be used with a valid license. + For latest updates, go to https://www.gaisler.com/ + Comments or bug-reports to support@gaisler.com + + This TSIM evaluation version will expire 2023-11-28 + +Number of CPUs: 2 +system frequency: 50.000 MHz +icache: 1 * 4 KiB, 16 bytes/line (4 KiB total) +dcache: 1 * 4 KiB, 16 bytes/line (4 KiB total) +Allocated 8192 KiB SRAM memory, in 1 bank at 0x40000000 +Allocated 32 MiB SDRAM memory, in 1 bank at 0x60000000 +Allocated 8192 KiB ROM memory at 0x00000000 +section: .text, addr: 0x40000000, size: 20528 bytes +section: .rodata, addr: 0x40005030, size: 128 bytes +section: .data, addr: 0x400050b0, size: 1176 bytes +read 347 symbols + +tsim> run + Initializing and starting from 0x40000000 +Hello, this is Rust! + + Program exited normally on CPU 0. +tsim> +``` diff --git a/src/doc/rustc/src/platform-support/unikraft-linux-musl.md b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md new file mode 100644 index 000000000..90fa18b98 --- /dev/null +++ b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md @@ -0,0 +1,67 @@ +# `*-unikraft-linux-musl` + +**Tier: 3** + +Targets for the [Unikraft] Unikernel Development Kit (with musl). + +[Unikraft]: https://unikraft.org/ + +Target triplets available so far: + +- `x86_64-unikraft-linux-musl` + +## Target maintainers + +- Martin Kröning ([@mkroening](https://github.com/mkroening)) + +## Requirements + +These targets only support cross-compilation. +The targets do support std. + +Unikraft pretends to behave exactly like Linux. +How much of that functionality is available depends on the individual unikernel configuration. +For example, the basic Unikraft + musl config does not support `poll` or networking out of the box. +That functionality requires enabling [`LIBPOSIX_EVENT`] or [lwIP] respectively. + +[`LIBPOSIX_EVENT`]: https://github.com/unikraft/unikraft/blob/RELEASE-0.13.1/lib/posix-event/Config.uk +[lwIP]: https://github.com/unikraft/lib-lwip + +The Unikraft targets follow Linux's `extern "C"` calling convention. + +For these targets, `rustc` does not perform the final linking step. +Instead, the Unikraft build system will produce the final Unikernel image for the selected platform (e.g., KVM, Linux user space, and Xen). + +## Building the targets + +You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: + +```toml +[build] +build-stage = 1 +target = [ "x86_64-unikraft-linux-musl" ] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for these targets. +To compile for these targets, you will either need to build Rust with the targets enabled +(see “Building the targets” above), or build your own copy of `core` by using `build-std` or similar. + +Linking requires a [KraftKit] shim. +See [unikraft/kraftkit#612] for more information. + +[KraftKit]: https://github.com/unikraft/kraftkit +[unikraft/kraftkit#612]: https://github.com/unikraft/kraftkit/issues/612 + +## Testing + +The targets do support running binaries in the form of unikernel images. +How the unikernel image is run depends on the specific platform (e.g., KVM, Linux user space, and Xen). +The targets do not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +The targets do support C code. +To build compatible C code, you have to use the same compiler and flags as does the Unikraft build system for your specific configuration. +The easiest way to achieve that, is to build the C code with the Unikraft build system when building your unikernel image. diff --git a/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md new file mode 100644 index 000000000..23b999248 --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm32-wasi-preview1-threads.md @@ -0,0 +1,148 @@ +# `wasm32-wasi-preview1-threads` + +**Tier: 2** + +The `wasm32-wasi-preview1-threads` target is a new and still (as of July 2023) an +experimental target. This target is an extension to `wasm32-wasi-preview1` target, +originally known as `wasm32-wasi`. It extends the original target with a +standardized set of syscalls that are intended to empower WebAssembly binaries with +native multi threading capabilities. + +[wasi-threads]: https://github.com/WebAssembly/wasi-threads +[threads]: https://github.com/WebAssembly/threads + + +## Target maintainers + +- Georgii Rylov, https://github.com/g0djan +- Alex Crichton, https://github.com/alexcrichton +- Andrew Brown, https://github.com/abrown +- Marcin Kolny, https://github.com/loganek + +## Requirements + +This target is cross-compiled. The target supports `std` fully. + +The Rust target definition here is interesting in a few ways. We want to +serve two use cases here with this target: +* First, we want Rust usage of the target to be as hassle-free as possible, + ideally avoiding the need to configure and install a local wasm32-wasi-preview1-threads + toolchain. +* Second, one of the primary use cases of LLVM's new wasm backend and the + wasm support in LLD is that any compiled language can interoperate with + any other. The `wasm32-wasi-preview1-threads` target is the first with a viable C + standard library and sysroot common definition, so we want Rust and C/C++ + code to interoperate when compiled to `wasm32-unknown-unknown`. + + +You'll note, however, that the two goals above are somewhat at odds with one +another. To attempt to solve both use cases in one go we define a target +that (ab)uses the `crt-static` target feature to indicate which one you're +in. +### No interop with C required +By default the `crt-static` target feature is enabled, and when enabled +this means that the bundled version of `libc.a` found in `liblibc.rlib` +is used. This isn't intended really for interoperation with a C because it +may be the case that Rust's bundled C library is incompatible with a +foreign-compiled C library. In this use case, though, we use `rust-lld` and +some copied crt startup object files to ensure that you can download the +wasi target for Rust and you're off to the races, no further configuration +necessary. +All in all, by default, no external dependencies are required. You can +compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +reliably interoperate with C code in this mode (yet). +### Interop with C required +For the second goal we repurpose the `target-feature` flag, meaning that +you'll need to do a few things to have C/Rust code interoperate. +1. All Rust code needs to be compiled with `-C target-feature=-crt-static`, + indicating that the bundled C standard library in the Rust sysroot will + not be used. +2. If you're using rustc to build a linked artifact then you'll need to + specify `-C linker` to a `clang` binary that supports + `wasm32-wasi-preview1-threads` and is configured with the `wasm32-wasi-preview1-threads` sysroot. This + will cause Rust code to be linked against the libc.a that the specified + `clang` provides. +3. If you're building a staticlib and integrating Rust code elsewhere, then + compiling with `-C target-feature=-crt-static` is all you need to do. + +All in all, by default, no external dependencies are required. You can +compile `wasm32-wasi-preview1-threads` binaries straight out of the box. You can't, however, +reliably interoperate with C code in this mode (yet). + + +Also note that at this time the `wasm32-wasi-preview1-threads` target assumes the +presence of other merged wasm proposals such as (with their LLVM feature flags): + +* [Bulk memory] - `+bulk-memory` +* Mutable imported globals - `+mutable-globals` +* Atomics - `+atomics` + +[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md + +LLVM 16 is required for this target. The reason is related to linker flags: prior to LLVM 16, --import-memory and --export-memory were not allowed together. The reason both are needed is an artifact of how WASI currently does things; see https://github.com/WebAssembly/WASI/issues/502 for more details. + +The target intends to match the corresponding Clang target for its `"C"` ABI. + +> **Note**: due to the relatively early-days nature of this target when working +> with this target you may encounter LLVM bugs. If an assertion hit or a bug is +> found it's recommended to open an issue either with rust-lang/rust or ideally +> with LLVM itself. + +## Platform requirements + +The runtime should support the same set of APIs as any other supported wasi target for interacting with the host environment through the WASI standard. The runtime also should have implemetation of [wasi-threads proposal](https://github.com/WebAssembly/wasi-threads). + +This target is not a stable target. This means that there are a few engines +which implement the `wasi-threads` feature and if they do they're likely behind a +flag, for example: + +* Wasmtime - `--wasm-features=threads --wasi-modules=experimental-wasi-threads` +* [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) - needs to be built with WAMR_BUILD_LIB_WASI_THREADS=1 + +## Building the target + +Users need to install or built wasi-sdk since release 20.0 +https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20 +and specify path to *wasi-root* `.cargo/config.toml` + +```toml +[target.wasm32-wasi-preview1-threads] +wasi-root = ".../wasi-libc/sysroot" +``` + +After that users can build this by adding it to the `target` list in +`config.toml`, or with `-Zbuild-std`. + +## Building Rust programs + +From Rust Nightly 1.71.1 (2023-08-03) on the artifacts are shipped pre-compiled: + +```text +rustup target add wasm32-wasi-preview1-threads --toolchain nightly +``` + +Rust programs can be built for that target: + +```text +rustc --target wasm32-wasi-preview1-threads your-code.rs +``` + +## Cross-compilation + +This target can be cross-compiled from any hosts. + +## Testing + +Currently testing is not well supported for `wasm32-wasi-preview1-threads` and the +Rust project doesn't run any tests for this target. However the UI testsuite can be run +manually following this instructions: + +0. Ensure [wamr](https://github.com/bytecodealliance/wasm-micro-runtime), [wasmtime](https://github.com/bytecodealliance/wasmtime) +or another engine that supports `wasi-threads` is installed and can be found in the `$PATH` env variable. +1. Clone master branch. +2. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. +3. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +4. Checkout branch with your changes. +5. Apply such [a change](https://github.com/g0djan/rust/compare/godjan/wasi-threads...g0djan:rust:godjan/wasi-run-ui-tests?expand=1) with an engine from the step 1. +6. Run `./x.py test --target wasm32-wasi-preview1-threads tests/ui` and save the list of failed tests. +7. For both lists of failed tests run `cat list | sort > sorted_list` and compare it with `diff sorted_list1 sorted_list2`. diff --git a/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md b/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md index 1a6f7bb83..0fe9d4eda 100644 --- a/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md +++ b/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md @@ -20,7 +20,7 @@ will fail to load on machines that do not support this. It should support the full standard library (`std` and `alloc` either with default or user-defined allocators). This target is probably most useful when -targetted via cross-compilation (including from `x86_64-apple-darwin`), but if +targeted via cross-compilation (including from `x86_64-apple-darwin`), but if built manually, the host tools work. It is similar to `x86_64-apple-darwin` in nearly all respects, although the @@ -49,7 +49,7 @@ suite seems to work. Cross-compilation to this target from Apple hosts should generally work without much configuration, so long as XCode and the CommandLineTools are installed. -Targetting it from non-Apple hosts is difficult, but no moreso than targetting +Targeting it from non-Apple hosts is difficult, but no more so than targeting `x86_64-apple-darwin`. When compiling C code for this target, either the "`x86_64h-apple-macosx*`" LLVM diff --git a/src/doc/rustc/src/symbol-mangling/index.md b/src/doc/rustc/src/symbol-mangling/index.md new file mode 100644 index 000000000..be58f2b41 --- /dev/null +++ b/src/doc/rustc/src/symbol-mangling/index.md @@ -0,0 +1,52 @@ +# Symbol Mangling + +[Symbol name mangling] is used by `rustc` to encode a unique name for symbols that are used during code generation. +The encoded names are used by the linker to associate the name with the thing it refers to. + +The method for mangling the names can be controlled with the [`-C symbol-mangling-version`] option. + +[Symbol name mangling]: https://en.wikipedia.org/wiki/Name_mangling +[`-C symbol-mangling-version`]: ../codegen-options/index.md#symbol-mangling-version + +## Per-item control + +The [`#[no_mangle]` attribute][reference-no_mangle] can be used on items to disable name mangling on that item. + +The [`#[export_name]`attribute][reference-export_name] can be used to specify the exact name that will be used for a function or static. + +Items listed in an [`extern` block][reference-extern-block] use the identifier of the item without mangling to refer to the item. +The [`#[link_name]` attribute][reference-link_name] can be used to change that name. + +<!-- +FIXME: This is incomplete for wasm, per https://github.com/rust-lang/rust/blob/d4c364347ce65cf083d4419195b8232440928d4d/compiler/rustc_symbol_mangling/src/lib.rs#L191-L210 +--> + +[reference-no_mangle]: ../../reference/abi.html#the-no_mangle-attribute +[reference-export_name]: ../../reference/abi.html#the-export_name-attribute +[reference-link_name]: ../../reference/items/external-blocks.html#the-link_name-attribute +[reference-extern-block]: ../../reference/items/external-blocks.html + +## Decoding + +The encoded names may need to be decoded in some situations. +For example, debuggers and other tooling may need to demangle the name so that it is more readable to the user. +Recent versions of `gdb` and `lldb` have built-in support for demangling Rust identifiers. +In situations where you need to do your own demangling, the [`rustc-demangle`] crate can be used to programmatically demangle names. +[`rustfilt`] is a CLI tool which can demangle names. + +An example of running rustfilt: + +```text +$ rustfilt _RNvCskwGfYPst2Cb_3foo16example_function +foo::example_function +``` + +[`rustc-demangle`]: https://crates.io/crates/rustc-demangle +[`rustfilt`]: https://crates.io/crates/rustfilt + +## Mangling versions + +`rustc` supports different mangling versions which encode the names in different ways. +The legacy version (which is currently the default) is not described here. +The "v0" mangling scheme addresses several limitations of the legacy format, +and is described in the [v0 Symbol Format](v0.md) chapter. diff --git a/src/doc/rustc/src/symbol-mangling/v0.md b/src/doc/rustc/src/symbol-mangling/v0.md new file mode 100644 index 000000000..61f747fac --- /dev/null +++ b/src/doc/rustc/src/symbol-mangling/v0.md @@ -0,0 +1,1222 @@ +# v0 Symbol Format + +The v0 mangling format was introduced in [RFC 2603]. +It has the following properties: + +- It provides an unambiguous string encoding for everything that can end up in a binary's symbol table. +- It encodes information about generic parameters in a reversible way. +- The mangled symbols are *decodable* such that the demangled form should be easily identifiable as some concrete instance of e.g. a polymorphic function. +- It has a consistent definition that does not rely on pretty-printing certain language constructs. +- Symbols can be restricted to only consist of the characters `A-Z`, `a-z`, `0-9`, and `_`. + This helps ensure that it is platform-independent, + where other characters might have special meaning in some context (e.g. `.` for MSVC `DEF` files). + Unicode symbols are optionally supported. +- It tries to stay efficient, avoiding unnecessarily long names, + and avoiding computationally expensive operations to demangle. + +The v0 format is not intended to be compatible with other mangling schemes (such as C++). + +The v0 format is not presented as a stable ABI for Rust. +This format is currently intended to be well-defined enough that a demangler can produce a reasonable human-readable form of the symbol. +There are several implementation-defined portions that result in it not being possible to entirely predict how a given Rust entity will be encoded. + +The sections below define the encoding of a v0 symbol. +There is no standardized demangled form of the symbols, +though suggestions are provided for how to demangle a symbol. +Implementers may choose to demangle in different ways. + +## Extensions + +This format may be extended in the future to add new tags as Rust is extended with new language items. +To be forward compatible, demanglers should gracefully handle symbols that have encodings where it encounters a tag character not described in this document. +For example, they may fall back to displaying the mangled symbol. +The format may be extended anywhere there is a tag character, such as the [type] rule. +The meaning of existing tags and encodings will not be changed. + +## Grammar notation + +The format of an encoded symbol is illustrated as a context free grammar in an extended BNF-like syntax. +A consolidated summary can be found in the [Symbol grammar summary][summary]. + +| Name | Syntax | Example | Description | +|------|--------|---------|-------------| +| Rule | → | <nobr>A → *B* *C*</nobr> | A production. | +| Concatenation | whitespace | <nobr>A → *B* *C* *D*</nobr> | Individual elements in sequence left-to-right. | +| Alternative | \| | <nobr>A → *B* \| *C*</nobr> | Matches either one or the other. | +| Grouping | () | <nobr>A → *B* (*C* \| *D*) *E*</nobr> | Groups multiple elements as one. | +| Repetition | {} | <nobr>A → {*B*}</nobr> | Repeats the enclosed zero or more times. | +| Option | <sub>opt</sub> | <nobr>A → *B*<sub>opt</sub> *C*</nobr> | An optional element. | +| Literal | `monospace` | <nobr>A → `G`</nobr> | A terminal matching the exact characters case-sensitive. | + +## Symbol name +[symbol-name]: #symbol-name + +> symbol-name → `_R` *[decimal-number]*<sub>opt</sub> *[path]* *[instantiating-crate]*<sub>opt</sub> *[vendor-specific-suffix]*<sub>opt</sub> + +A mangled symbol starts with the two characters `_R` which is a prefix to identify the symbol as a Rust symbol. +The prefix can optionally be followed by a *[decimal-number]* which specifies the encoding version. +This number is currently not used, and is never present in the current encoding. +Following that is a *[path]* which encodes the path to an entity. +The path is followed by an optional *[instantiating-crate]* which helps to disambiguate entities which may be instantiated multiple times in separate crates. +The final part is an optional *[vendor-specific-suffix]*. + +> **Recommended Demangling** +> +> A *symbol-name* should be displayed as the *[path]*. +> The *[instantiating-crate]* and the *[vendor-specific-suffix]* usually need not be displayed. + +> Example: +> ```rust +> std::path::PathBuf::new(); +> ``` +> +> The symbol for `PathBuf::new` in crate `mycrate` is: +> +> ```text +> _RNvMsr_NtCs3ssYzQotkvD_3std4pathNtB5_7PathBuf3newCs15kBYyAo9fc_7mycrate +> ├┘└───────────────────────┬──────────────────────┘└──────────┬─────────┘ +> │ │ │ +> │ │ └── instantiating-crate path "mycrate" +> │ └───────────────────────────────────── path to std::path::PathBuf::new +> └─────────────────────────────────────────────────────────────── `_R` symbol prefix +> ``` +> +> Recommended demangling: `<std::path::PathBuf>::new` + +## Symbol path +[path]: #symbol-path + +> path → \ +> *[crate-root]* \ +> | *[inherent-impl]* \ +> | *[trait-impl]* \ +> | *[trait-definition]* \ +> | *[nested-path]* \ +> | *[generic-args]* \ +> | *[backref]* + +A *path* represents a variant of a [Rust path][reference-paths] to some entity. +In addition to typical Rust path segments using identifiers, +it uses extra elements to represent unnameable entities (like an `impl`) or generic arguments for monomorphized items. + +The initial tag character can be used to determine which kind of path it represents: + +| Tag | Rule | Description | +|-----|------|-------------| +| `C` | *[crate-root]* | The root of a crate path. | +| `M` | *[inherent-impl]* | An inherent implementation. | +| `X` | *[trait-impl]* | A trait implementation. | +| `Y` | *[trait-definition]* | A trait definition. | +| `N` | *[nested-path]* | A nested path. | +| `I` | *[generic-args]* | Generic arguments. | +| `B` | *[backref]* | A back reference. | + +### Path: Crate root +[crate-root]: #path-crate-root + +> crate-root → `C` *[identifier]* + +A *crate-root* indicates a path referring to the root of a crate's module tree. +It consists of the character `C` followed by the crate name as an *[identifier]*. + +The crate name is the name as seen from the defining crate. +Since Rust supports linking multiple crates with the same name, +the *[disambiguator]* is used to make the name unique across the crate graph. + +> **Recommended Demangling** +> +> A *crate-root* can be displayed as the identifier such as `mycrate`. +> +> Usually the disambiguator in the identifier need not be displayed, +> but as an alternate form the disambiguator can be shown in hex such as +> `mycrate[ca63f166dbe9294]`. + +> Example: +> ```rust +> fn example() {} +> ``` +> +> The symbol for `example` in crate `mycrate` is: +> +> ```text +> _RNvCs15kBYyAo9fc_7mycrate7example +> │└────┬─────┘││└──┬──┘ +> │ │ ││ │ +> │ │ ││ └── crate-root identifier "mycrate" +> │ │ │└────── length 7 of "mycrate" +> │ │ └─────── end of base-62-number +> │ └────────────── disambiguator for crate-root "mycrate" 0xca63f166dbe9293 + 1 +> └──────────────────── crate-root +> ``` +> +> Recommended demangling: `mycrate::example` + +### Path: Inherent impl +[inherent-impl]: #path-inherent-impl + +> inherent-impl → `M` *[impl-path]* *[type]* + +An *inherent-impl* indicates a path to an [inherent implementation][reference-inherent-impl]. +It consists of the character `M` followed by an *[impl-path]*, which uniquely identifies the impl block the item is defined in. +Following that is a *[type]* representing the `Self` type of the impl. + +> **Recommended Demangling** +> +> An *inherent-impl* can be displayed as a qualified path segment to the *[type]* within angled brackets. +> The *[impl-path]* usually need not be displayed. + +> Example: +> ```rust +> struct Example; +> impl Example { +> fn foo() {} +> } +> ``` +> +> The symbol for `foo` in the impl for `Example` is: +> +> ```text +> _RNvMs_Cs4Cv8Wi1oAIB_7mycrateNtB4_7Example3foo +> │├┘└─────────┬──────────┘└────┬──────┘ +> ││ │ │ +> ││ │ └── Self type "Example" +> ││ └─────────────────── path to the impl's parent "mycrate" +> │└─────────────────────────────── disambiguator 1 +> └──────────────────────────────── inherent-impl +> ``` +> +> Recommended demangling: `<mycrate::Example>::foo` + +### Path: Trait impl +[trait-impl]: #path-trait-impl + +> trait-impl → `X` *[impl-path]* *[type]* *[path]* + +A *trait-impl* indicates a path to a [trait implementation][reference-trait-impl]. +It consists of the character `X` followed by an *[impl-path]* to the impl's parent followed by the *[type]* representing the `Self` type of the impl followed by a *[path]* to the trait. + +> **Recommended Demangling** +> +> A *trait-impl* can be displayed as a qualified path segment using the `<` *type* `as` *path* `>` syntax. +> The *[impl-path]* usually need not be displayed. + +> Example: +> ```rust +> struct Example; +> trait Trait { +> fn foo(); +> } +> impl Trait for Example { +> fn foo() {} +> } +> ``` +> +> The symbol for `foo` in the trait impl for `Example` is: +> +> ```text +> _RNvXCs15kBYyAo9fc_7mycrateNtB2_7ExampleNtB2_5Trait3foo +> │└─────────┬──────────┘└─────┬─────┘└────┬────┘ +> │ │ │ │ +> │ │ │ └── path to the trait "Trait" +> │ │ └────────────── Self type "Example" +> │ └──────────────────────────────── path to the impl's parent "mycrate" +> └─────────────────────────────────────────── trait-impl +> ``` +> +> Recommended demangling: `<mycrate::Example as mycrate::Trait>::foo` + +### Path: Impl +[impl-path]: #path-impl + +> impl-path → *[disambiguator]*<sub>opt</sub> *[path]* + +An *impl-path* is a path used for *[inherent-impl]* and *[trait-impl]* to indicate the path to parent of an [implementation][reference-implementations]. +It consists of an optional *[disambiguator]* followed by a *[path]*. +The *[path]* is the path to the parent that contains the impl. +The *[disambiguator]* can be used to distinguish between multiple impls within the same parent. + +> **Recommended Demangling** +> +> An *impl-path* usually need not be displayed (unless the location of the impl is desired). + +> Example: +> ```rust +> struct Example; +> impl Example { +> fn foo() {} +> } +> impl Example { +> fn bar() {} +> } +> ``` +> +> The symbol for `foo` in the impl for `Example` is: +> +> ```text +> _RNvMCs7qp2U7fqm6G_7mycrateNtB2_7Example3foo +> └─────────┬──────────┘ +> │ +> └── path to the impl's parent crate-root "mycrate" +> ``` +> +> The symbol for `bar` is similar, though it has a disambiguator to indicate it is in a different impl block. +> +> ```text +> _RNvMs_Cs7qp2U7fqm6G_7mycrateNtB4_7Example3bar +> ├┘└─────────┬──────────┘ +> │ │ +> │ └── path to the impl's parent crate-root "mycrate" +> └────────────── disambiguator 1 +> ``` +> +> Recommended demangling: +> * `foo`: `<mycrate::Example>::foo` +> * `bar`: `<mycrate::Example>::bar` + +### Path: Trait definition +[trait-definition]: #path-trait-definition + +> trait-definition → `Y` *[type]* *[path]* + +A *trait-definition* is a path to a [trait definition][reference-traits]. +It consists of the character `Y` followed by the *[type]* which is the `Self` type of the referrer, followed by the *[path]* to the trait definition. + +> **Recommended Demangling** +> +> A *trait-definition* can be displayed as a qualified path segment using the `<` *type* `as` *path* `>` syntax. + +> Example: +> ```rust +> trait Trait { +> fn example() {} +> } +> struct Example; +> impl Trait for Example {} +> ``` +> +> The symbol for `example` in the trait `Trait` implemented for `Example` is: +> +> ```text +> _RNvYNtCs15kBYyAo9fc_7mycrate7ExampleNtB4_5Trait7exampleB4_ +> │└──────────────┬───────────────┘└────┬────┘ +> │ │ │ +> │ │ └── path to the trait "Trait" +> │ └──────────────────────── path to the implementing type "mycrate::Example" +> └──────────────────────────────────────── trait-definition +> ``` +> +> Recommended demangling: `<mycrate::Example as mycrate::Trait>::example` + +### Path: Nested path +[nested-path]: #path-nested-path + +> nested-path → `N` *[namespace]* *[path]* *[identifier]* + +A *nested-path* is a path representing an optionally named entity. +It consists of the character `N` followed by a *[namespace]* indicating the namespace of the entity, +followed by a *[path]* which is a path representing the parent of the entity, +followed by an *[identifier]* of the entity. + +The identifier of the entity may have a length of 0 when the entity is not named. +For example, entities like closures, tuple-like struct constructors, and anonymous constants may not have a name. +The identifier may still have a disambiguator unless the disambiguator is 0. + +> **Recommended Demangling** +> +> A *nested-path* can be displayed by first displaying the *[path]* followed by a `::` separator followed by the *[identifier]*. +> If the *[identifier]* is empty, then the separating `::` should not be displayed. +> +> If a *[namespace]* is specified, then extra context may be added such as: \ +> *[path]* `::{` *[namespace]* (`:` *[identifier]*)<sub>opt</sub> `#` *disambiguator*<sub>as base-10 number</sub> `}` +> +> Here the namespace `C` may be printed as `closure` and `S` as `shim`. +> Others may be printed by their character tag. +> The `:` *name* portion may be skipped if the name is empty. +> +> The *[disambiguator]* in the *[identifier]* may be displayed if a *[namespace]* is specified. +> In other situations, it is usually not necessary to display the *[disambiguator]*. +> If it is displayed, it is recommended to place it in brackets, for example `[284a76a8b41a7fd3]`. +> If the *[disambiguator]* is not present, then its value is 0 and it can always be omitted from display. + +> Example: +> ```rust +> fn main() { +> let x = || {}; +> let y = || {}; +> x(); +> y(); +> } +> ``` +> +> The symbol for the closure `x` in crate `mycrate` is: +> +> ```text +> _RNCNvCsgStHSCytQ6I_7mycrate4main0B3_ +> ││└─────────────┬─────────────┘│ +> ││ │ │ +> ││ │ └── identifier with length 0 +> ││ └───────────────── path to "mycrate::main" +> │└──────────────────────────────── closure namespace +> └───────────────────────────────── nested-path +> ``` +> +> The symbol for the closure `y` is similar, with a disambiguator: +> +> ```text +> _RNCNvCsgStHSCytQ6I_7mycrate4mains_0B3_ +> ││ +> │└── base-62-number 0 +> └─── disambiguator 1 (base-62-number+1) +> ``` +> +> Recommended demangling: +> * `x`: `mycrate::main::{closure#0}` +> * `y`: `mycrate::main::{closure#1}` + +### Path: Generic arguments +[generic-args]: #path-generic-arguments +[generic-arg]: #path-generic-arguments + +> generic-args → `I` *[path]* {*[generic-arg]*} `E` +> +> generic-arg → \ +> *[lifetime]* \ +> | *[type]* \ +> | `K` *[const]* + +A *generic-args* is a path representing a list of generic arguments. +It consists of the character `I` followed by a *[path]* to the defining entity, followed by zero or more <em>[generic-arg]</em>s terminated by the character `E`. + +Each *[generic-arg]* is either a *[lifetime]* (starting with the character `L`), a *[type]*, or the character `K` followed by a *[const]* representing a const argument. + +> **Recommended Demangling** +> +> A *generic-args* may be printed as: *[path]* `::`<sub>opt</sub> `<` comma-separated list of args `>` +> The `::` separator may be elided for type paths (similar to Rust's rules). + +> > Example: +> ```rust +> fn main() { +> example([123]); +> } +> +> fn example<T, const N: usize>(x: [T; N]) {} +> ``` +> +> The symbol for the function `example` is: +> +> ```text +> _RINvCsgStHSCytQ6I_7mycrate7examplelKj1_EB2_ +> │└──────────────┬───────────────┘││││││ +> │ │ │││││└── end of generic-args +> │ │ ││││└─── end of const-data +> │ │ │││└──── const value `1` +> │ │ ││└───── const type `usize` +> │ │ │└────── const generic +> │ │ └─────── generic type i32 +> │ └──────────────────────── path to "mycrate::example" +> └──────────────────────────────────────── generic-args +> ``` +> +> Recommended demangling: `mycrate::example::<i32, 1>` + +### Namespace +[namespace]: #namespace + +> namespace → *[lower]* | *[upper]* + +A *namespace* is used to segregate names into separate logical groups, allowing identical names to otherwise avoid collisions. +It consists of a single character of an upper or lowercase ASCII letter. +Lowercase letters are reserved for implementation-internal disambiguation categories (and demanglers should never show them). +Uppercase letters are used for special namespaces which demanglers may display in a special way. + +Uppercase namespaces are: + +* `C` — A closure. +* `S` — A shim. Shims are added by the compiler in some situations where an intermediate is needed. + For example, a `fn()` pointer to a function with the [`#[track_caller]` attribute][reference-track_caller] needs a shim to deal with the implicit caller location. + +> **Recommended Demangling** +> +> See *[nested-path]* for recommended demangling. + +## Identifier +[identifier]: #identifier +[undisambiguated-identifier]: #identifier +[bytes]: #identifier + +> identifier → *[disambiguator]*<sub>opt</sub> *[undisambiguated-identifier]* +> +> undisambiguated-identifier → `u`<sub>opt</sub> *[decimal-number]* `_`<sub>opt</sub> *[bytes]* +> +> bytes → {*UTF-8 bytes*} + +An *identifier* is a named label used in a *[path]* to refer to an entity. +It consists of an optional *[disambiguator]* followed by an *[undisambiguated-identifier]*. + +The disambiguator is used to disambiguate identical identifiers that should not otherwise be considered the same. +For example, closures have no name, so the disambiguator is the only differentiating element between two different closures in the same parent path. + +The undisambiguated-identifier starts with an optional `u` character, +which indicates that the identifier is encoded in [Punycode][Punycode identifiers]. +The next part is a *[decimal-number]* which indicates the length of the *bytes*. + +Following the identifier size is an optional `_` character which is used to separate the length value from the identifier itself. +The `_` is mandatory if the *bytes* starts with a decimal digit or `_` in order to keep it unambiguous where the *decimal-number* ends and the *bytes* starts. + +*bytes* is the identifier itself encoded in UTF-8. + +> **Recommended Demangling** +> +> The display of an *identifier* can depend on its context. +> If it is Punycode-encoded, then it may first be decoded before being displayed. +> +> The *[disambiguator]* may or may not be displayed; see recommendations for rules that use *identifier*. + +### Punycode identifiers +[Punycode identifiers]: #punycode-identifiers + +Because some environments are restricted to ASCII alphanumerics and `_`, +Rust's [Unicode identifiers][reference-identifiers] may be encoded using a modified version of [Punycode]. + +For example, the function: + +```rust +mod gödel { + mod escher { + fn bach() {} + } +} +``` + +would be mangled as: + +```text +_RNvNtNtCsgOH4LzxkuMq_7mycrateu8gdel_5qa6escher4bach + ││└───┬──┘ + ││ │ + ││ └── gdel_5qa translates to gödel + │└─────── 8 is the length + └──────── `u` indicates it is a Unicode identifier +``` + +Standard Punycode generates strings of the form `([[:ascii:]]+-)?[[:alnum:]]+`. +This is problematic because the `-` character +(which is used to separate the ASCII part from the base-36 encoding) +is not in the supported character set for symbols. +For this reason, `-` characters in the Punycode encoding are replaced with `_`. + +Here are some examples: + +| Original | Punycode | Punycode + Encoding | +|-----------------|-----------------|---------------------| +| føø | f-5gaa | f_5gaa | +| α_ω | _-ylb7e | __ylb7e | +| 铁锈 | n84amf | n84amf | +| 🤦 | fq9h | fq9h | +| ρυστ | 2xaedc | 2xaedc | + +> Note: It is up to the compiler to decide whether or not to encode identifiers using Punycode or not. +> Some platforms may have native support for UTF-8 symbols, +> and the compiler may decide to use the UTF-8 encoding directly. +> Demanglers should be prepared to support either form. + +[Punycode]: https://tools.ietf.org/html/rfc3492 + +## Disambiguator +[disambiguator]: #disambiguator + +> disambiguator → `s` *[base-62-number]* + +A *disambiguator* is used in various parts of a symbol *[path]* to uniquely identify path elements that would otherwise be identical but should not be considered the same. +It starts with the character `s` and is followed by a *[base-62-number]*. + +If the *disambiguator* is not specified, then its value can be assumed to be zero. +Otherwise, when demangling, the value 1 should be added to the *[base-62-number]* +(thus a *base-62-number* of zero encoded as `_` has a value of 1). +This allows disambiguators that are encoded sequentially to use minimal bytes. + +> **Recommended Demangling** +> +> The *disambiguator* may or may not be displayed; see recommendations for rules that use *disambiguator*. + +## Lifetime +[lifetime]: #lifetime + +> lifetime → `L` *[base-62-number]* + +A *lifetime* is used to encode an anonymous (numbered) lifetime, either erased or [higher-ranked](#binder). +It starts with the character `L` and is followed by a *[base-62-number]*. +Index 0 is always erased. +Indices starting from 1 refer (as de Bruijn indices) to a higher-ranked lifetime bound by one of the enclosing <em>[binder]</em>s. + +> **Recommended Demangling** +> +> A *lifetime* may be displayed like a Rust lifetime using a single quote. +> +> Index 0 should be displayed as `'_`. +> Index 0 should not be displayed for lifetimes in a *[ref-type]*, *[mut-ref-type]*, or *[dyn-trait-type]*. +> +> A lifetime can be displayed by converting the De Bruijn index to a De Bruijn level +> (level = number of bound lifetimes - index) and selecting a unique name for each level. +> For example, starting with single lowercase letters such as `'a` for level 0. +> Levels over 25 may consider printing the numeric lifetime as in `'_123`. +> See *[binder]* for more on lifetime indexes and ordering. + +> Example: +> ```rust +> fn main() { +> example::<fn(&u8, &u16)>(); +> } +> +> pub fn example<T>() {} +> ``` +> +> The symbol for the function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleFG0_RL1_hRL0_tEuEB2_ +> │└┬┘│└┬┘││└┬┘││ +> │ │ │ │ ││ │ │└── end of input types +> │ │ │ │ ││ │ └─── type u16 +> │ │ │ │ ││ └───── lifetime #1 'b +> │ │ │ │ │└─────── reference type +> │ │ │ │ └──────── type u8 +> │ │ │ └────────── lifetime #2 'a +> │ │ └──────────── reference type +> │ └────────────── binder with 2 lifetimes +> └──────────────── function type +> ``` +> +> Recommended demangling: `mycrate::example::<for<'a, 'b> fn(&'a u8, &'b u16)>` + +## Const +[const]: #const +[const-data]: #const +[hex-digit]: #const + +> const → \ +> *[type]* *[const-data]* \ +> | `p` \ +> | *[backref]* +> +> const-data → `n`<sub>opt</sub> {*[hex-digit]*} `_` +> +> [hex-digit] → *[digit]* | `a` | `b` | `c` | `d` | `e` | `f` + +A *const* is used to encode a const value used in generics and types. +It has the following forms: + +* A constant value encoded as a *[type]* which represents the type of the constant and *[const-data]* which is the constant value, followed by `_` to terminate the *const*. +* The character `p` which represents a [placeholder]. +* A *[backref]* to a previously encoded *const* of the same value. + +The encoding of the *const-data* depends on the type: + +* `bool` — The value `false` is encoded as `0_`, the value true is encoded as `1_`. +* `char` — The Unicode scalar value of the character is encoded in hexadecimal. +* Unsigned integers — The value is encoded in hexadecimal. +* Signed integers — The character `n` is a prefix to indicate that it is negative, + followed by the absolute value encoded in hexadecimal. + +> **Recommended Demangling** +> +> A *const* may be displayed by the const value depending on the type. +> +> The `p` placeholder should be displayed as the `_` character. +> +> For specific types: +> * `b` (bool) — Display as `true` or `false`. +> * `c` (char) — Display the character in as a Rust character (such as `'A'` or `'\n'`). +> * integers — Display the integer (either in decimal or hex). + +> Example: +> ```rust +> fn main() { +> example::<0x12345678>(); +> } +> +> pub fn example<const N: u64>() {} +> ``` +> +> The symbol for function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleKy12345678_EB2_ +> ││└───┬───┘ +> ││ │ +> ││ └── const-data 0x12345678 +> │└─────── const type u64 +> └──────── const generic arg +> ``` +> +> Recommended demangling: `mycrate::example::<305419896>` + +### Placeholders +[placeholder]: #placeholders + +A *placeholder* may occur in circumstances where a type or const value is not relevant. + +> Example: +> ```rust +> pub struct Example<T, const N: usize>([T; N]); +> +> impl<T, const N: usize> Example<T, N> { +> pub fn foo() -> &'static () { +> static EXAMPLE_STATIC: () = (); +> &EXAMPLE_STATIC +> } +> } +> ``` +> +> In this example, the static `EXAMPLE_STATIC` would not be monomorphized by the type or const parameters `T` and `N`. +> Those will use the placeholder for those generic arguments. +> Its symbol is: +> +> ```text +> _RNvNvMCsd9PVOYlP1UU_7mycrateINtB4_7ExamplepKpE3foo14EXAMPLE_STATIC +> │ │││ +> │ ││└── const placeholder +> │ │└─── const generic argument +> │ └──── type placeholder +> └────────────────── generic-args +> ``` +> +> Recommended demangling: `<mycrate::Example<_, _>>::foo::EXAMPLE_STATIC` + + +## Type +[type]: #type +[basic-type]: #basic-type +[array-type]: #array-type +[slice-type]: #slice-type +[tuple-type]: #tuple-type +[ref-type]: #ref-type +[mut-ref-type]: #mut-ref-type +[const-ptr-type]: #const-ptr-type +[mut-ptr-type]: #mut-ptr-type +[fn-type]: #fn-type +[dyn-trait-type]: #dyn-trait-type + +> type → \ +> *[basic-type]* \ +> | *[array-type]* \ +> | *[slice-type]* \ +> | *[tuple-type]* \ +> | *[ref-type]* \ +> | *[mut-ref-type]* \ +> | *[const-ptr-type]* \ +> | *[mut-ptr-type]* \ +> | *[fn-type]* \ +> | *[dyn-trait-type]* \ +> | *[path]* \ +> | *[backref]* + +A *type* represents a Rust [type][reference-types]. +The initial character can be used to distinguish which type is encoded. +The type encodings based on the initial tag character are: + +* A <span id="basic-type">*basic-type*</span> is encoded as a single character: + * `a` — `i8` + * `b` — `bool` + * `c` — `char` + * `d` — `f64` + * `e` — `str` + * `f` — `f32` + * `h` — `u8` + * `i` — `isize` + * `j` — `usize` + * `l` — `i32` + * `m` — `u32` + * `n` — `i128` + * `o` — `u128` + * `s` — `i16` + * `t` — `u16` + * `u` — unit `()` + * `v` — variadic `...` + * `x` — `i64` + * `y` — `u64` + * `z` — `!` + * `p` — [placeholder] `_` + +* `A` — An [array][reference-array] `[T; N]`. + + > <span id="array-type">array-type</span> → `A` *[type]* *[const]* + + The tag `A` is followed by the *[type]* of the array followed by a *[const]* for the array size. + +* `S` — A [slice][reference-slice] `[T]`. + + > <span id="slice-type">slice-type</span> → `S` *[type]* + + The tag `S` is followed by the *[type]* of the slice. + +* `T` — A [tuple][reference-tuple] `(T1, T2, T3, ...)`. + + > <span id="tuple-type">tuple-type</span> → `T` {*[type]*} `E` + + The tag `T` is followed by one or more <em>[type]</em>s indicating the type of each field, followed by a terminating `E` character. + + Note that a zero-length tuple (unit) is encoded with the `u` *[basic-type]*. + +* `R` — A [reference][reference-shared-reference] `&T`. + + > <span id="ref-type">ref-type</span> → `R` *[lifetime]*<sub>opt</sub> *[type]* + + The tag `R` is followed by an optional *[lifetime]* followed by the *[type]* of the reference. + The lifetime is not included if it has been erased. + +* `Q` — A [mutable reference][reference-mutable-reference] `&mut T`. + + > <span id="mut-ref-type">mut-ref-type</span> → `Q` *[lifetime]*<sub>opt</sub> *[type]* + + The tag `Q` is followed by an optional *[lifetime]* followed by the *[type]* of the mutable reference. + The lifetime is not included if it has been erased. + +* `P` — A [constant raw pointer][reference-raw-pointer] `*const T`. + + The tag `P` is followed by the *[type]* of the pointer. + + > <span id="const-ptr-type">const-ptr-type</span> → `P` *[type]* + +* `O` — A [mutable raw pointer][reference-raw-pointer] `*mut T`. + + > <span id="mut-ptr-type">mut-ptr-type</span> → `O` *[type]* + + The tag `O` is followed by the *[type]* of the pointer. + +* `F` — A [function pointer][reference-fn-pointer] `fn(…) -> …`. + + > <span id="fn-type">fn-type</span> → `F` *[fn-sig]* + > + > <span id="fn-sig">fn-sig</span> → *[binder]*<sub>opt</sub> `U`<sub>opt</sub> (`K` *[abi]*)<sub>opt</sub> {*[type]*} `E` *[type]* + > + > <span id="abi">abi</span> → \ + > `C` \ + > | *[undisambiguated-identifier]* + + The tag `F` is followed by a *[fn-sig]* of the function signature. + A *fn-sig* is the signature for a function pointer. + + It starts with an optional *[binder]* which represents the higher-ranked trait bounds (`for<…>`). + + Following that is an optional `U` character which is present for an `unsafe` function. + + Following that is an optional `K` character which indicates that an *[abi]* is specified. + If the ABI is not specified, it is assumed to be the `"Rust"` ABI. + + The *[abi]* can be the letter `C` to indicate it is the `"C"` ABI. + Otherwise it is an *[undisambiguated-identifier]* of the ABI string with dashes converted to underscores. + + Following that is zero or more <em>[type]</em>s which indicate the input parameters of the function. + + Following that is the character `E` and then the *[type]* of the return value. + +[fn-sig]: #fn-sig +[abi]: #abi + +* `D` — A [trait object][reference-trait-object] `dyn Trait<Assoc=X> + Send + 'a`. + + > <span id="dyn-trait-type">dyn-trait-type</span> → `D` *[dyn-bounds]* *[lifetime]* + > + > <span id="dyn-bounds">dyn-bounds</span> → *[binder]*<sub>opt</sub> {*[dyn-trait]*} `E` + > + > <span id="dyn-trait">dyn-trait</span> → *[path]* {*[dyn-trait-assoc-binding]*} + > + > <span id="dyn-trait-assoc-binding">dyn-trait-assoc-binding</span> → `p` *[undisambiguated-identifier]* *[type]* + + The tag `D` is followed by a *[dyn-bounds]* which encodes the trait bounds, + followed by a *[lifetime]* of the trait object lifetime bound. + + A *dyn-bounds* starts with an optional *[binder]* which represents the higher-ranked trait bounds (`for<…>`). + Following that is a sequence of *[dyn-trait]* terminated by the character `E`. + + Each *[dyn-trait]* represents a trait bound, which consists of a *[path]* to the trait followed by zero or more *[dyn-trait-assoc-binding]* which list the associated types. + + Each *[dyn-trait-assoc-binding]* consists of a character `p` followed a *[undisambiguated-identifier]* representing the associated binding name, and finally a *[type]*. + +[dyn-bounds]: #dyn-bounds +[dyn-trait]: #dyn-trait +[dyn-trait-assoc-binding]: #dyn-trait-assoc-binding + + +* A *[path]* to a named type. + +* A *[backref]* to refer to a previously encoded type. + +> **Recommended Demangling** +> +> A *[type]* may be displayed as the type it represents, using typical Rust syntax to represent the type. + +> Example: +> ```rust +> fn main() { +> example::<[u16; 8]>(); +> } +> +> pub fn example<T>() {} +> ``` +> +> The symbol for function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleAtj8_EB2_ +> │││├┘│ +> ││││ └─── end of generic args +> │││└───── const data 8 +> ││└────── const type usize +> │└─────── array element type u16 +> └──────── array type +> ``` +> +> Recommended demangling: `mycrate::example::<[u16; 8]>` + +## Binder +[binder]: #binder + +> binder → `G` *[base-62-number]* + +A *binder* represents the number of [higher-ranked trait bound][reference-hrtb] lifetimes to bind. +It consists of the character `G` followed by a *[base-62-number]*. +The value 1 should be added to the *[base-62-number]* when decoding +(such that the *base-62-number* encoding of `_` is interpreted as having 1 binder). + +A *lifetime* rule can then refer to these numbered lifetimes. +The lowest indices represent the innermost lifetimes. +The number of bound lifetimes is the value of *[base-62-number]* plus one. + +For example, in `for<'a, 'b> fn(for<'c> fn (...))`, any <em>[lifetime]</em>s in `...` +(but not inside more binders) will observe the indices 1, 2, and 3 to refer to `'c`, `'b`, and `'a`, respectively. + +> **Recommended Demangling** +> +> A *binder* may be printed using `for<…>` syntax listing the lifetimes as recommended in *[lifetime]*. +> See *[lifetime]* for an example. + +## Backref +[backref]: #backref + +> backref → `B` *[base-62-number]* + +A *backref* is used to refer to a previous part of the mangled symbol. +This provides a simple form of compression to reduce the length of the mangled symbol. +This can help reduce the amount of work and resources needed by the compiler, linker, and loader. + +It consists of the character `B` followed by a *[base-62-number]*. +The number indicates the 0-based offset in bytes starting from just after the `_R` prefix of the symbol. +The *backref* represents the corresponding element starting at that position. + +<em>backref</em>s always refer to a position before the *backref* itself. + +The *backref* compression relies on the fact that all substitutable symbol elements have a self-terminating mangled form. +Given the start position of the encoded node, the grammar guarantees that it is always unambiguous where the node ends. +This is ensured by not allowing optional or repeating elements at the end of substitutable productions. + +> **Recommended Demangling** +> +> A *backref* should be demangled by rendering the element that it points to. +> Care should be considered when handling deeply nested backrefs to avoid using too much stack. + +> Example: +> ```rust +> fn main() { +> example::<Example, Example>(); +> } +> +> struct Example; +> +> pub fn example<T, U>() {} +> ``` +> +> The symbol for function `example` is: +> +> ```text +> _RINvCs7qp2U7fqm6G_7mycrate7exampleNtB2_7ExampleBw_EB2_ +> │├┘ │├┘ │├┘ +> ││ ││ ││ +> ││ ││ │└── backref to offset 3 (crate-root) +> ││ ││ └─── backref for instantiating-crate path +> ││ │└────── backref to offset 33 (path to Example) +> ││ └─────── backref for second generic-arg +> │└───────────────── backref to offset 3 (crate-root) +> └────────────────── backref for first generic-arg (first segment of Example path) +> ``` +> +> Recommended demangling: `mycrate::example::<mycrate::Example, mycrate::Example>` + +## Instantiating crate +[instantiating-crate]: #instantiating-crate + +> instantiating-crate → *[path]* + +The *instantiating-crate* is an optional element of the *[symbol-name]* which can be used to indicate which crate is instantiating the symbol. +It consists of a single *[path]*. + +This helps differentiate symbols that would otherwise be identical, +for example the monomorphization of a function from an external crate may result in a duplicate if another crate is also instantiating the same generic function with the same types. + +In practice, the instantiating crate is also often the crate where the symbol is defined, +so it is usually encoded as a *[backref]* to the *[crate-root]* encoded elsewhere in the symbol. + +> **Recommended Demangling** +> +> The *instantiating-crate* usually need not be displayed. + +> Example: +> ```rust +> std::path::Path::new("example"); +> ``` +> +> The symbol for `Path::new::<str>` instantiated from the `mycrate` crate is: +> +> ```text +> _RINvMsY_NtCseXNvpPnDBDp_3std4pathNtB6_4Path3neweECs7qp2U7fqm6G_7mycrate +> └──┬───┘ +> │ +> └── instantiating crate identifier `mycrate` +> ``` +> +> Recommended demangling: `<std::path::Path>::new::<str>` + +## Vendor-specific suffix +[vendor-specific-suffix]: #vendor-specific-suffix +[suffix]: #vendor-specific-suffix + +> vendor-specific-suffix → (`.` | `$`) *[suffix]* +> +> suffix → {*byte*} + +The *vendor-specific-suffix* is an optional element at the end of the *[symbol-name]*. +It consists of either a `.` or `$` character followed by zero or more bytes. +There are no restrictions on the characters following the period or dollar sign. + +This suffix is added as needed by the implementation. +One example where this can happen is when locally unique names need to become globally unique. +LLVM can append a `.llvm.<numbers>` suffix during LTO to ensure a unique name, +and `$` can be used for thread-local data on Mach-O. +In these situations it's generally fine to ignore the suffix; +the suffixed name has the same semantics as the original. + +> **Recommended Demangling** +> +> The *vendor-specific-suffix* usually need not be displayed. + +> Example: +> ```rust +> # use std::cell::RefCell; +> thread_local! { +> pub static EXAMPLE: RefCell<u32> = RefCell::new(1); +> } +> ``` +> +> The symbol for `EXAMPLE` on macOS may have the following for thread-local data: +> +> ```text +> _RNvNvNvCs7qp2U7fqm6G_7mycrate7EXAMPLE7___getit5___KEY$tlv$init +> └───┬───┘ +> │ +> └── vendor-specific-suffix +> ``` +> +> Recommended demangling: `mycrate::EXAMPLE::__getit::__KEY` + +## Common rules +[decimal-number]: #common-rules +[digit]: #common-rules +[non-zero-digit]: #common-rules +[lower]: #common-rules +[upper]: #common-rules + +> [decimal-number] → \ +> `0` \ +> | *[non-zero-digit]* {*[digit]*} +> +> [non-zero-digit] → `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | `9` \ +> [digit] → `0` | *[non-zero-digit]* +> +> [lower] → `a` |`b` |`c` |`d` |`e` |`f` |`g` |`h` |`i` |`j` |`k` |`l` |`m` |`n` |`o` |`p` |`q` |`r` |`s` |`t` |`u` |`v` |`w` |`x` |`y` |`z` +> +> [upper] → `A` | `B` | `C` | `D` | `E` | `F` | `G` | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` + +A *decimal-number* is encoded as one or more <em>[digit]</em>s indicating a numeric value in decimal. + +The value zero is encoded as a single byte `0`. +Beware that there are situations where `0` may be followed by another digit that should not be decoded as part of the decimal-number. +For example, a zero-length *[identifier]* within a *[nested-path]* which is in turn inside another *[nested-path]* will result in two identifiers in a row, where the first one only has the encoding of `0`. + +A *digit* is an ASCII number. + +A *lower* and *upper* is an ASCII lower and uppercase letter respectively. + +## base-62-number +[base-62-number]: #base-62-number + +> [base-62-number] → { *[digit]* | *[lower]* | *[upper]* } `_` + +A *base-62-number* is an encoding of a numeric value. +It uses ASCII numbers and lowercase and uppercase letters. +The value is terminated with the `_` character. +If the value is 0, then the encoding is the `_` character without any digits. +Otherwise, one is subtracted from the value, and it is encoded with the mapping: + +* `0`-`9` maps to 0-9 +* `a`-`z` maps to 10 to 35 +* `A`-`Z` maps to 36 to 61 + +The number is repeatedly divided by 62 (with integer division round towards zero) +to choose the next character in the sequence. +The remainder of each division is used in the mapping to choose the next character. +This is repeated until the number is 0. +The final sequence of characters is then reversed. + +Decoding is a similar process in reverse. + +Examples: + +| Value | Encoding | +|-------|----------| +| 0 | `_` | +| 1 | `0_` | +| 11 | `a_` | +| 62 | `Z_` | +| 63 | `10_` | +| 1000 | `g7_` | + +## Symbol grammar summary +[summary]: #symbol-grammar-summary + +The following is a summary of all of the productions of the symbol grammar. + +> [symbol-name] → `_R` *[decimal-number]*<sub>opt</sub> *[path]* *[instantiating-crate]*<sub>opt</sub> *[vendor-specific-suffix]*<sub>opt</sub> +> +> [path] → \ +> *[crate-root]* \ +> | *[inherent-impl]* \ +> | *[trait-impl]* \ +> | *[trait-definition]* \ +> | *[nested-path]* \ +> | *[generic-args]* \ +> | *[backref]* +> +> [crate-root] → `C` *[identifier]* \ +> [inherent-impl] → `M` *[impl-path]* *[type]* \ +> [trait-impl] → `X` *[impl-path]* *[type]* *[path]* \ +> [trait-definition] → `Y` *[type]* *[path]* \ +> [nested-path] → `N` *[namespace]* *[path]* *[identifier]* \ +> [generic-args] → `I` *[path]* {*[generic-arg]*} `E` +> +> [identifier] → *[disambiguator]*<sub>opt</sub> *[undisambiguated-identifier]* \ +> [undisambiguated-identifier] → `u`<sub>opt</sub> *[decimal-number]* `_`<sub>opt</sub> *[bytes]* \ +> [bytes] → {*UTF-8 bytes*} +> +> [disambiguator] → `s` *[base-62-number]* +> +> [impl-path] → *[disambiguator]*<sub>opt</sub> *[path]* +> +> [type] → \ +> *[basic-type]* \ +> | *[array-type]* \ +> | *[slice-type]* \ +> | *[tuple-type]* \ +> | *[ref-type]* \ +> | *[mut-ref-type]* \ +> | *[const-ptr-type]* \ +> | *[mut-ptr-type]* \ +> | *[fn-type]* \ +> | *[dyn-trait-type]* \ +> | *[path]* \ +> | *[backref]* +> +> [basic-type] → *[lower]* \ +> [array-type] → `A` *[type]* *[const]* \ +> [slice-type] → `S` *[type]* \ +> [tuple-type] → `T` {*[type]*} `E` \ +> [ref-type] → `R` *[lifetime]*<sub>opt</sub> *[type]* \ +> [mut-ref-type] → `Q` *[lifetime]*<sub>opt</sub> *[type]* \ +> [const-ptr-type] → `P` *[type]* \ +> [mut-ptr-type] → `O` *[type]* \ +> [fn-type] → `F` *[fn-sig]* \ +> [dyn-trait-type] → `D` *[dyn-bounds]* *[lifetime]* +> +> [namespace] → *[lower]* | *[upper]* +> +> [generic-arg] → \ +> *[lifetime]* \ +> | *[type]* \ +> | `K` *[const]* +> +> [lifetime] → `L` *[base-62-number]* +> +> [const] → \ +> *[type]* *[const-data]* \ +> | `p` \ +> | *[backref]* +> +> [const-data] → `n`<sub>opt</sub> {*[hex-digit]*} `_` +> +> [hex-digit] → *[digit]* | `a` | `b` | `c` | `d` | `e` | `f` +> +> [fn-sig] → *[binder]*<sub>opt</sub> `U`<sub>opt</sub> (`K` *[abi]*)<sub>opt</sub> {*[type]*} `E` *[type]* +> +> [abi] → \ +> `C` \ +> | *[undisambiguated-identifier]* +> +> [dyn-bounds] → *[binder]*<sub>opt</sub> {*[dyn-trait]*} `E` \ +> [dyn-trait] → *[path]* {*[dyn-trait-assoc-binding]*} \ +> [dyn-trait-assoc-binding] → `p` *[undisambiguated-identifier]* *[type]* +> +> [binder] → `G` *[base-62-number]* +> +> [backref] → `B` *[base-62-number]* +> +> [instantiating-crate] → *[path]* +> +> [vendor-specific-suffix] → (`.` | `$`) *[suffix]* \ +> [suffix] → {*byte*} +> +> [decimal-number] → \ +> `0` \ +> | *[non-zero-digit]* {*[digit]*} +> +> [base-62-number] → { *[digit]* | *[lower]* | *[upper]* } `_` +> +> [non-zero-digit] → `1` | `2` | `3` | `4` | `5` | `6` | `7` | `8` | `9` \ +> [digit] → `0` | *[non-zero-digit]* \ +> [lower] → `a` |`b` |`c` |`d` |`e` |`f` |`g` |`h` |`i` |`j` |`k` |`l` |`m` |`n` |`o` |`p` |`q` |`r` |`s` |`t` |`u` |`v` |`w` |`x` |`y` |`z` \ +> [upper] → `A` | `B` | `C` | `D` | `E` | `F` | `G` | `H` | `I` | `J` | `K` | `L` | `M` | `N` | `O` | `P` | `Q` | `R` | `S` | `T` | `U` | `V` | `W` | `X` | `Y` | `Z` + +## Encoding of Rust entities + +The following are guidelines for how Rust entities are encoded in a symbol. +The compiler has some latitude in how an entity is encoded as long as the symbol is unambiguous. + +* Named functions, methods, and statics shall be represented by a *[path]* production. + +* Paths should be rooted at the inner-most entity that can act as a path root. + Roots can be crate-ids, inherent impls, trait impls, and (for items within default methods) trait definitions. + +* The compiler is free to choose disambiguation indices and namespace tags from + the reserved ranges as long as it ascertains identifier unambiguity. + +* Generic arguments that are equal to the default should not be encoded in order to save space. + + +[RFC 2603]: https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html +[reference-array]: ../../reference/types/array.html +[reference-fn-pointer]: ../../reference/types/function-pointer.html +[reference-hrtb]: ../../reference/trait-bounds.html#higher-ranked-trait-bounds +[reference-identifiers]: ../../reference/identifiers.html +[reference-implementations]: ../../reference/items/implementations.html +[reference-inherent-impl]: ../../reference/items/implementations.html#inherent-implementations +[reference-mutable-reference]: ../../reference/types/pointer.html#mutable-references-mut +[reference-paths]: ../../reference/paths.html +[reference-raw-pointer]: ../../reference/types/pointer.html#raw-pointers-const-and-mut +[reference-shared-reference]: ../../reference/types/pointer.html#shared-references- +[reference-slice]: ../../reference/types/slice.html +[reference-track_caller]: ../../reference/attributes/codegen.html#the-track_caller-attribute +[reference-trait-impl]: ../../reference/items/implementations.html#trait-implementations +[reference-trait-object]: ../../reference/types/trait-object.html +[reference-traits]: ../../reference/items/traits.html +[reference-tuple]: ../../reference/types/tuple.html +[reference-types]: ../../reference/types.html diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index fd57b0796..f15e6e451 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -412,3 +412,37 @@ help: if you meant to use a literal backtick, escape it warning: 1 warning emitted ``` + +## `redundant_explicit_links` + +This lint is **warned by default**. It detects explicit links that are same +as computed automatic links. +This usually means the explicit links is removeable. For example: + +```rust +#![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default. + +/// add takes 2 [`usize`](usize) and performs addition +/// on them, then returns result. +pub fn add(left: usize, right: usize) -> usize { + left + right +} +``` + +Which will give: + +```text +error: redundant explicit rustdoc link + --> src/lib.rs:3:27 + | +3 | /// add takes 2 [`usize`](usize) and performs addition + | ^^^^^ + | + = note: Explicit link does not affect the original link +note: the lint level is defined here + --> src/lib.rs:1:9 + | +1 | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: Remove explicit link instead +``` diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 013b93e01..f69156b7c 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -200,6 +200,7 @@ To do so, the `#[doc(keyword = "...")]` attribute is used. Example: ```rust #![feature(rustdoc_internals)] +#![allow(internal_features)] /// Some documentation about the keyword. #[doc(keyword = "keyword")] diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md index 7a444d77c..7179ee0cf 100644 --- a/src/doc/rustdoc/src/what-is-rustdoc.md +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -37,7 +37,7 @@ top, with no contents. ## Configuring rustdoc There are two problems with this: first, why does it -think that our package is named "lib"? Second, why does it not have any +think that our crate is named "lib"? Second, why does it not have any contents? The first problem is due to `rustdoc` trying to be helpful; like `rustc`, diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md index b8aa64ba1..f4d759673 100644 --- a/src/doc/style-guide/src/README.md +++ b/src/doc/style-guide/src/README.md @@ -36,11 +36,10 @@ options. ### Indentation and line width -* Use spaces, not tabs. -* Each level of indentation must be four spaces (that is, all indentation - outside of string literals and comments must be a multiple of four). -* The maximum width for a line is 100 characters. -* A tool may choose to make some of these configurable. +- Use spaces, not tabs. +- Each level of indentation must be 4 spaces (that is, all indentation + outside of string literals and comments must be a multiple of 4). +- The maximum width for a line is 100 characters. #### Block indent @@ -63,7 +62,8 @@ example) and less rightward drift. ### Trailing commas -Lists should have a trailing comma when followed by a newline: +In comma-separated lists of any kind, use a trailing comma when followed by a +newline: ```rust function_call( @@ -99,13 +99,13 @@ fn bar() {} fn baz() {} ``` -Formatting tools may wish to make the bounds on blank lines configurable. - ### [Module-level items](items.md) + ### [Statements](statements.md) + ### [Expressions](expressions.md) -### [Types](types.md) +### [Types](types.md) ### Comments @@ -114,17 +114,17 @@ formatter might skip formatting of comments. Prefer line comments (`//`) to block comments (`/* ... */`). -When using line comments there should be a single space after the opening sigil. +When using line comments, put a single space after the opening sigil. -When using single-line block comments there should be a single space after the -opening sigil and before the closing sigil. Multi-line block comments should -have a newline after the opening sigil and before the closing sigil. +When using single-line block comments, put a single space after the opening +sigil and before the closing sigil. For multi-line block comments, put a +newline after the opening sigil, and a newline before the closing sigil. -Prefer to put a comment on its own line. Where a comment follows code, there -should be a single space before it. Where a block comment is inline, there -should be surrounding whitespace as if it were an identifier or keyword. There -should be no trailing whitespace after a comment or at the end of any line in a -multi-line comment. Examples: +Prefer to put a comment on its own line. Where a comment follows code, put a +single space before it. Where a block comment appears inline, use surrounding +whitespace as if it were an identifier or keyword. Do not include trailing +whitespace after a comment or at the end of any line in a multi-line comment. +Examples: ```rust // A comment on an item. @@ -173,7 +173,7 @@ Prefer line comments (`///`) to block comments (`/** ... */`). Prefer outer doc comments (`///` or `/** ... */`), only use inner doc comments (`//!` and `/*! ... */`) to write module-level or crate-level documentation. -Doc comments should come before attributes. +Put doc comments before attributes. ### Attributes @@ -198,18 +198,20 @@ struct CRepr { } ``` -For attributes with an equal sign, there should be a single space before and -after the `=`, e.g., `#[foo = 42]`. +For attributes with an equal sign, put a single space before and after the `=`, +e.g., `#[foo = 42]`. There must only be a single `derive` attribute. Note for tool authors: if combining multiple `derive` attributes into a single attribute, the ordering of -the derived names should be preserved. E.g., `#[derive(bar)] #[derive(foo)] -struct Baz;` should be formatted to `#[derive(bar, foo)] struct Baz;`. +the derived names must generally be preserved for correctness: +`#[derive(Foo)] #[derive(Bar)] struct Baz;` must be formatted to +`#[derive(Foo, Bar)] struct Baz;`. ### *small* items -In many places in this guide we specify that a formatter may format an item -differently if it is *small*, for example struct literals: +In many places in this guide we specify formatting that depends on a code +construct being *small*. For example, single-line vs multi-line struct +literals: ```rust // Normal formatting @@ -218,7 +220,7 @@ Foo { f2: another_expression(), } -// *small* formatting +// "small" formatting Foo { f1, f2 } ``` @@ -231,10 +233,6 @@ complexity of an item (for example, that all components must be simple names, not more complex sub-expressions). For more discussion on suitable heuristics, see [this issue](https://github.com/rust-lang-nursery/fmt-rfcs/issues/47). -Tools should give the user an option to ignore such heuristics and always use -the normal formatting. - - ## [Non-formatting conventions](advice.md) ## [Cargo.toml conventions](cargo.md) diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md index 606485bfb..64540c399 100644 --- a/src/doc/style-guide/src/SUMMARY.md +++ b/src/doc/style-guide/src/SUMMARY.md @@ -9,4 +9,5 @@ - [Other style advice](advice.md) - [`Cargo.toml` conventions](cargo.md) - [Guiding principles and rationale](principles.md) +- [Rust style editions](editions.md) - [Nightly-only syntax](nightly.md) diff --git a/src/doc/style-guide/src/advice.md b/src/doc/style-guide/src/advice.md index 9a617be50..65cf8cb6e 100644 --- a/src/doc/style-guide/src/advice.md +++ b/src/doc/style-guide/src/advice.md @@ -18,16 +18,16 @@ if y { ## Names - * Types shall be `UpperCamelCase`, - * Enum variants shall be `UpperCamelCase`, - * Struct fields shall be `snake_case`, - * Function and method names shall be `snake_case`, - * Local variables shall be `snake_case`, - * Macro names shall be `snake_case`, - * Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`. - * When a name is forbidden because it is a reserved word (such as `crate`), - either use a raw identifier (`r#crate`) or use a trailing underscore - (`crate_`). Don't misspell the word (`krate`). +- Types shall be `UpperCamelCase`, +- Enum variants shall be `UpperCamelCase`, +- Struct fields shall be `snake_case`, +- Function and method names shall be `snake_case`, +- Local variables shall be `snake_case`, +- Macro names shall be `snake_case`, +- Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`. +- When a name is forbidden because it is a reserved word (such as `crate`), + either use a raw identifier (`r#crate`) or use a trailing underscore + (`crate_`). Don't misspell the word (`krate`). ### Modules diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md new file mode 100644 index 000000000..5c67a185b --- /dev/null +++ b/src/doc/style-guide/src/editions.md @@ -0,0 +1,46 @@ +# Rust style editions + +The default Rust style evolves over time, as Rust does. However, to avoid +breaking established code style, and CI jobs checking code style, changes to +the default Rust style only appear in *style editions*. + +Code written in a given +[Rust edition](https://doc.rust-lang.org/edition-guide/) +uses the corresponding Rust style edition by default. To make it easier to +migrate code style separately from the semantic changes between Rust editions, +formatting tools such as `rustfmt` allow updating the style edition separately +from the Rust edition. + +The current version of the style guide describes the latest Rust style edition. +Each distinct past style will have a corresponding archived version of the +style guide. + +Note that archived versions of the style guide do not document formatting for +newer Rust constructs that did not exist at the time that version of the style +guide was archived. However, each style edition will still format all +constructs valid in that Rust edition, with the style of newer constructs +coming from the first subsequent style edition providing formatting rules for +that construct (without any of the systematic/global changes from that style +edition). + +Not all Rust editions have corresponding changes to the Rust style. For +instance, Rust 2015, Rust 2018, and Rust 2021 all use the same style edition. + +## Rust 2024 style edition + +This style guide describes the Rust 2024 style edition. The Rust 2024 style +edition is currently nightly-only and may change before the release of Rust +2024. + +For a full history of changes in the Rust 2024 style edition, see the git +history of the style guide. Notable changes in the Rust 2024 style edition +include: + +- Miscellaneous `rustfmt` bugfixes. + +## Rust 2015/2018/2021 style edition + +The archived version of the style guide at +<https://github.com/rust-lang/rust/tree/37343f4a4d4ed7ad0891cb79e8eb25acf43fb821/src/doc/style-guide/src> +describes the style edition corresponding to Rust 2015, Rust 2018, and Rust +2021. diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 143161da6..32c604f9f 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -1,11 +1,14 @@ -## Expressions +# Expressions -### Blocks +## Blocks -A block expression should have a newline after the initial `{` and before the -terminal `}`. Any qualifier before the block (e.g., `unsafe`) should always be -on the same line as the opening brace, and separated with a single space. The -contents of the block should be block indented: +A block expression must have a newline after the initial `{` and before the +terminal `}`, unless it qualifies to be written as a single line based on +another style rule. + +A keyword before the block (such as `unsafe` or `async`) must be on the same +line as the opening brace, with a single space between the keyword and the +opening brace. Indent the contents of the block. ```rust fn block_as_stmt() { @@ -40,7 +43,7 @@ fn unsafe_block_as_stmt() { } ``` -If a block has an attribute, it should be on its own line: +If a block has an attribute, put it on its own line before the block: ```rust fn block_as_stmt() { @@ -54,18 +57,18 @@ fn block_as_stmt() { } ``` -Avoid writing comments on the same line as the braces. +Avoid writing comments on the same lines as either of the braces. -An empty block should be written as `{}`. +Write an empty block as `{}`. -A block may be written on a single line if: +Write a block on a single line if: -* it is either used in expression position (not statement position) or is an - unsafe block in statement position -* contains a single-line expression and no statements -* contains no comments +- it is either used in expression position (not statement position) or is an + unsafe block in statement position, +- it contains a single-line expression and no statements, and +- it contains no comments -A single line block should have spaces after the opening brace and before the +For a single-line block, put spaces after the opening brace and before the closing brace. Examples: @@ -113,18 +116,17 @@ fn main() { } ``` - -### Closures +## Closures Don't put any extra spaces before the first `|` (unless the closure is prefixed -by `move`); put a space between the second `|` and the expression of the -closure. Between the `|`s, you should use function definition syntax, however, -elide types where possible. +by a keyword such as `move`); put a space between the second `|` and the +expression of the closure. Between the `|`s, use function definition syntax, +but elide types where possible. Use closures without the enclosing `{}`, if possible. Add the `{}` when you have -a return type, when there are statements, there are comments in the body, or the -body expression spans multiple lines and is a control-flow expression. If using -braces, follow the rules above for blocks. Examples: +a return type, when there are statements, when there are comments inside the +closure, or when the body expression is a control-flow expression that spans +multiple lines. If using braces, follow the rules above for blocks. Examples: ```rust |arg1, arg2| expr @@ -152,16 +154,16 @@ move |arg1: i32, arg2: i32| -> i32 { } ``` +## Struct literals -### Struct literals +If a struct literal is *small*, format it on a single line, and do not use a +trailing comma. If not, split it across multiple lines, with each field on its +own block-indented line, and use a trailing comma. -If a struct literal is *small* it may be formatted on a single line. If not, -each field should be on it's own, block-indented line. There should be a -trailing comma in the multi-line form only. There should be a space after the -colon only. +For each `field: value` entry, put a space after the colon only. -There should be a space before the opening brace. In the single-line form there -should be spaces after the opening brace and before the closing brace. +Put a space before the opening brace. In the single-line form, put spaces after +the opening brace and before the closing brace. ```rust Foo { field1, field2: 0 } @@ -172,19 +174,24 @@ let f = Foo { ``` Functional record update syntax is treated like a field, but it must never have -a trailing comma. There should be no space after `..`. +a trailing comma. Do not put a space after `..`. +```rust let f = Foo { field1, ..an_expr }; +``` +## Tuple literals -### Tuple literals +Use a single-line form where possible. Do not put spaces between the opening +parenthesis and the first element, or between the last element and the closing +parenthesis. Separate elements with a comma followed by a space. -Use a single-line form where possible. There should not be spaces around the -parentheses. Where a single-line form is not possible, each element of the tuple -should be on its own block-indented line and there should be a trailing comma. +Where a single-line form is not possible, write the tuple across +multiple lines, with each element of the tuple on its own block-indented line, +and use a trailing comma. ```rust (a, b, c) @@ -195,17 +202,24 @@ let x = ( ); ``` +## Tuple struct literals -### Tuple struct literals +Do not put space between the identifier and the opening parenthesis. Otherwise, +follow the rules for tuple literals: -There should be no space between the identifier and the opening parenthesis. -Otherwise, follow the rules for tuple literals, e.g., `Foo(a, b)`. +```rust +Foo(a, b, c) +let x = Foo( + a_long_expr, + another_very_long_expr, +); +``` -### Enum literals +## Enum literals Follow the formatting rules for the various struct literals. Prefer using the -name of the enum as a qualifying name, unless the enum is in the prelude. E.g., +name of the enum as a qualifying name, unless the enum is in the prelude: ```rust Foo::Bar(a, b) @@ -216,27 +230,31 @@ Foo::Baz { Ok(an_expr) ``` +## Array literals -### Array literals +Write small array literals on a single line. Do not put spaces between the opening +square bracket and the first element, or between the last element and the closing +square bracket. Separate elements with a comma followed by a space. -For simple array literals, avoid line breaking, no spaces around square -brackets, contents of the array should be separated by commas and spaces. If -using the repeating initialiser, there should be a space after the semicolon -only. Apply the same rules if using the `vec!` or similar macros (always use -square brackets here). Examples: +If using the repeating initializer, put a space after the semicolon +only. + +Apply the same rules if using `vec!` or similar array-like macros; always use +square brackets with such macros. Examples: ```rust fn main() { - [1, 2, 3]; - vec![a, b, c, d]; + let x = [1, 2, 3]; + let y = vec![a, b, c, d]; let a = [42; 10]; } ``` -If a line must be broken, prefer breaking only after the `;`, if possible. -Otherwise, follow the rules below for function calls. In any case, the contents -of the initialiser should be block indented and there should be line breaks -after the opening bracket and before the closing bracket: +For arrays that have to be broken across lines, if using the repeating +initializer, break after the `;`, not before. Otherwise, follow the rules below +for function calls. In any case, block-indent the contents of the initializer, +and put line breaks after the opening square bracket and before the closing +square bracket: ```rust fn main() { @@ -252,14 +270,14 @@ fn main() { } ``` +## Array accesses, indexing, and slicing -### Array accesses, indexing, and slicing. - -No spaces around the square brackets, avoid breaking lines if possible, never -break a line between the target expression and the opening bracket. If the -indexing expression covers multiple lines, then it should be block indented and -there should be newlines after the opening brackets and before the closing -bracket. However, this should be avoided where possible. +Don't put spaces around the square brackets. Avoid breaking lines if possible. +Never break a line between the target expression and the opening square +bracket. If the indexing expression must be broken onto a subsequent line, or +spans multiple lines itself, then block-indent the indexing expression, and put +newlines after the opening square bracket and before the closing square +bracket: Examples: @@ -275,13 +293,13 @@ fn main() { } ``` -### Unary operations +## Unary operations Do not include a space between a unary op and its operand (i.e., `!x`, not `! x`). However, there must be a space after `&mut`. Avoid line-breaking between a unary operator and its operand. -### Binary operations +## Binary operations Do include spaces around binary ops (i.e., `x + 1`, not `x+1`) (including `=` and other assignment operators such as `+=` or `*=`). @@ -291,7 +309,7 @@ if you have `t: &T`, and `u: U`, prefer `*t op u` to `t op &u`. In general, within expressions, prefer dereferencing to taking references, unless necessary (e.g. to avoid an unnecessarily expensive operation). -Use parentheses liberally, do not necessarily elide them due to precedence. +Use parentheses liberally; do not necessarily elide them due to precedence. Tools should not automatically insert or remove parentheses. Do not use spaces to indicate precedence. @@ -310,7 +328,7 @@ foo_bar Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather than at other binary operators. -### Control flow +## Control flow Do not include extraneous parentheses for `if` and `while` expressions. @@ -329,7 +347,7 @@ if (true) { Do include extraneous parentheses if it makes an arithmetic or logic expression easier to understand (`(x * 15) + (y * 20)` is fine) -### Function calls +## Function calls Do not put a space between the function name, and the opening parenthesis. @@ -339,7 +357,7 @@ Do put a space between an argument, and the comma which precedes it. Prefer not to break a line in the callee expression. -#### Single-line calls +### Single-line calls Do not put a space between the function name and open paren, between the open paren and the first argument, or between the last argument and the close paren. @@ -350,13 +368,13 @@ Do not put a comma after the last argument. foo(x, y, z) ``` -#### Multi-line calls +### Multi-line calls If the function call is not *small*, it would otherwise over-run the max width, -or any argument or the callee is multi-line, then the call should be formatted -across multiple lines. In this case, each argument should be on it's own block- -indented line, there should be a newline after the opening parenthesis and -before the closing parenthesis, and there should be a trailing comma. E.g., +or any argument or the callee is multi-line, then format the call across +multiple lines. In this case, put each argument on its own block-indented line, +break after the opening parenthesis and before the closing parenthesis, +and use a trailing comma: ```rust a_function_call( @@ -365,8 +383,7 @@ a_function_call( ) ``` - -### Method calls +## Method calls Follow the function rules for calling. @@ -376,20 +393,20 @@ Do not put any spaces around the `.`. x.foo().bar().baz(x, y, z); ``` +## Macro uses -### Macro uses - -Macros which can be parsed like other constructs should be formatted like those +If a macro can be parsed like other constructs, format it like those constructs. For example, a macro use `foo!(a, b, c)` can be parsed like a -function call (ignoring the `!`), therefore it should be formatted following the -rules for function calls. +function call (ignoring the `!`), so format it using the rules for function +calls. -#### Special case macros +### Special case macros -Macros which take a format string and where all other arguments are *small* may -be formatted with arguments before and after the format string on a single line -and the format string on its own line, rather than putting each argument on its -own line. For example, +For macros which take a format string, if all other arguments are *small*, +format the arguments before the format string on a single line if they fit, and +format the arguments after the format string on a single line if they fit, with +the format string on its own line. If the arguments are not small or do not +fit, put each on its own line as with a function. For example: ```rust println!( @@ -404,8 +421,7 @@ assert_eq!( ); ``` - -### Casts (`as`) +## Casts (`as`) Put spaces before and after `as`: @@ -413,16 +429,15 @@ Put spaces before and after `as`: let cstr = "Hi\0" as *const str as *const [u8] as *const std::os::raw::c_char; ``` +## Chains of fields and method calls -### Chains of fields and method calls - -A chain is a sequence of field accesses and/or method calls. A chain may also -include the try operator ('?'). E.g., `a.b.c().d` or `foo?.bar().baz?`. +A chain is a sequence of field accesses, method calls, and/or uses of the try +operator `?`. E.g., `a.b.c().d` or `foo?.bar().baz?`. -Prefer formatting on one line if possible, and the chain is *small*. If -formatting on multiple lines, each field access or method call in the chain -should be on its own line with the line-break before the `.` and after any `?`. -Each line should be block-indented. E.g., +Format the chain on one line if it is "small" and otherwise possible to do so. +If formatting on multiple lines, put each field access or method call in the +chain on its own line, with the line-break before the `.` and after any `?`. +Block-indent each subsequent line: ```rust let foo = bar @@ -431,13 +446,16 @@ let foo = bar ``` If the length of the last line of the first element plus its indentation is -less than or equal to the indentation of the second line (and there is space), -then combine the first and second lines, e.g., +less than or equal to the indentation of the second line, then combine the +first and second lines if they fit. Apply this rule recursively. ```rust x.baz? .qux() +x.y.z + .qux() + let foo = x .baz? .qux(); @@ -449,14 +467,13 @@ foo( .qux(); ``` -#### Multi-line elements +### Multi-line elements -If any element in a chain is formatted across multiple lines, then that element -and any later elements must be on their own line. Earlier elements may be kept -on a single line. E.g., +If any element in a chain is formatted across multiple lines, put that element +and any later elements on their own lines. ```rust -a.b.c()?.d +a.b.c()? .foo( an_expr, another_expr, @@ -485,18 +502,18 @@ self.pre_comment.as_ref().map_or( ) ``` -### Control flow expressions +## Control flow expressions This section covers `if`, `if let`, `loop`, `while`, `while let`, and `for` expressions. -The keyword, any initial clauses, and the opening brace of the block should be -on a single line. The usual rules for [block formatting](#blocks) should be -applied to the block. +Put the keyword, any initial clauses, and the opening brace of the block all on +a single line, if they fit. Apply the usual rules for [block +formatting](#blocks) to the block. -If there is an `else` component, then the closing brace, `else`, any following -clause, and the opening brace should all be on the same line. There should be a -single space before and after the `else` keyword. For example: +If there is an `else` component, then put the closing brace, `else`, any +following clause, and the opening brace all on the same line, with a single +space before and after the `else` keyword: ```rust if ... { @@ -514,10 +531,10 @@ if let ... { } ``` -If the control line needs to be broken, then prefer to break before the `=` in -`* let` expressions and before `in` in a `for` expression; the following line -should be block indented. If the control line is broken for any reason, then the -opening brace should be on its own line and not indented. Examples: +If the control line needs to be broken, prefer to break before the `=` in `* +let` expressions and before `in` in a `for` expression; block-indent the +following line. If the control line is broken for any reason, put the opening +brace on its own line, not indented. Examples: ```rust while let Some(foo) @@ -540,10 +557,10 @@ if a_long_expression } ``` -Where the initial clause is multi-lined and ends with one or more closing -parentheses, square brackets, or braces, and there is nothing else on that line, -and that line is not indented beyond the indent on the first line of the control -flow expression, then the opening brace of the block should be put on the same +Where the initial clause spans multiple lines and ends with one or more closing +parentheses, square brackets, or braces, and there is nothing else on that +line, and that line is not indented beyond the indent on the first line of the +control flow expression, then put the opening brace of the block on the same line with a preceding space. For example: ```rust @@ -556,12 +573,11 @@ if !self.config.file_lines().intersects( } ``` +### Single line `if else` -#### Single line `if else` - -Formatters may place an `if else` or `if let else` on a single line if it occurs -in expression context (i.e., is not a standalone statement), it contains a -single `else` clause, and is *small*. For example: +Put an `if else` or `if let else` on a single line if it occurs in expression +context (i.e., is not a standalone statement), it contains a single `else` +clause, and is *small*: ```rust let y = if x { 0 } else { 1 }; @@ -580,12 +596,11 @@ if x { } ``` +## Match -### Match - -Prefer not to line-break inside the discriminant expression. There must always -be a line break after the opening brace and before the closing brace. The match -arms must be block indented once: +Prefer not to line-break inside the discriminant expression. Always break after +the opening brace and before the closing brace. Block-indent the match arms +once: ```rust match foo { @@ -599,7 +614,7 @@ let x = match foo.bar.baz() { Use a trailing comma for a match arm if and only if not using a block. -Never start a match arm pattern with `|`, e.g., +Never start a match arm pattern with `|`: ```rust match foo { @@ -609,14 +624,13 @@ match foo { | a_very_long_pattern | another_pattern | yet_another_pattern - | a_forth_pattern => { + | a_fourth_pattern => { ... } } ``` -Prefer - +Prefer: ```rust match foo { @@ -624,7 +638,7 @@ match foo { a_very_long_pattern | another_pattern | yet_another_pattern - | a_forth_pattern => { + | a_fourth_pattern => { ... } } @@ -634,11 +648,12 @@ Avoid splitting the left-hand side (before the `=>`) of a match arm where possible. If the right-hand side of the match arm is kept on the same line, never use a block (unless the block is empty). -If the right-hand side consists of multiple statements or has line comments or -the start of the line cannot be fit on the same line as the left-hand side, use -a block. +If the right-hand side consists of multiple statements, or has line comments, +or the start of the line does not fit on the same line as the left-hand side, +use a block. Do not flatten a right-hand side block containing a single macro call +because its expanded form could contain a trailing semicolon. -The body of a block arm should be block indented once. +Block-indent the body of a block arm. Examples: @@ -659,12 +674,16 @@ match foo { bar => {} // Trailing comma on last item. foo => bar, + baz => qux!(), + lorem => { + ipsum!() + } } ``` If the body is a single expression with no line comments and not a control flow -expression, then it may be started on the same line as the right-hand side. If -not, then it must be in a block. Example, +expression, start it on the same line as the left-hand side. If not, then it +must be in a block. Example: ```rust match foo { @@ -686,10 +705,10 @@ match foo { } ``` -#### Line-breaking +### Line-breaking -Where it is possible to use a block form on the right-hand side and avoid -breaking the left-hand side, do that. E.g. +If using a block form on the right-hand side of a match arm makes it possible +to avoid breaking on the left-hand side, do that: ```rust // Assuming the following line does not fit in the max width @@ -721,7 +740,7 @@ body on a new line: If required to break the pattern, put each clause of the pattern on its own line with no additional indent, breaking before the `|`. If there is an `if` -clause, then you must use the above form: +clause, use the above form: ```rust a_very_long_pattern @@ -741,7 +760,7 @@ clause, then you must use the above form: ``` If the pattern is multi-line, and the last line is less wide than the indent, do -not put the `if` clause on a newline. E.g., +not put the `if` clause on a new line. E.g., ```rust Token::Dimension { @@ -754,8 +773,8 @@ not put the `if` clause on a newline. E.g., ``` If every clause in a pattern is *small*, but the whole pattern does not fit on -one line, then the pattern may be formatted across multiple lines with as many -clauses per line as possible. Again break before a `|`: +one line, then format the pattern across multiple lines with as many clauses +per line as possible. Again, break before a `|`: ```rust foo | bar | baz @@ -780,12 +799,11 @@ small_no_tuple: E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not. - -### Combinable expressions +## Combinable expressions Where a function call has a single argument, and that argument is formatted -across multiple-lines, the outer call may be formatted as if it were a single- -line call. The same combining behaviour may be applied to any similar +across multiple-lines, format the outer call as if it were a single-line call, +if the result fits. Apply the same combining behaviour to any similar expressions which have multi-line, block-indented lists of sub-expressions delimited by parentheses (e.g., macros or tuple struct literals). E.g., @@ -803,15 +821,24 @@ foo(|param| { action(); foo(param) }) + +let x = combinable([ + an_expr, + another_expr, +]); + +let arr = [combinable( + an_expr, + another_expr, +)]; ``` -Such behaviour should extend recursively, however, tools may choose to limit the -depth of nesting. +Apply this behavior recursively. -Only where the multi-line sub-expression is a closure with an explicit block, -this combining behaviour may be used where there are other arguments, as long as -all the arguments and the first line of the closure fit on the first line, the -closure is the last argument, and there is only one closure argument: +For a function with multiple arguments, if the last argument is a multi-line +closure with an explicit block, there are no other closure arguments, and all +the arguments and the first line of the closure fit on the first line, use the +same combining behavior: ```rust foo(first_arg, x, |param| { @@ -820,34 +847,30 @@ foo(first_arg, x, |param| { }) ``` - -### Ranges +## Ranges Do not put spaces in ranges, e.g., `0..10`, `x..=y`, `..x.len()`, `foo..`. When writing a range with both upper and lower bounds, if the line must be -broken, break before the range operator and block indent the second line: +broken within the range, break before the range operator and block indent the +second line: ```rust a_long_expression ..another_long_expression ``` -For the sake of indicating precedence, we recommend that if either bound is a -compound expression, then use parentheses around it, e.g., `..(x + 1)`, -`(x.f)..(x.f.len())`, or `0..(x - 10)`. +For the sake of indicating precedence, if either bound is a compound +expression, use parentheses around it, e.g., `..(x + 1)`, `(x.f)..(x.f.len())`, +or `0..(x - 10)`. - -### Hexadecimal literals +## Hexadecimal literals Hexadecimal literals may use upper- or lower-case letters, but they must not be mixed within the same literal. Projects should use the same case for all literals, but we do not make a recommendation for either lower- or upper-case. -Tools should have an option to convert mixed case literals to upper-case, and -may have an option to convert all literals to either lower- or upper-case. - ## Patterns -Patterns should be formatted like their corresponding expressions. See the -section on `match` for additional formatting for patterns in match arms. +Format patterns like their corresponding expressions. See the section on +`match` for additional formatting for patterns in match arms. diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index 1e0e60248..a6d941f6d 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -1,4 +1,4 @@ -## Items +# Items Items consist of the set of things permitted at the top level of a module. However, Rust also allows some items to appear within some other types of @@ -9,19 +9,17 @@ an item appears at module level or within another item. alphabetically. `use` statements, and module *declarations* (`mod foo;`, not `mod { ... }`) -must come before other items. We recommend that imports come before module -declarations; if imports and modules are separated, then they should be ordered -alphabetically. When sorting, `self` and `super` must come before any other -names. Module declarations should not be moved if they are annotated with -`#[macro_use]`, since that may be semantics changing. +must come before other items. Put imports before module declarations. Sort each +alphabetically, except that `self` and `super` must come before any other +names. -Tools should make the above ordering optional. +Don't automatically move module declarations annotated with `#[macro_use]`, +since that might change semantics. - -### Function definitions +## Function definitions In Rust, people often find functions by searching for `fn [function-name]`, so -the formatting of function definitions shold enable this. +the formatting of function definitions must enable this. The proper ordering and spacing is: @@ -48,14 +46,13 @@ fn foo( Note the trailing comma on the last argument. - -### Tuples and tuple structs +## Tuples and tuple structs Write the type list as you would a parameter list to a function. Build a tuple or tuple struct as you would call a function. -#### Single-line +### Single-line ```rust struct Bar(Type1, Type2); @@ -64,7 +61,7 @@ let x = Bar(11, 22); let y = (11, 22, 33); ``` -### Enums +## Enums In the declaration, put each variant on its own line, block indented. @@ -83,9 +80,9 @@ enum FooBar { } ``` -If a struct variant is [*small*](index.html#small-items), it may be formatted on -one line. In this case, do not use a trailing comma for the field list, but do -put spaces around each brace: +If a struct variant is [*small*](index.html#small-items), format it on one +line. In this case, do not use a trailing comma for the field list, but do put +spaces around each brace: ```rust enum FooBar { @@ -94,12 +91,11 @@ enum FooBar { ``` In an enum with multiple struct variants, if any struct variant is written on -multiple lines, then the multi-line formatting should be used for all struct -variants. However, such a situation might be an indication that you should -factor out the fields of the variant into their own struct. - +multiple lines, use the multi-line formatting for all struct variants. However, +such a situation might be an indication that you should factor out the fields +of the variant into their own struct. -### Structs and Unions +## Structs and Unions Struct names follow on the same line as the `struct` keyword, with the opening brace on the same line when it fits within the right margin. All struct fields @@ -140,12 +136,11 @@ union Foo { } ``` +## Tuple structs -### Tuple structs - -Put the whole struct on one line if possible. Types in the parentheses should be -separated by a comma and space with no trailing comma. No spaces around the -parentheses or semicolon: +Put the whole struct on one line if possible. Separate types within the +parentheses using a comma and space. Don't use a trailing comma for a +single-line tuple struct. Don't put spaces around the parentheses or semicolon: ```rust pub struct Foo(String, u8); @@ -154,9 +149,11 @@ pub struct Foo(String, u8); Prefer unit structs to empty tuple structs (these only exist to simplify code generation), e.g., `struct Foo;` rather than `struct Foo();`. -For more than a few fields, prefer a proper struct with named fields. Given -this, a tuple struct should always fit on one line. If it does not, block format -the fields with a field on each line and a trailing comma: +For more than a few fields (in particular if the tuple struct does not fit on +one line), prefer a proper struct with named fields. + +For a multi-line tuple struct, block-format the fields with a field on each +line and a trailing comma: ```rust pub struct Foo( @@ -165,12 +162,11 @@ pub struct Foo( ); ``` +## Traits -### Traits - -Trait items should be block-indented. If there are no items, the trait may be -formatted on a single line. Otherwise there should be line-breaks after the -opening brace and before the closing brace: +Use block-indent for trait items. If there are no items, format the trait (including its `{}`) +on a single line. Otherwise, break after the opening brace and before +the closing brace: ```rust trait Foo {} @@ -180,8 +176,8 @@ pub trait Bar { } ``` -If the trait has bounds, there should be a space after the colon but not before -and before and after each `+`, e.g., +If the trait has bounds, put a space after the colon but not before, +and put spaces around each `+`, e.g., ```rust trait Foo: Debug + Bar {} @@ -204,12 +200,11 @@ pub trait IndexRanges: } ``` +## Impls -### Impls - -Impl items should be block indented. If there are no items, the impl may be -formatted on a single line. Otherwise there should be line-breaks after the -opening brace and before the closing brace: +Use block-indent for impl items. If there are no items, format the impl +(including its `{}`) on a single line. Otherwise, break after the opening brace +and before the closing brace: ```rust impl Foo {} @@ -231,15 +226,13 @@ impl Bar } ``` - -### Extern crate +## Extern crate `extern crate foo;` Use spaces around keywords, no spaces around the semicolon. - -### Modules +## Modules ```rust mod foo { @@ -253,7 +246,7 @@ mod foo; Use spaces around keywords and before the opening brace, no spaces around the semicolon. -### macro\_rules! +## `macro_rules!` Use `{}` for the full definition of the macro. @@ -262,17 +255,16 @@ macro_rules! foo { } ``` - -### Generics +## Generics Prefer to put a generics clause on one line. Break other parts of an item declaration rather than line-breaking a generics clause. If a generics clause is -large enough to require line-breaking, you should prefer to use a `where` clause -instead. +large enough to require line-breaking, prefer a `where` clause instead. -Do not put spaces before or after `<` nor before `>`. Only put a space after `>` -if it is followed by a word or opening brace, not an opening parenthesis. There -should be a space after each comma and no trailing comma. +Do not put spaces before or after `<` nor before `>`. Only put a space after +`>` if it is followed by a word or opening brace, not an opening parenthesis. +Put a space after each comma. Do not use a trailing comma for a single-line +generics clause. ```rust fn foo<T: Display, U: Debug>(x: Vec<T>, y: Vec<U>) ... @@ -280,10 +272,9 @@ fn foo<T: Display, U: Debug>(x: Vec<T>, y: Vec<U>) ... impl<T: Display, U: Debug> SomeType<T, U> { ... ``` -If the generics clause must be formatted across multiple lines, each parameter -should have its own block-indented line, there should be newlines after the -opening bracket and before the closing bracket, and the should be a trailing -comma. +If the generics clause must be formatted across multiple lines, put each +parameter on its own block-indented line, break after the opening `<` and +before the closing `>`, and use a trailing comma. ```rust fn foo< @@ -292,8 +283,7 @@ fn foo< >(x: Vec<T>, y: Vec<U>) ... ``` -If an associated type is bound in a generic type, then there should be spaces on -either side of the `=`: +If an associated type is bound in a generic type, put spaces around the `=`: ```rust <T: Example<Item = u32>> @@ -301,17 +291,18 @@ either side of the `=`: Prefer to use single-letter names for generic parameters. - -### `where` clauses +## `where` clauses These rules apply for `where` clauses on any item. -A `where` clause may immediately follow a closing bracket of any kind. -Otherwise, it must start a new line, with no indent. Each component of a `where` -clause must be on its own line and be block indented. There should be a trailing +If immediately following a closing bracket of any kind, write the keyword +`where` on the same line, with a space before it. + +Otherwise, put `where` on a new line at the same indentation level. Put each +component of a `where` clause on its own line, block-indented. Use a trailing comma, unless the clause is terminated with a semicolon. If the `where` clause -is followed by a block (or assignment), the block should be started on a new -line. Examples: +is followed by a block (or assignment), start that block on a new line. +Examples: ```rust fn function<T, U>(args) @@ -355,12 +346,12 @@ where = Bar<T>; ``` -If a `where` clause is very short, we recommend using an inline bound on the -type parameter. - +If a `where` clause is very short, prefer using an inline bound on the type +parameter. -If a component of a `where` clause is long, it may be broken before `+` and -further block indented. Each bound should go on its own line. E.g., +If a component of a `where` clause does not fit and contains `+`, break it +before each `+` and block-indent the continuation lines. Put each bound on its +own line. E.g., ```rust impl<T: ?Sized, Idx> IndexRanges<Idx> for T @@ -369,40 +360,14 @@ where + Index<RangeTo<Idx>, Output = Self::Output> + Index<RangeFrom<Idx>, Output = Self::Output> + Index<RangeInclusive<Idx>, Output = Self::Output> - + Index<RangeToInclusive<Idx>, Output = Self::Output> + Index<RangeFull> + + Index<RangeToInclusive<Idx>, Output = Self::Output> + + Index<RangeFull>, ``` -#### Option - `where_single_line` +## Type aliases -`where_single_line` is `false` by default. If `true`, then a where clause with -exactly one component may be formatted on a single line if the rest of the -item's signature is also kept on one line. In this case, there is no need for a -trailing comma and if followed by a block, no need for a newline before the -block. E.g., - -```rust -// May be single-lined. -fn foo<T>(args) -> ReturnType -where T: Bound { - body -} - -// Must be multi-lined. -fn foo<T>( - args -) -> ReturnType -where - T: Bound, -{ - body -} -``` - - -### Type aliases - -Type aliases should generally be kept on one line. If necessary to break the -line, do so after the `=`; the right-hand-side should be block indented: +Keep type aliases on one line when they fit. If necessary to break the line, do +so after the `=`, and block-indent the right-hand side: ```rust pub type Foo = Bar<T>; @@ -424,29 +389,24 @@ where = AnEvenLongerType<T, U, Foo<T>>; ``` +## Associated types -### Associated types - -Associated types should follow the guidelines above for type aliases. Where an -associated type has a bound, there should be a space after the colon but not -before: +Format associated types like type aliases. Where an associated type has a +bound, put a space after the colon but not before: ```rust pub type Foo: Bar; ``` +## extern items -### extern items - -When writing extern items (such as `extern "C" fn`), always be explicit about -the ABI. For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or +When writing extern items (such as `extern "C" fn`), always specify the ABI. +For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or `extern "C" { ... }`. +## Imports (`use` statements) -### Imports (`use` statements) - -If an import can be formatted on one line, do so. There should be no spaces -around braces. +Format imports on one line where possible. Don't put spaces around braces. ```rust use a::b::c; @@ -454,18 +414,16 @@ use a::b::d::*; use a::b::{foo, bar, baz}; ``` - -#### Large list imports +### Large list imports Prefer to use multiple imports rather than a multi-line import. However, tools -should not split imports by default (they may offer this as an option). +should not split imports by default. If an import does require multiple lines (either because a list of single names does not fit within the max width, or because of the rules for nested imports below), then break after the opening brace and before the closing brace, use a trailing comma, and block indent the names. - ```rust // Prefer foo::{long, list, of, imports}; @@ -478,8 +436,7 @@ foo::{ }; ``` - -#### Ordering of imports +### Ordering of imports A *group* of imports is a set of imports on the same or sequential lines. One or more blank lines or other items (e.g., a function) separate groups of imports. @@ -487,7 +444,6 @@ more blank lines or other items (e.g., a function) separate groups of imports. Within a group of imports, imports must be sorted ASCIIbetically (uppercase before lowercase). Groups of imports must not be merged or re-ordered. - E.g., input: ```rust @@ -511,29 +467,25 @@ use b; Because of `macro_use`, attributes must also start a new group and prevent re-ordering. -#### Ordering list import +### Ordering list import Names in a list import must be sorted ASCIIbetically, but with `self` and `super` first, and groups and glob imports last. This applies recursively. For example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g., `use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`. +### Normalisation -#### Normalisation - -Tools must make the following normalisations: - -* `use a::self;` -> `use a;` -* `use a::{};` -> (nothing) -* `use a::{b};` -> `use a::b;` +Tools must make the following normalisations, recursively: -And must apply these recursively. +- `use a::self;` -> `use a;` +- `use a::{};` -> (nothing) +- `use a::{b};` -> `use a::b;` Tools must not otherwise merge or un-merge import lists or adjust glob imports (without an explicit option). - -#### Nested imports +### Nested imports If there are any nested imports in a list import, then use the multi-line form, even if the import fits on one line. Each nested import must be on its own line, @@ -549,8 +501,7 @@ use a::b::{ }; ``` - -#### Merging/un-merging imports +### Merging/un-merging imports An example: diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md index 031811b0e..66e7fa3c9 100644 --- a/src/doc/style-guide/src/nightly.md +++ b/src/doc/style-guide/src/nightly.md @@ -1,3 +1,5 @@ +# Nightly + This chapter documents style and formatting for nightly-only syntax. The rest of the style guide documents style for stable Rust syntax; nightly syntax only appears in this chapter. Each section here includes the name of the feature gate, so that searches (e.g. `git grep`) for a nightly feature in the Rust repository also turn up the style guide section. Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization. diff --git a/src/doc/style-guide/src/principles.md b/src/doc/style-guide/src/principles.md index d548693e3..ce57c649a 100644 --- a/src/doc/style-guide/src/principles.md +++ b/src/doc/style-guide/src/principles.md @@ -3,27 +3,27 @@ When deciding on style guidelines, the style team follows these guiding principles (in rough priority order): -* readability - - scan-ability - - avoiding misleading formatting - - accessibility - readable and editable by users using the widest - variety of hardware, including non-visual accessibility interfaces - - readability of code in contexts without syntax highlighting or IDE - assistance, such as rustc error messages, diffs, grep, and other - plain-text contexts +- readability + - scan-ability + - avoiding misleading formatting + - accessibility - readable and editable by users using the widest + variety of hardware, including non-visual accessibility interfaces + - readability of code in contexts without syntax highlighting or IDE + assistance, such as rustc error messages, diffs, grep, and other + plain-text contexts -* aesthetics - - sense of 'beauty' - - consistent with other languages/tools +- aesthetics + - sense of 'beauty' + - consistent with other languages/tools -* specifics - - compatibility with version control practices - preserving diffs, - merge-friendliness, etc. - - preventing rightward drift - - minimising vertical space +- specifics + - compatibility with version control practices - preserving diffs, + merge-friendliness, etc. + - preventing rightward drift + - minimising vertical space -* application - - ease of manual application - - ease of implementation (in `rustfmt`, and in other tools/editors/code generators) - - internal consistency - - simplicity of formatting rules +- application + - ease of manual application + - ease of implementation (in `rustfmt`, and in other tools/editors/code generators) + - internal consistency + - simplicity of formatting rules diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md index a5cd6da10..6f322b3d6 100644 --- a/src/doc/style-guide/src/statements.md +++ b/src/doc/style-guide/src/statements.md @@ -1,9 +1,9 @@ -## Statements +# Statements -### Let statements +## Let statements -There should be spaces after the `:` and on both sides of the `=` (if they are -present). No space before the semicolon. +Put a space after the `:` and on both sides of the `=` (if they are present). +Don't put a space before the semicolon. ```rust // A comment. @@ -14,20 +14,19 @@ let pattern: Type; let pattern = expr; ``` -If possible the declaration should be formatted on a single line. If this is not -possible, then try splitting after the `=`, if the declaration can fit on two -lines. The expression should be block indented. +If possible, format the declaration on a single line. If not possible, then try +splitting after the `=`, if the declaration fits on two lines. Block-indent the +expression. ```rust let pattern: Type = expr; ``` -If the first line does not fit on a single line, then split after the colon, -using block indentation. If the type covers multiple lines, even after line- -breaking after the `:`, then the first line may be placed on the same line as -the `:`, subject to the [combining rules](https://github.com/rust-lang-nursery/fmt-rfcs/issues/61) (WIP). - +If the first line still does not fit on a single line, split after the `:`, and +use block indentation. If the type requires multiple lines, even after +line-breaking after the `:`, then place the first line on the same line as the +`:`, subject to the [combining rules](expressions.html#combinable-expressions). ```rust let pattern: @@ -51,12 +50,12 @@ let (abcd, ``` If the expression covers multiple lines, if the first line of the expression -fits in the remaining space, it stays on the same line as the `=`, the rest of the -expression is not indented. If the first line does not fit, then it should start -on the next lines, and should be block indented. If the expression is a block -and the type or pattern cover multiple lines, then the opening brace should be -on a new line and not indented (this provides separation for the interior of the -block from the type), otherwise the opening brace follows the `=`. +fits in the remaining space, it stays on the same line as the `=`, and the rest +of the expression is not further indented. If the first line does not fit, then +put the expression on subsequent lines, block indented. If the expression is a +block and the type or pattern cover multiple lines, put the opening brace on a +new line and not indented (this provides separation for the interior of the +block from the type); otherwise, the opening brace follows the `=`. Examples: @@ -101,15 +100,15 @@ let Foo { ); ``` -#### else blocks (let-else statements) +### else blocks (let-else statements) A let statement can contain an `else` component, making it a let-else statement. In this case, always apply the same formatting rules to the components preceding the `else` block (i.e. the `let pattern: Type = initializer_expr` portion) as described [for other let statements](#let-statements). -The entire let-else statement may be formatted on a single line if all the -following are true: +Format the entire let-else statement on a single line if all the following are +true: * the entire statement is *short* * the `else` block contains only a single-line expression and no statements @@ -120,9 +119,6 @@ following are true: let Some(1) = opt else { return }; ``` -Formatters may allow users to configure the value of the threshold -used to determine whether a let-else statement is *short*. - Otherwise, the let-else statement requires some line breaks. If breaking a let-else statement across multiple lines, never break between the @@ -157,9 +153,9 @@ before the `else`. }; ``` -If the initializer expression is multi-line, the `else` keyword and opening -brace of the block (i.e. `else {`) should be put on the same line as the end of -the initializer expression, with a space between them, if and only if all the +If the initializer expression is multi-line, put the `else` keyword and opening +brace of the block (i.e. `else {`) on the same line as the end of the +initializer expression, with a space between them, if and only if all the following are true: * The initializer expression ends with one or more closing @@ -182,9 +178,9 @@ let Some(x) = y.foo( } ``` -Otherwise, the `else` keyword and opening brace should be placed on the next -line after the end of the initializer expression, and the `else` keyword should -have the same indentation level as the `let` keyword. +Otherwise, put the `else` keyword and opening brace on the next line after the +end of the initializer expression, with the `else` keyword at the same +indentation level as the `let` keyword. For example: @@ -234,28 +230,27 @@ fn main() { } ``` -### Macros in statement position +## Macros in statement position -A macro use in statement position should use parentheses or square brackets as -delimiters and should be terminated with a semicolon. There should be no spaces -between the name, `!`, the delimiters, or the `;`. +For a macro use in statement position, use parentheses or square brackets as +delimiters, and terminate it with a semicolon. Do not put spaces around the +name, `!`, the delimiters, or the `;`. ```rust // A comment. a_macro!(...); ``` +## Expressions in statement position -### Expressions in statement position - -There should be no space between the expression and the semicolon. +Do not put space between the expression and the semicolon. ``` <expr>; ``` -All expressions in statement position should be terminated with a semicolon, -unless they end with a block or are used as the value for a block. +Terminate all expressions in statement position with a semicolon, unless they +end with a block or are used as the value for a block. E.g., diff --git a/src/doc/style-guide/src/types.md b/src/doc/style-guide/src/types.md index ae456ef21..b7921c891 100644 --- a/src/doc/style-guide/src/types.md +++ b/src/doc/style-guide/src/types.md @@ -1,23 +1,22 @@ -## Types and Bounds +# Types and Bounds -### Single line formatting +## Single line formatting -* `[T]` no spaces -* `[T; expr]`, e.g., `[u32; 42]`, `[Vec<Foo>; 10 * 2 + foo()]` (space after colon, no spaces around square brackets) -* `*const T`, `*mut T` (no space after `*`, space before type) -* `&'a T`, `&T`, `&'a mut T`, `&mut T` (no space after `&`, single spaces separating other words) -* `unsafe extern "C" fn<'a, 'b, 'c>(T, U, V) -> W` or `fn()` (single spaces around keywords and sigils, and after commas, no trailing commas, no spaces around brackets) -* `!` should be treated like any other type name, `Name` -* `(A, B, C, D)` (spaces after commas, no spaces around parens, no trailing comma unless it is a one-tuple) -* `<Baz<T> as SomeTrait>::Foo::Bar` or `Foo::Bar` or `::Foo::Bar` (no spaces around `::` or angle brackets, single spaces around `as`) -* `Foo::Bar<T, U, V>` (spaces after commas, no trailing comma, no spaces around angle brackets) -* `T + T + T` (single spaces between types, and `+`). -* `impl T + T + T` (single spaces between keyword, types, and `+`). +- `[T]` no spaces +- `[T; expr]`, e.g., `[u32; 42]`, `[Vec<Foo>; 10 * 2 + foo()]` (space after colon, no spaces around square brackets) +- `*const T`, `*mut T` (no space after `*`, space before type) +- `&'a T`, `&T`, `&'a mut T`, `&mut T` (no space after `&`, single spaces separating other words) +- `unsafe extern "C" fn<'a, 'b, 'c>(T, U, V) -> W` or `fn()` (single spaces around keywords and sigils, and after commas, no trailing commas, no spaces around brackets) +- `!` gets treated like any other type name, `Name` +- `(A, B, C, D)` (spaces after commas, no spaces around parens, no trailing comma unless it is a one-tuple) +- `<Baz<T> as SomeTrait>::Foo::Bar` or `Foo::Bar` or `::Foo::Bar` (no spaces around `::` or angle brackets, single spaces around `as`) +- `Foo::Bar<T, U, V>` (spaces after commas, no trailing comma, no spaces around angle brackets) +- `T + T + T` (single spaces between types, and `+`). +- `impl T + T + T` (single spaces between keyword, types, and `+`). -Parentheses used in types should not be surrounded by whitespace, e.g., `(Foo)` +Do not put space around parentheses used in types, e.g., `(Foo)` - -### Line breaks +## Line breaks Avoid breaking lines in types where possible. Prefer breaking at outermost scope, e.g., prefer @@ -37,13 +36,17 @@ Foo<Bar, Baz< >> ``` -`[T; expr]` may be broken after the `;` if necessary. +If a type requires line-breaks in order to fit, this section outlines where to +break such types if necessary. + +Break `[T; expr]` after the `;` if necessary. -Function types may be broken following the rules for function declarations. +Break function types following the rules for function declarations. -Generic types may be broken following the rules for generics. +Break generic types following the rules for generics. -Types with `+` may be broken after any `+` using block indent and breaking before the `+`. When breaking such a type, all `+`s should be line broken, e.g., +Break types with `+` by breaking before the `+` and block-indenting the +subsequent lines. When breaking such a type, break before *every* `+`: ```rust impl Clone diff --git a/src/doc/unstable-book/src/compiler-flags/no-parallel-llvm.md b/src/doc/unstable-book/src/compiler-flags/no-parallel-llvm.md new file mode 100644 index 000000000..f19ba16b6 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/no-parallel-llvm.md @@ -0,0 +1,8 @@ +# `no-parallel-llvm` + +--------------------- + +This flag disables parallelization of codegen and linking, while otherwise preserving +behavior with regard to codegen units and LTO. + +This flag is not useful for regular users, but it can be useful for debugging the backend. Codegen issues commonly only manifest under specific circumstances, e.g. if multiple codegen units are used and ThinLTO is enabled. Serialization of these threaded configurations makes the use of LLVM debugging facilities easier, by avoiding the interleaving of output. diff --git a/src/doc/unstable-book/src/compiler-flags/path-options.md b/src/doc/unstable-book/src/compiler-flags/path-options.md new file mode 100644 index 000000000..0786ef1f1 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/path-options.md @@ -0,0 +1,11 @@ +# `--print` Options + +The behavior of the `--print` flag can be modified by optionally be specifying a filepath +for each requested information kind, in the format `--print KIND=PATH`, just like for +`--emit`. When a path is specified, information will be written there instead of to stdout. + +This is unstable feature, so you have to provide `-Zunstable-options` to enable it. + +## Examples + +`rustc main.rs -Z unstable-options --print cfg=cfgs.txt` diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md index ce894ce6a..2dd1f6f8e 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md +++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md @@ -1,4 +1,4 @@ -# `profile-sample-use +# `profile-sample-use` --- diff --git a/src/doc/unstable-book/src/language-features/abi-thiscall.md b/src/doc/unstable-book/src/language-features/abi-thiscall.md deleted file mode 100644 index 73bc6eacf..000000000 --- a/src/doc/unstable-book/src/language-features/abi-thiscall.md +++ /dev/null @@ -1,12 +0,0 @@ -# `abi_thiscall` - -The tracking issue for this feature is: [#42202] - -[#42202]: https://github.com/rust-lang/rust/issues/42202 - ------------------------- - -The MSVC ABI on x86 Windows uses the `thiscall` calling convention for C++ -instance methods by default; it is identical to the usual (C) calling -convention on x86 Windows except that the first parameter of the method, -the `this` pointer, is passed in the ECX register. diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index c634dc50d..968c9bb4e 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -17,6 +17,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - AVR - MSP430 - M68k +- CSKY - s390x ## Register classes @@ -46,6 +47,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `reg` | `d[0-7]`, `a[0-7]` | `r` | | M68k | `reg_data` | `d[0-7]` | `d` | | M68k | `reg_addr` | `a[0-3]` | `a` | +| CSKY | `reg` | `r[0-31]` | `r` | +| CSKY | `freg` | `f[0-31]` | `f` | | s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | | s390x | `freg` | `f[0-15]` | `f` | @@ -79,6 +82,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | MSP430 | `reg` | None | `i8`, `i16` | | M68k | `reg`, `reg_addr` | None | `i16`, `i32` | | M68k | `reg_data` | None | `i8`, `i16`, `i32` | +| CSKY | `reg` | None | `i8`, `i16`, `i32` | +| CSKY | `freg` | None | `f32`, | | s390x | `reg` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | @@ -102,6 +107,17 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `a5` | `bp` | | M68k | `a6` | `fp` | | M68k | `a7` | `sp`, `usp`, `ssp`, `isp` | +| CSKY | `r[0-3]` | `a[0-3]` | +| CSKY | `r[4-11]` | `l[0-7]` | +| CSKY | `r[12-13]` | `t[0-1]` | +| CSKY | `r14` | `sp` | +| CSKY | `r15` | `lr` | +| CSKY | `r[16-17]` | `l[8-9]` | +| CSKY | `r[18-25]` | `t[2-9]` | +| CSKY | `r28` | `rgb` | +| CSKY | `r29` | `rtb` | +| CSKY | `r30` | `svbr` | +| CSKY | `r31` | `tls` | > **Notes**: > - TI does not mandate a frame pointer for MSP430, but toolchains are allowed @@ -123,6 +139,13 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | |MSP430 | `r0`, `r2`, `r3` | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to. | | M68k | `a4`, `a5` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r7`, `r28` | Used internally by LLVM for the base pointer and global base pointer. | +| CSKY | `r8` | Used internally by LLVM for the frame pointer. | +| CSKY | `r14` | Used internally by LLVM for the stack pointer. | +| CSKY | `r15` | This is the link register. | +| CSKY | `r[26-30]` | Reserved by its ABI. | +| CSKY | `r31` | This is the TLS register. | + ## Template modifiers @@ -139,6 +162,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `freg` | None | `0` | None | | s390x | `reg` | None | `%r0` | None | | s390x | `freg` | None | `%f0` | None | +| CSKY | `reg` | None | `r0` | None | +| CSKY | `freg` | None | `f0` | None | # Flags covered by `preserves_flags` diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index ea9bace6d..8fa8f567d 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -17,6 +17,7 @@ via a declaration like ```rust #![feature(intrinsics)] +#![allow(internal_features)] # fn main() {} extern "rust-intrinsic" { diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index f4bc18bc7..9e20662ff 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -9,25 +9,60 @@ functionality that isn't hard-coded into the language, but is implemented in libraries, with a special marker to tell the compiler it exists. The marker is the attribute `#[lang = "..."]` and there are various different values of `...`, i.e. various different 'lang -items'. +items'. Most of them can only be defined once. -For example, `Box` pointers require a lang item for allocation. -A freestanding program that uses the `Box` -sugar for dynamic allocations via `malloc` and `free`: +Lang items are loaded lazily by the compiler; e.g. if one never uses `Box` +then there is no need to define a function for `exchange_malloc`. +`rustc` will emit an error when an item is needed but not found in the current +crate or any that it depends on. + +Some features provided by lang items: + +- overloadable operators via traits: the traits corresponding to the + `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all + marked with lang items; those specific four are `eq`, `partial_ord`, + `deref`/`deref_mut`, and `add` respectively. +- panicking: the `panic` and `panic_impl` lang items, among others. +- stack unwinding: the lang item `eh_personality` is a function used by the + failure mechanisms of the compiler. This is often mapped to GCC's personality + function (see the [`std` implementation][personality] for more information), + but programs which don't trigger a panic can be assured that this function is + never called. Additionally, a `eh_catch_typeinfo` static is needed for certain + targets which implement Rust panics on top of C++ exceptions. +- the traits in `core::marker` used to indicate types of + various kinds; e.g. lang items `sized`, `sync` and `copy`. +- memory allocation, see below. + +Most lang items are defined by `core`, but if you're trying to build +an executable without the `std` crate, you might run into the need +for lang item definitions. + +[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs + +## Example: Implementing a `Box` + +`Box` pointers require two lang items: one for the type itself and one for +allocation. A freestanding program that uses the `Box` sugar for dynamic +allocations via `malloc` and `free`: ```rust,ignore (libc-is-finicky) -#![feature(lang_items, start, libc, core_intrinsics, rustc_private, rustc_attrs)] +#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] +#![allow(internal_features)] #![no_std] + +extern crate libc; +extern crate unwind; + +use core::ffi::c_void; use core::intrinsics; use core::panic::PanicInfo; use core::ptr::NonNull; -extern crate libc; - +pub struct Global; // the global allocator struct Unique<T>(NonNull<T>); #[lang = "owned_box"] -pub struct Box<T>(Unique<T>); +pub struct Box<T, A = Global>(Unique<T>, A); impl<T> Box<T> { pub fn new(x: T) -> Self { @@ -36,24 +71,26 @@ impl<T> Box<T> { } } +impl<T, A> Drop for Box<T, A> { + fn drop(&mut self) { + unsafe { + libc::free(self.0.0.as_ptr() as *mut c_void); + } + } +} + #[lang = "exchange_malloc"] unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { - let p = libc::malloc(size as libc::size_t) as *mut u8; + let p = libc::malloc(size) as *mut u8; // Check if `malloc` failed: - if p as usize == 0 { + if p.is_null() { intrinsics::abort(); } p } -impl<T> Drop for Box<T> { - fn drop(&mut self) { - libc::free(self.0.0.0 as *mut libc::c_void) - } -} - #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { let _x = Box::new(1); @@ -61,245 +98,18 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { 0 } -#[lang = "eh_personality"] extern fn rust_eh_personality() {} -#[lang = "panic_impl"] extern fn rust_begin_panic(_info: &PanicInfo) -> ! { intrinsics::abort() } -#[no_mangle] pub extern fn rust_eh_register_frames () {} -#[no_mangle] pub extern fn rust_eh_unregister_frames () {} -``` - -Note the use of `abort`: the `exchange_malloc` lang item is assumed to -return a valid pointer, and so needs to do the check internally. - -Other features provided by lang items include: - -- overloadable operators via traits: the traits corresponding to the - `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all - marked with lang items; those specific four are `eq`, `ord`, - `deref`, and `add` respectively. -- stack unwinding and general failure; the `eh_personality`, - `panic` and `panic_bounds_check` lang items. -- the traits in `std::marker` used to indicate types of - various kinds; lang items `send`, `sync` and `copy`. -- the marker types and variance indicators found in - `std::marker`; lang items `covariant_type`, - `contravariant_lifetime`, etc. - -Lang items are loaded lazily by the compiler; e.g. if one never uses -`Box` then there is no need to define a function for `exchange_malloc`. -`rustc` will emit an error when an item is needed -but not found in the current crate or any that it depends on. - -Most lang items are defined by `libcore`, but if you're trying to build -an executable without the standard library, you'll run into the need -for lang items. The rest of this page focuses on this use-case, even though -lang items are a bit broader than that. - -### Using libc - -In order to build a `#[no_std]` executable we will need libc as a dependency. -We can specify this using our `Cargo.toml` file: - -```toml -[dependencies] -libc = { version = "0.2.14", default-features = false } -``` - -Note that the default features have been disabled. This is a critical step - -**the default features of libc include the standard library and so must be -disabled.** - -### Writing an executable without stdlib - -Controlling the entry point is possible in two ways: the `#[start]` attribute, -or overriding the default shim for the C `main` function with your own. - -The function marked `#[start]` is passed the command line parameters -in the same format as C: - -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. #[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} +fn rust_eh_personality() {} -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} +#[panic_handler] +fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } ``` -To override the compiler-inserted `main` shim, one has to disable it -with `#![no_main]` and then create the appropriate symbol with the -correct ABI and the correct name, which requires overriding the -compiler's name mangling too: - -```rust,ignore (libc-is-finicky) -#![feature(lang_items, core_intrinsics, rustc_private)] -#![feature(start)] -#![no_std] -#![no_main] -use core::intrinsics; -use core::panic::PanicInfo; - -// Pull in the system libc library for what crt0.o likely requires. -extern crate libc; - -// Entry point for this program. -#[no_mangle] // ensure that this symbol is called `main` in the output -pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { - 0 -} - -// These functions are used by the compiler, but not -// for a bare-bones hello world. These are normally -// provided by libstd. -#[lang = "eh_personality"] -#[no_mangle] -pub extern fn rust_eh_personality() { -} - -#[lang = "panic_impl"] -#[no_mangle] -pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { - unsafe { intrinsics::abort() } -} -``` - -In many cases, you may need to manually link to the `compiler_builtins` crate -when building a `no_std` binary. You may observe this via linker error messages -such as "```undefined reference to `__rust_probestack'```". - -## More about the language items - -The compiler currently makes a few assumptions about symbols which are -available in the executable to call. Normally these functions are provided by -the standard library, but without it you must define your own. These symbols -are called "language items", and they each have an internal name, and then a -signature that an implementation must conform to. - -The first of these functions, `rust_eh_personality`, is used by the failure -mechanisms of the compiler. This is often mapped to GCC's personality function -(see the [libstd implementation][unwind] for more information), but crates -which do not trigger a panic can be assured that this function is never -called. The language item's name is `eh_personality`. - -[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs - -The second function, `rust_begin_panic`, is also used by the failure mechanisms of the -compiler. When a panic happens, this controls the message that's displayed on -the screen. While the language item's name is `panic_impl`, the symbol name is -`rust_begin_panic`. - -Finally, a `eh_catch_typeinfo` static is needed for certain targets which -implement Rust panics on top of C++ exceptions. +Note the use of `abort`: the `exchange_malloc` lang item is assumed to +return a valid pointer, and so needs to do the check internally. ## List of all language items -This is a list of all language items in Rust along with where they are located in -the source code. +An up-to-date list of all language items can be found [here] in the compiler code. -- Primitives - - `i8`: `libcore/num/mod.rs` - - `i16`: `libcore/num/mod.rs` - - `i32`: `libcore/num/mod.rs` - - `i64`: `libcore/num/mod.rs` - - `i128`: `libcore/num/mod.rs` - - `isize`: `libcore/num/mod.rs` - - `u8`: `libcore/num/mod.rs` - - `u16`: `libcore/num/mod.rs` - - `u32`: `libcore/num/mod.rs` - - `u64`: `libcore/num/mod.rs` - - `u128`: `libcore/num/mod.rs` - - `usize`: `libcore/num/mod.rs` - - `f32`: `libstd/f32.rs` - - `f64`: `libstd/f64.rs` - - `char`: `libcore/char.rs` - - `slice`: `liballoc/slice.rs` - - `str`: `liballoc/str.rs` - - `const_ptr`: `libcore/ptr.rs` - - `mut_ptr`: `libcore/ptr.rs` - - `unsafe_cell`: `libcore/cell.rs` -- Runtime - - `start`: `libstd/rt.rs` - - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) - - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - - `panic`: `libcore/panicking.rs` - - `panic_bounds_check`: `libcore/panicking.rs` - - `panic_impl`: `libcore/panicking.rs` - - `panic_impl`: `libstd/panicking.rs` -- Allocations - - `owned_box`: `liballoc/boxed.rs` - - `exchange_malloc`: `liballoc/heap.rs` -- Operands - - `not`: `libcore/ops/bit.rs` - - `bitand`: `libcore/ops/bit.rs` - - `bitor`: `libcore/ops/bit.rs` - - `bitxor`: `libcore/ops/bit.rs` - - `shl`: `libcore/ops/bit.rs` - - `shr`: `libcore/ops/bit.rs` - - `bitand_assign`: `libcore/ops/bit.rs` - - `bitor_assign`: `libcore/ops/bit.rs` - - `bitxor_assign`: `libcore/ops/bit.rs` - - `shl_assign`: `libcore/ops/bit.rs` - - `shr_assign`: `libcore/ops/bit.rs` - - `deref`: `libcore/ops/deref.rs` - - `deref_mut`: `libcore/ops/deref.rs` - - `index`: `libcore/ops/index.rs` - - `index_mut`: `libcore/ops/index.rs` - - `add`: `libcore/ops/arith.rs` - - `sub`: `libcore/ops/arith.rs` - - `mul`: `libcore/ops/arith.rs` - - `div`: `libcore/ops/arith.rs` - - `rem`: `libcore/ops/arith.rs` - - `neg`: `libcore/ops/arith.rs` - - `add_assign`: `libcore/ops/arith.rs` - - `sub_assign`: `libcore/ops/arith.rs` - - `mul_assign`: `libcore/ops/arith.rs` - - `div_assign`: `libcore/ops/arith.rs` - - `rem_assign`: `libcore/ops/arith.rs` - - `eq`: `libcore/cmp.rs` - - `ord`: `libcore/cmp.rs` -- Functions - - `fn`: `libcore/ops/function.rs` - - `fn_mut`: `libcore/ops/function.rs` - - `fn_once`: `libcore/ops/function.rs` - - `generator_state`: `libcore/ops/generator.rs` - - `generator`: `libcore/ops/generator.rs` -- Other - - `coerce_unsized`: `libcore/ops/unsize.rs` - - `drop`: `libcore/ops/drop.rs` - - `drop_in_place`: `libcore/ptr.rs` - - `clone`: `libcore/clone.rs` - - `copy`: `libcore/marker.rs` - - `send`: `libcore/marker.rs` - - `sized`: `libcore/marker.rs` - - `unsize`: `libcore/marker.rs` - - `sync`: `libcore/marker.rs` - - `phantom_data`: `libcore/marker.rs` - - `discriminant_kind`: `libcore/marker.rs` - - `freeze`: `libcore/marker.rs` - - `debug_trait`: `libcore/fmt/mod.rs` - - `non_zero`: `libcore/nonzero.rs` - - `arc`: `liballoc/sync.rs` - - `rc`: `liballoc/rc.rs` +[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs diff --git a/src/doc/unstable-book/src/language-features/start.md b/src/doc/unstable-book/src/language-features/start.md new file mode 100644 index 000000000..09e4875a2 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/start.md @@ -0,0 +1,59 @@ +# `start` + +The tracking issue for this feature is: [#29633] + +[#29633]: https://github.com/rust-lang/rust/issues/29633 + +------------------------ + +Allows you to mark a function as the entry point of the executable, which is +necessary in `#![no_std]` environments. + +The function marked `#[start]` is passed the command line parameters in the same +format as the C main function (aside from the integer types being used). +It has to be non-generic and have the following signature: + +```rust,ignore (only-for-syntax-highlight) +# let _: +fn(isize, *const *const u8) -> isize +# ; +``` + +This feature should not be confused with the `start` *lang item* which is +defined by the `std` crate and is written `#[lang = "start"]`. + +## Usage together with the `std` crate + +`#[start]` can be used in combination with the `std` crate, in which case the +normal `main` function (which would get called from the `std` crate) won't be +used as an entry point. +The initialization code in `std` will be skipped this way. + +Example: + +```rust +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + 0 +} +``` + +Unwinding the stack past the `#[start]` function is currently considered +Undefined Behavior (for any unwinding implementation): + +```rust,ignore (UB) +#![feature(start)] + +#[start] +fn start(_argc: isize, _argv: *const *const u8) -> isize { + std::panic::catch_unwind(|| { + panic!(); // panic safely gets caught or safely aborts execution + }); + + panic!(); // UB! + + 0 +} +``` diff --git a/src/doc/unstable-book/src/library-features/default-free-fn.md b/src/doc/unstable-book/src/library-features/default-free-fn.md deleted file mode 100644 index bafc9ac4d..000000000 --- a/src/doc/unstable-book/src/library-features/default-free-fn.md +++ /dev/null @@ -1,47 +0,0 @@ -# `default_free_fn` - -The tracking issue for this feature is: [#73014] - -[#73014]: https://github.com/rust-lang/rust/issues/73014 - ------------------------- - -Adds a free `default()` function to the `std::default` module. This function -just forwards to [`Default::default()`], but may remove repetition of the word -"default" from the call site. - -[`Default::default()`]: ../../std/default/trait.Default.html#tymethod.default - -Here is an example: - -```rust -#![feature(default_free_fn)] -use std::default::default; - -#[derive(Default)] -struct AppConfig { - foo: FooConfig, - bar: BarConfig, -} - -#[derive(Default)] -struct FooConfig { - foo: i32, -} - -#[derive(Default)] -struct BarConfig { - bar: f32, - baz: u8, -} - -fn main() { - let options = AppConfig { - foo: default(), - bar: BarConfig { - bar: 10.1, - ..default() - }, - }; -} -``` |