From 66b489f42f682bddd01e8e1a5207a8337f44a79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 20 Jun 2026 16:10:53 +0200 Subject: [PATCH 01/25] Update syntax of try build delegation in bors --- src/doc/rustc-dev-guide/src/tests/ci.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 8f06d69d8cffe..31c6949d85d6c 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -209,7 +209,7 @@ to help make the perf comparison as fair as possible. > > 3. Run the prescribed try jobs with `@bors try`. As aforementioned, this > requires the user to either (1) have `try` permissions or (2) be delegated -> with `try` permissions by `@bors delegate=try` by someone who has `try` +> with `try` permissions by `@bors delegate try` by someone who has `try` > permissions. > > Note that this is usually easier to do than manually edit [`jobs.yml`]. From 35990d1bd15a3a10efca261cfef4d1ef00b5188c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 22 Jun 2026 14:24:53 +0200 Subject: [PATCH 02/25] do not use title case for section names --- src/doc/rustc-dev-guide/src/compiler-debugging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index a07b418c64d4d..f9766706ad133 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -248,7 +248,7 @@ You can then look at the PR to get more context on *why* it was changed. [bisect]: https://github.com/rust-lang/cargo-bisect-rustc [bisect-tutorial]: https://rust-lang.github.io/cargo-bisect-rustc/tutorial.html -## Downloading Artifacts from Rust's CI +## Downloading artifacts from Rust's CI The [rustup-toolchain-install-master][rtim] tool by kennytm can be used to download the artifacts produced by Rust's CI for a specific SHA1 -- this From 616c9f81997cf2e04fea6806bdc31543a8759714 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 22 Jun 2026 14:27:11 +0200 Subject: [PATCH 03/25] do not use title case for section names (part 2) --- src/doc/rustc-dev-guide/src/compiler-debugging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index a07b418c64d4d..2a4365ba669ef 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -236,7 +236,7 @@ The compiler uses the [`tracing`] crate for logging. For details, see [the chapter on tracing](./tracing.md). -## Narrowing (Bisecting) Regressions +## Narrowing (bisecting) regressions The [cargo-bisect-rustc][bisect] tool can be used as a quick and easy way to find exactly which PR caused a change in `rustc` behavior. From 4928ea5384ba03ed9560890408938f76190199f2 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 29 Jun 2026 05:50:11 +0000 Subject: [PATCH 04/25] Prepare for merging from rust-lang/rust This updates the rust-version file to 7fb284d9037fa54f6a9b24261c82b394472cbfd7. --- 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 a05eac34eb1e9..f930573748e28 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -8c75e93c5c7671c29f3e8c096b7acf56822ed23a +7fb284d9037fa54f6a9b24261c82b394472cbfd7 From 9af8904a21515948826ea28aa65f1421b13aa756 Mon Sep 17 00:00:00 2001 From: Fallible <118682743+fallible-algebra@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:54:29 +0100 Subject: [PATCH 05/25] Add well-formedness chapter --- src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + .../src/analysis/well-formed.md | 293 ++++++++++++++++++ .../rustc-dev-guide/src/appendix/glossary.md | 1 + 3 files changed, 295 insertions(+) create mode 100644 src/doc/rustc-dev-guide/src/analysis/well-formed.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 9a9861186011d..9b59170de4d05 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -191,6 +191,7 @@ - [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) +- [Well-Formedness](./analysis/well-formed.md) - [Variance](./variance.md) - [Coherence checking](./coherence.md) - [HIR Type checking](./hir-typeck/summary.md) diff --git a/src/doc/rustc-dev-guide/src/analysis/well-formed.md b/src/doc/rustc-dev-guide/src/analysis/well-formed.md new file mode 100644 index 0000000000000..49c9509fea466 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/analysis/well-formed.md @@ -0,0 +1,293 @@ +# Well-Formedness + +## What is Well-Formedness? + +"Well-formed" means "correctly built."[^wf-history] Something is _well-formed_ when its structure follows rules. When we use this term in the Rust compiler we are concerned with establishing some kind of _internal consistency_. + +## Well-Formedness in Rust + +To check that something is well-formed is to perform a "Well-formedness check." + +In the Rust compiler there are two different forms of well-formedness checking: + +- **Type-Level Term**[^terms][^terms-abbreviated] well-formedness check. + - Also called "Term well-formedness" or "Term well-formedness checking." + - Not a distinct analysis stage, this gets performed throughout analysis. +- **Item**[^items] well-formedness check (item-wfck.) + - "Item-wfck" will often wind up requiring Terms be well-formed, but skips some areas. + - Inner "Terms" can (incorrectly) get normalized first. + - More coherent as a stage in the compiler than "term well-formedness" (which is performed in many places.) + +See: [What Well-Formedness Isn't](#what-well-formedness-isnt). + +## Well-Formedness of Type-Level Terms + +Term well-formedness checking begins with building a list of things that need to be true for a term to be well-formed. We call these "Obligations"[^obligations]. + +Type-Level Terms are considered Well-Formed when their associated obligations are satisfied by the trait solver. + +### Obligations for Well-Formedness + +Specific obligations are things like `String: Clone`, `A: usize`, or `::Item: Debug`. + +On this page we show the split between obligations and terms/items as: + +```rust,ignore + +--- + +``` + +Here is an example of a well-formed type-level term: + +```rust,ignore +Vec +--- +// Obligations to fulfill +Vec where T: Sized +// Trait solver says `String: Sized` is true, so this is well-formed. +Vec where String: Sized +``` + +When we compute the obligations for `Vec`, we'll find that `Vec` generates the obligation `T: Sized`. We substitute `T` with `String` in `Vec`, so we find the obligation `String: Sized` which the trait solver will determine to be satisfied. + +The following **is not** well-formed: + +```rust,ignore +Vec +--- +// Obligations to fulfill +Vec where T: Sized +// Trait solver says `str: Sized` is not true, so this is not well-formed. +Vec where str: Sized +``` + +The above computes the obligation `T: Sized`, like before, but we substitute `T` for `str` in the instance of `Vec` finding the obligation `str: sized`. This obligation will be determined by the trait solver to be _unsatisfied_. + +#### Determining Obligations + +In the compiler, obligations of terms are found through the [`obligations`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/wf/fn.obligations.html) function in the [term well-formedness module](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/wf/index.html). + +#### Other Obligations + +Obligations are more than just trait and const generic bounds, but we've only mentioned these specific obligations so far as they are what we care about when we do "well-formedness checking" of terms. See: [`PredicateKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.PredicateKind.html) and [`ClauseKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.ClauseKind.html) for a full list of obligations. + +### We Don't Need Normalization (Yet) + +[Normalization](../normalization.md) is the process of resolving [type aliases](../normalization.md#aliases) into their underlying type. + +A type alias is considered well-formed if its where clauses are satisfied. The underlying type undergoes well-formedness checking at most definition and instantiation sites, but there are exceptions. + +### Const Generic Arguments + +Term well-formedness is responsible for getting "type checking" obligations of const generic terms[^tyck-const-generics]. Let's look at the following use of const generics: + +```rust,ignore +fn use_const_generics() { /* ... */ } +// call site +use_const_generics::<6>(); +--- +// call site wfck obligations +const 6: usize +``` + +The call site will provide us with the obligation `6: usize` during well-formedness checking. This obligation will be passed off to the trait solver just like any trait-style obligation, as the trait solver has more responsibilities than its name suggests. + +## Well-Formedness of Items + +Items are, generally speaking, "Things that get defined." Item-wfck happens at the signature level for types and functions, methods, and definitions/implementations of traits. + +```rust,ignore +// The `Vec` is checked during item wfck +fn foo(_: Vec) { + // The `Vec<[u8]>` is not handled by item wfck as it's not in the signature + let _: Vec<[u8]> +} +--- +Vec: Sized // Generated +Vec<[u8]>: Sized // Not done at item-wfck. Done elsewhere. +``` + +Item-wfck has more responsibilities than only collecting the obligations of its internal type-level terms and passing them to the trait solver. We do not talk about all of these here, but they can be found at the individual `check_*` functions in [**the item-wfck module**](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/index.html). + + + +### Global and Trivial Bounds + + + +Trait bounds are a common Obligation. Global and Trivial trait bounds are kinds of trait bounds where we already have enough information to determine if they are true or false. Item-wfck is responsible for finding and checking these bounds. + +- **Global bounds** are, in the old solver, post-normalization bounds that don't contain any generic parameters (like `` or `'a`) or bound variables (like `for<'b>`). +- **Trivial bounds** are bounds that do not need further normalization to determine if they're well-formed or not. + +Consider the following function definition: + +```rust,ignore +fn apartment_complex(block: T, name: String) where String: Clone { /* ... */ } +--- +String: Clone // Trivial & Global bound! There's no aliases to resolve. +// There could be bligations on T but we don't care about them here. +``` + +This produces a trait bound obligation `String: Clone` that is _Global_ (no generic parameters) and _Trivial_ (didn't require normalization to be well-formedness checked). The trait solver doesn't need to be given any additional information for it to be able to make a judgment on the well-formedness of `String: Clone`. + +False trivial bounds are simply trivial bounds that do not hold. The following is a basic example: + +```rust,ignore +fn apartment_simple(block: T, name: String) where String: Copy { /* ... */ } +--- +String: Copy // Trivial bound again, but this one is false! +``` + +Here we have a trivial bound that does not hold, because `String` is not `Copy`. + +#### Trivial Bounds Are Not Always Global + +Trivial Bounds are not a subset of Global Bounds. A trivial bound that isn't Global is `for<'a> String: Clone` (trivially true, has a bound variable) or `&'a str: Copy` (trivially false, has a generic parameter). + +#### Item-Wfck and Trivial/Global Bounds + + + +When checking items are well-formed we will check that there are no trivially false global bounds. + +## When We Don't Fully Do Well-Formedness Checking + +Well-formedness checking is not a coherent "stage" of type checking. There are many areas where well-formedness checking is performed, and some areas where we skip over well-formedness checking due to limitations in what kinds of analysis we can currently perform. Ideally, we would never skip or defer well-formedness checking. + +### We (Sometimes) Need Normalization + +There are places where normalization of an Item happens before its Terms have gone through well-formedness checking. This is considered problematic as doing so allows some terms to [bypass term well-formedness checking entirely](https://github.com/rust-lang/rust/issues/100041). + +### Trait Objects + +We do not require the where clauses of trait objects to be well-formed when determining if that trait object is well-formed. These where clauses are proven when coercing into a trait object, but this remains a hole in well-formedness checking. + +As an example, the following will compile because we don't have a point where we're constructing the trait object from a concrete type: + +```rust,ignore +trait Trait +where + for<'a> [u8]: Sized {} + +fn foo(_: &dyn Trait) {} +--- +// This doesn't end up being generated, because it happens within a trait object. +[u8]: Sized +``` + +The above should not compile because `[u8]: Sized`, but this won't be checked until actual use: + +```rust +trait Trait +where + for<'a> [u8]: Sized {} + +fn foo(_: &dyn Trait) {} + +// We still need to specify the bound here, otherwise `[u8]: Sized` _is_ +// checked as an obligation. +impl Trait for u8 where for<'a> [u8]: Sized {} + +fn main() { + // No matter what we do, this boundary between concrete type and trait + // object will produce the obligation `[u8]: Sized`, which will fail when + // handed over to the trait solver. + let object: Box = Box::new(42u8); + foo(&object); +} +``` + +This exception does not apply to Const Generic Arguments in trait objects: + +```rust,ignore +trait Trait {} +fn foo(_: &dyn Trait) {} +--- +const N: usize +const B: bool +N = B // Substitution +const B: usize + bool +``` + +The above doesn't compile, unlike the previous example we gave. We're doing _some_ well-formedness checking here when it comes to the const generic arguments. + +### Binders / Higher-Ranked Types + +Binders / Higher-Ranked Types reduce the amount well-formedness checking we do on a term, leaving well-formedness checking to when the bound is instantiated: + +```rust,ignore +let _: for<'a> fn(Vec<[&'a ()]>); +--- +// This doesn't end up being generated, because it happens within a HRB +[&'a ()]: Sized // slices aren't sized, this would fail! +``` + +Specifically, obligations involving variables from binders (`for<'a>`) are only checked when the binder is instantiated. Some things are stilled checked under the `for<'a>`, but we still skip a lot of things. + +A lot of unsoundness surrounds this behavior. See: [#25860](https://github.com/rust-lang/rust/issues/25860), [#84591](https://github.com/rust-lang/rust/issues/84591). + +Let's consider the following: + +```rust,ignore +for<'a, 'b> fn(&'a &'b ()) +``` + +The above HRB implies `'b: 'a` (a lifetime bound), rather than two completely separate lifetimes. This is normal lifetime behavior, but during well-formedness checking we cannot prove that this bound is generally true[^horrible], so we skip it. + +### Free Type Aliases + +The right-hand side of Free Type Aliases[^fta] is not fully checked to be well-formed at the definition site, only the types of const generic arguments in the RHS are checked. + +The following free type alias passes type checking, at time of writing: + +```rust,ignore +type WorksButShouldNot = Vec; +--- +// This should fail! But we skip the RHS of free type aliases +str: Sized // Not generated +``` + +This shouldn't work, as both `T: Sized`, `str: Sized` are implied by `Vec`. This "passes" item-wfck because the RHS of a free type alias doesn't go through well-formedness checking _until it's used_. Item-wfck is **deferred until use** for this specific case. + +For Const Generics we still do a small amount of well-formedness checking at the definition site of a free type alias. This is consistent with our current special-casing of const generic well-formedness checking when we skip over things like where bounds. + +This means that the following, despite being of a similar form to the above example, fails as it should: + +```rust,ignore +pub struct Consty; +type Alias = Consty<42>; +--- +// This *is* generated as an obligation, so this (correctly) fails. +42: bool // This is generated! +``` + + + +## "Well-Formed" or "Wellformed"? + +Prefer "well-formed" over "wellformed," as this is consistent with logic literature. This also gets abbreviated to WF in other parts of the dev guide / docs. + +## Informal Usage + +In conversation, contributors may refer to something as "well-formed" and not necessarily mean what we cover here because "well-formedness" is a general phrase associated with the correctness of formal structures. This isn't necessarily in error, but it should be looked out for. + +## What Well-Formedness Isn't + +Well-formedness checking is not "number of parameters" or "parameter type" checking[^kind-checking]. Neither term well-formedness checking nor item-wfck is concerned with if a type with 2 parameters has 1 or 3 types applied to it (assuming no defaults), or if a const generic parameter has a type applied to it. These kinds of problems will get handled during HIR-ty Lowering[^hir-ty-lower], not wfck. + +Well-formedness doesn't check or validate lifetimes, this is handled in [MIR](../borrow-check.md). + +Well-formedness in the Rust compiler doesn't correspond to "correct syntax" as it does in logic. The term has a history of general use in a mathematical context of "follows a given set of rules." In Rust, our original usage was closer to "this thing is internally consistent" with respect to the bounds on a type in places such as the original [clarification on projections and well-formedness RFC](https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md). + +[^obligations]: These get referred to as Obligations, Requirements, or Constraints in the documentation. Preferred term is "obligations", as this matches the suffix of the type and the names of relevant functions. In future, this may be superseded by the new solver's term "Goal." +[^wf-history]: In linguistics this is "grammatically correct," in logic it is "syntactically correct," and in casual mathematician use it can be read as a more general "follows the rules we set for this domain." +[^horrible]: Instead, this bound is checked during "MIR borrowck" when the lifetimes are instantiated. +[^fta]: Type aliases not associated with anything, i.e. a module-level `type Alias = Vec;`. +[^items]: "Definition" style things in rust, See the [glossary](../appendix/glossary.md). +[^terms]: AKA Type expressions and subexpressions in the general sense, not a specific struct or enum in the rust compiler. See the [glossary](../appendix/glossary.md). +[^terms-abbreviated]: Abbreviated as "Terms" on this page in some areas. +[^kind-checking]: AKA "kind checking", as we might see in languages like Haskell. +[^hir-ty-lower]: +[^tyck-const-generics]: \ No newline at end of file diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 30959f4b39e6f..527da87b7b7e1 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -102,6 +102,7 @@ Term | Meaning 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. +Type-Level Term | An expression at the type level, such as a Type or Const Generic. 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. From 6bf1cd9b2c2ad1a0d50ed9173ad211c31013c389 Mon Sep 17 00:00:00 2001 From: Kiran Shila Date: Tue, 23 Jun 2026 12:43:41 -0700 Subject: [PATCH 06/25] update autodiff install docs for nix --- .../src/autodiff/installation.md | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/autodiff/installation.md b/src/doc/rustc-dev-guide/src/autodiff/installation.md index 7247efd46a380..4176763a7bd62 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/installation.md +++ b/src/doc/rustc-dev-guide/src/autodiff/installation.md @@ -18,30 +18,30 @@ Please run: rustup +nightly component add enzyme ``` -## Installation guide for Nix user. +## Installation guide for Nix + +On [Nix], you can declare a nightly Rust toolchain with the Enzyme component using the [oxalica rust-overlay]. + +For example: + +```nix +rust-bin.selectLatestNightlyWith (toolchain: toolchain.default.override { + extensions = [ "enzyme" ]; +}) +``` + +Alternatively, you can create a [toolchain file] that declares the Enzyme component such as + +```toml +[toolchain] +channel = "nightly-2026-06-23" +components = [ "enzyme" ] +``` + +and consume it in the overlay -This setup was recommended by a nix and autodiff user. -It uses [`Overlay`]. -Please verify for yourself if you are comfortable using that repository. -In that case you might use the following nix configuration to get a rustc that supports `std::autodiff`. ```nix -{ - enzymeLib = pkgs.fetchzip { - url = "https://ci-artifacts.rust-lang.org/rustc-builds/ec818fda361ca216eb186f5cf45131bd9c776bb4/enzyme-nightly-x86_64-unknown-linux-gnu.tar.xz"; - sha256 = "sha256-Rnrop44vzS+qmYNaRoMNNMFyAc3YsMnwdNGYMXpZ5VY="; - }; - - rustToolchain = pkgs.symlinkJoin { - name = "rust-with-enzyme"; - paths = [pkgs.rust-bin.nightly.latest.default]; - nativeBuildInputs = [pkgs.makeWrapper]; - postBuild = '' - libdir=$out/lib/rustlib/x86_64-unknown-linux-gnu/lib - cp ${enzymeLib}/enzyme-preview/lib/rustlib/x86_64-unknown-linux-gnu/lib/libEnzyme-22.so $libdir/ - wrapProgram $out/bin/rustc --add-flags "--sysroot $out" - ''; - }; -} +rust-bin.fromRustupToolchainFile ./rust-toolchain.toml ``` ## Build instructions @@ -135,4 +135,6 @@ This will build Enzyme, and you can find it in `Enzyme/enzyme/build/lib/ Date: Wed, 1 Jul 2026 04:39:15 +0200 Subject: [PATCH 07/25] Fix typo in best-practices.md --- src/doc/rustc-dev-guide/src/tests/best-practices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md index b6daffa6683c0..c0230c6717473 100644 --- a/src/doc/rustc-dev-guide/src/tests/best-practices.md +++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md @@ -171,7 +171,7 @@ place. If a test suite can randomly spuriously fail due to flaky tests, did the whole test suite pass or did I just get lucky/unlucky? -- Flaky tests can randomly fail in full CI, wasting previous full CI resources. +- Flaky tests can randomly fail in full CI, wasting precious full CI resources. ## Compiletest directives From a4eba1dae50971b11bbdad7bbe65de3275b2a5a3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 1 Jul 2026 09:12:53 +0200 Subject: [PATCH 08/25] make more simple --- src/doc/rustc-dev-guide/src/tests/best-practices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md index c0230c6717473..d1378a849a9d4 100644 --- a/src/doc/rustc-dev-guide/src/tests/best-practices.md +++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md @@ -171,7 +171,7 @@ place. If a test suite can randomly spuriously fail due to flaky tests, did the whole test suite pass or did I just get lucky/unlucky? -- Flaky tests can randomly fail in full CI, wasting precious full CI resources. +- Flaky tests can randomly fail in full CI, wasting precious resources. ## Compiletest directives From c341ff552bdc30be78db9603e0519819561865bc Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 10:59:05 +0200 Subject: [PATCH 09/25] sembr src/analysis/well-formed.md --- .../src/analysis/well-formed.md | 88 +++++++++++++------ 1 file changed, 59 insertions(+), 29 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/analysis/well-formed.md b/src/doc/rustc-dev-guide/src/analysis/well-formed.md index 49c9509fea466..464ffce817369 100644 --- a/src/doc/rustc-dev-guide/src/analysis/well-formed.md +++ b/src/doc/rustc-dev-guide/src/analysis/well-formed.md @@ -2,7 +2,8 @@ ## What is Well-Formedness? -"Well-formed" means "correctly built."[^wf-history] Something is _well-formed_ when its structure follows rules. When we use this term in the Rust compiler we are concerned with establishing some kind of _internal consistency_. +"Well-formed" means "correctly built."[^wf-history] Something is _well-formed_ when its structure follows rules. +When we use this term in the Rust compiler we are concerned with establishing some kind of _internal consistency_. ## Well-Formedness in Rust @@ -12,7 +13,7 @@ In the Rust compiler there are two different forms of well-formedness checking: - **Type-Level Term**[^terms][^terms-abbreviated] well-formedness check. - Also called "Term well-formedness" or "Term well-formedness checking." - - Not a distinct analysis stage, this gets performed throughout analysis. + - Not a distinct analysis stage, this gets performed throughout analysis. - **Item**[^items] well-formedness check (item-wfck.) - "Item-wfck" will often wind up requiring Terms be well-formed, but skips some areas. - Inner "Terms" can (incorrectly) get normalized first. @@ -22,7 +23,8 @@ See: [What Well-Formedness Isn't](#what-well-formedness-isnt). ## Well-Formedness of Type-Level Terms -Term well-formedness checking begins with building a list of things that need to be true for a term to be well-formed. We call these "Obligations"[^obligations]. +Term well-formedness checking begins with building a list of things that need to be true for a term to be well-formed. +We call these "Obligations"[^obligations]. Type-Level Terms are considered Well-Formed when their associated obligations are satisfied by the trait solver. @@ -49,7 +51,8 @@ Vec where T: Sized Vec where String: Sized ``` -When we compute the obligations for `Vec`, we'll find that `Vec` generates the obligation `T: Sized`. We substitute `T` with `String` in `Vec`, so we find the obligation `String: Sized` which the trait solver will determine to be satisfied. +When we compute the obligations for `Vec`, we'll find that `Vec` generates the obligation `T: Sized`. +We substitute `T` with `String` in `Vec`, so we find the obligation `String: Sized` which the trait solver will determine to be satisfied. The following **is not** well-formed: @@ -62,7 +65,8 @@ Vec where T: Sized Vec where str: Sized ``` -The above computes the obligation `T: Sized`, like before, but we substitute `T` for `str` in the instance of `Vec` finding the obligation `str: sized`. This obligation will be determined by the trait solver to be _unsatisfied_. +The above computes the obligation `T: Sized`, like before, but we substitute `T` for `str` in the instance of `Vec` finding the obligation `str: sized`. +This obligation will be determined by the trait solver to be _unsatisfied_. #### Determining Obligations @@ -70,17 +74,20 @@ In the compiler, obligations of terms are found through the [`obligations`](http #### Other Obligations -Obligations are more than just trait and const generic bounds, but we've only mentioned these specific obligations so far as they are what we care about when we do "well-formedness checking" of terms. See: [`PredicateKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.PredicateKind.html) and [`ClauseKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.ClauseKind.html) for a full list of obligations. +Obligations are more than just trait and const generic bounds, but we've only mentioned these specific obligations so far as they are what we care about when we do "well-formedness checking" of terms. +See: [`PredicateKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.PredicateKind.html) and [`ClauseKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.ClauseKind.html) for a full list of obligations. ### We Don't Need Normalization (Yet) -[Normalization](../normalization.md) is the process of resolving [type aliases](../normalization.md#aliases) into their underlying type. +[Normalization](../normalization.md) is the process of resolving [type aliases](../normalization.md#aliases) into their underlying type. -A type alias is considered well-formed if its where clauses are satisfied. The underlying type undergoes well-formedness checking at most definition and instantiation sites, but there are exceptions. +A type alias is considered well-formed if its where clauses are satisfied. +The underlying type undergoes well-formedness checking at most definition and instantiation sites, but there are exceptions. ### Const Generic Arguments -Term well-formedness is responsible for getting "type checking" obligations of const generic terms[^tyck-const-generics]. Let's look at the following use of const generics: +Term well-formedness is responsible for getting "type checking" obligations of const generic terms[^tyck-const-generics]. +Let's look at the following use of const generics: ```rust,ignore fn use_const_generics() { /* ... */ } @@ -91,7 +98,8 @@ use_const_generics::<6>(); const 6: usize ``` -The call site will provide us with the obligation `6: usize` during well-formedness checking. This obligation will be passed off to the trait solver just like any trait-style obligation, as the trait solver has more responsibilities than its name suggests. +The call site will provide us with the obligation `6: usize` during well-formedness checking. +This obligation will be passed off to the trait solver just like any trait-style obligation, as the trait solver has more responsibilities than its name suggests. ## Well-Formedness of Items @@ -108,7 +116,8 @@ Vec: Sized // Generated Vec<[u8]>: Sized // Not done at item-wfck. Done elsewhere. ``` -Item-wfck has more responsibilities than only collecting the obligations of its internal type-level terms and passing them to the trait solver. We do not talk about all of these here, but they can be found at the individual `check_*` functions in [**the item-wfck module**](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/index.html). +Item-wfck has more responsibilities than only collecting the obligations of its internal type-level terms and passing them to the trait solver. +We do not talk about all of these here, but they can be found at the individual `check_*` functions in [**the item-wfck module**](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/wfcheck/index.html). @@ -116,7 +125,9 @@ Item-wfck has more responsibilities than only collecting the obligations of its -Trait bounds are a common Obligation. Global and Trivial trait bounds are kinds of trait bounds where we already have enough information to determine if they are true or false. Item-wfck is responsible for finding and checking these bounds. +Trait bounds are a common Obligation. +Global and Trivial trait bounds are kinds of trait bounds where we already have enough information to determine if they are true or false. +Item-wfck is responsible for finding and checking these bounds. - **Global bounds** are, in the old solver, post-normalization bounds that don't contain any generic parameters (like `` or `'a`) or bound variables (like `for<'b>`). - **Trivial bounds** are bounds that do not need further normalization to determine if they're well-formed or not. @@ -130,9 +141,11 @@ String: Clone // Trivial & Global bound! There's no aliases to resolve. // There could be bligations on T but we don't care about them here. ``` -This produces a trait bound obligation `String: Clone` that is _Global_ (no generic parameters) and _Trivial_ (didn't require normalization to be well-formedness checked). The trait solver doesn't need to be given any additional information for it to be able to make a judgment on the well-formedness of `String: Clone`. +This produces a trait bound obligation `String: Clone` that is _Global_ (no generic parameters) and _Trivial_ (didn't require normalization to be well-formedness checked). +The trait solver doesn't need to be given any additional information for it to be able to make a judgment on the well-formedness of `String: Clone`. -False trivial bounds are simply trivial bounds that do not hold. The following is a basic example: +False trivial bounds are simply trivial bounds that do not hold. +The following is a basic example: ```rust,ignore fn apartment_simple(block: T, name: String) where String: Copy { /* ... */ } @@ -144,7 +157,8 @@ Here we have a trivial bound that does not hold, because `String` is not `Copy`. #### Trivial Bounds Are Not Always Global -Trivial Bounds are not a subset of Global Bounds. A trivial bound that isn't Global is `for<'a> String: Clone` (trivially true, has a bound variable) or `&'a str: Copy` (trivially false, has a generic parameter). +Trivial Bounds are not a subset of Global Bounds. +A trivial bound that isn't Global is `for<'a> String: Clone` (trivially true, has a bound variable) or `&'a str: Copy` (trivially false, has a generic parameter). #### Item-Wfck and Trivial/Global Bounds @@ -154,15 +168,19 @@ When checking items are well-formed we will check that there are no trivially fa ## When We Don't Fully Do Well-Formedness Checking -Well-formedness checking is not a coherent "stage" of type checking. There are many areas where well-formedness checking is performed, and some areas where we skip over well-formedness checking due to limitations in what kinds of analysis we can currently perform. Ideally, we would never skip or defer well-formedness checking. +Well-formedness checking is not a coherent "stage" of type checking. +There are many areas where well-formedness checking is performed, and some areas where we skip over well-formedness checking due to limitations in what kinds of analysis we can currently perform. +Ideally, we would never skip or defer well-formedness checking. ### We (Sometimes) Need Normalization -There are places where normalization of an Item happens before its Terms have gone through well-formedness checking. This is considered problematic as doing so allows some terms to [bypass term well-formedness checking entirely](https://github.com/rust-lang/rust/issues/100041). +There are places where normalization of an Item happens before its Terms have gone through well-formedness checking. +This is considered problematic as doing so allows some terms to [bypass term well-formedness checking entirely](https://github.com/rust-lang/rust/issues/100041). ### Trait Objects -We do not require the where clauses of trait objects to be well-formed when determining if that trait object is well-formed. These where clauses are proven when coercing into a trait object, but this remains a hole in well-formedness checking. +We do not require the where clauses of trait objects to be well-formed when determining if that trait object is well-formed. +These where clauses are proven when coercing into a trait object, but this remains a hole in well-formedness checking. As an example, the following will compile because we don't have a point where we're constructing the trait object from a concrete type: @@ -211,7 +229,8 @@ N = B // Substitution const B: usize + bool ``` -The above doesn't compile, unlike the previous example we gave. We're doing _some_ well-formedness checking here when it comes to the const generic arguments. +The above doesn't compile, unlike the previous example we gave. +We're doing _some_ well-formedness checking here when it comes to the const generic arguments. ### Binders / Higher-Ranked Types @@ -224,9 +243,11 @@ let _: for<'a> fn(Vec<[&'a ()]>); [&'a ()]: Sized // slices aren't sized, this would fail! ``` -Specifically, obligations involving variables from binders (`for<'a>`) are only checked when the binder is instantiated. Some things are stilled checked under the `for<'a>`, but we still skip a lot of things. +Specifically, obligations involving variables from binders (`for<'a>`) are only checked when the binder is instantiated. +Some things are stilled checked under the `for<'a>`, but we still skip a lot of things. -A lot of unsoundness surrounds this behavior. See: [#25860](https://github.com/rust-lang/rust/issues/25860), [#84591](https://github.com/rust-lang/rust/issues/84591). +A lot of unsoundness surrounds this behavior. +See: [#25860](https://github.com/rust-lang/rust/issues/25860), [#84591](https://github.com/rust-lang/rust/issues/84591). Let's consider the following: @@ -234,7 +255,8 @@ Let's consider the following: for<'a, 'b> fn(&'a &'b ()) ``` -The above HRB implies `'b: 'a` (a lifetime bound), rather than two completely separate lifetimes. This is normal lifetime behavior, but during well-formedness checking we cannot prove that this bound is generally true[^horrible], so we skip it. +The above HRB implies `'b: 'a` (a lifetime bound), rather than two completely separate lifetimes. +This is normal lifetime behavior, but during well-formedness checking we cannot prove that this bound is generally true[^horrible], so we skip it. ### Free Type Aliases @@ -249,9 +271,12 @@ type WorksButShouldNot = Vec; str: Sized // Not generated ``` -This shouldn't work, as both `T: Sized`, `str: Sized` are implied by `Vec`. This "passes" item-wfck because the RHS of a free type alias doesn't go through well-formedness checking _until it's used_. Item-wfck is **deferred until use** for this specific case. +This shouldn't work, as both `T: Sized`, `str: Sized` are implied by `Vec`. +This "passes" item-wfck because the RHS of a free type alias doesn't go through well-formedness checking _until it's used_. +Item-wfck is **deferred until use** for this specific case. -For Const Generics we still do a small amount of well-formedness checking at the definition site of a free type alias. This is consistent with our current special-casing of const generic well-formedness checking when we skip over things like where bounds. +For Const Generics we still do a small amount of well-formedness checking at the definition site of a free type alias. +This is consistent with our current special-casing of const generic well-formedness checking when we skip over things like where bounds. This means that the following, despite being of a similar form to the above example, fails as it should: @@ -267,19 +292,24 @@ type Alias = Consty<42>; ## "Well-Formed" or "Wellformed"? -Prefer "well-formed" over "wellformed," as this is consistent with logic literature. This also gets abbreviated to WF in other parts of the dev guide / docs. +Prefer "well-formed" over "wellformed," as this is consistent with logic literature. +This also gets abbreviated to WF in other parts of the dev guide / docs. ## Informal Usage -In conversation, contributors may refer to something as "well-formed" and not necessarily mean what we cover here because "well-formedness" is a general phrase associated with the correctness of formal structures. This isn't necessarily in error, but it should be looked out for. +In conversation, contributors may refer to something as "well-formed" and not necessarily mean what we cover here because "well-formedness" is a general phrase associated with the correctness of formal structures. +This isn't necessarily in error, but it should be looked out for. ## What Well-Formedness Isn't -Well-formedness checking is not "number of parameters" or "parameter type" checking[^kind-checking]. Neither term well-formedness checking nor item-wfck is concerned with if a type with 2 parameters has 1 or 3 types applied to it (assuming no defaults), or if a const generic parameter has a type applied to it. These kinds of problems will get handled during HIR-ty Lowering[^hir-ty-lower], not wfck. +Well-formedness checking is not "number of parameters" or "parameter type" checking[^kind-checking]. +Neither term well-formedness checking nor item-wfck is concerned with if a type with 2 parameters has 1 or 3 types applied to it (assuming no defaults), or if a const generic parameter has a type applied to it. +These kinds of problems will get handled during HIR-ty Lowering[^hir-ty-lower], not wfck. Well-formedness doesn't check or validate lifetimes, this is handled in [MIR](../borrow-check.md). -Well-formedness in the Rust compiler doesn't correspond to "correct syntax" as it does in logic. The term has a history of general use in a mathematical context of "follows a given set of rules." In Rust, our original usage was closer to "this thing is internally consistent" with respect to the bounds on a type in places such as the original [clarification on projections and well-formedness RFC](https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md). +Well-formedness in the Rust compiler doesn't correspond to "correct syntax" as it does in logic. +The term has a history of general use in a mathematical context of "follows a given set of rules." In Rust, our original usage was closer to "this thing is internally consistent" with respect to the bounds on a type in places such as the original [clarification on projections and well-formedness RFC](https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md). [^obligations]: These get referred to as Obligations, Requirements, or Constraints in the documentation. Preferred term is "obligations", as this matches the suffix of the type and the names of relevant functions. In future, this may be superseded by the new solver's term "Goal." [^wf-history]: In linguistics this is "grammatically correct," in logic it is "syntactically correct," and in casual mathematician use it can be read as a more general "follows the rules we set for this domain." @@ -290,4 +320,4 @@ Well-formedness in the Rust compiler doesn't correspond to "correct syntax" as i [^terms-abbreviated]: Abbreviated as "Terms" on this page in some areas. [^kind-checking]: AKA "kind checking", as we might see in languages like Haskell. [^hir-ty-lower]: -[^tyck-const-generics]: \ No newline at end of file +[^tyck-const-generics]: From ccec2e040b53fb9e84e7604095e97a4c3ac397df Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 11:07:58 +0200 Subject: [PATCH 10/25] fix misplaced quotes --- .../src/analysis/well-formed.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/analysis/well-formed.md b/src/doc/rustc-dev-guide/src/analysis/well-formed.md index 464ffce817369..b50063072d71a 100644 --- a/src/doc/rustc-dev-guide/src/analysis/well-formed.md +++ b/src/doc/rustc-dev-guide/src/analysis/well-formed.md @@ -2,17 +2,17 @@ ## What is Well-Formedness? -"Well-formed" means "correctly built."[^wf-history] Something is _well-formed_ when its structure follows rules. +"Well-formed" means "correctly built"[^wf-history]. Something is _well-formed_ when its structure follows rules. When we use this term in the Rust compiler we are concerned with establishing some kind of _internal consistency_. ## Well-Formedness in Rust -To check that something is well-formed is to perform a "Well-formedness check." +To check that something is well-formed is to perform a "Well-formedness check". In the Rust compiler there are two different forms of well-formedness checking: - **Type-Level Term**[^terms][^terms-abbreviated] well-formedness check. - - Also called "Term well-formedness" or "Term well-formedness checking." + - Also called "Term well-formedness" or "Term well-formedness checking". - Not a distinct analysis stage, this gets performed throughout analysis. - **Item**[^items] well-formedness check (item-wfck.) - "Item-wfck" will often wind up requiring Terms be well-formed, but skips some areas. @@ -103,7 +103,7 @@ This obligation will be passed off to the trait solver just like any trait-style ## Well-Formedness of Items -Items are, generally speaking, "Things that get defined." Item-wfck happens at the signature level for types and functions, methods, and definitions/implementations of traits. +Items are, generally speaking, "Things that get defined". Item-wfck happens at the signature level for types and functions, methods, and definitions/implementations of traits. ```rust,ignore // The `Vec` is checked during item wfck @@ -186,7 +186,7 @@ As an example, the following will compile because we don't have a point where we ```rust,ignore trait Trait -where +where for<'a> [u8]: Sized {} fn foo(_: &dyn Trait) {} @@ -199,13 +199,13 @@ The above should not compile because `[u8]: Sized`, but this won't be checked un ```rust trait Trait -where +where for<'a> [u8]: Sized {} - + fn foo(_: &dyn Trait) {} // We still need to specify the bound here, otherwise `[u8]: Sized` _is_ -// checked as an obligation. +// checked as an obligation. impl Trait for u8 where for<'a> [u8]: Sized {} fn main() { @@ -226,7 +226,7 @@ fn foo(_: &dyn Trait) {} const N: usize const B: bool N = B // Substitution -const B: usize + bool +const B: usize + bool ``` The above doesn't compile, unlike the previous example we gave. @@ -292,7 +292,7 @@ type Alias = Consty<42>; ## "Well-Formed" or "Wellformed"? -Prefer "well-formed" over "wellformed," as this is consistent with logic literature. +Prefer "well-formed" over "wellformed", as this is consistent with logic literature. This also gets abbreviated to WF in other parts of the dev guide / docs. ## Informal Usage @@ -309,10 +309,10 @@ These kinds of problems will get handled during HIR-ty Lowering[^hir-ty-lower], Well-formedness doesn't check or validate lifetimes, this is handled in [MIR](../borrow-check.md). Well-formedness in the Rust compiler doesn't correspond to "correct syntax" as it does in logic. -The term has a history of general use in a mathematical context of "follows a given set of rules." In Rust, our original usage was closer to "this thing is internally consistent" with respect to the bounds on a type in places such as the original [clarification on projections and well-formedness RFC](https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md). +The term has a history of general use in a mathematical context of "follows a given set of rules". In Rust, our original usage was closer to "this thing is internally consistent" with respect to the bounds on a type in places such as the original [clarification on projections and well-formedness RFC](https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md). -[^obligations]: These get referred to as Obligations, Requirements, or Constraints in the documentation. Preferred term is "obligations", as this matches the suffix of the type and the names of relevant functions. In future, this may be superseded by the new solver's term "Goal." -[^wf-history]: In linguistics this is "grammatically correct," in logic it is "syntactically correct," and in casual mathematician use it can be read as a more general "follows the rules we set for this domain." +[^obligations]: These get referred to as Obligations, Requirements, or Constraints in the documentation. Preferred term is "obligations", as this matches the suffix of the type and the names of relevant functions. In future, this may be superseded by the new solver's term "Goal". +[^wf-history]: In linguistics this is "grammatically correct", in logic it is "syntactically correct", and in casual mathematician use it can be read as a more general "follows the rules we set for this domain". [^horrible]: Instead, this bound is checked during "MIR borrowck" when the lifetimes are instantiated. [^fta]: Type aliases not associated with anything, i.e. a module-level `type Alias = Vec;`. [^items]: "Definition" style things in rust, See the [glossary](../appendix/glossary.md). From eefd538c162aed470cf456a8d3e51c5d900a0ca7 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 11:08:08 +0200 Subject: [PATCH 11/25] sembr src/analysis/well-formed.md --- src/doc/rustc-dev-guide/src/analysis/well-formed.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/analysis/well-formed.md b/src/doc/rustc-dev-guide/src/analysis/well-formed.md index b50063072d71a..dc938f22fbe01 100644 --- a/src/doc/rustc-dev-guide/src/analysis/well-formed.md +++ b/src/doc/rustc-dev-guide/src/analysis/well-formed.md @@ -2,7 +2,8 @@ ## What is Well-Formedness? -"Well-formed" means "correctly built"[^wf-history]. Something is _well-formed_ when its structure follows rules. +"Well-formed" means "correctly built"[^wf-history]. +Something is _well-formed_ when its structure follows rules. When we use this term in the Rust compiler we are concerned with establishing some kind of _internal consistency_. ## Well-Formedness in Rust @@ -103,7 +104,8 @@ This obligation will be passed off to the trait solver just like any trait-style ## Well-Formedness of Items -Items are, generally speaking, "Things that get defined". Item-wfck happens at the signature level for types and functions, methods, and definitions/implementations of traits. +Items are, generally speaking, "Things that get defined". +Item-wfck happens at the signature level for types and functions, methods, and definitions/implementations of traits. ```rust,ignore // The `Vec` is checked during item wfck @@ -309,7 +311,8 @@ These kinds of problems will get handled during HIR-ty Lowering[^hir-ty-lower], Well-formedness doesn't check or validate lifetimes, this is handled in [MIR](../borrow-check.md). Well-formedness in the Rust compiler doesn't correspond to "correct syntax" as it does in logic. -The term has a history of general use in a mathematical context of "follows a given set of rules". In Rust, our original usage was closer to "this thing is internally consistent" with respect to the bounds on a type in places such as the original [clarification on projections and well-formedness RFC](https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md). +The term has a history of general use in a mathematical context of "follows a given set of rules". +In Rust, our original usage was closer to "this thing is internally consistent" with respect to the bounds on a type in places such as the original [clarification on projections and well-formedness RFC](https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md). [^obligations]: These get referred to as Obligations, Requirements, or Constraints in the documentation. Preferred term is "obligations", as this matches the suffix of the type and the names of relevant functions. In future, this may be superseded by the new solver's term "Goal". [^wf-history]: In linguistics this is "grammatically correct", in logic it is "syntactically correct", and in casual mathematician use it can be read as a more general "follows the rules we set for this domain". From 6b77786795d9e0d6c37c95e83ec3d76a448351f9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 11:23:00 +0200 Subject: [PATCH 12/25] use sentence case --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- .../src/analysis/well-formed.md | 44 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 6b17426e165ef..bf2de84575d69 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -193,7 +193,7 @@ - [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) -- [Well-Formedness](./analysis/well-formed.md) +- [Well-formedness](./analysis/well-formed.md) - [Variance](./variance.md) - [Coherence checking](./coherence.md) - [HIR Type checking](./hir-typeck/summary.md) diff --git a/src/doc/rustc-dev-guide/src/analysis/well-formed.md b/src/doc/rustc-dev-guide/src/analysis/well-formed.md index dc938f22fbe01..df60aa2ec59b7 100644 --- a/src/doc/rustc-dev-guide/src/analysis/well-formed.md +++ b/src/doc/rustc-dev-guide/src/analysis/well-formed.md @@ -1,12 +1,12 @@ -# Well-Formedness +# Well-formedness -## What is Well-Formedness? +## What is well-formedness? "Well-formed" means "correctly built"[^wf-history]. Something is _well-formed_ when its structure follows rules. When we use this term in the Rust compiler we are concerned with establishing some kind of _internal consistency_. -## Well-Formedness in Rust +## Well-formedness in Rust To check that something is well-formed is to perform a "Well-formedness check". @@ -22,14 +22,14 @@ In the Rust compiler there are two different forms of well-formedness checking: See: [What Well-Formedness Isn't](#what-well-formedness-isnt). -## Well-Formedness of Type-Level Terms +## Well-formedness of type-level terms Term well-formedness checking begins with building a list of things that need to be true for a term to be well-formed. We call these "Obligations"[^obligations]. -Type-Level Terms are considered Well-Formed when their associated obligations are satisfied by the trait solver. +Type-Level Terms are considered well-formed when their associated obligations are satisfied by the trait solver. -### Obligations for Well-Formedness +### Obligations for well-formedness Specific obligations are things like `String: Clone`, `A: usize`, or `::Item: Debug`. @@ -69,23 +69,23 @@ Vec where str: Sized The above computes the obligation `T: Sized`, like before, but we substitute `T` for `str` in the instance of `Vec` finding the obligation `str: sized`. This obligation will be determined by the trait solver to be _unsatisfied_. -#### Determining Obligations +#### Determining obligations In the compiler, obligations of terms are found through the [`obligations`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/wf/fn.obligations.html) function in the [term well-formedness module](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_trait_selection/traits/wf/index.html). -#### Other Obligations +#### Other obligations Obligations are more than just trait and const generic bounds, but we've only mentioned these specific obligations so far as they are what we care about when we do "well-formedness checking" of terms. See: [`PredicateKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.PredicateKind.html) and [`ClauseKind`](https://doc.rust-lang.org/beta/nightly-rustc/rustc_type_ir/predicate_kind/enum.ClauseKind.html) for a full list of obligations. -### We Don't Need Normalization (Yet) +### We don't need normalization (yet) [Normalization](../normalization.md) is the process of resolving [type aliases](../normalization.md#aliases) into their underlying type. A type alias is considered well-formed if its where clauses are satisfied. The underlying type undergoes well-formedness checking at most definition and instantiation sites, but there are exceptions. -### Const Generic Arguments +### Const generic arguments Term well-formedness is responsible for getting "type checking" obligations of const generic terms[^tyck-const-generics]. Let's look at the following use of const generics: @@ -102,7 +102,7 @@ const 6: usize The call site will provide us with the obligation `6: usize` during well-formedness checking. This obligation will be passed off to the trait solver just like any trait-style obligation, as the trait solver has more responsibilities than its name suggests. -## Well-Formedness of Items +## Well-formedness of items Items are, generally speaking, "Things that get defined". Item-wfck happens at the signature level for types and functions, methods, and definitions/implementations of traits. @@ -123,7 +123,7 @@ We do not talk about all of these here, but they can be found at the individual -### Global and Trivial Bounds +### Global and trivial bounds @@ -157,29 +157,29 @@ String: Copy // Trivial bound again, but this one is false! Here we have a trivial bound that does not hold, because `String` is not `Copy`. -#### Trivial Bounds Are Not Always Global +#### Trivial bounds are not always global Trivial Bounds are not a subset of Global Bounds. A trivial bound that isn't Global is `for<'a> String: Clone` (trivially true, has a bound variable) or `&'a str: Copy` (trivially false, has a generic parameter). -#### Item-Wfck and Trivial/Global Bounds +#### Item-wfck and trivial/global bounds When checking items are well-formed we will check that there are no trivially false global bounds. -## When We Don't Fully Do Well-Formedness Checking +## When we don't fully do well-formedness checking Well-formedness checking is not a coherent "stage" of type checking. There are many areas where well-formedness checking is performed, and some areas where we skip over well-formedness checking due to limitations in what kinds of analysis we can currently perform. Ideally, we would never skip or defer well-formedness checking. -### We (Sometimes) Need Normalization +### We (sometimes) need normalization There are places where normalization of an Item happens before its Terms have gone through well-formedness checking. This is considered problematic as doing so allows some terms to [bypass term well-formedness checking entirely](https://github.com/rust-lang/rust/issues/100041). -### Trait Objects +### Trait objects We do not require the where clauses of trait objects to be well-formed when determining if that trait object is well-formed. These where clauses are proven when coercing into a trait object, but this remains a hole in well-formedness checking. @@ -234,7 +234,7 @@ const B: usize + bool The above doesn't compile, unlike the previous example we gave. We're doing _some_ well-formedness checking here when it comes to the const generic arguments. -### Binders / Higher-Ranked Types +### Binders / higher-ranked types Binders / Higher-Ranked Types reduce the amount well-formedness checking we do on a term, leaving well-formedness checking to when the bound is instantiated: @@ -260,7 +260,7 @@ for<'a, 'b> fn(&'a &'b ()) The above HRB implies `'b: 'a` (a lifetime bound), rather than two completely separate lifetimes. This is normal lifetime behavior, but during well-formedness checking we cannot prove that this bound is generally true[^horrible], so we skip it. -### Free Type Aliases +### Free type aliases The right-hand side of Free Type Aliases[^fta] is not fully checked to be well-formed at the definition site, only the types of const generic arguments in the RHS are checked. @@ -292,17 +292,17 @@ type Alias = Consty<42>; -## "Well-Formed" or "Wellformed"? +## "well-formed" or "wellformed"? Prefer "well-formed" over "wellformed", as this is consistent with logic literature. This also gets abbreviated to WF in other parts of the dev guide / docs. -## Informal Usage +## Informal usage In conversation, contributors may refer to something as "well-formed" and not necessarily mean what we cover here because "well-formedness" is a general phrase associated with the correctness of formal structures. This isn't necessarily in error, but it should be looked out for. -## What Well-Formedness Isn't +## What well-formedness isn't Well-formedness checking is not "number of parameters" or "parameter type" checking[^kind-checking]. Neither term well-formedness checking nor item-wfck is concerned with if a type with 2 parameters has 1 or 3 types applied to it (assuming no defaults), or if a const generic parameter has a type applied to it. From 2452d9d8f0224787c8408727581c7794906be7f2 Mon Sep 17 00:00:00 2001 From: krishna3554 Date: Sat, 4 Jul 2026 00:11:25 +0530 Subject: [PATCH 13/25] Update date-check markers for July 2026 --- src/doc/rustc-dev-guide/src/contributing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 4e292c5476d1c..0c1feb3f48b3f 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -444,20 +444,20 @@ Just a few things to keep in mind: For the action to pick the date, add a special annotation before specifying the date: ```md - Nov 2025 + Jul 2026 ``` Example: ```md - As of Nov 2025, the foo did the bar. + As of Jul 2026, the foo did the bar. ``` For cases where the date should not be part of the visible rendered output, use the following instead: ```md - + ``` - A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide From 5ba2f10884f4874043d98d8300fc9bc4eb394aa4 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 11:59:13 +0200 Subject: [PATCH 14/25] less words --- src/doc/rustc-dev-guide/src/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 4e292c5476d1c..0bfacb017f27c 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -425,7 +425,7 @@ Just a few things to keep in mind: - When contributing text to the guide, please contextualize the information with some time period and/or a reason so that the reader knows how much to trust the information. - Aim to provide a reasonable amount of context, possibly including but not limited to: + Aim to provide a reasonable amount of context, and consider including: - A reason for why the text may be out of date other than "change", as change is a constant across the project. From bae7fbab10e0e7dfba0c9ab8648d395a582fd471 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:10:34 +0200 Subject: [PATCH 15/25] new mdbook now gives this for free Should of been in 6f0ae3e918b9d6bb09761e7d9f4119f387f14675 --- src/doc/rustc-dev-guide/src/contributing.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 0bfacb017f27c..be0b76af34159 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -464,10 +464,6 @@ Just a few things to keep in mind: further explanation for the change process or a way to verify that the information is not outdated. -- If a text grows rather long (more than a few page scrolls) or complicated (more than four - subsections), it might benefit from having a Table of Contents at the beginning, - which you can auto-generate by including the `` marker at the top. - #### ⚠️ Note: Where to contribute `rustc-dev-guide` changes For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, From 769c5bd5a6afd6b4317c5762bb5d6f0e2d821e30 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:20:16 +0200 Subject: [PATCH 16/25] document accepted practice --- src/doc/rustc-dev-guide/src/contributing.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index be0b76af34159..c0d44518e9013 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -464,6 +464,10 @@ Just a few things to keep in mind: further explanation for the change process or a way to verify that the information is not outdated. +- Use sentence case for chapter and sections titles. + +- Use dashes (`-`) to separate words file names. + #### ⚠️ Note: Where to contribute `rustc-dev-guide` changes For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, From dd200bae9258960d720d19316505cae30fefd6d3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:39:56 +0200 Subject: [PATCH 17/25] use local --- src/doc/rustc-dev-guide/src/analysis/well-formed.md | 2 +- src/doc/rustc-dev-guide/src/contributing.md | 2 +- src/doc/rustc-dev-guide/src/offload/installation.md | 2 +- .../rustc-dev-guide/src/traits/separate-projection-bounds.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/analysis/well-formed.md b/src/doc/rustc-dev-guide/src/analysis/well-formed.md index df60aa2ec59b7..4a2450a480ed2 100644 --- a/src/doc/rustc-dev-guide/src/analysis/well-formed.md +++ b/src/doc/rustc-dev-guide/src/analysis/well-formed.md @@ -323,4 +323,4 @@ In Rust, our original usage was closer to "this thing is internally consistent" [^terms-abbreviated]: Abbreviated as "Terms" on this page in some areas. [^kind-checking]: AKA "kind checking", as we might see in languages like Haskell. [^hir-ty-lower]: -[^tyck-const-generics]: +[^tyck-const-generics]: #checking-types-of-const-arguments diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index c0d44518e9013..546ce55bda2e5 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -257,7 +257,7 @@ In particular, we don't recommend running the full `./x test` suite locally, since it takes a very long time to execute. See the [Testing with CI] chapter for using Rust's CI to test your changes. -[Testing with CI]: https://rustc-dev-guide.rust-lang.org/tests/ci.html#testing-with-ci +[Testing with CI]: tests/ci.md#testing-with-ci ### r+ diff --git a/src/doc/rustc-dev-guide/src/offload/installation.md b/src/doc/rustc-dev-guide/src/offload/installation.md index 4b67f31cd3c28..ab8e7984d5b4a 100644 --- a/src/doc/rustc-dev-guide/src/offload/installation.md +++ b/src/doc/rustc-dev-guide/src/offload/installation.md @@ -44,7 +44,7 @@ Run this test script for offload-specific tests: ./x test --stage 1 tests/codegen-llvm/gpu_offload ``` -For testing the CI locally, you may use the commands outlined in [Testing with Docker](https://rustc-dev-guide.rust-lang.org/tests/docker.html): +For testing the CI locally, you may use the commands outlined in [Testing with Docker](../tests/docker.md): ```console cargo run --manifest-path src/ci/citool/Cargo.toml run-local dist-x86_64-linux ``` 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 144e27316cbb4..94a0d752c945b 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 @@ -8,7 +8,7 @@ The way we prove `Projection` bounds directly relies on proving the correspondin 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). +See [alias-bound vs where-bound](../solve/candidate-preference.md#we-always-consider-aliasbound-candidates) and [global where-bound vs impl](../solve/candidate-preference.md#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; From 4132d73e54b2f6894d2d12f9f4e6752706b5719e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:47:55 +0200 Subject: [PATCH 18/25] sembr src/building/bootstrapping/debugging-bootstrap.md --- .../bootstrapping/debugging-bootstrap.md | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md index 93b11c0690a92..da7c07cb23c52 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md @@ -1,12 +1,15 @@ # Debugging bootstrap -There are two main ways of debugging (and profiling bootstrap). The first is through println logging, and the second is through the `tracing` feature. +There are two main ways of debugging (and profiling bootstrap). +The first is through println logging, and the second is through the `tracing` feature. ## `println` logging -Bootstrap has extensive unstructured logging. Most of it is gated behind the `--verbose` flag (pass `-vv` for even more detail). +Bootstrap has extensive unstructured logging. +Most of it is gated behind the `--verbose` flag (pass `-vv` for even more detail). -If you want to see verbose output of executed Cargo commands and other kinds of detailed logs, pass `-v` or `-vv` when invoking bootstrap. Note that the logs are unstructured and may be overwhelming. +If you want to see verbose output of executed Cargo commands and other kinds of detailed logs, pass `-v` or `-vv` when invoking bootstrap. +Note that the logs are unstructured and may be overwhelming. ``` $ ./x dist rustc --dry-run -vv @@ -27,7 +30,8 @@ Bootstrap has a conditional `tracing` feature, which provides the following feat - It generates a command execution summary, which shows which commands were executed, how many of their executions were cached, and what commands were the slowest to run. - The generated `command-stats.txt` file is in a simple human-readable format. -The structured logs will be written to standard error output (`stderr`), while the other outputs will be stored in files in the `/bootstrap-trace/` directory. For convenience, bootstrap will also create a symlink to the latest generated trace output directory at `/bootstrap-trace/latest`. +The structured logs will be written to standard error output (`stderr`), while the other outputs will be stored in files in the `/bootstrap-trace/` directory. +For convenience, bootstrap will also create a symlink to the latest generated trace output directory at `/bootstrap-trace/latest`. > Note that if you execute bootstrap with `--dry-run`, the tracing output directory might change. Bootstrap will always print a path where the tracing output files were stored at the end of its execution. @@ -73,18 +77,24 @@ Build completed successfully in 0:00:00 #### Controlling tracing output -The environment variable `BOOTSTRAP_TRACING` accepts a [`tracing_subscriber` filter][tracing-env-filter]. If you set `BOOTSTRAP_TRACING=trace`, you will enable all logs, but that can be overwhelming. You can thus use the filter to reduce the amount of data logged. +The environment variable `BOOTSTRAP_TRACING` accepts a [`tracing_subscriber` filter][tracing-env-filter]. +If you set `BOOTSTRAP_TRACING=trace`, you will enable all logs, but that can be overwhelming. +You can thus use the filter to reduce the amount of data logged. There are two orthogonal ways to control which kind of tracing logs you want: 1. You can specify the log **level**, e.g. `debug` or `trace`. - If you select a level, all events/spans with an equal or higher priority level will be shown. 2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` or a custom target like `CONFIG_HANDLING` or `STEP`. - - Custom targets are used to limit what kinds of spans you are interested in, as the `BOOTSTRAP_TRACING=trace` output can be quite verbose. Currently, you can use the following custom targets: + - Custom targets are used to limit what kinds of spans you are interested in, as the `BOOTSTRAP_TRACING=trace` output can be quite verbose. + Currently, you can use the following custom targets: - `CONFIG_HANDLING`: show spans related to config handling. - - `STEP`: show all executed steps. Executed commands have `info` event level. - - `COMMAND`: show all executed commands. Executed commands have `trace` event level. - - `IO`: show performed I/O operations. Executed commands have `trace` event level. + - `STEP`: show all executed steps. + Executed commands have `info` event level. + - `COMMAND`: show all executed commands. + Executed commands have `trace` event level. + - `IO`: show performed I/O operations. + Executed commands have `trace` event level. - Note that many I/O are currently not being traced. You can of course combine them (custom target logs are typically gated behind `TRACE` log level additionally): @@ -100,14 +110,15 @@ Note that the level that you specify using `BOOTSTRAP_TRACING` also has an effec ##### FIXME(#96176): specific tracing for `compiler()` vs `compiler_for()` The additional targets `COMPILER` and `COMPILER_FOR` are used to help trace what -`builder.compiler()` and `builder.compiler_for()` does. They should be removed -if [#96176][cleanup-compiler-for] is resolved. +`builder.compiler()` and `builder.compiler_for()` does. +They should be removed if [#96176][cleanup-compiler-for] is resolved. [cleanup-compiler-for]: https://github.com/rust-lang/rust/issues/96176 ### Using `tracing` in bootstrap -Both `tracing::*` macros and the `tracing::instrument` proc-macro attribute need to be gated behind `tracing` feature. Examples: +Both `tracing::*` macros and the `tracing::instrument` proc-macro attribute need to be gated behind `tracing` feature. +Examples: ```rs #[cfg(feature = "tracing")] From d8954e6586b989beaa49a715d0144366e27b2139 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:49:45 +0200 Subject: [PATCH 19/25] sembr src/building/bootstrapping/intro.md --- .../src/building/bootstrapping/intro.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md index 7f53097824cc9..307455595d4ba 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md @@ -1,14 +1,13 @@ # Bootstrapping the compiler [*Bootstrapping*][boot] is the process of using a compiler to compile itself. -More accurately, it means using an older compiler to compile a newer version -of the same compiler. +More accurately, it means using an older compiler to compile a newer version of the same compiler. This raises a chicken-and-egg paradox: where did the first compiler come from? -It must have been written in a different language. In Rust's case it was -[written in OCaml][ocaml-compiler]. However, it was abandoned long ago, and the -only way to build a modern version of rustc is with a slightly less modern -version. +It must have been written in a different language. +In Rust's case it was [written in OCaml][ocaml-compiler]. +However, it was abandoned long ago, and the +only way to build a modern version of rustc is with a slightly less modern version. This is exactly how `x.py` works: it downloads the current beta release of rustc, then uses it to compile the new compiler. @@ -17,8 +16,7 @@ In this section, we give a high-level overview of [what Bootstrap does](./what-bootstrapping-does.md), followed by a high-level introduction to [how Bootstrap does it](./how-bootstrap-does-it.md). -Additionally, see [debugging bootstrap](./debugging-bootstrap.md) to learn -about debugging methods. +Additionally, see [debugging bootstrap](./debugging-bootstrap.md) to learn about debugging methods. [boot]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers) [ocaml-compiler]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot From 3b40dd01db62d03ea5420b8036c3714635b33ad6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:52:42 +0200 Subject: [PATCH 20/25] indirection --- .../rustc-dev-guide/src/building/bootstrapping/intro.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md index 307455595d4ba..e4704a10e0a78 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/intro.md @@ -1,11 +1,11 @@ # Bootstrapping the compiler -[*Bootstrapping*][boot] is the process of using a compiler to compile itself. +[*Bootstrapping*] is the process of using a compiler to compile itself. More accurately, it means using an older compiler to compile a newer version of the same compiler. This raises a chicken-and-egg paradox: where did the first compiler come from? It must have been written in a different language. -In Rust's case it was [written in OCaml][ocaml-compiler]. +In Rust's case it was [written in OCaml]. However, it was abandoned long ago, and the only way to build a modern version of rustc is with a slightly less modern version. @@ -18,5 +18,5 @@ introduction to [how Bootstrap does it](./how-bootstrap-does-it.md). Additionally, see [debugging bootstrap](./debugging-bootstrap.md) to learn about debugging methods. -[boot]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers) -[ocaml-compiler]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot +[*Bootstrapping*]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers) +[written in OCaml]: https://github.com/rust-lang/rust/tree/ef75860a0a72f79f97216f8aaa5b388d98da6480/src/boot From 02b4d2bbec5d1434abcaf242764048527b5e786b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:53:16 +0200 Subject: [PATCH 21/25] sembr src/building/bootstrapping/how-bootstrap-does-it.md --- .../bootstrapping/how-bootstrap-does-it.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/how-bootstrap-does-it.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/how-bootstrap-does-it.md index 4d301b3abae1a..63c154d25d22f 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/how-bootstrap-does-it.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/how-bootstrap-does-it.md @@ -1,14 +1,16 @@ # How Bootstrap does it The core concept in Bootstrap is a build [`Step`], which are chained together -by [`Builder::ensure`]. [`Builder::ensure`] takes a [`Step`] as input, and runs -the [`Step`] if and only if it has not already been run. Let's take a closer -look at [`Step`]. +by [`Builder::ensure`]. +[`Builder::ensure`] takes a [`Step`] as input, and runs +the [`Step`] if and only if it has not already been run. +Let's take a closer look at [`Step`]. ## Synopsis of [`Step`] A [`Step`] represents a granular collection of actions involved in the process -of producing some artifact. It can be thought of like a rule in Makefiles. +of producing some artifact. +It can be thought of like a rule in Makefiles. The [`Step`] trait is defined as: ```rs,no_run @@ -30,8 +32,8 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { - `run` is the function that is responsible for doing the work. [`Builder::ensure`] invokes `run`. - `should_run` is the command-line interface, which determines if an invocation - such as `x build foo` should run a given [`Step`]. In a "default" context - where no paths are provided, then `make_run` is called directly. + such as `x build foo` should run a given [`Step`]. + In a "default" context where no paths are provided, then `make_run` is called directly. - `make_run` is invoked only for things directly asked via the CLI and not for steps which are dependencies of other steps. From 3ca83eba7aa278fb504629e02fbea02f3c17dcc7 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:54:06 +0200 Subject: [PATCH 22/25] sembr src/building/bootstrapping/bootstrap-in-dependencies.md --- .../src/building/bootstrapping/bootstrap-in-dependencies.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md index 68c5c2386bd5e..03772f4a580df 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md @@ -1,6 +1,7 @@ # `cfg(bootstrap)` in compiler dependencies -The rust compiler uses some external crates that can run into cyclic dependencies with the compiler itself: the compiler needs an updated crate to build, but the crate needs an updated compiler. This page describes how `#[cfg(bootstrap)]` can be used to break this cycle. +The rust compiler uses some external crates that can run into cyclic dependencies with the compiler itself: the compiler needs an updated crate to build, but the crate needs an updated compiler. +This page describes how `#[cfg(bootstrap)]` can be used to break this cycle. ## Enabling `#[cfg(bootstrap)]` @@ -50,4 +51,5 @@ For `compiler-builtins` this meant a version bump, in other cases it may be a gi ### Step 4: remove the old behavior from the compiler ([#139753](https://github.com/rust-lang/rust/pull/139753)) -The updated crate can now be used. In this example that meant that the old behavior could be removed. +The updated crate can now be used. +In this example that meant that the old behavior could be removed. From ecb36ae3834cf06e6f0ebd501a5875885e472789 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:54:59 +0200 Subject: [PATCH 23/25] capitalise --- .../src/building/bootstrapping/bootstrap-in-dependencies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md index 03772f4a580df..35a0d5d9302bc 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md @@ -1,6 +1,6 @@ # `cfg(bootstrap)` in compiler dependencies -The rust compiler uses some external crates that can run into cyclic dependencies with the compiler itself: the compiler needs an updated crate to build, but the crate needs an updated compiler. +The Rust compiler uses some external crates that can run into cyclic dependencies with the compiler itself: the compiler needs an updated crate to build, but the crate needs an updated compiler. This page describes how `#[cfg(bootstrap)]` can be used to break this cycle. ## Enabling `#[cfg(bootstrap)]` From 41462bbdd202e04019131f47c7b3409b68f1b6b6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:55:16 +0200 Subject: [PATCH 24/25] overlong --- .../src/building/bootstrapping/bootstrap-in-dependencies.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md index 35a0d5d9302bc..2780fc36709e6 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md @@ -1,6 +1,7 @@ # `cfg(bootstrap)` in compiler dependencies -The Rust compiler uses some external crates that can run into cyclic dependencies with the compiler itself: the compiler needs an updated crate to build, but the crate needs an updated compiler. +The Rust compiler uses some external crates that can run into cyclic dependencies with the compiler itself: +the compiler needs an updated crate to build, but the crate needs an updated compiler. This page describes how `#[cfg(bootstrap)]` can be used to break this cycle. ## Enabling `#[cfg(bootstrap)]` From b593a46b0eaa48c30a642adf9a69101a83476f03 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 4 Jul 2026 12:55:46 +0200 Subject: [PATCH 25/25] missing pause --- .../src/building/bootstrapping/bootstrap-in-dependencies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md index 2780fc36709e6..33697e1690f21 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/bootstrap-in-dependencies.md @@ -40,7 +40,7 @@ As a concrete example we'll use a change where the `#[naked]` attribute was made ### Step 1: accept the new behavior in the compiler ([#139797](https://github.com/rust-lang/rust/pull/139797)) -In this example it is possible to accept both the old and new behavior at the same time by disabling an error. +In this example, it is possible to accept both the old and new behavior at the same time by disabling an error. ### Step 2: update the crate ([#821](https://github.com/rust-lang/compiler-builtins/pull/821))