From bf5adeb8d8ec87b89c9ce6c73dcc314983bdb4f5 Mon Sep 17 00:00:00 2001 From: Redddy Date: Thu, 12 Mar 2026 17:41:14 +0900 Subject: [PATCH 01/37] Add reference link for HIR ID validator --- src/doc/rustc-dev-guide/src/hir/lowering.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/hir/lowering.md b/src/doc/rustc-dev-guide/src/hir/lowering.md index c0057a69c10d..b8c757feccc3 100644 --- a/src/doc/rustc-dev-guide/src/hir/lowering.md +++ b/src/doc/rustc-dev-guide/src/hir/lowering.md @@ -16,7 +16,7 @@ of such structures include but are not limited to * Converted to a virtual `existential type` declaration Lowering needs to uphold several invariants in order to not trigger the -sanity checks in `compiler/rustc_passes/src/hir_id_validator.rs`: +sanity checks in [`compiler/rustc_passes/src/hir_id_validator.rs`][hir_id_validator]: 1. A `HirId` must be used if created. So if you use the `lower_node_id`, you *must* use the resulting `NodeId` or `HirId` (either is fine, since @@ -33,6 +33,8 @@ sanity checks in `compiler/rustc_passes/src/hir_id_validator.rs`: which produces both a new `NodeId` as well as automatically lowering it for you so you also get the `HirId`. +[hir_id_validator]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_passes/src/hir_id_validator.rs + If you are creating new `DefId`s, since each `DefId` needs to have a corresponding `NodeId`, it is advisable to add these `NodeId`s to the `AST` so you don't have to generate new ones during lowering. This has From df4242f8efd518d622be20d4131e5952ab292404 Mon Sep 17 00:00:00 2001 From: Redddy Date: Thu, 19 Mar 2026 11:20:57 +0900 Subject: [PATCH 02/37] Document AST lowering implementation --- src/doc/rustc-dev-guide/src/hir/lowering.md | 25 +++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/hir/lowering.md b/src/doc/rustc-dev-guide/src/hir/lowering.md index b8c757feccc3..b7d0293bede9 100644 --- a/src/doc/rustc-dev-guide/src/hir/lowering.md +++ b/src/doc/rustc-dev-guide/src/hir/lowering.md @@ -15,6 +15,24 @@ of such structures include but are not limited to * Existential `impl Trait` * Converted to a virtual `existential type` declaration +The implementation of AST lowering is in the [`rustc_ast_lowering`] crate. +The entry point is [`lower_to_hir`], which retrieves the post-expansion AST +and resolver data from [`TyCtxt`] and builds the [`hir::Crate`] for the whole crate. + +Lowering is organized around HIR owners. [`lower_to_hir`] first indexes the +crate and then [`ItemLowerer::lower_node`] lowers each crate, item, associated +item, and foreign item. + +Most of the lowering logic lives on [`LoweringContext`]. The implementation is +split across multiple files in the [`rustc_ast_lowering`] crate such as `item.rs`, +`expr.rs`, `pat.rs`, `path.rs`, and others, but they all share the same [`LoweringContext`] +state and ID‑lowering machinery. + +Each owner is lowered in its own [`with_hir_id_owner`] scope. This is why the +`HirId` invariants below matter: `lower_node_id` maps AST `NodeId`s into the +current owner, while `next_id` creates fresh HIR-only nodes introduced during +desugaring. + Lowering needs to uphold several invariants in order to not trigger the sanity checks in [`compiler/rustc_passes/src/hir_id_validator.rs`][hir_id_validator]: @@ -33,6 +51,13 @@ sanity checks in [`compiler/rustc_passes/src/hir_id_validator.rs`][hir_id_valida which produces both a new `NodeId` as well as automatically lowering it for you so you also get the `HirId`. +[`rustc_ast_lowering`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/index.html +[`lower_to_hir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/fn.lower_to_hir.html +[`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html +[`hir::Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Crate.html +[`ItemLowerer::lower_node`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/item/struct.ItemLowerer.html +[`LoweringContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/struct.LoweringContext.html +[`with_hir_id_owner`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/struct.LoweringContext.html#method.with_hir_id_owner [hir_id_validator]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_passes/src/hir_id_validator.rs If you are creating new `DefId`s, since each `DefId` needs to have a From 126c923eadc9d64dd3be54c9ef664fcf8452d1dd Mon Sep 17 00:00:00 2001 From: malezjaa Date: Sat, 21 Mar 2026 09:29:30 +0100 Subject: [PATCH 03/37] new on_unimplemented match values --- src/doc/rustc-dev-guide/src/diagnostics.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index bdd7a3dfa9b8..98f890a0f02e 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -964,6 +964,7 @@ The compiler can provide several values to match on, for example: - references to said slices and arrays. - `"fn"`, `"unsafe fn"` or `"#[target_feature] fn"` when self is a function. - `"{integer}"` and `"{float}"` if the type is a number but we haven't inferred it yet. + - `"{struct}"`, `"{enum}"` and `"{union}"` to match self as an ADT - combinations of the above, like `"[{integral}; _]"`. For example, the `Iterator` trait can be filtered in the following way: From 2c09d28e4b44218d07371d9ccbe266d39b292055 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Tue, 24 Mar 2026 00:23:51 +0100 Subject: [PATCH 04/37] start paragraph with upper case --- src/doc/rustc-dev-guide/src/diagnostics/lintstore.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md index cda975a9a15e..11a7a573f38b 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/lintstore.md @@ -20,7 +20,7 @@ which boils down to a static with type [`&rustc_lint_defs::Lint`] as the macro is somewhat unwieldy to add new fields to, like all macros). -we lint against direct declarations without the use of the macro. +We lint against direct declarations without the use of the macro. Lint declarations don't carry any "state" - they are merely global identifiers and descriptions of lints. From 6a4a3b3436d31e455a8b4a7c91a3c14da9f642f7 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 26 Mar 2026 10:07:54 -0400 Subject: [PATCH 05/37] Update information about adding unit tests - Specifically guide new contributors that unit tests for `core` and `alloc` do not belong within those crates and instead belong in the `coretests` and `alloctests` crates. - Also add some information about which `lib.rs` file needs the unstable feature declarations --- src/doc/rustc-dev-guide/src/tests/adding.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index ebbbb1cfc0d3..5471900e41d3 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -17,8 +17,12 @@ guidelines: - The majority of standard library tests are written as doctests, which illustrate and exercise typical API behavior. - Additional [unit tests](intro.md#package-tests) should go in - `library/${crate}/tests` (where `${crate}` is usually `core`, `alloc`, or - `std`). + `library/${crate}/tests` (where `${crate}` is usually `std`). + - Tests for the `alloc` or `core` crates must go within their respective + `library/${crate}tests/tests` folder. + - NOTE: That when adding unit tests for unstable features the `#![feature(...)]` + declaration **must** be added to `library/${crate}tests/tests/lib.rs` and not to + `library/${crate}tests/lib.rs`. - If the code is part of an isolated system, and you are not testing compiler output, consider using a [unit or integration test](intro.md#package-tests). - Need to run rustdoc? Prefer a `rustdoc` or `rustdoc-ui` test. Occasionally From 04cec1e24fa543bb84064fc0a6eaca40997b36f4 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 26 Mar 2026 10:56:35 -0400 Subject: [PATCH 06/37] Tweak wording of adding new tests guide --- src/doc/rustc-dev-guide/src/tests/adding.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index 5471900e41d3..10483265c468 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -18,10 +18,9 @@ guidelines: illustrate and exercise typical API behavior. - Additional [unit tests](intro.md#package-tests) should go in `library/${crate}/tests` (where `${crate}` is usually `std`). - - Tests for the `alloc` or `core` crates must go within their respective - `library/${crate}tests/tests` folder. + - Tests for the `alloc` or `core` crates must go in separate crates: `alloctests` or `coretests` respectively. - NOTE: That when adding unit tests for unstable features the `#![feature(...)]` - declaration **must** be added to `library/${crate}tests/tests/lib.rs` and not to + declaration must be added to `library/${crate}tests/tests/lib.rs` and not to `library/${crate}tests/lib.rs`. - If the code is part of an isolated system, and you are not testing compiler output, consider using a [unit or integration test](intro.md#package-tests). From c9d64633aa82f2790cd993fb6ac4b71be11ffb01 Mon Sep 17 00:00:00 2001 From: apiraino Date: Thu, 26 Mar 2026 17:54:28 +0100 Subject: [PATCH 07/37] Mention GPU notification group --- src/doc/rustc-dev-guide/src/SUMMARY.md | 7 ++++--- .../src/notification-groups/about.md | 1 + .../src/notification-groups/gpu-target.md | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 22f4da50b62c..0aab04530c78 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -72,6 +72,7 @@ - [WASI](notification-groups/wasi.md) - [WebAssembly](notification-groups/wasm.md) - [Windows](notification-groups/windows.md) + - [GPU target](notification-groups/gpu-target.md) - [Licenses](./licenses.md) - [Editions](guides/editions.md) @@ -100,9 +101,9 @@ - [Parallel compilation](./parallel-rustc.md) - [Rustdoc internals](./rustdoc-internals.md) - [Search](./rustdoc-internals/search.md) - - [The `rustdoc-html` test suite](./rustdoc-internals/rustdoc-html-test-suite.md) - - [The `rustdoc-gui` test suite](./rustdoc-internals/rustdoc-gui-test-suite.md) - - [The `rustdoc-json` test suite](./rustdoc-internals/rustdoc-json-test-suite.md) + - [The `rustdoc-html` test suite](./rustdoc-internals/rustdoc-html-test-suite.md) + - [The `rustdoc-gui` test suite](./rustdoc-internals/rustdoc-gui-test-suite.md) + - [The `rustdoc-json` test suite](./rustdoc-internals/rustdoc-json-test-suite.md) - [GPU offload internals](./offload/internals.md) - [Installation](./offload/installation.md) - [Usage](./offload/usage.md) 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 86797b1e0bb5..28c836dc4dba 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/about.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/about.md @@ -28,6 +28,7 @@ Here's the list of the notification groups: - [WebAssembly](./wasm.md) - [Windows](./windows.md) - [Rust for Linux](./rust-for-linux.md) +- [GPU target](./gpu-target.md) ## What issues are a good fit for notification groups? diff --git a/src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md b/src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md new file mode 100644 index 000000000000..b46233e98b41 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md @@ -0,0 +1,18 @@ +# GPU target notification group + +**Github Label:** None
+**Ping command:** `@rustbot ping gpu-target` + +This notification group deals with linker related issues and their integration +within the compiler. + +The group also has an associated Zulip stream ([`#t-compiler/linker`]) +where people can go to ask questions and discuss GPU-related topics and issues. + +if you're interested in participating, feel free to sign up for this group! To +do so, open a PR against the [rust-lang/team] repository and add your GitHub +user to [this file][gpu-target-team]. + +[`#t-compiler/linker`]: https://rust-lang.zulipchat.com/#narrow/channel/585172-t-compiler.2Flinker +[rust-lang/team]: https://github.com/rust-lang/team +[gpu-target-team]: https://github.com/rust-lang/team/blob/main/teams/gpu-target.toml From 6eb9ff60bdcb611b19143c1c00947fe81a39f363 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Sat, 28 Mar 2026 10:36:14 +0100 Subject: [PATCH 08/37] Explain how nested generic args are represented --- .../src/ty-module/generic-arguments.md | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md index 3339d3114251..3d6124c2ec97 100644 --- a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md +++ b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md @@ -126,3 +126,35 @@ For the `MyStruct` written in the `Foo` type alias, we would represent it in - There would be an `AdtDef` (and corresponding `DefId`) for `MyStruct`. - There would be a `GenericArgs` containing the list `[GenericArgKind::Type(Ty(u32))]` - And finally a `TyKind::Adt` with the `AdtDef` and `GenericArgs` listed above. + +## Nested generic args + +```rust +struct MyStruct(T); + +impl MyStruct { + fn func() {} +} + +fn main() { + MyStruct::::func::(); +} +``` + +The construct `MyStruct::::func::` is represented by a tuple: a DefId pointing at `func`, and then a +`GenericArgs` list that "walks" all containing generic parameters - in this case, the list would be `[u32, bool, char]`. + +The [`ty::Generics`] type (returned by the [`generics_of`] query) contains the information of how a nested hierarchy +gets flattened down to a list, and lets you figure out which index in the `GenericArgs` list corresponds to which +generic. The general theme of how it works is outermost to innermost (`T` before `T2` in the example), left to right +(`T2` before `T3`), but there are several complications: + +- `Self` is sometimes a generic parameter, and should sometimes be included in the list. +- Only early-bound generic parameters are included, [late-bound generics] are not. +- ... and more... + +Check out [`ty::Generics`] for exact specifics on how the flattening works. + +[`ty::Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html +[`generics_of`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.generics_of +[late-bound generics]: ../early-late-parameters.md From 99f0fd9405546a4016b6f24e69de2cfcce8a92fd Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 28 Mar 2026 21:39:06 +0100 Subject: [PATCH 09/37] reflow sentence regarding early bounds --- src/doc/rustc-dev-guide/src/early-late-parameters.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/early-late-parameters.md b/src/doc/rustc-dev-guide/src/early-late-parameters.md index d78d5331baac..4dd4d74174eb 100644 --- a/src/doc/rustc-dev-guide/src/early-late-parameters.md +++ b/src/doc/rustc-dev-guide/src/early-late-parameters.md @@ -130,9 +130,9 @@ f(&String::new()); f(&String::new()); ``` +The lifetime parameter on `foo` being early bound requires all callers of `f` to provide a borrow with the same lifetime. In this example, we call `foo`'s function item type twice, each time with a borrow of a temporary. -These two borrows could not possibly have lifetimes that overlap as the temporaries are only alive during the function call, not after. -The lifetime parameter on `foo` being early bound requires all callers of `f` to provide a borrow with the same lifetime, as this is not possible the borrow checker errors. +These two borrows could not possibly have lifetimes that overlap as the temporaries are only alive during the function call, not after, so we get a compilation error. If the lifetime parameter on `foo` was late bound, this would be able to compile as each caller could provide a different lifetime argument for its borrow. See the following example, which demonstrates this using the `bar` function defined above: From 74b3d554b364a0304c80b73cf856736b67f26c69 Mon Sep 17 00:00:00 2001 From: Redddy Date: Sun, 29 Mar 2026 13:52:40 +0900 Subject: [PATCH 10/37] Fix rustc_hir::Crate links --- src/doc/rustc-dev-guide/src/hir.md | 2 +- src/doc/rustc-dev-guide/src/rustdoc-internals.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md index 0b341a40f1dd..250b02902377 100644 --- a/src/doc/rustc-dev-guide/src/hir.md +++ b/src/doc/rustc-dev-guide/src/hir.md @@ -35,7 +35,7 @@ data structure basically just contains the root module, the HIR `Crate` structure contains a number of maps and other things that serve to organize the content of the crate for easier access. -[`Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Crate.html +[`Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/struct.Crate.html For example, the contents of individual items (e.g. modules, functions, traits, impls, etc) in the HIR are not immediately diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index 989a77290b6b..9fd05aa0b20d 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -48,7 +48,7 @@ The "entry point" to this module is The first step in [`clean::utils::krate`][ck1] is to invoke [`visit_ast::RustdocVisitor`] to process the module tree into an intermediate [`visit_ast::Module`]. This is the step that actually crawls the -[`rustc_hir::Crate`], normalizing various aspects of name resolution, such as: +[`rustc_middle::hir::Crate`], normalizing various aspects of name resolution, such as: * handling `#[doc(inline)]` and `#[doc(no_inline)]` * handling import globs and cycles, so there are no duplicates or infinite @@ -79,7 +79,7 @@ which describe the publicly-documentable items in the target crate. [`core.rs`]: https://github.com/rust-lang/rust/blob/HEAD/src/librustdoc/core.rs [`Item`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/clean/types/struct.Item.html [`run_global_ctxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/core/fn.run_global_ctxt.html -[`rustc_hir::Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Crate.html +[`rustc_middle::hir::Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/struct.Crate.html [`rustdoc::core::DocContext`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/core/struct.DocContext.html [`rustdoc::core::run_global_ctxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/core/fn.run_global_ctxt.html [`visit_ast::Module`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/visit_ast/struct.Module.html From bb219348703e7edbf5d4aaa84c6086ed0a730d6c Mon Sep 17 00:00:00 2001 From: Redddy Date: Mon, 30 Mar 2026 13:48:03 +0900 Subject: [PATCH 11/37] Add explanation of default flags for UI tests --- src/doc/rustc-dev-guide/src/tests/ui.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 7332d1fb3851..d90240af2591 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -636,6 +636,13 @@ but not `tests/rustdoc-ui`) will specify - `-A unused` - `-W unused_attributes` (since these tend to be interesting for ui tests) - `-A internal_features` +- `-A incomplete_features` +- `-A unused_parens` +- `-A unused_braces` + +For more details, see [runtest]. + +[runtest]: https://github.com/rust-lang/rust/blob/HEAD/src/tools/compiletest/src/runtest.rs If: From 10d28220fc34feea91edad42e622eb806bee2e4f Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 30 Mar 2026 11:10:46 +0200 Subject: [PATCH 12/37] add chapter on projection vs trait split --- src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + .../src/traits/separate-projection-bounds.md | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 22f4da50b62c..b86c91f88fc1 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -189,6 +189,7 @@ - [Significant changes and quirks](./solve/significant-changes.md) - [Sharing the trait solver with rust-analyzer](./solve/sharing-crates-with-rust-analyzer.md) - [`Unsize` and `CoerceUnsized` traits](./traits/unsize.md) + - [Having separate `Trait` and `Projection` bounds](./traits/separate-projection-bounds.md) - [Variance](./variance.md) - [Coherence checking](./coherence.md) - [HIR Type checking](./hir-typeck/summary.md) diff --git a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md new file mode 100644 index 000000000000..95b91fd6ecfc --- /dev/null +++ b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md @@ -0,0 +1,41 @@ +# Having separate `Trait` and `Projection` bounds + +Given `T: Foo` where-bound, we currently lower it to a `Trait(Foo)` and separate `Projection(::AssocA, u32)` and `Projection(::AssocB, i32)` bounds. Why do we not represent this as a single `Trait(Foo[T], [AssocA = u32, AssocB = u32]` bound instead? + +The way we prove `Projection` bounds directly relies on proving the corresponding `Trait` bound: +- old solver: https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_trait_selection/src/traits/project.rs#L898 +- new solver: https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs#L37-L41 + +We may use a different candidate for norm than for the corresponding trait bound: +- https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-always-consider-aliasbound-candidates +- https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-prefer-orphaned-where-bounds + +There are also some other subtle reasons for why we can't do so. The most stupid is that for rigid aliases, trying to normalize them does not consider any lifetime constraints from proving the trait bound. This is necessary due to a lack of assumptions on binders - https://github.com/rust-lang/trait-system-refactor-initiative/issues/177 - and should be fixed longterm. + +A separate issue is that right now, fetching the `type_of` associated types for `Trait` goals or in shadowed `Projection` candidates can cause query cycles for RPITIT. See https://github.com/rust-lang/trait-system-refactor-initiative/issues/185. + +There are also slight differences between candidates for some of the builtin impls, these do all seem generally undesirable and I consider them to be bugs which would be fixed if we had a unified approach here. + +Finally, not having this split makes lowering where-clauses more annoying. With the current system having duplicate where-clauses is not an issue and it can easily happen when elaborating super trait bounds. We now need to make sure we merge all associated type constraints, e.g. + +```rust +trait Super { + type A; + type B; +} + +trait Trait: Super {} +// how to elaborate Trait +``` +Or even worse +```rust +trait Super<'a> { + type A; + type B; +} + +trait Trait<'a>: Super<'a, A = i32> {} +// how to elaborate +// T: Trait<'a> + for<'b> Super<'b, B = u32> +``` + From 4ffd0b5d2b838cb024405acbd7961c4e49d32040 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 30 Mar 2026 11:20:31 +0100 Subject: [PATCH 13/37] reword `Self` parameter bullet point --- src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md index 3d6124c2ec97..cbf7b2c682fc 100644 --- a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md +++ b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md @@ -149,7 +149,7 @@ gets flattened down to a list, and lets you figure out which index in the `Gener generic. The general theme of how it works is outermost to innermost (`T` before `T2` in the example), left to right (`T2` before `T3`), but there are several complications: -- `Self` is sometimes a generic parameter, and should sometimes be included in the list. +- Traits have an implicit `Self` generic parameter which is the first (i.e. 0th) generic parameter. Note that `Self` doesn't mean a generic parameter in all situations, see [Res::SelfTyAlias](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def/enum.Res.html#variant.SelfTyAlias) and [Res::SelfCtor](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def/enum.Res.html#variant.SelfCtor). - Only early-bound generic parameters are included, [late-bound generics] are not. - ... and more... From dab7d0abacdf52512000381ca4457ba7aeea2829 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 30 Mar 2026 13:17:15 +0200 Subject: [PATCH 14/37] cleanup --- .../src/traits/separate-projection-bounds.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md index 95b91fd6ecfc..07e88c37b0a2 100644 --- a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md @@ -2,13 +2,11 @@ Given `T: Foo` where-bound, we currently lower it to a `Trait(Foo)` and separate `Projection(::AssocA, u32)` and `Projection(::AssocB, i32)` bounds. Why do we not represent this as a single `Trait(Foo[T], [AssocA = u32, AssocB = u32]` bound instead? -The way we prove `Projection` bounds directly relies on proving the corresponding `Trait` bound: -- old solver: https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_trait_selection/src/traits/project.rs#L898 -- new solver: https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs#L37-L41 +The way we prove `Projection` bounds directly relies on proving the corresponding `Trait` bound: [old solver](https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_trait_selection/src/traits/project.rs#L898) [new solver](https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs#L37-L41). -We may use a different candidate for norm than for the corresponding trait bound: -- https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-always-consider-aliasbound-candidates -- https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-prefer-orphaned-where-bounds +It feels like it might make more sense to just have a single implementation which checks whether a trait is implemented and returns (a way to compute) its associated types. + +This is unfortunately quite difficult, as we may use a different candidate for norm than for the corresponding trait bound. See [alias-bound vs where-bound](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-always-consider-aliasbound-candidates) and [global where-bound vs impl](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-prefer-global-where-bounds-over-impls). There are also some other subtle reasons for why we can't do so. The most stupid is that for rigid aliases, trying to normalize them does not consider any lifetime constraints from proving the trait bound. This is necessary due to a lack of assumptions on binders - https://github.com/rust-lang/trait-system-refactor-initiative/issues/177 - and should be fixed longterm. From 20ce0f0488a57fe748c4c4187c11deb431eb86a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 1 Apr 2026 13:53:40 +0200 Subject: [PATCH 15/37] Fix rustc-pull CI workflow --- src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml index fd21b149db8f..0a2cfd1c8598 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml @@ -12,6 +12,7 @@ jobs: uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@main with: github-app-id: ${{ vars.APP_CLIENT_ID }} + pr-author: "workflows-rustc-dev-guide[bot]" zulip-stream-id: 196385 zulip-bot-email: "rustc-dev-guide-gha-notif-bot@rust-lang.zulipchat.com" pr-base-branch: main From 9a01adc4a09becd56b314b653fd34b275dc7ca68 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Thu, 2 Apr 2026 17:48:28 +0530 Subject: [PATCH 16/37] Change 'ConstValue::ByRef' to 'ConstValue::Indirect' inline with the rename in PR https://github.com/rust-lang/rust/pull/115764 --- src/doc/rustc-dev-guide/src/const-eval/interpret.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/const-eval/interpret.md b/src/doc/rustc-dev-guide/src/const-eval/interpret.md index 8487b2bed43a..afd6c4f4c07e 100644 --- a/src/doc/rustc-dev-guide/src/const-eval/interpret.md +++ b/src/doc/rustc-dev-guide/src/const-eval/interpret.md @@ -89,7 +89,7 @@ what is needed *during* const evaluation, while [`ConstValue`] is shaped by the needs of the remaining parts of the compiler that consume the results of const evaluation. As part of this conversion, for types with scalar values, even if the resulting [`Operand`] is `Indirect`, it will return an immediate -`ConstValue::Scalar(computed_value)` (instead of the usual `ConstValue::ByRef`). +`ConstValue::Scalar(computed_value)` (instead of the usual `ConstValue::Indirect`). This makes using the result much more efficient and also more convenient, as no further queries need to be executed in order to get at something as simple as a `usize`. @@ -110,7 +110,7 @@ The interpreter's outside-facing datastructures can be found in This is mainly the error enum and the [`ConstValue`] and [`Scalar`] types. A `ConstValue` can be either `Scalar` (a single `Scalar`, i.e., integer or thin pointer), `Slice` (to represent byte slices and strings, as needed for pattern -matching) or `ByRef`, which is used for anything else and refers to a virtual +matching) or `Indirect`, which is used for anything else and refers to a virtual allocation. These allocations can be accessed via the methods on `tcx.interpret_interner`. A `Scalar` is either some `Raw` integer or a pointer; see [the next section](#memory) for more on that. @@ -207,7 +207,7 @@ values. Although the main entry point to constant evaluation is the `tcx.const_eval_*` functions, there are additional functions in [rustc_const_eval/src/const_eval](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/index.html) -that allow accessing the fields of a `ConstValue` (`ByRef` or otherwise). You should +that allow accessing the fields of a `ConstValue` (`Indirect` or otherwise). You should never have to access an `Allocation` directly except for translating it to the compilation target (at the moment just LLVM). From 938b564bd41406a94044b8dfb6b5d4331ff52acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Mon, 4 Nov 2024 14:31:37 +0100 Subject: [PATCH 17/37] Extend and tweak the glossary --- .../rustc-dev-guide/src/appendix/glossary.md | 74 ++++++++++++------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 43935b12a238..30959f4b39e6 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -1,17 +1,22 @@ # Glossary -Term | Meaning -------------------------------------------------------|-------- +Term | Meaning +-----------------------------------------------|-------- +1-ZST | A *one-aligned [zero-sized type](#zst)*. A type of size zero with an [alignment][size-align] of one. arena, arena allocation | An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info. -AST | The _abstract syntax tree_ produced by the `rustc_ast` crate; reflects user syntax very closely. -APIT | An argument-position `impl Trait`. Also known as an anonymous type parameter. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#anonymous-type-parameters)). -binder | A _binder_ is a place where a variable or type is declared; for example, the `` is a binder for the generic type parameter `T` in `fn foo(..)`, and \|`a`\|` ...` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound). -`BodyId` | An identifier that refers to a specific body (definition of a function or constant) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). -bound variable | A _bound variable_ is one that is declared within an expression/term. For example, the variable `a` is bound within the closure expression \|`a`\|` a * 2`. See [the background chapter for more](./background.md#free-vs-bound) +AFIDT | Short for _async function in `dyn Trait`_. See also [AFIT](#afit). +AFIT | Short for _async function in trait_. They desugar to [RPITITs](#rpitit). +AST | The _abstract syntax tree_ (an [IR](#ir)) produced by the parser; reflects the surface / user syntax very closely. +APIT | Short for _argument-position `impl Trait`_. Also known as universial `impl Trait` (as opposed to existential) or anonymous type parameter. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#anonymous-type-parameters)). +ATPIT | Short for _associated-type-position `impl Trait`_. Also known as [ITIAT](#itiat). +binder | A _binder_ is a place where a variable or type is declared; for example, the `` is a binder for the type parameter `T` in `fn foo(..)`, `for<'a>` is a binder for the lifetime parameter `'a` and `\|a\| …` is a binder for the parameter `a`. See [the background chapter for more](./background.md#free-vs-bound). +body | The definition of a function or constant that contains "executable code". +`BodyId` | An identifier that refers to a specific [body](#body) in the crate. See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). +bound variable | A _bound variable_ is one that is declared within an expression or term (in the general sense). For example, the variable `a` is bound within the closure expression `\|a\| a * 2` and lifetime variable `'a` is bound within the type expression `for<'a> fn(&'a str) -> bool`. See [the background chapter for more](./background.md#free-vs-bound) codegen | Short for _code generation_. The code to translate MIR into LLVM IR. codegen unit | When we produce LLVM IR, we group the Rust code into a number of codegen units (sometimes abbreviated as CGUs). Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. ([see more](../backend/codegen.md)) completeness | A technical term in type theory, it means that every type-safe program also type-checks. Having both soundness and completeness is very hard, and usually soundness is more important. (see "soundness"). -control-flow graph | A representation of the control-flow of a program; see [the background chapter for more](./background.md#cfg) +control-flow graph, CFG | A representation of the control-flow of a program; see [the background chapter for more](./background.md#cfg) CTFE | Short for _compile-time function evaluation_, this is the ability of the compiler to evaluate `const fn`s at compile time. This is part of the compiler's constant evaluation system. ([see more](../const-eval.md)) `cx` | We tend to use _cx_ as an abbreviation for _context_. See also `tcx`, `infcx`, etc. `ctxt` | We also use _ctxt_ as an abbreviation for _context_, e.g. [`TyCtxt`](#TyCtxt). See also [cx](#cx) or [tcx](#tcx). @@ -23,14 +28,18 @@ Term | Meaning double pointer | A pointer with additional metadata. See [fat pointer](#fat-ptr) for more. drop glue | (Internal) compiler-generated instructions that handle calling the destructors (`Drop`) for data types. DST | Short for *dynamically-sized type*, this is a type for which the compiler cannot statically know the size in memory (e.g. `str` or `[u8]`). Such types don't implement `Sized` and cannot be allocated on the stack. They can only occur as the last field in a struct. They can only be used behind a pointer (e.g. `&str` or `&[u8]`). -early-bound lifetime | A lifetime region that is substituted at its definition site. Bound in an item's `Generics` and substituted/instantiated using a `GenericArgs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/region_kind/enum.RegionKind.html#bound-regions)) +early-bound lifetime | A lifetime / region that is substituted at its definition site. Bound in an item's `Generics` and substituted/instantiated using a `GenericArgs`. Contrast with **late-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/region_kind/enum.RegionKind.html#bound-regions)) effects | Right now only means const traits and `~const` bounds. ([see more](../effects.md)) empty type | See [uninhabited type](#ut). fat pointer | A two word value carrying the address of some value, along with some further information necessary to put the value to use. Rust includes two kinds of _fat pointers_: references to slices, and trait objects. A reference to a slice carries the starting address of the slice and its length. A trait object carries a value's address and a pointer to the trait's implementation appropriate to that value. "Fat pointers" are also known as "wide pointers", and "double pointers". -free variable | A _free variable_ is one that is not bound within an expression or term; see [the background chapter for more](./background.md#free-vs-bound) +free variable | A _free variable_ is one that is not bound within an expression or term (in the general sense); see [the background chapter for more](./background.md#free-vs-bound) +GAC | A _generic associated constant_, an associated constant with (own) generic parameters or a where-clause. Part of feature [`generic_const_items`] (GCI). +GAT | A _generic associated type_, an associated type that has (own) generic parameters or a where-clause. Introduced in [RFC 1598]. generics | The list of generic parameters defined on an item. There are three kinds of generic parameters: Type, lifetime and const parameters. -HIR | The _high-level [IR](#ir)_, created by lowering and desugaring the AST. ([see more](../hir.md)) +HIR | The _high-level [IR](#ir)_, created by lowering / desugaring the AST. ([see more](../hir.md)) `HirId` | Identifies a particular node in the HIR by combining a def-id with an "intra-definition offset". See [the HIR chapter for more](../hir.md#identifiers-in-the-hir). +IAC | A (more often than not type-level) _inherent associated constant_, an associated constant in an inherent impl `impl Type { … }`. Often mentioned in the context of feature [`min_generic_const_items`] (mGCA, MGCA). An IGAC is an inherent [GAC](#gac). +IAT | An _inherent associated type_, an associated type defined in an inherent impl `impl Type { … }`. An IGAT is an inherent [GAT](#gat), a generic IAT. ICE | Short for _internal compiler error_, this is when the compiler crashes. ICH | Short for _incremental compilation hash_, these are used as fingerprints for things such as HIR and crate metadata, to check if changes have been made. This is useful in incremental compilation to see if part of a crate has changed and should be recompiled. `infcx` | The type inference context (`InferCtxt`). (see `rustc_middle::infer`) @@ -41,12 +50,17 @@ Term | Meaning IR | Short for _intermediate representation_, a general term in compilers. During compilation, the code is transformed from raw source (ASCII text) to various IRs. In Rust, these are primarily HIR, MIR, and LLVM IR. Each IR is well-suited for some set of computations. For example, MIR is well-suited for the borrow checker, and LLVM IR is well-suited for codegen because LLVM accepts it. IRLO, irlo | Sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org). item | A kind of "definition" in the language, such as a static, const, use statement, module, struct, etc. Concretely, this corresponds to the `Item` type. +item signature | The type signature / annotation / ascription of an item (e.g., struct, function). Often mentioned in the context of type inference since they are a place where we don't perform inference contrary to types in [bodies](#body). +ITIAT | Short for _`impl Trait` in associated type_. Also known as [ATPIT](#atpit). lang item | Items that represent concepts intrinsic to the language itself, such as special built-in traits like `Sync` and `Send`; or traits representing operations such as `Add`; or functions that are called by the compiler. ([see more](https://doc.rust-lang.org/1.9.0/book/lang-items.html)) -late-bound lifetime | A lifetime region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/region_kind/enum.RegionKind.html#bound-regions)) +late-bound lifetime | A lifetime / region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/region_kind/enum.RegionKind.html#bound-regions)) local crate | The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate. +lowering | The act of converting a higher-level [IR](#ir) to a lower-level one. E.g., AST lowering (from [AST](#ast) to [HIR](#hir)) or HIR ty lowering (from HIR to [middle ty IR](#middle-ty-ir)). +LTA | A _lazy type alias_, a type alias that gets "properly" represented as an alias in the [middle ty IR](#middle-ty-ir); contrary to (eager) type aliases whose reference sites get expanded to the underlying aliased type (the RHS of the type alias after instantiation) during HIR ty lowering, its reference sites get [lowered](#lowering) to an [`AliasTy`]. LTO | Short for *link-time optimizations*, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto]. [LLVM] | (actually not an acronym :P) an open-source compiler backend. It accepts LLVM IR and outputs native binaries. Various languages (e.g. Rust) can then implement a compiler front-end that outputs LLVM IR and use LLVM to compile to all the platforms LLVM supports. memoization | The process of storing the results of (pure) computations (such as pure function calls) to avoid having to repeat them in the future. This is typically a trade-off between execution speed and memory usage. +middle ty IR | The collection of types defined in module [`rustc_middle::ty`] used by the type checker and the trait solver. They essentially form an [IR](#ir). MIR | The _mid-level [IR](#ir)_ that is created after type-checking for use by borrowck and codegen. ([see more](../mir/index.md)) Miri | A tool to detect Undefined Behavior in (unsafe) Rust code. ([see more](https://github.com/rust-lang/miri)) monomorphization | The process of taking generic implementations of types and functions and instantiating them with concrete types. For example, in the code we might have `Vec`, but in the final executable, we will have a copy of the `Vec` code for every concrete type used in the program (e.g. a copy for `Vec`, a copy for `Vec`, etc). @@ -66,39 +80,49 @@ Term | Meaning recovery | Recovery refers to handling invalid syntax during parsing (e.g. a missing comma) and continuing to parse the AST. This avoid showing spurious errors to the user (e.g. showing 'missing field' errors when the struct definition contains errors). region | Another term for "lifetime" often used in the literature and in the borrow checker. rib | A data structure in the name resolver that keeps track of a single scope for names. ([see more](../name-resolution.md)) -RPIT | A return-position `impl Trait`. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#abstract-return-types)). -RPITIT | A return-position `impl Trait` in trait. Unlike RPIT, this is desugared to a generic associated type (GAT). Introduced in [RFC 3425](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html). ([see more](../return-position-impl-trait-in-trait.md)) -rustbuild | A deprecated term for the part of bootstrap that is written in Rust +RPIT | Short for _return-position `impl Trait`_. An existential `impl Trait` (as opposed to universial) like [TAITs](#tait) and [ATPIT](#atpit). ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#abstract-return-types)). +RPITIT | Short for _return-position `impl Trait` in trait_. Unlike [RPIT](#rpit), this is desugared to a generic associated type ([GAT](#gat)). Introduced in [RFC 3425]. ([see more](../return-position-impl-trait-in-trait.md)) +rustbuild 👎 | A **deprecated** term for the part of bootstrap that is written in Rust scrutinee | A scrutinee is the expression that is matched on in `match` expressions and similar pattern matching constructs. For example, in `match x { A => 1, B => 2 }`, the expression `x` is the scrutinee. `sess` | The compiler _session_, which stores global data used throughout compilation side tables | Because the [AST](#ast) and HIR are immutable once created, we often carry extra information about them in the form of hashtables, indexed by the id of a particular node. sigil | Like a keyword but composed entirely of non-alphanumeric tokens. For example, `&` is a sigil for references. soundness | A technical term in type theory. Roughly, if a type system is sound, then a program that type-checks is type-safe. That is, one can never (in safe rust) force a value into a variable of the wrong type. (see "completeness"). span | A location in the user's source code, used for error reporting primarily. These are like a file-name/line-number/column tuple on steroids: they carry a start/end point, and also track macro expansions and compiler desugaring. All while being packed into a few bytes (really, it's an index into a table). See the [`Span`] datatype for more. -subst | The act of _substituting_ the generic parameters inside of a type, constant expression, etc. with concrete generic arguments by supplying [substs](#substs). Nowadays referred to as _instantiating_ in the compiler. -substs | The _substitutions_ for a given generic item (e.g. the `i32`, `u32` in `HashMap`). Nowadays referred to as the list of _generic arguments_ in the compiler (but note that strictly speaking these two concepts differ, see the literature). +subst 👎 | The act of _substituting_ the generic parameters inside of a type, constant expression, etc. with concrete generic arguments by supplying [substs](#substs). Nowadays referred to as _instantiating_ in the compiler. +substs 👎 | The _substitutions_ for a given generic item (e.g. the `i32`, `u32` in `HashMap`). Nowadays referred to as the list of _generic arguments_ in the compiler (but note that strictly speaking these two concepts differ, see the literature). sysroot | The directory for build artifacts that are loaded by the compiler at runtime. ([see more](../building/bootstrapping/what-bootstrapping-does.html#what-is-a-sysroot)) tag | The "tag" of an enum/generator encodes the [discriminant](#discriminant) of the active variant/state. Tags can either be "direct" (simply storing the discriminant in a field) or use a ["niche"](#niche). -TAIT | A type-alias `impl Trait`. Introduced in [RFC 2515](https://rust-lang.github.io/rfcs/2515-type_alias_impl_trait.html). +TAIT | Short for _type-alias `impl Trait`_. Introduced in [RFC 2515]. `tcx` | Standard variable name for the "typing context" (`TyCtxt`), main data structure of the compiler. ([see more](../ty.md)) `'tcx` | The lifetime of the allocation arenas used by `TyCtxt`. Most data interned during a compilation session will use this lifetime with the exception of HIR data which uses the `'hir` lifetime. ([see more](../ty.md)) token | The smallest unit of parsing. Tokens are produced after lexing ([see more](../the-parser.md)). -[TLS] | *Thread-local storage*. Variables may be defined so that each thread has its own copy (rather than all threads sharing the variable). This has some interactions with LLVM. Not all platforms support TLS. +[TLS] | _Thread-local storage_. Variables may be defined so that each thread has its own copy (rather than all threads sharing the variable). This has some interactions with LLVM. Not all platforms support TLS. trait reference, trait ref | The name of a trait along with a suitable list of generic arguments. ([see more](../traits/goals-and-clauses.md#trait-ref)) -trans | Short for _translation_, the code to translate MIR into LLVM IR. Renamed to [codegen](#codegen). +trans 👎 | Short for _translation_, the code to translate MIR into LLVM IR. **Renamed to** [codegen](#codegen). `Ty` | The internal representation of a type. ([see more](../ty.md)) `TyCtxt` | The data structure often referred to as [`tcx`](#tcx) in code which provides access to session data and the query system. -UFCS | Short for _universal function call syntax_, this is an unambiguous syntax for calling a method. **Term no longer in use!** Prefer _fully-qualified path/syntax_. ([see more](../hir-typeck/summary.md), [see the reference](https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls)) +UFCS 👎 | Short for _universal function call syntax_, this is an unambiguous syntax for calling a method. **Term no longer in use!** Prefer _fully-qualified path / syntax_. ([see more](../hir-typeck/summary.md), [see the reference](https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls)) uninhabited type | A type which has _no_ values. This is not the same as a ZST, which has exactly 1 value. An example of an uninhabited type is `enum Foo {}`, which has no variants, and so, can never be created. The compiler can treat code that deals with uninhabited types as dead code, since there is no such value to be manipulated. `!` (the never type) is an uninhabited type. Uninhabited types are also called _empty types_. upvar | A variable captured by a closure from outside the closure. variance | Determines how changes to a generic parameter affect subtyping; for example, if `T` is a subtype of `U`, then `Vec` is a subtype `Vec` because `Vec` is _covariant_ in its generic parameter. See [the background chapter](./background.md#variance) for a more general explanation. See the [variance chapter](../variance.md) for an explanation of how type checking handles variance. variant index | In an enum, identifies a variant by assigning them indices starting at 0. This is purely internal and not to be confused with the ["discriminant"](#discriminant) which can be overwritten by the user (e.g. `enum Bool { True = 42, False = 0 }`). -well-formedness | Semantically: An expression that evaluates to meaningful result. In type systems: A type related construct which follows rules of the type system. +well-formedness, wfness, wf | Semantically: An expression that evaluates to meaningful result. In type systems: A type related construct which follows rules of the type system. wide pointer | A pointer with additional metadata. See [fat pointer](#fat-ptr) for more. ZST | *Zero-sized type*. A type whose values have size 0 bytes. Since `2^0 = 1`, such types can have exactly one value. For example, `()` (unit) is a ZST. `struct Foo;` is also a ZST. The compiler can do some nice optimizations around ZSTs. +See also . + [LLVM]: https://llvm.org/ -[lto]: https://llvm.org/docs/LinkTimeOptimization.html -[`Span`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html -[thinlto]: https://clang.llvm.org/docs/ThinLTO.html +[RFC 1598]: https://rust-lang.github.io/rfcs/1598-generic_associated_types.html +[RFC 2515]: https://rust-lang.github.io/rfcs/2515-type_alias_impl_trait.html +[RFC 3425]: https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html [TLS]: https://llvm.org/docs/LangRef.html#thread-local-storage-models +[`AliasTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.AliasTy.html +[`Span`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html +[`generic_const_items`]: https://github.com/rust-lang/rust/issues/113521 +[`min_generic_const_items`]: https://github.com/rust-lang/rust/issues/132980 +[`rustc_middle::ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/index.html +[lto]: https://llvm.org/docs/LinkTimeOptimization.html +[size-align]: https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment +[thinlto]: https://clang.llvm.org/docs/ThinLTO.html From 9e06819f283f6b95eb890f17349f6ff9d426b8c8 Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 3 Apr 2026 04:57:39 +0000 Subject: [PATCH 18/37] Update hir::Crate link --- src/doc/rustc-dev-guide/src/appendix/code-index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index 3e1eed17eba6..6c5f85da49df 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -9,7 +9,7 @@ Item | Kind | Short description | Chapter | `BodyId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir/src/hir.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.BodyId.html) `Compiler` | struct | Represents a compiler session and can be used to drive a compilation. | [The Rustc Driver and Interface] | [compiler/rustc_interface/src/interface.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html) `ast::Crate` | struct | A syntax-level representation of a parsed crate | [The parser] | [compiler/rustc_ast/src/ast.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.Crate.html) -`rustc_hir::Crate` | struct | A more abstract, compiler-friendly form of a crate's AST | [The Hir] | [compiler/rustc_hir/src/hir.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Crate.html) +`hir::Crate` | struct | A more abstract, compiler-friendly form of a crate's AST | [The Hir] | [compiler/rustc_middle/src/hir/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/struct.Crate.html) `DefId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir/src/def_id.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html) `Diag` | struct | A struct for a compiler diagnostic, such as an error or lint | [Emitting Diagnostics] | [compiler/rustc_errors/src/diagnostic.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html) `DocContext` | struct | A state container used by rustdoc when crawling through a crate to gather its documentation | [Rustdoc] | [src/librustdoc/core.rs](https://github.com/rust-lang/rust/blob/HEAD/src/librustdoc/core.rs) From 48db8c72fffec385839d232925aefce7b5596074 Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 3 Apr 2026 05:18:49 +0000 Subject: [PATCH 19/37] Update docs to use `TyCtxtEnsureOk::typeck` Co-authored-by: Daria Sukhonina --- .../rustc-dev-guide/src/rustc-driver/getting-diagnostics.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md index 518cf4e821a7..268b612e3ee7 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/getting-diagnostics.md @@ -7,7 +7,7 @@ otherwise be printed to stderr. To get diagnostics from the compiler, configure [`rustc_interface::Config`] to output diagnostic to a buffer, -and run [`rustc_hir_typeck::typeck`] for each item. +and run [`TyCtxtEnsureOk::typeck`] for each item. ```rust {{#include ../../examples/rustc-interface-getting-diagnostics.rs}} @@ -15,5 +15,4 @@ and run [`rustc_hir_typeck::typeck`] for each item. [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html [`rustc_interface::Config`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Config.html -[`TyCtxt.analysis`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/passes/fn.analysis.html -[`rustc_hir_typeck::typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn.typeck.html +[`TyCtxtEnsureOk::typeck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/struct.TyCtxtEnsureOk.html#method.typeck From 28c94943eba186341cedf396e363cb161458c974 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 6 Apr 2026 05:04:13 +0000 Subject: [PATCH 20/37] Prepare for merging from rust-lang/rust This updates the rust-version file to 9602bda1dd0c1bbf5787e398385bbac81fd532f8. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index a51e46f6191a..c1b9fe3ea0b5 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -562dee4820c458d823175268e41601d4c060588a +9602bda1dd0c1bbf5787e398385bbac81fd532f8 From ca691688a1dc402586ff90d64a4fbf0283248e58 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 07:40:44 +0200 Subject: [PATCH 21/37] missing pause --- src/doc/rustc-dev-guide/src/diagnostics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index bdd7a3dfa9b8..2056dc264800 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -953,7 +953,7 @@ You can match on the following names and values, using `name = "value"`: Only `"MainFunctionType"` is supported. - `from_desugaring`: Match against a particular variant of the `DesugaringKind` enum. The desugaring is identified by its variant name, for example - `"QuestionMark"` for `?` desugaring or `"TryBlock"` for `try` blocks. + `"QuestionMark"` for `?` desugaring, or `"TryBlock"` for `try` blocks. - `Self` and any generic arguments of the trait, like `Self = "alloc::string::String"` or `Rhs="i32"`. From 1b09ce5272e4ff4abe8ce999d67311a910ccc897 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Wed, 8 Apr 2026 06:16:43 +0000 Subject: [PATCH 22/37] Prepare for merging from rust-lang/rust This updates the rust-version file to 30d0309fa821f7a0984a9629e0d227ca3c0d2eda. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index c1b9fe3ea0b5..ac3099d84593 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -9602bda1dd0c1bbf5787e398385bbac81fd532f8 +30d0309fa821f7a0984a9629e0d227ca3c0d2eda From 97eb1be51090b9b205169f7b08f82c11f8bd87a1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:24:24 +0200 Subject: [PATCH 23/37] sembr src/appendix/code-index.md --- src/doc/rustc-dev-guide/src/appendix/code-index.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index 6c5f85da49df..067dcffb260f 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -1,6 +1,7 @@ # Code Index -rustc has a lot of important data structures. This is an attempt to give some +rustc has a lot of important data structures. +This is an attempt to give some guidance on where to learn more about some of the key data structures of the compiler. From 49b1d75ba2f29dc3ac6d2f303919161881673fb2 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:26:24 +0200 Subject: [PATCH 24/37] re-wrap --- src/doc/rustc-dev-guide/src/appendix/code-index.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index 067dcffb260f..25c770d4fbe8 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -1,9 +1,8 @@ # Code Index rustc has a lot of important data structures. -This is an attempt to give some -guidance on where to learn more about some of the key data structures of the -compiler. +This is an attempt to give some guidance on where to learn more +about some of the key data structures of the compiler. Item | Kind | Short description | Chapter | Declaration ----------------|----------|-----------------------------|--------------------|------------------- From 91cfd3b869893e98d3480a11d75b18b0eebd1254 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:27:18 +0200 Subject: [PATCH 25/37] sembr src/const-eval/interpret.md --- .../src/const-eval/interpret.md | 130 +++++++++++------- 1 file changed, 82 insertions(+), 48 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/const-eval/interpret.md b/src/doc/rustc-dev-guide/src/const-eval/interpret.md index afd6c4f4c07e..268b8a3b114d 100644 --- a/src/doc/rustc-dev-guide/src/const-eval/interpret.md +++ b/src/doc/rustc-dev-guide/src/const-eval/interpret.md @@ -1,8 +1,9 @@ # Interpreter The interpreter is a virtual machine for executing MIR without compiling to -machine code. It is usually invoked via `tcx.const_eval_*` functions. The -interpreter is shared between the compiler (for compile-time function +machine code. +It is usually invoked via `tcx.const_eval_*` functions. +The interpreter is shared between the compiler (for compile-time function evaluation, CTFE) and the tool [Miri](https://github.com/rust-lang/miri/), which uses the same virtual machine to detect Undefined Behavior in (unsafe) Rust code. @@ -26,7 +27,8 @@ The compiler needs to figure out the length of the array before being able to create items that use the type (locals, constants, function arguments, ...). To obtain the (in this case empty) parameter environment, one can call -`let param_env = tcx.param_env(length_def_id);`. The `GlobalId` needed is +`let param_env = tcx.param_env(length_def_id);`. +The `GlobalId` needed is ```rust,ignore let gid = GlobalId { @@ -36,7 +38,8 @@ let gid = GlobalId { ``` Invoking `tcx.const_eval(param_env.and(gid))` will now trigger the creation of -the MIR of the array length expression. The MIR will look something like this: +the MIR of the array length expression. +The MIR will look something like this: ```mir Foo::{{constant}}#0: usize = { @@ -59,35 +62,43 @@ Before the evaluation, a virtual memory location (in this case essentially a `vec![u8; 4]` or `vec![u8; 8]`) is created for storing the evaluation result. At the start of the evaluation, `_0` and `_1` are -`Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef))`. This is quite +`Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef))`. +This is quite a mouthful: [`Operand`] can represent either data stored somewhere in the [interpreter memory](#memory) (`Operand::Indirect`), or (as an optimization) -immediate data stored in-line. And [`Immediate`] can either be a single +immediate data stored in-line. + And [`Immediate`] can either be a single (potentially uninitialized) [scalar value][`Scalar`] (integer or thin pointer), -or a pair of two of them. In our case, the single scalar value is *not* (yet) -initialized. +or a pair of two of them. +In our case, the single scalar value is *not* (yet) initialized. When the initialization of `_1` is invoked, the value of the `FOO` constant is required, and triggers another call to `tcx.const_eval_*`, which will not be shown -here. If the evaluation of FOO is successful, `42` will be subtracted from its +here. +If the evaluation of FOO is successful, `42` will be subtracted from its value `4096` and the result stored in `_1` as `Operand::Immediate(Immediate::ScalarPair(Scalar::Raw { data: 4054, .. }, -Scalar::Raw { data: 0, .. })`. The first part of the pair is the computed value, -the second part is a bool that's true if an overflow happened. A `Scalar::Raw` +Scalar::Raw { data: 0, .. })`. +The first part of the pair is the computed value, +the second part is a bool that's true if an overflow happened. +A `Scalar::Raw` also stores the size (in bytes) of this scalar value; we are eliding that here. -The next statement asserts that said boolean is `0`. In case the assertion +The next statement asserts that said boolean is `0`. +In case the assertion fails, its error message is used for reporting a compile-time error. Since it does not fail, `Operand::Immediate(Immediate::Scalar(Scalar::Raw { data: 4054, .. }))` is stored in the virtual memory it was allocated before the -evaluation. `_0` always refers to that location directly. +evaluation. +`_0` always refers to that location directly. After the evaluation is done, the return value is converted from [`Operand`] to [`ConstValue`] by [`op_to_const`]: the former representation is geared towards what is needed *during* const evaluation, while [`ConstValue`] is shaped by the needs of the remaining parts of the compiler that consume the results of const -evaluation. As part of this conversion, for types with scalar values, even if +evaluation. + As part of this conversion, for types with scalar values, even if the resulting [`Operand`] is `Indirect`, it will return an immediate `ConstValue::Scalar(computed_value)` (instead of the usual `ConstValue::Indirect`). This makes using the result much more efficient and also more convenient, as no @@ -107,12 +118,14 @@ the interpreter, but just use the cached result. The interpreter's outside-facing datastructures can be found in [rustc_middle/src/mir/interpret](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_middle/src/mir/interpret). -This is mainly the error enum and the [`ConstValue`] and [`Scalar`] types. A +This is mainly the error enum and the [`ConstValue`] and [`Scalar`] types. +A `ConstValue` can be either `Scalar` (a single `Scalar`, i.e., integer or thin pointer), `Slice` (to represent byte slices and strings, as needed for pattern matching) or `Indirect`, which is used for anything else and refers to a virtual -allocation. These allocations can be accessed via the methods on -`tcx.interpret_interner`. A `Scalar` is either some `Raw` integer or a pointer; +allocation. +These allocations can be accessed via the methods on `tcx.interpret_interner`. + A `Scalar` is either some `Raw` integer or a pointer; see [the next section](#memory) for more on that. If you are expecting a numeric result, you can use `eval_usize` (panics on @@ -122,29 +135,38 @@ in an `Option` yielding the `Scalar` if possible. ## Memory To support any kind of pointers, the interpreter needs to have a "virtual memory" that the -pointers can point to. This is implemented in the [`Memory`] type. In the -simplest model, every global variable, stack variable and every dynamic -allocation corresponds to an [`Allocation`] in that memory. (Actually using an +pointers can point to. + This is implemented in the [`Memory`] type. + In the simplest model, every global variable, stack variable and every dynamic +allocation corresponds to an [`Allocation`] in that memory. + (Actually using an allocation for every MIR stack variable would be very inefficient; that's why we have `Operand::Immediate` for stack variables that are both small and never have -their address taken. But that is purely an optimization.) +their address taken. + But that is purely an optimization.) Such an `Allocation` is basically just a sequence of `u8` storing the value of -each byte in this allocation. (Plus some extra data, see below.) Every -`Allocation` has a globally unique `AllocId` assigned in `Memory`. With that, a +each byte in this allocation. + (Plus some extra data, see below.) Every +`Allocation` has a globally unique `AllocId` assigned in `Memory`. + With that, a [`Pointer`] consists of a pair of an `AllocId` (indicating the allocation) and an offset into the allocation (indicating which byte of the allocation the -pointer points to). It may seem odd that a `Pointer` is not just an integer +pointer points to). + It may seem odd that a `Pointer` is not just an integer address, but remember that during const evaluation, we cannot know at which actual integer address the allocation will end up -- so we use `AllocId` as -symbolic base addresses, which means we need a separate offset. (As an aside, +symbolic base addresses, which means we need a separate offset. + (As an aside, it turns out that pointers at run-time are [more than just integers, too](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#pointer-provenance).) These allocations exist so that references and raw pointers have something to -point to. There is no global linear heap in which things are allocated, but each +point to. +There is no global linear heap in which things are allocated, but each allocation (be it for a local variable, a static or a (future) heap allocation) -gets its own little memory with exactly the required size. So if you have a +gets its own little memory with exactly the required size. +So if you have a pointer to an allocation for a local variable `a`, there is no possible (no matter how unsafe) operation that you can do that would ever change said pointer to a pointer to a different local variable `b`. @@ -152,30 +174,36 @@ Pointer arithmetic on `a` will only ever change its offset; the `AllocId` stays This, however, causes a problem when we want to store a `Pointer` into an `Allocation`: we cannot turn it into a sequence of `u8` of the right length! -`AllocId` and offset together are twice as big as a pointer "seems" to be. This +`AllocId` and offset together are twice as big as a pointer "seems" to be. + This is what the `relocation` field of `Allocation` is for: the byte offset of the `Pointer` gets stored as a bunch of `u8`, while its `AllocId` gets stored -out-of-band. The two are reassembled when the `Pointer` is read from memory. +out-of-band. + The two are reassembled when the `Pointer` is read from memory. The other bit of extra data an `Allocation` needs is `undef_mask` for keeping track of which of its bytes are initialized. ### Global memory and exotic allocations `Memory` exists only during evaluation; it gets destroyed when the -final value of the constant is computed. In case that constant contains any +final value of the constant is computed. + In case that constant contains any pointers, those get "interned" and moved to a global "const eval memory" that is -part of `TyCtxt`. These allocations stay around for the remaining computation +part of `TyCtxt`. + These allocations stay around for the remaining computation and get serialized into the final output (so that dependent crates can use them). Moreover, to also support function pointers, the global memory in `TyCtxt` can also contain "virtual allocations": instead of an `Allocation`, these contain an -`Instance`. That allows a `Pointer` to point to either normal data or a +`Instance`. + That allows a `Pointer` to point to either normal data or a function, which is needed to be able to evaluate casts from function pointers to raw pointers. Finally, the [`GlobalAlloc`] type used in the global memory also contains a -variant `Static` that points to a particular `const` or `static` item. This is +variant `Static` that points to a particular `const` or `static` item. + This is needed to support circular statics, where we need to have a `Pointer` to a `static` for which we cannot yet have an `Allocation` as we do not know the bytes of its value. @@ -188,17 +216,19 @@ bytes of its value. ### Pointer values vs Pointer types One common cause of confusion in the interpreter is that being a pointer *value* and having -a pointer *type* are entirely independent properties. By "pointer value", we +a pointer *type* are entirely independent properties. + By "pointer value", we refer to a `Scalar::Ptr` containing a `Pointer` and thus pointing somewhere into -the interpreter's virtual memory. This is in contrast to `Scalar::Raw`, which is just some -concrete integer. +the interpreter's virtual memory. + This is in contrast to `Scalar::Raw`, which is just some concrete integer. However, a variable of pointer or reference *type*, such as `*const T` or `&T`, does not have to have a pointer *value*: it could be obtained by casting or -transmuting an integer to a pointer. +transmuting an integer to a pointer. And similarly, when casting or transmuting a reference to some actual allocation to an integer, we end up with a pointer *value* -(`Scalar::Ptr`) at integer *type* (`usize`). This is a problem because we +(`Scalar::Ptr`) at integer *type* (`usize`). + This is a problem because we cannot meaningfully perform integer operations such as division on pointer values. @@ -207,30 +237,34 @@ values. Although the main entry point to constant evaluation is the `tcx.const_eval_*` functions, there are additional functions in [rustc_const_eval/src/const_eval](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/index.html) -that allow accessing the fields of a `ConstValue` (`Indirect` or otherwise). You should +that allow accessing the fields of a `ConstValue` (`Indirect` or otherwise). +You should never have to access an `Allocation` directly except for translating it to the compilation target (at the moment just LLVM). The interpreter starts by creating a virtual stack frame for the current constant that is -being evaluated. There's essentially no difference between a constant and a +being evaluated. +There's essentially no difference between a constant and a function with no arguments, except that constants do not allow local (named) variables at the time of writing this guide. A stack frame is defined by the `Frame` type in [rustc_const_eval/src/interpret/eval_context.rs](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_const_eval/src/interpret/eval_context.rs) -and contains all the local -variables memory (`None` at the start of evaluation). Each frame refers to the -evaluation of either the root constant or subsequent calls to `const fn`. The +and contains all the local variables memory (`None` at the start of evaluation). +Each frame refers to the +evaluation of either the root constant or subsequent calls to `const fn`. +The evaluation of another constant simply calls `tcx.const_eval_*`, which produce an entirely new and independent stack frame. The frames are just a `Vec`, there's no way to actually refer to a -`Frame`'s memory even if horrible shenanigans are done via unsafe code. The only -memory that can be referred to are `Allocation`s. +`Frame`'s memory even if horrible shenanigans are done via unsafe code. +The only memory that can be referred to are `Allocation`s. The interpreter now calls the `step` method (in [rustc_const_eval/src/interpret/step.rs](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_const_eval/src/interpret/step.rs) -) until it either returns an error or has no further statements to execute. Each -statement will now initialize or modify the locals or the virtual memory -referred to by a local. This might require evaluating other constants or +) until it either returns an error or has no further statements to execute. +Each statement will now initialize or modify the locals or the virtual memory +referred to by a local. +This might require evaluating other constants or statics, which just recursively invokes `tcx.const_eval_*`. From 238aabb2bff73d4560aab2e250d829f6b6eed17b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:35:36 +0200 Subject: [PATCH 26/37] whitespace --- .../src/const-eval/interpret.md | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/const-eval/interpret.md b/src/doc/rustc-dev-guide/src/const-eval/interpret.md index 268b8a3b114d..0462876ef359 100644 --- a/src/doc/rustc-dev-guide/src/const-eval/interpret.md +++ b/src/doc/rustc-dev-guide/src/const-eval/interpret.md @@ -67,7 +67,7 @@ This is quite a mouthful: [`Operand`] can represent either data stored somewhere in the [interpreter memory](#memory) (`Operand::Indirect`), or (as an optimization) immediate data stored in-line. - And [`Immediate`] can either be a single +And [`Immediate`] can either be a single (potentially uninitialized) [scalar value][`Scalar`] (integer or thin pointer), or a pair of two of them. In our case, the single scalar value is *not* (yet) initialized. @@ -98,7 +98,7 @@ After the evaluation is done, the return value is converted from [`Operand`] to what is needed *during* const evaluation, while [`ConstValue`] is shaped by the needs of the remaining parts of the compiler that consume the results of const evaluation. - As part of this conversion, for types with scalar values, even if +As part of this conversion, for types with scalar values, even if the resulting [`Operand`] is `Indirect`, it will return an immediate `ConstValue::Scalar(computed_value)` (instead of the usual `ConstValue::Indirect`). This makes using the result much more efficient and also more convenient, as no @@ -119,13 +119,12 @@ the interpreter, but just use the cached result. The interpreter's outside-facing datastructures can be found in [rustc_middle/src/mir/interpret](https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_middle/src/mir/interpret). This is mainly the error enum and the [`ConstValue`] and [`Scalar`] types. -A -`ConstValue` can be either `Scalar` (a single `Scalar`, i.e., integer or thin +A `ConstValue` can be either `Scalar` (a single `Scalar`, i.e., integer or thin pointer), `Slice` (to represent byte slices and strings, as needed for pattern matching) or `Indirect`, which is used for anything else and refers to a virtual allocation. These allocations can be accessed via the methods on `tcx.interpret_interner`. - A `Scalar` is either some `Raw` integer or a pointer; +A `Scalar` is either some `Raw` integer or a pointer; see [the next section](#memory) for more on that. If you are expecting a numeric result, you can use `eval_usize` (panics on @@ -136,28 +135,28 @@ in an `Option` yielding the `Scalar` if possible. To support any kind of pointers, the interpreter needs to have a "virtual memory" that the pointers can point to. - This is implemented in the [`Memory`] type. - In the simplest model, every global variable, stack variable and every dynamic +This is implemented in the [`Memory`] type. +In the simplest model, every global variable, stack variable and every dynamic allocation corresponds to an [`Allocation`] in that memory. - (Actually using an +(Actually using an allocation for every MIR stack variable would be very inefficient; that's why we have `Operand::Immediate` for stack variables that are both small and never have their address taken. - But that is purely an optimization.) +But that is purely an optimization.) Such an `Allocation` is basically just a sequence of `u8` storing the value of each byte in this allocation. - (Plus some extra data, see below.) Every +(Plus some extra data, see below.) Every `Allocation` has a globally unique `AllocId` assigned in `Memory`. - With that, a +With that, a [`Pointer`] consists of a pair of an `AllocId` (indicating the allocation) and an offset into the allocation (indicating which byte of the allocation the pointer points to). - It may seem odd that a `Pointer` is not just an integer +It may seem odd that a `Pointer` is not just an integer address, but remember that during const evaluation, we cannot know at which actual integer address the allocation will end up -- so we use `AllocId` as symbolic base addresses, which means we need a separate offset. - (As an aside, +(As an aside, it turns out that pointers at run-time are [more than just integers, too](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#pointer-provenance).) @@ -175,11 +174,10 @@ Pointer arithmetic on `a` will only ever change its offset; the `AllocId` stays This, however, causes a problem when we want to store a `Pointer` into an `Allocation`: we cannot turn it into a sequence of `u8` of the right length! `AllocId` and offset together are twice as big as a pointer "seems" to be. - This -is what the `relocation` field of `Allocation` is for: the byte offset of the +This is what the `relocation` field of `Allocation` is for: the byte offset of the `Pointer` gets stored as a bunch of `u8`, while its `AllocId` gets stored out-of-band. - The two are reassembled when the `Pointer` is read from memory. +The two are reassembled when the `Pointer` is read from memory. The other bit of extra data an `Allocation` needs is `undef_mask` for keeping track of which of its bytes are initialized. @@ -187,24 +185,23 @@ track of which of its bytes are initialized. `Memory` exists only during evaluation; it gets destroyed when the final value of the constant is computed. - In case that constant contains any +In case that constant contains any pointers, those get "interned" and moved to a global "const eval memory" that is part of `TyCtxt`. - These allocations stay around for the remaining computation +These allocations stay around for the remaining computation and get serialized into the final output (so that dependent crates can use them). Moreover, to also support function pointers, the global memory in `TyCtxt` can also contain "virtual allocations": instead of an `Allocation`, these contain an `Instance`. - That allows a `Pointer` to point to either normal data or a +That allows a `Pointer` to point to either normal data or a function, which is needed to be able to evaluate casts from function pointers to raw pointers. Finally, the [`GlobalAlloc`] type used in the global memory also contains a variant `Static` that points to a particular `const` or `static` item. - This is -needed to support circular statics, where we need to have a `Pointer` to a +This is needed to support circular statics, where we need to have a `Pointer` to a `static` for which we cannot yet have an `Allocation` as we do not know the bytes of its value. @@ -217,10 +214,10 @@ bytes of its value. One common cause of confusion in the interpreter is that being a pointer *value* and having a pointer *type* are entirely independent properties. - By "pointer value", we +By "pointer value", we refer to a `Scalar::Ptr` containing a `Pointer` and thus pointing somewhere into the interpreter's virtual memory. - This is in contrast to `Scalar::Raw`, which is just some concrete integer. +This is in contrast to `Scalar::Raw`, which is just some concrete integer. However, a variable of pointer or reference *type*, such as `*const T` or `&T`, does not have to have a pointer *value*: it could be obtained by casting or @@ -253,8 +250,7 @@ A stack frame is defined by the `Frame` type in and contains all the local variables memory (`None` at the start of evaluation). Each frame refers to the evaluation of either the root constant or subsequent calls to `const fn`. -The -evaluation of another constant simply calls `tcx.const_eval_*`, which produce an +The evaluation of another constant simply calls `tcx.const_eval_*`, which produce an entirely new and independent stack frame. The frames are just a `Vec`, there's no way to actually refer to a From 67ce02bb3b3d748b4a9f03c3999ff54bf7f5c566 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:37:03 +0200 Subject: [PATCH 27/37] sembr src/traits/separate-projection-bounds.md --- .../src/traits/separate-projection-bounds.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md index 07e88c37b0a2..bc501eda3e5b 100644 --- a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md @@ -1,16 +1,21 @@ # Having separate `Trait` and `Projection` bounds -Given `T: Foo` where-bound, we currently lower it to a `Trait(Foo)` and separate `Projection(::AssocA, u32)` and `Projection(::AssocB, i32)` bounds. Why do we not represent this as a single `Trait(Foo[T], [AssocA = u32, AssocB = u32]` bound instead? +Given `T: Foo` where-bound, we currently lower it to a `Trait(Foo)` and separate `Projection(::AssocA, u32)` and `Projection(::AssocB, i32)` bounds. +Why do we not represent this as a single `Trait(Foo[T], [AssocA = u32, AssocB = u32]` bound instead? The way we prove `Projection` bounds directly relies on proving the corresponding `Trait` bound: [old solver](https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_trait_selection/src/traits/project.rs#L898) [new solver](https://github.com/rust-lang/rust/blob/461e9738a47e313e4457957fa95ff6a19a4b88d4/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs#L37-L41). It feels like it might make more sense to just have a single implementation which checks whether a trait is implemented and returns (a way to compute) its associated types. -This is unfortunately quite difficult, as we may use a different candidate for norm than for the corresponding trait bound. See [alias-bound vs where-bound](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-always-consider-aliasbound-candidates) and [global where-bound vs impl](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-prefer-global-where-bounds-over-impls). +This is unfortunately quite difficult, as we may use a different candidate for norm than for the corresponding trait bound. +See [alias-bound vs where-bound](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-always-consider-aliasbound-candidates) and [global where-bound vs impl](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-prefer-global-where-bounds-over-impls). -There are also some other subtle reasons for why we can't do so. The most stupid is that for rigid aliases, trying to normalize them does not consider any lifetime constraints from proving the trait bound. This is necessary due to a lack of assumptions on binders - https://github.com/rust-lang/trait-system-refactor-initiative/issues/177 - and should be fixed longterm. +There are also some other subtle reasons for why we can't do so. +The most stupid is that for rigid aliases, trying to normalize them does not consider any lifetime constraints from proving the trait bound. +This is necessary due to a lack of assumptions on binders - https://github.com/rust-lang/trait-system-refactor-initiative/issues/177 - and should be fixed longterm. -A separate issue is that right now, fetching the `type_of` associated types for `Trait` goals or in shadowed `Projection` candidates can cause query cycles for RPITIT. See https://github.com/rust-lang/trait-system-refactor-initiative/issues/185. +A separate issue is that right now, fetching the `type_of` associated types for `Trait` goals or in shadowed `Projection` candidates can cause query cycles for RPITIT. +See https://github.com/rust-lang/trait-system-refactor-initiative/issues/185. There are also slight differences between candidates for some of the builtin impls, these do all seem generally undesirable and I consider them to be bugs which would be fixed if we had a unified approach here. From 66bf17e1ef4854d7cba1706a699ecc10015196f8 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:39:46 +0200 Subject: [PATCH 28/37] slight improvements --- .../src/traits/separate-projection-bounds.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md index bc501eda3e5b..82f2e0caf6ce 100644 --- a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md @@ -11,10 +11,12 @@ This is unfortunately quite difficult, as we may use a different candidate for n See [alias-bound vs where-bound](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-always-consider-aliasbound-candidates) and [global where-bound vs impl](https://rustc-dev-guide.rust-lang.org/solve/candidate-preference.html#we-prefer-global-where-bounds-over-impls). There are also some other subtle reasons for why we can't do so. -The most stupid is that for rigid aliases, trying to normalize them does not consider any lifetime constraints from proving the trait bound. +The most stupid is that for rigid aliases; +trying to normalize them does not consider any lifetime constraints from proving the trait bound. This is necessary due to a lack of assumptions on binders - https://github.com/rust-lang/trait-system-refactor-initiative/issues/177 - and should be fixed longterm. -A separate issue is that right now, fetching the `type_of` associated types for `Trait` goals or in shadowed `Projection` candidates can cause query cycles for RPITIT. +A separate issue is that, right now, +fetching the `type_of` associated types for `Trait` goals or in shadowed `Projection` candidates can cause query cycles for RPITIT. See https://github.com/rust-lang/trait-system-refactor-initiative/issues/185. There are also slight differences between candidates for some of the builtin impls, these do all seem generally undesirable and I consider them to be bugs which would be fixed if we had a unified approach here. @@ -41,4 +43,3 @@ trait Trait<'a>: Super<'a, A = i32> {} // how to elaborate // T: Trait<'a> + for<'b> Super<'b, B = u32> ``` - From 425b2b385034987d24a6ea38807df1f7c4ffc8a2 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:40:47 +0200 Subject: [PATCH 29/37] skipped by sembr tool (due to "e.g.") --- .../rustc-dev-guide/src/traits/separate-projection-bounds.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md index 82f2e0caf6ce..144e27316cbb 100644 --- a/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/separate-projection-bounds.md @@ -21,7 +21,9 @@ See https://github.com/rust-lang/trait-system-refactor-initiative/issues/185. There are also slight differences between candidates for some of the builtin impls, these do all seem generally undesirable and I consider them to be bugs which would be fixed if we had a unified approach here. -Finally, not having this split makes lowering where-clauses more annoying. With the current system having duplicate where-clauses is not an issue and it can easily happen when elaborating super trait bounds. We now need to make sure we merge all associated type constraints, e.g. +Finally, not having this split makes lowering where-clauses more annoying. +With the current system having duplicate where-clauses is not an issue and it can easily happen when elaborating super trait bounds. +We now need to make sure we merge all associated type constraints, e.g.: ```rust trait Super { From b03b12e6a86343d10602ab858d8f4f2caf711321 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:41:25 +0200 Subject: [PATCH 30/37] sembr src/ty-module/generic-arguments.md --- .../src/ty-module/generic-arguments.md | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md index cbf7b2c682fc..48b7e3621087 100644 --- a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md +++ b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md @@ -24,12 +24,14 @@ Adt(&'tcx AdtDef, GenericArgs<'tcx>) There are two parts: - The [`AdtDef`][adtdef] references the struct/enum/union but without the values for its type - parameters. In our example, this is the `MyStruct` part *without* the argument `u32`. + parameters. + In our example, this is the `MyStruct` part *without* the argument `u32`. (Note that in the HIR, structs, enums and unions are represented differently, but in `ty::Ty`, they are all represented using `TyKind::Adt`.) - The [`GenericArgs`] is a list of values that are to be substituted -for the generic parameters. In our example of `MyStruct`, we would end up with a list like -`[u32]`. We’ll dig more into generics and substitutions in a little bit. +for the generic parameters. + In our example of `MyStruct`, we would end up with a list like `[u32]`. +We’ll dig more into generics and substitutions in a little bit. [adtdef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.AdtDef.html [`GenericArgs`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.GenericArgs.html @@ -37,25 +39,31 @@ for the generic parameters. In our example of `MyStruct`, we would end up ### **`AdtDef` and `DefId`** For every type defined in the source code, there is a unique `DefId` (see [this -chapter](../hir.md#identifiers-in-the-hir)). This includes ADTs and generics. In the `MyStruct` -definition we gave above, there are two `DefId`s: one for `MyStruct` and one for `T`. Notice that +chapter](../hir.md#identifiers-in-the-hir)). +This includes ADTs and generics. +In the `MyStruct` +definition we gave above, there are two `DefId`s: one for `MyStruct` and one for `T`. + Notice that the code above does not generate a new `DefId` for `u32` because it is not defined in that code (it is only referenced). -`AdtDef` is more or less a wrapper around `DefId` with lots of useful helper methods. There is -essentially a one-to-one relationship between `AdtDef` and `DefId`. You can get the `AdtDef` for a -`DefId` with the [`tcx.adt_def(def_id)` query][adtdefq]. `AdtDef`s are all interned, as shown -by the `'tcx` lifetime. +`AdtDef` is more or less a wrapper around `DefId` with lots of useful helper methods. +There is essentially a one-to-one relationship between `AdtDef` and `DefId`. +You can get the `AdtDef` for a +`DefId` with the [`tcx.adt_def(def_id)` query][adtdefq]. +`AdtDef`s are all interned, as shown by the `'tcx` lifetime. [adtdefq]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.adt_def ## Question: Why not substitute “inside” the `AdtDef`? -Recall that we represent a generic struct with `(AdtDef, args)`. So why bother with this scheme? +Recall that we represent a generic struct with `(AdtDef, args)`. +So why bother with this scheme? Well, the alternate way we could have chosen to represent types would be to always create a new, -fully-substituted form of the `AdtDef` where all the types are already substituted. This seems like -less of a hassle. However, the `(AdtDef, args)` scheme has some advantages over this. +fully-substituted form of the `AdtDef` where all the types are already substituted. +This seems like less of a hassle. +However, the `(AdtDef, args)` scheme has some advantages over this. First, `(AdtDef, args)` scheme has an efficiency win: @@ -68,7 +76,8 @@ struct MyStruct { ``` in an example like this, we can instantiate `MyStruct` as `MyStruct` (and so on) very cheaply, -by just replacing the one reference to `A` with `B`. But if we eagerly instantiated all the fields, +by just replacing the one reference to `A` with `B`. +But if we eagerly instantiated all the fields, that could be a lot more work because we might have to go through all of the fields in the `AdtDef` and update all of their types. @@ -83,7 +92,9 @@ definition of that name, and not carried along “within” the type itself). Given a generic type `MyType`, we have to store the list of generic arguments for `MyType`. -In rustc this is done using [`GenericArgs`]. `GenericArgs` is a thin pointer to a slice of [`GenericArg`] representing a list of generic arguments for a generic item. For example, given a `struct HashMap` with two type parameters, `K` and `V`, the `GenericArgs` used to represent the type `HashMap` would be represented by `&'tcx [tcx.types.i32, tcx.types.u32]`. +In rustc this is done using [`GenericArgs`]. +`GenericArgs` is a thin pointer to a slice of [`GenericArg`] representing a list of generic arguments for a generic item. +For example, given a `struct HashMap` with two type parameters, `K` and `V`, the `GenericArgs` used to represent the type `HashMap` would be represented by `&'tcx [tcx.types.i32, tcx.types.u32]`. `GenericArg` is conceptually an `enum` with three variants, one for type arguments, one for const arguments and one for lifetime arguments. In practice that is actually represented by [`GenericArgKind`] and [`GenericArg`] is a more space efficient version that has a method to @@ -146,7 +157,8 @@ The construct `MyStruct::::func::` is represented by a tuple: a The [`ty::Generics`] type (returned by the [`generics_of`] query) contains the information of how a nested hierarchy gets flattened down to a list, and lets you figure out which index in the `GenericArgs` list corresponds to which -generic. The general theme of how it works is outermost to innermost (`T` before `T2` in the example), left to right +generic. +The general theme of how it works is outermost to innermost (`T` before `T2` in the example), left to right (`T2` before `T3`), but there are several complications: - Traits have an implicit `Self` generic parameter which is the first (i.e. 0th) generic parameter. Note that `Self` doesn't mean a generic parameter in all situations, see [Res::SelfTyAlias](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def/enum.Res.html#variant.SelfTyAlias) and [Res::SelfCtor](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def/enum.Res.html#variant.SelfCtor). From 7440567b40f76ceb6f3588b69afacde24122009a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:44:26 +0200 Subject: [PATCH 31/37] re-wrap --- .../src/ty-module/generic-arguments.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md index 48b7e3621087..295b654e0ce4 100644 --- a/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md +++ b/src/doc/rustc-dev-guide/src/ty-module/generic-arguments.md @@ -41,16 +41,14 @@ We’ll dig more into generics and substitutions in a little bit. For every type defined in the source code, there is a unique `DefId` (see [this chapter](../hir.md#identifiers-in-the-hir)). This includes ADTs and generics. -In the `MyStruct` -definition we gave above, there are two `DefId`s: one for `MyStruct` and one for `T`. - Notice that -the code above does not generate a new `DefId` for `u32` because it is not defined in that code (it -is only referenced). +In the `MyStruct` definition we gave above, +there are two `DefId`s: one for `MyStruct` and one for `T`. +Notice that the code above does not generate a new `DefId` for `u32` +because it is not defined in that code (it is only referenced). `AdtDef` is more or less a wrapper around `DefId` with lots of useful helper methods. There is essentially a one-to-one relationship between `AdtDef` and `DefId`. -You can get the `AdtDef` for a -`DefId` with the [`tcx.adt_def(def_id)` query][adtdefq]. +You can get the `AdtDef` for a `DefId` with the [`tcx.adt_def(def_id)` query][adtdefq]. `AdtDef`s are all interned, as shown by the `'tcx` lifetime. [adtdefq]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.adt_def From 2554c21df2961cd8dd0b58bac7ae569859c4325f Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:45:18 +0200 Subject: [PATCH 32/37] sembr src/hir.md --- src/doc/rustc-dev-guide/src/hir.md | 54 ++++++++++++++++++------------ 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md index 250b02902377..adcf573ca749 100644 --- a/src/doc/rustc-dev-guide/src/hir.md +++ b/src/doc/rustc-dev-guide/src/hir.md @@ -1,13 +1,15 @@ # The HIR The HIR – "High-Level Intermediate Representation" – is the primary IR used -in most of rustc. It is a compiler-friendly representation of the abstract +in most of rustc. +It is a compiler-friendly representation of the abstract syntax tree (AST) that is generated after parsing, macro expansion, and name resolution (see [Lowering](./hir/lowering.md) for how the HIR is created). Many parts of HIR resemble Rust surface syntax quite closely, with the exception that some of Rust's expression forms have been desugared away. For example, `for` loops are converted into a `loop` and do not appear in -the HIR. This makes HIR more amenable to analysis than a normal AST. +the HIR. +This makes HIR more amenable to analysis than a normal AST. This chapter covers the main concepts of the HIR. @@ -30,7 +32,8 @@ cargo rustc -- -Z unpretty=hir The top-level data-structure in the HIR is the [`Crate`], which stores the contents of the crate currently being compiled (we only ever -construct HIR for the current crate). Whereas in the AST the crate +construct HIR for the current crate). +Whereas in the AST the crate data structure basically just contains the root module, the HIR `Crate` structure contains a number of maps and other things that serve to organize the content of the crate for easier access. @@ -39,8 +42,8 @@ serve to organize the content of the crate for easier access. For example, the contents of individual items (e.g. modules, functions, traits, impls, etc) in the HIR are not immediately -accessible in the parents. So, for example, if there is a module item -`foo` containing a function `bar()`: +accessible in the parents. +So, for example, if there is a module item `foo` containing a function `bar()`: ```rust mod foo { @@ -49,8 +52,8 @@ mod foo { ``` then in the HIR the representation of module `foo` (the [`Mod`] -struct) would only have the **`ItemId`** `I` of `bar()`. To get the -details of the function `bar()`, we would lookup `I` in the +struct) would only have the **`ItemId`** `I` of `bar()`. +To get the details of the function `bar()`, we would lookup `I` in the `items` map. [`Mod`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.Mod.html @@ -62,9 +65,11 @@ There are similar maps for things like trait items and impl items, as well as "bodies" (explained below). The other reason to set up the representation this way is for better -integration with incremental compilation. This way, if you gain access +integration with incremental compilation. +This way, if you gain access to an [`&rustc_hir::Item`] (e.g. for the mod `foo`), you do not immediately -gain access to the contents of the function `bar()`. Instead, you only +gain access to the contents of the function `bar()`. +Instead, you only gain access to the **id** for `bar()`, and you must invoke some function to lookup the contents of `bar()` given its id; this gives the compiler a chance to observe that you accessed the data for @@ -79,23 +84,28 @@ the compiler a chance to observe that you accessed the data for The HIR uses a bunch of different identifiers that coexist and serve different purposes. - A [`DefId`], as the name suggests, identifies a particular definition, or top-level - item, in a given crate. It is composed of two parts: a [`CrateNum`] which identifies + item, in a given crate. + It is composed of two parts: a [`CrateNum`] which identifies the crate the definition comes from, and a [`DefIndex`] which identifies the definition - within the crate. Unlike [`HirId`]s, there isn't a [`DefId`] for every expression, which + within the crate. + Unlike [`HirId`]s, there isn't a [`DefId`] for every expression, which makes them more stable across compilations. - A [`LocalDefId`] is basically a [`DefId`] that is known to come from the current crate. This allows us to drop the [`CrateNum`] part, and use the type system to ensure that only local definitions are passed to functions that expect a local definition. -- A [`HirId`] uniquely identifies a node in the HIR of the current crate. It is composed - of two parts: an `owner` and a `local_id` that is unique within the `owner`. This +- A [`HirId`] uniquely identifies a node in the HIR of the current crate. + It is composed + of two parts: an `owner` and a `local_id` that is unique within the `owner`. + This combination makes for more stable values which are helpful for incremental compilation. Unlike [`DefId`]s, a [`HirId`] can refer to [fine-grained entities][Node] like expressions, but stays local to the current crate. -- A [`BodyId`] identifies a HIR [`Body`] in the current crate. It is currently only - a wrapper around a [`HirId`]. For more info about HIR bodies, please refer to the +- A [`BodyId`] identifies a HIR [`Body`] in the current crate. + It is currently only a wrapper around a [`HirId`]. + For more info about HIR bodies, please refer to the [HIR chapter][hir-bodies]. These identifiers can be converted into one another through the `TyCtxt`. @@ -112,8 +122,8 @@ These identifiers can be converted into one another through the `TyCtxt`. ## HIR Operations -Most of the time when you are working with the HIR, you will do so via -`TyCtxt`. It contains a number of methods, defined in the `hir::map` module and +Most of the time when you are working with the HIR, you will do so via `TyCtxt`. +It contains a number of methods, defined in the `hir::map` module and mostly prefixed with `hir_`, to convert between IDs of various kinds and to lookup data associated with a HIR node. @@ -126,8 +136,10 @@ You need a `LocalDefId`, rather than a `DefId`, since only local items have HIR [local_def_id_to_hir_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.local_def_id_to_hir_id Similarly, you can use [`tcx.hir_node(n)`][hir_node] to lookup the node for a -[`HirId`]. This returns a `Option>`, where [`Node`] is an enum -defined in the map. By matching on this, you can find out what sort of +[`HirId`]. +This returns a `Option>`, where [`Node`] is an enum +defined in the map. +By matching on this, you can find out what sort of node the `HirId` referred to and also get a pointer to the data itself. Often, you know what sort of node `n` is – e.g. if you know that `n` must be some HIR expression, you can do @@ -148,8 +160,8 @@ calls like [`tcx.parent_hir_node(n)`][parent_hir_node]. ## HIR Bodies A [`rustc_hir::Body`] represents some kind of executable code, such as the body -of a function/closure or the definition of a constant. Bodies are -associated with an **owner**, which is typically some kind of item +of a function/closure or the definition of a constant. +Bodies are associated with an **owner**, which is typically some kind of item (e.g. an `fn()` or `const`), but could also be a closure expression (e.g. `|x, y| x + y`). You can use the `TyCtxt` to find the body associated with a given def-id ([`hir_maybe_body_owned_by`]) or to find From 9634bb7e6b1214ba29aa0a43ea5eaabf28d666a9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:47:51 +0200 Subject: [PATCH 33/37] re-wrap --- src/doc/rustc-dev-guide/src/hir.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md index adcf573ca749..c2e227dc936c 100644 --- a/src/doc/rustc-dev-guide/src/hir.md +++ b/src/doc/rustc-dev-guide/src/hir.md @@ -96,10 +96,9 @@ The HIR uses a bunch of different identifiers that coexist and serve different p only local definitions are passed to functions that expect a local definition. - A [`HirId`] uniquely identifies a node in the HIR of the current crate. - It is composed - of two parts: an `owner` and a `local_id` that is unique within the `owner`. - This - combination makes for more stable values which are helpful for incremental compilation. + It is composed of two parts: + an `owner` and a `local_id` that is unique within the `owner`. + This combination makes for more stable values which are helpful for incremental compilation. Unlike [`DefId`]s, a [`HirId`] can refer to [fine-grained entities][Node] like expressions, but stays local to the current crate. From d82e7c11722c469cc5d50413bd8e6c94dd44357b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:48:20 +0200 Subject: [PATCH 34/37] sembr src/rustdoc-internals.md --- src/doc/rustc-dev-guide/src/rustdoc-internals.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index 9fd05aa0b20d..a0787282a456 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -108,19 +108,21 @@ Here is the list of passes as of March 2023: - `calculate-doc-coverage` calculates information used for the `--show-coverage` flag. -- `check-doc-test-visibility` runs `doctest` visibility–related `lint`s. This pass +- `check-doc-test-visibility` runs `doctest` visibility–related `lint`s. + This pass runs before `strip-private`, which is why it needs to be separate from `run-lints`. - `collect-intra-doc-links` resolves [intra-doc links](https://doc.rust-lang.org/nightly/rustdoc/write-documentation/linking-to-items-by-name.html). -- `collect-trait-impls` collects `trait` `impl`s for each item in the crate. For +- `collect-trait-impls` collects `trait` `impl`s for each item in the crate. + For example, if we define a `struct` that implements a `trait`, this pass will note that the `struct` implements that `trait`. - `propagate-doc-cfg` propagates `#[doc(cfg(...))]` to child items. -- `run-lints` runs some of `rustdoc`'s `lint`s, defined in `passes/lint`. This is - the last pass to run. +- `run-lints` runs some of `rustdoc`'s `lint`s, defined in `passes/lint`. + This is the last pass to run. - `bare_urls` detects links that are not linkified, e.g., in Markdown such as `Go to https://example.com/.` It suggests wrapping the link with angle brackets: @@ -233,7 +235,8 @@ is complicated from two other constraints that `rustdoc` runs under: configurations, such as `libstd` having a single package of docs that cover all supported operating systems. This means `rustdoc` has to be able to generate docs from `HIR`. -* Docs can inline across crates. Since crate metadata doesn't contain `HIR`, +* Docs can inline across crates. + Since crate metadata doesn't contain `HIR`, it must be possible to generate inlined docs from the `rustc_middle` data. The "clean" [`AST`][ast] acts as a common output format for both input formats. From 9c0a07250faa60c1c032a337d3dc2cbb83bfd407 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:50:45 +0200 Subject: [PATCH 35/37] re-wrap --- src/doc/rustc-dev-guide/src/rustdoc-internals.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index a0787282a456..f3fd47812a96 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -109,15 +109,14 @@ Here is the list of passes as of March 2023: flag. - `check-doc-test-visibility` runs `doctest` visibility–related `lint`s. - This pass - runs before `strip-private`, which is why it needs to be separate from `run-lints`. + This pass runs before `strip-private`, + which is why it needs to be separate from `run-lints`. - `collect-intra-doc-links` resolves [intra-doc links](https://doc.rust-lang.org/nightly/rustdoc/write-documentation/linking-to-items-by-name.html). - `collect-trait-impls` collects `trait` `impl`s for each item in the crate. - For - example, if we define a `struct` that implements a `trait`, this pass will note - that the `struct` implements that `trait`. + For example, if we define a `struct` that implements a `trait`, + this pass will note that the `struct` implements that `trait`. - `propagate-doc-cfg` propagates `#[doc(cfg(...))]` to child items. From da97a7f7bb6c2e541fdf2bc60e63aa3675c69da5 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:52:00 +0200 Subject: [PATCH 36/37] sembr src/tests/adding.md --- src/doc/rustc-dev-guide/src/tests/adding.md | 89 ++++++++++++--------- 1 file changed, 53 insertions(+), 36 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index 10483265c468..f1c40d7324f3 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -2,12 +2,13 @@ **In general, we expect every PR that fixes a bug in rustc to come accompanied by a regression test of some kind.** This test should fail in `main` but pass -after the PR. These tests are really useful for preventing us from repeating the +after the PR. +These tests are really useful for preventing us from repeating the mistakes of the past. -The first thing to decide is which kind of test to add. This will depend on the -nature of the change and what you want to exercise. Here are some rough -guidelines: +The first thing to decide is which kind of test to add. +This will depend on the nature of the change and what you want to exercise. +Here are some rough guidelines: - The majority of compiler tests are done with [compiletest]. - The majority of compiletest tests are [UI](ui.md) tests in the [`tests/ui`] @@ -24,14 +25,17 @@ guidelines: `library/${crate}tests/lib.rs`. - If the code is part of an isolated system, and you are not testing compiler output, consider using a [unit or integration test](intro.md#package-tests). -- Need to run rustdoc? Prefer a `rustdoc` or `rustdoc-ui` test. Occasionally - you'll need `rustdoc-js` as well. +- Need to run rustdoc? + Prefer a `rustdoc` or `rustdoc-ui` test. + Occasionally you'll need `rustdoc-js` as well. - Other compiletest test suites are generally used for special purposes: - - Need to run gdb or lldb? Use the `debuginfo` test suite. - - Need to inspect LLVM IR or MIR IR? Use the `codegen` or `mir-opt` test - suites. - - Need to inspect the resulting binary in some way? Or if all the other test - suites are too limited for your purposes? Then use `run-make`. + - Need to run gdb or lldb? + Use the `debuginfo` test suite. + - Need to inspect LLVM IR or MIR IR? + Use the `codegen` or `mir-opt` test suites. + - Need to inspect the resulting binary in some way? + Or if all the other test suites are too limited for your purposes? + Then use `run-make`. - Use `run-make-cargo` if you need to exercise in-tree `cargo` in conjunction with in-tree `rustc`. - Check out the [compiletest] chapter for more specialized test suites. @@ -47,14 +51,16 @@ modified several years later, how can we make it easier for them?). ## UI test walkthrough The following is a basic guide for creating a [UI test](ui.md), which is one of -the most common compiler tests. For this tutorial, we'll be adding a test for an -async error message. +the most common compiler tests. +For this tutorial, we'll be adding a test for an async error message. ### Step 1: Add a test file The first step is to create a Rust source file somewhere in the [`tests/ui`] -tree. When creating a test, do your best to find a good location and name (see -[Test organization](ui.md#test-organization) for more). Since naming is the +tree. +When creating a test, do your best to find a good location and name (see +[Test organization](ui.md#test-organization) for more). +Since naming is the hardest part of development, everything should be downhill from here! Let's place our async test at `tests/ui/async-await/await-without-async.rs`: @@ -77,19 +83,23 @@ A few things to notice about our test: - The top should start with a short comment that [explains what the test is for](#explanatory_comment). - The `//@ edition:2018` comment is called a [directive](directives.md) which - provides instructions to compiletest on how to build the test. Here we need to + provides instructions to compiletest on how to build the test. + Here we need to set the edition for `async` to work (the default is edition 2015). -- Following that is the source of the test. Try to keep it succinct and to the - point. This may require some effort if you are trying to minimize an example +- Following that is the source of the test. + Try to keep it succinct and to the point. + This may require some effort if you are trying to minimize an example from a bug report. -- We end this test with an empty `fn main` function. This is because the default +- We end this test with an empty `fn main` function. + This is because the default for UI tests is a `bin` crate-type, and we don't want the "main not found" - error in our test. Alternatively, you could add `#![crate_type="lib"]`. + error in our test. + Alternatively, you could add `#![crate_type="lib"]`. ### Step 2: Generate the expected output -The next step is to create the expected output snapshots from the compiler. This -can be done with the `--bless` option: +The next step is to create the expected output snapshots from the compiler. +This can be done with the `--bless` option: ```sh ./x test tests/ui/async-await/await-without-async.rs --bless @@ -99,8 +109,8 @@ This will build the compiler (if it hasn't already been built), compile the test, and place the output of the compiler in a file called `tests/ui/async-await/await-without-async.stderr`. -However, this step will fail! You should see an error message, something like -this: +However, this step will fail! +You should see an error message, something like this: > error: /rust/tests/ui/async-await/await-without-async.rs:7: unexpected > error: '7:10: 7:16: `await` is only allowed inside `async` functions and @@ -112,7 +122,8 @@ annotations in the source file. ### Step 3: Add error annotations Every error needs to be annotated with a comment in the source with the text of -the error. In this case, we can add the following comment to our test file: +the error. +In this case, we can add the following comment to our test file: ```rust,ignore fn bar() { @@ -136,7 +147,8 @@ It should now pass, yay! ### Step 4: Review the output Somewhat hand-in-hand with the previous step, you should inspect the `.stderr` -file that was created to see if it looks like how you expect. If you are adding +file that was created to see if it looks like how you expect. +If you are adding a new diagnostic message, now would be a good time to also consider how readable the message looks overall, particularly for people new to Rust. @@ -161,9 +173,9 @@ You may notice some things look a little different than the regular compiler output. - The `$DIR` removes the path information which will differ between systems. -- The `LL` values replace the line numbers. That helps avoid small changes in - the source from triggering large diffs. See the - [Normalization](ui.md#normalization) section for more. +- The `LL` values replace the line numbers. + That helps avoid small changes in the source from triggering large diffs. + See the [Normalization](ui.md#normalization) section for more. Around this stage, you may need to iterate over the last few steps a few times to tweak your test, re-bless the test, and re-review the output. @@ -171,8 +183,10 @@ to tweak your test, re-bless the test, and re-review the output. ### Step 5: Check other tests Sometimes when adding or changing a diagnostic message, this will affect other -tests in the test suite. The final step before posting a PR is to check if you -have affected anything else. Running the UI suite is usually a good start: +tests in the test suite. +The final step before posting a PR is to check if you +have affected anything else. +Running the UI suite is usually a good start: ```sh ./x test tests/ui @@ -188,16 +202,19 @@ You may also need to re-bless the output with the `--bless` flag. ## Comment explaining what the test is about The first comment of a test file should **summarize the point of the test**, and -highlight what is important about it. If there is an issue number associated -with the test, include the issue number. +highlight what is important about it. +If there is an issue number associated with the test, include the issue number. -This comment doesn't have to be super extensive. Just something like "Regression +This comment doesn't have to be super extensive. +Just something like "Regression test for #18060: match arms were matching in the wrong order." might already be enough. These comments are very useful to others later on when your test breaks, since -they often can highlight what the problem is. They are also useful if for some +they often can highlight what the problem is. +They are also useful if for some reason the tests need to be refactored, since they let others know which parts -of the test were important. Often a test must be rewritten because it no longer +of the test were important. +Often a test must be rewritten because it no longer tests what it was meant to test, and then it's useful to know what it *was* meant to test exactly. From 050110d50736b20e9b7b1ebac6cb1d5bbadc3024 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 8 Apr 2026 08:57:19 +0200 Subject: [PATCH 37/37] re-flow --- src/doc/rustc-dev-guide/src/tests/adding.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index f1c40d7324f3..7e2b9015f8d3 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -148,9 +148,9 @@ It should now pass, yay! Somewhat hand-in-hand with the previous step, you should inspect the `.stderr` file that was created to see if it looks like how you expect. -If you are adding -a new diagnostic message, now would be a good time to also consider how readable -the message looks overall, particularly for people new to Rust. +If you are adding a new diagnostic message, +now would be a good time to also consider how readable the message looks overall, +particularly for people new to Rust. Our example `tests/ui/async-await/await-without-async.stderr` file should look like this: @@ -206,9 +206,8 @@ highlight what is important about it. If there is an issue number associated with the test, include the issue number. This comment doesn't have to be super extensive. -Just something like "Regression -test for #18060: match arms were matching in the wrong order." might already be -enough. +Just something like the following might be enough: +"Regression test for #18060: match arms were matching in the wrong order". These comments are very useful to others later on when your test breaks, since they often can highlight what the problem is.