diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index daf5223cb..6eabb999f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -17,7 +17,6 @@ jobs:
       MDBOOK_VERSION: 0.4.48
       MDBOOK_LINKCHECK2_VERSION: 0.9.1
       MDBOOK_MERMAID_VERSION: 0.12.6
-      MDBOOK_TOC_VERSION: 0.11.2
       MDBOOK_OUTPUT__LINKCHECK__FOLLOW_WEB_LINKS: ${{ github.event_name != 'pull_request' }}
       DEPLOY_DIR: book/html
       BASE_SHA: ${{ github.event.pull_request.base.sha }}
@@ -34,7 +33,7 @@ jobs:
         with:
           path: |
             ~/.cargo/bin
-          key: ${{ runner.os }}-${{ env.MDBOOK_VERSION }}--${{ env.MDBOOK_LINKCHECK2_VERSION }}--${{ env.MDBOOK_TOC_VERSION }}--${{ env.MDBOOK_MERMAID_VERSION }}
+          key: ${{ runner.os }}-${{ env.MDBOOK_VERSION }}--${{ env.MDBOOK_LINKCHECK2_VERSION }}--${{ env.MDBOOK_MERMAID_VERSION }}
 
       - name: Restore cached Linkcheck
         if: github.event_name == 'schedule'
@@ -57,7 +56,6 @@ jobs:
         run: |
           cargo install mdbook --version ${{ env.MDBOOK_VERSION }}
           cargo install mdbook-linkcheck2 --version ${{ env.MDBOOK_LINKCHECK2_VERSION }}
-          cargo install mdbook-toc --version ${{ env.MDBOOK_TOC_VERSION }}
           cargo install mdbook-mermaid --version ${{ env.MDBOOK_MERMAID_VERSION }}
 
       - name: Check build
diff --git a/.github/workflows/rustc-pull.yml b/.github/workflows/rustc-pull.yml
index 7190fc733..5ff311896 100644
--- a/.github/workflows/rustc-pull.yml
+++ b/.github/workflows/rustc-pull.yml
@@ -3,111 +3,19 @@ name: rustc-pull
 on:
   workflow_dispatch:
   schedule:
-    # Run at 04:00 UTC every Monday and Thursday
-    - cron: '0 4 * * 1,4'
+    # Run at 04:00 UTC every Monday
+    - cron: '0 4 * * 1'
 
 jobs:
   pull:
     if: github.repository == 'rust-lang/rustc-dev-guide'
-    runs-on: ubuntu-latest
-    outputs:
-      pr_url: ${{ steps.update-pr.outputs.pr_url }}
-    permissions:
-      contents: write
-      pull-requests: write
-    steps:
-      - uses: actions/checkout@v4
-        with:
-          # We need the full history for josh to work
-          fetch-depth: '0'
-      - name: Install stable Rust toolchain
-        run: rustup update stable
-      - uses: Swatinem/rust-cache@v2
-        with:
-          # Cache the josh directory with checked out rustc
-          cache-directories: "/home/runner/.cache/rustc-josh"
-      - name: Install rustc-josh-sync
-        run: cargo install --locked --git https://github.com/rust-lang/josh-sync
-      - name: Setup bot git name and email
-        run: |
-          git config --global user.name 'The rustc-dev-guide Cronjob Bot'
-          git config --global user.email 'github-actions@github.com'
-      - name: Perform rustc-pull
-        id: rustc-pull
-        # Turn off -e to disable early exit
-        shell: bash {0}
-        run: |
-          rustc-josh-sync pull
-          exitcode=$?
-
-          # If no pull was performed, we want to mark this job as successful,
-          # but we do not want to perform the follow-up steps.
-          if [ $exitcode -eq 0 ]; then
-            echo "pull_result=pull-finished" >> $GITHUB_OUTPUT
-          elif [ $exitcode -eq 2 ]; then
-            echo "pull_result=skipped" >> $GITHUB_OUTPUT
-            exitcode=0
-          fi
-
-          exit ${exitcode}
-      - name: Push changes to a branch
-        if: ${{ steps.rustc-pull.outputs.pull_result == 'pull-finished' }}
-        run: |
-          # Update a sticky branch that is used only for rustc pulls
-          BRANCH="rustc-pull"
-          git switch -c $BRANCH
-          git push -u origin $BRANCH --force
-      - name: Create pull request
-        id: update-pr
-        if: ${{ steps.rustc-pull.outputs.pull_result == 'pull-finished' }}
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        run: |
-          # Check if an open pull request for an rustc pull update already exists
-          # If it does, the previous push has just updated it
-          # If not, we create it now
-          RESULT=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | length' --json title`
-          if [[ "$RESULT" -eq 0 ]]; then
-            echo "Creating new pull request"
-            PR_URL=`gh pr create -B master --title 'Rustc pull update' --body 'Latest update from rustc.'`
-            echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
-          else
-            PR_URL=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].url' --json url,title`
-            echo "Updating pull request ${PR_URL}"
-            echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
-          fi
-  send-zulip-message:
-    needs: [pull]
-    if: ${{ !cancelled() }}
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-      - name: Compute message
-        id: create-message
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        run: |
-          if [ "${{ needs.pull.result }}" == "failure" ]; then
-            WORKFLOW_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
-            echo "message=Rustc pull sync failed. Check out the [workflow URL]($WORKFLOW_URL)." >> $GITHUB_OUTPUT
-          else
-            CREATED_AT=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].createdAt' --json createdAt,title`
-            PR_URL=`gh pr list --author github-actions[bot] --state open -q 'map(select(.title=="Rustc pull update")) | .[0].url' --json url,title`
-            week_ago=$(date +%F -d '7 days ago')
-
-            # If there is an open PR that is at least a week old, post a message about it
-            if [[ -n $DATE_GH && $DATE_GH < $week_ago ]]; then
-              echo "message=A PR with a Rustc pull has been opened for more a week. Check out the [PR](${PR_URL})." >> $GITHUB_OUTPUT
-            fi
-          fi
-      - name: Send a Zulip message about updated PR
-        if: ${{ steps.create-message.outputs.message != '' }}
-        uses: zulip/github-actions-zulip/send-message@e4c8f27c732ba9bd98ac6be0583096dea82feea5
-        with:
-          api-key: ${{ secrets.ZULIP_API_TOKEN }}
-          email: "rustc-dev-guide-gha-notif-bot@rust-lang.zulipchat.com"
-          organization-url: "https://rust-lang.zulipchat.com"
-          to: 196385
-          type: "stream"
-          topic: "Subtree sync automation"
-          content: ${{ steps.create-message.outputs.message }}
+    uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@main
+    with:
+      github-app-id: ${{ vars.APP_CLIENT_ID }}
+      zulip-stream-id: 196385
+      zulip-bot-email:  "rustc-dev-guide-gha-notif-bot@rust-lang.zulipchat.com"
+      pr-base-branch: master
+      branch-name: rustc-pull
+    secrets:
+      zulip-api-token: ${{ secrets.ZULIP_API_TOKEN }}
+      github-app-secret: ${{ secrets.APP_PRIVATE_KEY }}
diff --git a/README.md b/README.md
index 5932da467..1ad895aed 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ rustdocs][rustdocs].
 To build a local static HTML site, install [`mdbook`](https://github.com/rust-lang/mdBook) with:
 
 ```
-cargo install mdbook mdbook-linkcheck2 mdbook-toc mdbook-mermaid
+cargo install mdbook mdbook-linkcheck2 mdbook-mermaid
 ```
 
 and execute the following command in the root of the repository:
@@ -67,8 +67,8 @@ ENABLE_LINKCHECK=1 mdbook serve
 
 ### Table of Contents
 
-We use `mdbook-toc` to auto-generate TOCs for long sections. You can invoke the preprocessor by
-including the `<!-- toc -->` marker at the place where you want the TOC.
+Each page has a TOC that is automatically generated by `pagetoc.js`.
+There is an associated `pagetoc.css`, for styling.
 
 ## Synchronizing josh subtree with rustc
 
diff --git a/book.toml b/book.toml
index b84b1e754..daf237ed9 100644
--- a/book.toml
+++ b/book.toml
@@ -6,17 +6,18 @@ description = "A guide to developing the Rust compiler (rustc)"
 [build]
 create-missing = false
 
-[preprocessor.toc]
-command = "mdbook-toc"
-renderer = ["html"]
-
 [preprocessor.mermaid]
 command = "mdbook-mermaid"
 
 [output.html]
 git-repository-url = "https://github.com/rust-lang/rustc-dev-guide"
 edit-url-template = "https://github.com/rust-lang/rustc-dev-guide/edit/master/{path}"
-additional-js = ["mermaid.min.js", "mermaid-init.js"]
+additional-js = [
+  "mermaid.min.js",
+  "mermaid-init.js",
+  "pagetoc.js",
+]
+additional-css = ["pagetoc.css"]
 
 [output.html.search]
 use-boolean-and = true
diff --git a/pagetoc.css b/pagetoc.css
new file mode 100644
index 000000000..fa709194f
--- /dev/null
+++ b/pagetoc.css
@@ -0,0 +1,84 @@
+/* Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) */
+
+:root {
+    --toc-width: 270px;
+    --center-content-toc-shift: calc(-1 * var(--toc-width) / 2);
+}
+
+.nav-chapters {
+    /* adjust width of buttons that bring to the previous or the next page */
+    min-width: 50px;
+}
+
+@media only screen {
+    @media (max-width: 1179px) {
+        .sidebar-hidden #sidetoc {
+            display: none;
+        }
+    }
+
+    @media (max-width: 1439px) {
+        .sidebar-visible #sidetoc {
+            display: none;
+        }
+    }
+
+    @media (1180px <= width <= 1439px) {
+        .sidebar-hidden main {
+            position: relative;
+            left: var(--center-content-toc-shift);
+        }
+    }
+
+    @media (1440px <= width <= 1700px) {
+        .sidebar-visible main {
+            position: relative;
+            left: var(--center-content-toc-shift);
+        }
+    }
+
+    #sidetoc {
+        margin-left: calc(100% + 20px);
+    }
+    #pagetoc {
+        position: fixed;
+        /* adjust TOC width */
+        width: var(--toc-width);
+        height: calc(100vh - var(--menu-bar-height) - 0.67em * 4);
+        overflow: auto;
+    }
+    #pagetoc a {
+        border-left: 1px solid var(--sidebar-bg);
+        color: var(--fg);
+        display: block;
+        padding-bottom: 5px;
+        padding-top: 5px;
+        padding-left: 10px;
+        text-align: left;
+        text-decoration: none;
+    }
+    #pagetoc a:hover,
+    #pagetoc a.active {
+        background: var(--sidebar-bg);
+        color: var(--sidebar-active) !important;
+    }
+    #pagetoc .active {
+        background: var(--sidebar-bg);
+        color: var(--sidebar-active);
+    }
+    #pagetoc .pagetoc-H2 {
+        padding-left: 20px;
+    }
+    #pagetoc .pagetoc-H3 {
+        padding-left: 40px;
+    }
+    #pagetoc .pagetoc-H4 {
+        padding-left: 60px;
+    }
+}
+
+@media print {
+    #sidetoc {
+        display: none;
+    }
+}
diff --git a/pagetoc.js b/pagetoc.js
new file mode 100644
index 000000000..927a5b107
--- /dev/null
+++ b/pagetoc.js
@@ -0,0 +1,104 @@
+// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL)
+
+let activeHref = location.href;
+function updatePageToc(elem = undefined) {
+    let selectedPageTocElem = elem;
+    const pagetoc = document.getElementById("pagetoc");
+
+    function getRect(element) {
+        return element.getBoundingClientRect();
+    }
+
+    function overflowTop(container, element) {
+        return getRect(container).top - getRect(element).top;
+    }
+
+    function overflowBottom(container, element) {
+        return getRect(container).bottom - getRect(element).bottom;
+    }
+
+    // We've not selected a heading to highlight, and the URL needs updating
+    // so we need to find a heading based on the URL
+    if (selectedPageTocElem === undefined && location.href !== activeHref) {
+        activeHref = location.href;
+        for (const pageTocElement of pagetoc.children) {
+            if (pageTocElement.href === activeHref) {
+                selectedPageTocElem = pageTocElement;
+            }
+        }
+    }
+
+    // We still don't have a selected heading, let's try and find the most
+    // suitable heading based on the scroll position
+    if (selectedPageTocElem === undefined) {
+        const margin = window.innerHeight / 3;
+
+        const headers = document.getElementsByClassName("header");
+        for (let i = 0; i < headers.length; i++) {
+            const header = headers[i];
+            if (selectedPageTocElem === undefined && getRect(header).top >= 0) {
+                if (getRect(header).top < margin) {
+                    selectedPageTocElem = header;
+                } else {
+                    selectedPageTocElem = headers[Math.max(0, i - 1)];
+                }
+            }
+            // a very long last section's heading is over the screen
+            if (selectedPageTocElem === undefined && i === headers.length - 1) {
+                selectedPageTocElem = header;
+            }
+        }
+    }
+
+    // Remove the active flag from all pagetoc elements
+    for (const pageTocElement of pagetoc.children) {
+        pageTocElement.classList.remove("active");
+    }
+
+    // If we have a selected heading, set it to active and scroll to it
+    if (selectedPageTocElem !== undefined) {
+        for (const pageTocElement of pagetoc.children) {
+            if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) {
+                pageTocElement.classList.add("active");
+                if (overflowTop(pagetoc, pageTocElement) > 0) {
+                    pagetoc.scrollTop = pageTocElement.offsetTop;
+                }
+                if (overflowBottom(pagetoc, pageTocElement) < 0) {
+                    pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement);
+                }
+            }
+        }
+    }
+}
+
+if (document.getElementById("sidetoc") === null &&
+    document.getElementsByClassName("header").length > 0) {
+    // The sidetoc element doesn't exist yet, let's create it
+
+    // Create the empty sidetoc and pagetoc elements
+    const sidetoc = document.createElement("div");
+    const pagetoc = document.createElement("div");
+    sidetoc.id = "sidetoc";
+    pagetoc.id = "pagetoc";
+    sidetoc.appendChild(pagetoc);
+
+    // And append them to the current DOM
+    const main = document.querySelector('main');
+    main.insertBefore(sidetoc, main.firstChild);
+
+    // Populate sidebar on load
+    window.addEventListener("load", () => {
+        for (const header of document.getElementsByClassName("header")) {
+            const link = document.createElement("a");
+            link.innerHTML = header.innerHTML;
+            link.href = header.hash;
+            link.classList.add("pagetoc-" + header.parentElement.tagName);
+            document.getElementById("pagetoc").appendChild(link);
+            link.onclick = () => updatePageToc(link);
+        }
+        updatePageToc();
+    });
+
+    // Update page table of contents selected heading on scroll
+    window.addEventListener("scroll", () => updatePageToc());
+}
diff --git a/rust-version b/rust-version
index e444613e6..6ec700b9b 100644
--- a/rust-version
+++ b/rust-version
@@ -1 +1 @@
-c96a69059ecc618b519da385a6ccd03155aa0237
+6bcdcc73bd11568fd85f5a38b58e1eda054ad1cd
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 7f2f32c62..9ded467d5 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -35,7 +35,6 @@
         - [Cranelift codegen backend](./tests/codegen-backend-tests/cg_clif.md)
         - [GCC codegen backend](./tests/codegen-backend-tests/cg_gcc.md)
     - [Performance testing](./tests/perf.md)
-    - [Suggest tests tool](./tests/suggest-tests.md)
     - [Misc info](./tests/misc.md)
 - [Debugging the compiler](./compiler-debugging.md)
     - [Using the tracing/logging instrumentation](./tracing.md)
@@ -54,7 +53,8 @@
 - [Walkthrough: a typical contribution](./walkthrough.md)
 - [Implementing new language features](./implementing_new_features.md)
 - [Stability attributes](./stability.md)
-- [Stabilizing Features](./stabilization_guide.md)
+- [Stabilizing language features](./stabilization_guide.md)
+    - [Stabilization report template](./stabilization_report_template.md)
 - [Feature Gates](./feature-gates.md)
 - [Coding conventions](./conventions.md)
 - [Procedures for breaking changes](./bug-fix-procedure.md)
@@ -176,6 +176,7 @@
     - [Next-gen trait solving](./solve/trait-solving.md)
         - [Invariants of the type system](./solve/invariants.md)
         - [The solver](./solve/the-solver.md)
+        - [Candidate preference](./solve/candidate-preference.md)
         - [Canonicalization](./solve/canonicalization.md)
         - [Coinduction](./solve/coinduction.md)
         - [Caching](./solve/caching.md)
diff --git a/src/about-this-guide.md b/src/about-this-guide.md
index 057e4a4cc..f39577249 100644
--- a/src/about-this-guide.md
+++ b/src/about-this-guide.md
@@ -74,7 +74,6 @@ You might also find the following sites useful:
   of the team procedures, active working groups, and the team calendar.
 - [std-dev-guide] -- a similar guide for developing the standard library.
 - [The t-compiler zulip][z]
-- `#contribute` and `#wg-rustup` on [Discord](https://discord.gg/rust-lang).
 - The [Rust Internals forum][rif], a place to ask questions and
   discuss Rust's internals
 - The [Rust reference][rr], even though it doesn't specifically talk about
diff --git a/src/appendix/humorust.md b/src/appendix/humorust.md
index 6df3b212a..8681512ed 100644
--- a/src/appendix/humorust.md
+++ b/src/appendix/humorust.md
@@ -3,7 +3,7 @@
 What's a project without a sense of humor? And frankly some of these are
 enlightening?
 
-- [Weird exprs test](https://github.com/rust-lang/rust/blob/master/tests/ui/weird-exprs.rs)
+- [Weird exprs test](https://github.com/rust-lang/rust/blob/master/tests/ui/expr/weird-exprs.rs)
 - [Ferris Rap](https://fitzgen.com/2018/12/13/rust-raps.html)
 - [The Genesis of Generic Germination](https://github.com/rust-lang/rust/pull/53645#issue-210543221)
 - [The Bastion of the Turbofish test](https://github.com/rust-lang/rust/blob/79d8a0fcefa5134db2a94739b1d18daa01fc6e9f/src/test/ui/bastion-of-the-turbofish.rs)
diff --git a/src/asm.md b/src/asm.md
index eec9d448b..b5857d546 100644
--- a/src/asm.md
+++ b/src/asm.md
@@ -1,7 +1,5 @@
 # Inline assembly
 
-<!-- toc -->
-
 ## Overview
 
 Inline assembly in rustc mostly revolves around taking an `asm!` macro invocation and plumbing it
@@ -155,9 +153,9 @@ can't know ahead of time whether a function will require a frame/base pointer.
 
 Various tests for inline assembly are available:
 
-- `tests/assembly/asm`
+- `tests/assembly-llvm/asm`
 - `tests/ui/asm`
-- `tests/codegen/asm-*`
+- `tests/codegen-llvm/asm-*`
 
 Every architecture supported by inline assembly must have exhaustive tests in
-`tests/assembly/asm` which test all combinations of register classes and types.
+`tests/assembly-llvm/asm` which test all combinations of register classes and types.
diff --git a/src/autodiff/installation.md b/src/autodiff/installation.md
index 92e79b2f3..ddbb3a054 100644
--- a/src/autodiff/installation.md
+++ b/src/autodiff/installation.md
@@ -6,7 +6,7 @@ In the near future, `std::autodiff` should become available in nightly builds fo
 
 First you need to clone and configure the Rust repository:
 ```bash
-git clone --depth=1 git@github.com:rust-lang/rust.git
+git clone git@github.com:rust-lang/rust
 cd rust
 ./configure --enable-llvm-link-shared --enable-llvm-plugins --enable-llvm-enzyme --release-channel=nightly --enable-llvm-assertions --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs
 ```
@@ -25,7 +25,7 @@ rustup toolchain install nightly # enables -Z unstable-options
 You can then run our test cases:
 
 ```bash
-./x test --stage 1 tests/codegen/autodiff
+./x test --stage 1 tests/codegen-llvm/autodiff
 ./x test --stage 1 tests/pretty/autodiff
 ./x test --stage 1 tests/ui/autodiff
 ./x test --stage 1 tests/ui/feature-gates/feature-gate-autodiff.rs
@@ -45,7 +45,7 @@ apt install wget vim python3 git curl libssl-dev pkg-config lld ninja-build cmak
 ```
 Then build rustc in a slightly altered way:
 ```bash
-git clone --depth=1 https://github.com/rust-lang/rust.git
+git clone https://github.com/rust-lang/rust
 cd rust
 ./configure --enable-llvm-link-shared --enable-llvm-plugins --enable-llvm-enzyme --release-channel=nightly --enable-llvm-assertions --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs
 ./x dist
@@ -66,7 +66,7 @@ We recommend that approach, if you just want to use any of them and have no expe
 However, if you prefer to just build Enzyme without Rust, then these instructions might help.
 
 ```bash
-git clone --depth=1 git@github.com:llvm/llvm-project.git 
+git clone git@github.com:llvm/llvm-project
 cd llvm-project
 mkdir build
 cd build
@@ -77,7 +77,7 @@ ninja install
 This gives you a working LLVM build, now we can continue with building Enzyme.
 Leave the `llvm-project` folder, and execute the following commands:
 ```bash
-git clone git@github.com:EnzymeAD/Enzyme.git 
+git clone git@github.com:EnzymeAD/Enzyme
 cd Enzyme/enzyme
 mkdir build 
 cd build 
diff --git a/src/backend/backend-agnostic.md b/src/backend/backend-agnostic.md
index 0f81d3cb4..2fdda4eda 100644
--- a/src/backend/backend-agnostic.md
+++ b/src/backend/backend-agnostic.md
@@ -1,7 +1,5 @@
 # Backend Agnostic Codegen
 
-<!-- toc -->
-
 [`rustc_codegen_ssa`]
 provides an abstract interface for all backends to implement,
 namely LLVM, [Cranelift], and [GCC].
diff --git a/src/backend/implicit-caller-location.md b/src/backend/implicit-caller-location.md
index c5ee00813..9ca4bcab0 100644
--- a/src/backend/implicit-caller-location.md
+++ b/src/backend/implicit-caller-location.md
@@ -1,7 +1,5 @@
 # Implicit caller location
 
-<!-- toc -->
-
 Approved in [RFC 2091], this feature enables the accurate reporting of caller location during panics
 initiated from functions like `Option::unwrap`, `Result::expect`, and `Index::index`. This feature
 adds the [`#[track_caller]`][attr-reference] attribute for functions, the
diff --git a/src/backend/monomorph.md b/src/backend/monomorph.md
index 7ebb4d2b1..e9d98597e 100644
--- a/src/backend/monomorph.md
+++ b/src/backend/monomorph.md
@@ -1,7 +1,5 @@
 # Monomorphization
 
-<!-- toc -->
-
 As you probably know, Rust has a very expressive type system that has extensive
 support for generic types. But of course, assembly is not generic, so we need
 to figure out the concrete types of all the generics before the code can
diff --git a/src/backend/updating-llvm.md b/src/backend/updating-llvm.md
index 18c822aad..ebef15d40 100644
--- a/src/backend/updating-llvm.md
+++ b/src/backend/updating-llvm.md
@@ -1,7 +1,5 @@
 # Updating LLVM
 
-<!-- toc -->
-
 <!-- date-check: Aug 2024 -->
 Rust supports building against multiple LLVM versions:
 
diff --git a/src/borrow_check/moves_and_initialization/move_paths.md b/src/borrow_check/moves_and_initialization/move_paths.md
index ad9c75d62..95518fbc0 100644
--- a/src/borrow_check/moves_and_initialization/move_paths.md
+++ b/src/borrow_check/moves_and_initialization/move_paths.md
@@ -1,7 +1,5 @@
 # Move paths
 
-<!-- toc -->
-
 In reality, it's not enough to track initialization at the granularity
 of local variables. Rust also allows us to do moves and initialization
 at the field granularity:
diff --git a/src/borrow_check/region_inference.md b/src/borrow_check/region_inference.md
index 85e71b4fa..0d55ab955 100644
--- a/src/borrow_check/region_inference.md
+++ b/src/borrow_check/region_inference.md
@@ -1,7 +1,5 @@
 # Region inference (NLL)
 
-<!-- toc -->
-
 The MIR-based region checking code is located in [the `rustc_mir::borrow_check`
 module][nll].
 
diff --git a/src/borrow_check/region_inference/constraint_propagation.md b/src/borrow_check/region_inference/constraint_propagation.md
index 4c30d25e0..c3f8c03cb 100644
--- a/src/borrow_check/region_inference/constraint_propagation.md
+++ b/src/borrow_check/region_inference/constraint_propagation.md
@@ -1,7 +1,5 @@
 # Constraint propagation
 
-<!-- toc -->
-
 The main work of the region inference is **constraint propagation**,
 which is done in the [`propagate_constraints`] function.  There are
 three sorts of constraints that are used in NLL, and we'll explain how
diff --git a/src/borrow_check/region_inference/lifetime_parameters.md b/src/borrow_check/region_inference/lifetime_parameters.md
index fadfac404..2d337dbc0 100644
--- a/src/borrow_check/region_inference/lifetime_parameters.md
+++ b/src/borrow_check/region_inference/lifetime_parameters.md
@@ -1,7 +1,5 @@
 # Universal regions
 
-<!-- toc -->
-
 "Universal regions" is the name that the code uses to refer to "named
 lifetimes" -- e.g., lifetime parameters and `'static`. The name
 derives from the fact that such lifetimes are "universally quantified"
diff --git a/src/borrow_check/region_inference/member_constraints.md b/src/borrow_check/region_inference/member_constraints.md
index fd7c87ffc..2804c9772 100644
--- a/src/borrow_check/region_inference/member_constraints.md
+++ b/src/borrow_check/region_inference/member_constraints.md
@@ -1,7 +1,5 @@
 # Member constraints
 
-<!-- toc -->
-
 A member constraint `'m member of ['c_1..'c_N]` expresses that the
 region `'m` must be *equal* to some **choice regions** `'c_i` (for
 some `i`). These constraints cannot be expressed by users, but they
diff --git a/src/borrow_check/region_inference/placeholders_and_universes.md b/src/borrow_check/region_inference/placeholders_and_universes.md
index 91c8c4526..11fd2a5fc 100644
--- a/src/borrow_check/region_inference/placeholders_and_universes.md
+++ b/src/borrow_check/region_inference/placeholders_and_universes.md
@@ -1,7 +1,5 @@
 # Placeholders and universes
 
-<!-- toc -->
-
 From time to time we have to reason about regions that we can't
 concretely know. For example, consider this program:
 
diff --git a/src/bug-fix-procedure.md b/src/bug-fix-procedure.md
index 55436261f..6b13c9702 100644
--- a/src/bug-fix-procedure.md
+++ b/src/bug-fix-procedure.md
@@ -1,7 +1,5 @@
 # Procedures for breaking changes
 
-<!-- toc -->
-
 This page defines the best practices procedure for making bug fixes or soundness
 corrections in the compiler that can cause existing code to stop compiling. This
 text is based on
diff --git a/src/building/bootstrapping/debugging-bootstrap.md b/src/building/bootstrapping/debugging-bootstrap.md
index ed2678504..9c5ebbd36 100644
--- a/src/building/bootstrapping/debugging-bootstrap.md
+++ b/src/building/bootstrapping/debugging-bootstrap.md
@@ -123,6 +123,12 @@ if [#96176][cleanup-compiler-for] is resolved.
 
 [cleanup-compiler-for]: https://github.com/rust-lang/rust/issues/96176
 
+### Rendering step graph
+
+When you run bootstrap with the `BOOTSTRAP_TRACING` environment variable configured, bootstrap will automatically output a DOT file that shows all executed steps and their dependencies. The files will have a prefix `bootstrap-steps`. You can use e.g. `xdot` to visualize the file or e.g. `dot -Tsvg` to convert the DOT file to a SVG file.
+
+A separate DOT file will be outputted for dry-run and non-dry-run execution.
+
 ### Using `tracing` in bootstrap
 
 Both `tracing::*` macros and the `tracing::instrument` proc-macro attribute need to be gated behind `tracing` feature. Examples:
@@ -168,10 +174,17 @@ For `#[instrument]`, it's recommended to:
 
 ### Profiling bootstrap
 
-You can use the `COMMAND` tracing target to trace execution of most commands spawned by bootstrap. If you also use the `BOOTSTRAP_PROFILE=1` environment variable, bootstrap will generate a Chrome JSON trace file, which can be visualized in Chrome's `chrome://tracing` page or on https://ui.perfetto.dev.
+You can set the `BOOTSTRAP_PROFILE=1` environment variable to enable command execution profiling during bootstrap. This generates:
+
+* A Chrome trace file (for visualization in `chrome://tracing` or [Perfetto](https://ui.perfetto.dev)) if tracing is enabled via `BOOTSTRAP_TRACING=COMMAND=trace`
+* A plain-text summary file, `bootstrap-profile-{pid}.txt`, listing all commands sorted by execution time (slowest first), along with cache hits and working directories
+
+Note: the `.txt` report is always generated when `BOOTSTRAP_PROFILE=1` is set — tracing is not required.
+
+Example usage:
 
 ```bash
-$ BOOTSTRAP_TRACING=COMMAND=trace BOOTSTRAP_PROFILE=1 ./x build library
+$ BOOTSTRAP_PROFILE=1 BOOTSTRAP_TRACING=COMMAND=trace ./x build library
 ```
 
 ### rust-analyzer integration?
diff --git a/src/building/bootstrapping/what-bootstrapping-does.md b/src/building/bootstrapping/what-bootstrapping-does.md
index 2793ad438..da425d8d3 100644
--- a/src/building/bootstrapping/what-bootstrapping-does.md
+++ b/src/building/bootstrapping/what-bootstrapping-does.md
@@ -1,7 +1,5 @@
 # What Bootstrapping does
 
-<!-- toc -->
-
 [*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.
diff --git a/src/building/how-to-build-and-run.md b/src/building/how-to-build-and-run.md
index d29cd1448..b07d3533f 100644
--- a/src/building/how-to-build-and-run.md
+++ b/src/building/how-to-build-and-run.md
@@ -1,7 +1,5 @@
 # How to build and run the compiler
 
-<!-- toc -->
-
 <div class="warning">
 
 For `profile = "library"` users, or users who use `download-rustc = true | "if-unchanged"`, please be advised that
diff --git a/src/building/new-target.md b/src/building/new-target.md
index e11a2cd8e..436aec8ee 100644
--- a/src/building/new-target.md
+++ b/src/building/new-target.md
@@ -6,8 +6,6 @@ relevant to your desired goal.
 
 See also the associated documentation in the [target tier policy].
 
-<!-- toc -->
-
 [target tier policy]: https://doc.rust-lang.org/rustc/target-tier-policy.html#adding-a-new-target
 
 ## Specifying a new LLVM
diff --git a/src/building/optimized-build.md b/src/building/optimized-build.md
index 62dfaca89..863ed9749 100644
--- a/src/building/optimized-build.md
+++ b/src/building/optimized-build.md
@@ -1,7 +1,5 @@
 # Optimized build of the compiler
 
-<!-- toc -->
-
 There are multiple additional build configuration options and techniques that can be used to compile a
 build of `rustc` that is as optimized as possible (for example when building `rustc` for a Linux
 distribution). The status of these configuration options for various Rust targets is tracked [here].
diff --git a/src/building/quickstart.md b/src/building/quickstart.md
index 9a8ab353e..97314d803 100644
--- a/src/building/quickstart.md
+++ b/src/building/quickstart.md
@@ -61,9 +61,6 @@ and check the output.
 Use `--bless` if you've made a change and want to update the `.stderr` files
 with the new output.
 
-> `./x suggest` can also be helpful for suggesting which tests to run after a
-> change.
-
 Congrats, you are now ready to make a change to the compiler! If you have more
 questions, [the full chapter](./how-to-build-and-run.md) might contain the
 answers, and if it doesn't, feel free to ask for help on
diff --git a/src/building/suggested.md b/src/building/suggested.md
index bfb2f4d10..35c7e935b 100644
--- a/src/building/suggested.md
+++ b/src/building/suggested.md
@@ -3,8 +3,6 @@
 The full bootstrapping process takes quite a while. Here are some suggestions to
 make your life easier.
 
-<!-- toc -->
-
 ## Installing a pre-push hook
 
 CI will automatically fail your build if it doesn't pass `tidy`, our internal
@@ -162,7 +160,7 @@ create a `.vim/coc-settings.json`. The settings can be edited with
 [`src/etc/rust_analyzer_settings.json`].
 
 Another way is without a plugin, and creating your own logic in your
-configuration. The following code will work for any checkout of rust-lang/rust (newer than Febuary 2025):
+configuration. The following code will work for any checkout of rust-lang/rust (newer than February 2025):
 
 ```lua
 local function expand_config_variables(option)
@@ -270,23 +268,6 @@ run the tests at some later time. You can then use `git bisect` to track down
 is that you are left with a fairly fine-grained set of commits at the end, all
 of which build and pass tests. This often helps reviewing.
 
-## `x suggest`
-
-The `x suggest` subcommand suggests (and runs) a subset of the extensive
-`rust-lang/rust` tests based on files you have changed. This is especially
-useful for new contributors who have not mastered the arcane `x` flags yet and
-more experienced contributors as a shorthand for reducing mental effort. In all
-cases it is useful not to run the full tests (which can take on the order of
-tens of minutes) and just run a subset which are relevant to your changes. For
-example, running `tidy` and `linkchecker` is useful when editing Markdown files,
-whereas UI tests are much less likely to be helpful. While `x suggest` is a
-useful tool, it does not guarantee perfect coverage (just as PR CI isn't a
-substitute for bors). See the [dedicated chapter](../tests/suggest-tests.md) for
-more information and contribution instructions.
-
-Please note that `x suggest` is in a beta state currently and the tests that it
-will suggest are limited.
-
 ## Configuring `rustup` to use nightly
 
 Some parts of the bootstrap process uses pinned, nightly versions of tools like
diff --git a/src/compiler-debugging.md b/src/compiler-debugging.md
index 102e20207..edd2aa6c5 100644
--- a/src/compiler-debugging.md
+++ b/src/compiler-debugging.md
@@ -1,7 +1,5 @@
 # Debugging the compiler
 
-<!-- toc -->
-
 This chapter contains a few tips to debug the compiler. These tips aim to be
 useful no matter what you are working on.  Some of the other chapters have
 advice about specific parts of the compiler (e.g. the [Queries Debugging and
diff --git a/src/compiler-src.md b/src/compiler-src.md
index 00aa96226..d67bacb1b 100644
--- a/src/compiler-src.md
+++ b/src/compiler-src.md
@@ -1,7 +1,5 @@
 # High-level overview of the compiler source
 
-<!-- toc -->
-
 Now that we have [seen what the compiler does][orgch],
 let's take a look at the structure of the [`rust-lang/rust`] repository,
 where the rustc source code lives.
diff --git a/src/const-eval/interpret.md b/src/const-eval/interpret.md
index 51a539de5..08382b12f 100644
--- a/src/const-eval/interpret.md
+++ b/src/const-eval/interpret.md
@@ -1,7 +1,5 @@
 # Interpreter
 
-<!-- toc -->
-
 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
diff --git a/src/contributing.md b/src/contributing.md
index b3fcd79ec..963bef3af 100644
--- a/src/contributing.md
+++ b/src/contributing.md
@@ -1,7 +1,5 @@
 # Contribution procedures
 
-<!-- toc -->
-
 ## Bug reports
 
 While bugs are unfortunate, they're a reality in software. We can't fix what we
diff --git a/src/coroutine-closures.md b/src/coroutine-closures.md
index 48cdba44a..2617c824a 100644
--- a/src/coroutine-closures.md
+++ b/src/coroutine-closures.md
@@ -1,7 +1,5 @@
 # Async closures/"coroutine-closures"
 
-<!-- toc -->
-
 Please read [RFC 3668](https://rust-lang.github.io/rfcs/3668-async-closures.html) to understand the general motivation of the feature. This is a very technical and somewhat "vertical" chapter; ideally we'd split this and sprinkle it across all the relevant chapters, but for the purposes of understanding async closures *holistically*, I've put this together all here in one chapter.
 
 ## Coroutine-closures -- a technical deep dive
diff --git a/src/crates-io.md b/src/crates-io.md
index 4431585a2..677b1fc03 100644
--- a/src/crates-io.md
+++ b/src/crates-io.md
@@ -11,7 +11,7 @@ you should avoid adding dependencies to the compiler for several reasons:
 - The dependency may have transitive dependencies that have one of the above
   problems.
 
-<!-- date-check: Feb 2023 -->
+<!-- date-check: Aug 2025 -->
 Note that there is no official policy for vetting new dependencies to the compiler.
 Decisions are made on a case-by-case basis, during code review.
 
diff --git a/src/debugging-support-in-rustc.md b/src/debugging-support-in-rustc.md
index ac629934e..bd4f795ce 100644
--- a/src/debugging-support-in-rustc.md
+++ b/src/debugging-support-in-rustc.md
@@ -1,7 +1,5 @@
 # Debugging support in the Rust compiler
 
-<!-- toc -->
-
 This document explains the state of debugging tools support in the Rust compiler (rustc).
 It gives an overview of GDB, LLDB, WinDbg/CDB,
 as well as infrastructure around Rust compiler to debug Rust code.
diff --git a/src/diagnostics.md b/src/diagnostics.md
index 33f5441d3..82191e0a6 100644
--- a/src/diagnostics.md
+++ b/src/diagnostics.md
@@ -1,7 +1,5 @@
 # Errors and lints
 
-<!-- toc -->
-
 A lot of effort has been put into making `rustc` have great error messages.
 This chapter is about how to emit compile errors and lints from the compiler.
 
diff --git a/src/diagnostics/error-codes.md b/src/diagnostics/error-codes.md
index 1b6b87e4c..1693432b9 100644
--- a/src/diagnostics/error-codes.md
+++ b/src/diagnostics/error-codes.md
@@ -20,7 +20,7 @@ explanations should help users understand why their code cannot be accepted by
 the compiler. Rust prides itself on helpful error messages and long-form
 explanations are no exception. However, before error explanations are
 overhauled[^new-explanations] it is a bit open as to how exactly they should be
-written, as always: ask your reviewer or ask around on the Rust Discord or Zulip.
+written, as always: ask your reviewer or ask around on the Rust Zulip.
 
 [^new-explanations]: See the draft RFC [here][new-explanations-rfc].
 
diff --git a/src/early_late_parameters.md b/src/early_late_parameters.md
index 3f94b0905..c472bdc2c 100644
--- a/src/early_late_parameters.md
+++ b/src/early_late_parameters.md
@@ -1,8 +1,6 @@
 
 # Early vs Late bound parameters
 
-<!-- toc -->
-
 > **NOTE**: This chapter largely talks about early/late bound as being solely relevant when discussing function item types/function definitions. This is potentially not completely true, async blocks and closures should likely be discussed somewhat in this chapter.
 
 ## What does it mean to be "early" bound or "late" bound
diff --git a/src/effects.md b/src/effects.md
index c7aa27146..87b0103a7 100644
--- a/src/effects.md
+++ b/src/effects.md
@@ -67,10 +67,8 @@ in [`wfcheck::check_impl`].
 Here's an example:
 
 ```rust
-#[const_trait]
-trait Bar {}
-#[const_trait]
-trait Foo: ~const Bar {}
+const trait Bar {}
+const trait Foo: ~const Bar {}
 // `const_conditions` contains `HostEffect(Self: Bar, maybe)`
 
 impl const Bar for () {}
@@ -85,8 +83,7 @@ predicates of the trait method, and we attempt to prove the predicates of the
 impl method. We do the same for `const_conditions`:
 
 ```rust
-#[const_trait]
-trait Foo {
+const trait Foo {
     fn hi<T: ~const Default>();
 }
 
diff --git a/src/external-repos.md b/src/external-repos.md
index 0f7322357..5fb7eeee8 100644
--- a/src/external-repos.md
+++ b/src/external-repos.md
@@ -40,26 +40,27 @@ implement a new tool feature or test, that should happen in one collective rustc
     * `portable-simd` ([sync script](https://github.com/rust-lang/portable-simd/blob/master/subtree-sync.sh))
     * `rustfmt`
     * `rustc_codegen_cranelift` ([sync script](https://github.com/rust-lang/rustc_codegen_cranelift/blob/113af154d459e41b3dc2c5d7d878e3d3a8f33c69/scripts/rustup.sh#L7))
-* Using the [josh] tool
-    * `miri` ([sync guide](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#advanced-topic-syncing-with-the-rustc-repo))
-    * `rust-analyzer` ([sync script](https://github.com/rust-lang/rust-analyzer/blob/2e13684be123eca7181aa48e043e185d8044a84a/xtask/src/release.rs#L147))
-    * `rustc-dev-guide` ([josh sync](#synchronizing-a-josh-subtree))
+* Using the [josh](#synchronizing-a-josh-subtree) tool
+    * `miri`
+    * `rust-analyzer`
+    * `rustc-dev-guide`
     * `compiler-builtins`
-    * `stdarch` ([josh sync](#synchronizing-a-josh-subtree))
+    * `stdarch`
 
 ### Josh subtrees
 
-The [josh] tool is an alternative to git subtrees, which manages git history in a different way and scales better to larger repositories. Specific tooling is required to work with josh; you can check out the `miri` or `rust-analyzer` scripts linked above for inspiration. We provide a helper [`rustc-josh-sync`][josh-sync] tool to help with the synchronization, described [below](#synchronizing-a-josh-subtree).
+The [josh] tool is an alternative to git subtrees, which manages git history in a different way and scales better to larger repositories. Specific tooling is required to work with josh. We provide a helper [`rustc-josh-sync`][josh-sync] tool to help with the synchronization, described [below](#synchronizing-a-josh-subtree).
 
 ### Synchronizing a Josh subtree
 
 We use a dedicated tool called [`rustc-josh-sync`][josh-sync] for performing Josh subtree updates.
-Currently, we are migrating Josh repositories to it. So far, it is used in:
+The commands below can be used for all our Josh subtrees, although note that `miri`
+requires you to perform some [additional steps](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#advanced-topic-syncing-with-the-rustc-repo) during pulls.
 
-- rustc-dev-guide
-- stdarch
-
-To use the tool, first install it with `cargo install --locked --git https://github.com/rust-lang/josh-sync`.
+You can install the tool using the following command:
+```
+cargo install --locked --git https://github.com/rust-lang/josh-sync
+```
 
 Both pulls (synchronize changes from rust-lang/rust into the subtree) and pushes (synchronize
 changes from the subtree to rust-lang/rust) are performed from the subtree repository (so first
@@ -76,6 +77,9 @@ switch to its repository checkout directory in your terminal).
 
 #### Performing push
 
+> NOTE:
+> Before you proceed, look at some guidance related to Git [on josh-sync README].
+
 1) Run the push command to create a branch named `<branch-name>` in a `rustc` fork under the `<gh-username>` account
     ```
     rustc-josh-sync push <branch-name> <gh-username>
@@ -169,3 +173,4 @@ the week leading up to the beta cut.
 [Toolstate chapter]: https://forge.rust-lang.org/infra/toolstate.html
 [josh]: https://josh-project.github.io/josh/intro.html
 [josh-sync]: https://github.com/rust-lang/josh-sync
+[on josh-sync README]: https://github.com/rust-lang/josh-sync#git-peculiarities
diff --git a/src/getting-started.md b/src/getting-started.md
index d6c5c3ac8..87e26d379 100644
--- a/src/getting-started.md
+++ b/src/getting-started.md
@@ -3,8 +3,6 @@
 Thank you for your interest in contributing to Rust! There are many ways to
 contribute, and we appreciate all of them.
 
-<!-- toc -->
-
 If this is your first time contributing, the [walkthrough] chapter can give you a good example of
 how a typical contribution would go.
 
@@ -13,7 +11,6 @@ quick guide for the most useful things. For more information, [see this
 chapter on how to build and run the compiler](./building/how-to-build-and-run.md).
 
 [internals]: https://internals.rust-lang.org
-[rust-discord]: http://discord.gg/rust-lang
 [rust-zulip]: https://rust-lang.zulipchat.com
 [coc]: https://www.rust-lang.org/policies/code-of-conduct
 [walkthrough]: ./walkthrough.md
@@ -22,8 +19,7 @@ chapter on how to build and run the compiler](./building/how-to-build-and-run.md
 ## Asking Questions
 
 If you have questions, please make a post on the [Rust Zulip server][rust-zulip] or
-[internals.rust-lang.org][internals]. If you are contributing to Rustup, be aware they are not on
-Zulip - you can ask questions in `#wg-rustup` [on Discord][rust-discord].
+[internals.rust-lang.org][internals].
 See the [list of teams and working groups][governance] and [the Community page][community] on the
 official website for more resources.
 
@@ -32,19 +28,23 @@ official website for more resources.
 
 As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
 
-The compiler team (or `t-compiler`) usually hangs out in Zulip [in this
-"stream"][z]; it will be easiest to get questions answered there.
+The compiler team (or `t-compiler`) usually hangs out in Zulip in
+[the #t-compiler channel][z-t-compiler];
+questions about how the compiler works can go in [#t-compiler/help][z-help].
 
-[z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler
+[z-t-compiler]: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler
+[z-help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp
 
 **Please ask questions!** A lot of people report feeling that they are "wasting
-expert time", but nobody on `t-compiler` feels this way. Contributors are
+expert's time", but nobody on `t-compiler` feels this way. Contributors are
 important to us.
 
 Also, if you feel comfortable, prefer public topics, as this means others can
 see the questions and answers, and perhaps even integrate them back into this
 guide :)
 
+**Tip**: If you're not a native English speaker and feel unsure about writing, try using a translator to help. But avoid using LLM tools that generate long, complex words. In daily teamwork, **simple and clear words** are best for easy understanding. Even small typos or grammar mistakes can make you seem more human, and people connect better with humans.
+
 ### Experts
 
 Not all `t-compiler` members are experts on all parts of `rustc`; it's a
@@ -164,15 +164,12 @@ incredibly helpful:
 - [Triaging issues][triage]: categorizing, replicating, and minimizing issues is very helpful to the Rust maintainers.
 - [Working groups][wg]: there are a bunch of working groups on a wide variety
   of rust-related things.
-- Answer questions in the _Get Help!_ channels on the [Rust Discord
-  server][rust-discord], on [users.rust-lang.org][users], or on
-  [StackOverflow][so].
+- Answer questions on [users.rust-lang.org][users], or on [Stack Overflow][so].
 - Participate in the [RFC process](https://github.com/rust-lang/rfcs).
 - Find a [requested community library][community-library], build it, and publish
   it to [Crates.io](http://crates.io). Easier said than done, but very, very
   valuable!
 
-[rust-discord]: https://discord.gg/rust-lang
 [users]: https://users.rust-lang.org/
 [so]: http://stackoverflow.com/questions/tagged/rust
 [community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library
diff --git a/src/git.md b/src/git.md
index 8726ddfce..8f0511a45 100644
--- a/src/git.md
+++ b/src/git.md
@@ -1,7 +1,5 @@
 # Using Git
 
-<!-- toc -->
-
 The Rust project uses [Git] to manage its source code. In order to
 contribute, you'll need some familiarity with its features so that your changes
 can be incorporated into the compiler.
@@ -340,13 +338,13 @@ your fork with `git push --force-with-lease`.
 
 ### Keeping things up to date
 
-The above section on [Rebasing](#rebasing) is a specific
+The [above section](#rebasing) is a specific
 guide on rebasing work and dealing with merge conflicts.
 Here is some general advice about how to keep your local repo
 up-to-date with upstream changes:
 
 Using `git pull upstream master` while on your local master branch regularly
-will keep it up-to-date. You will also want to rebase your feature branches
+will keep it up-to-date. You will also want to keep your feature branches
 up-to-date as well. After pulling, you can checkout the feature branches
 and rebase them:
 
diff --git a/src/guides/editions.md b/src/guides/editions.md
index 9a92d4ebc..b65fbb13c 100644
--- a/src/guides/editions.md
+++ b/src/guides/editions.md
@@ -1,7 +1,5 @@
 # Editions
 
-<!-- toc -->
-
 This chapter gives an overview of how Edition support works in rustc.
 This assumes that you are familiar with what Editions are (see the [Edition Guide]).
 
diff --git a/src/hir.md b/src/hir.md
index 72fb10701..38ba33112 100644
--- a/src/hir.md
+++ b/src/hir.md
@@ -1,7 +1,5 @@
 # The HIR
 
-<!-- toc -->
-
 The HIR – "High-Level Intermediate Representation" – is the primary IR used
 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
diff --git a/src/hir/ambig-unambig-ty-and-consts.md b/src/hir/ambig-unambig-ty-and-consts.md
index 709027883..d4f504ad2 100644
--- a/src/hir/ambig-unambig-ty-and-consts.md
+++ b/src/hir/ambig-unambig-ty-and-consts.md
@@ -38,7 +38,7 @@ Note that places 3 and 4 would never actually be possible to encounter as we alw
 This has a few failure modes:
 - People may write visitors which check for `GenericArg::Infer` but forget to check for `hir::TyKind/ConstArgKind::Infer`, only handling infers in ambig positions by accident.
 - People may write visitors which check for `hir::TyKind/ConstArgKind::Infer` but forget to check for `GenericArg::Infer`, only handling infers in unambig positions by accident.
-- People may write visitors which check for `GenerArg::Type/Const(TyKind/ConstArgKind::Infer)` and `GenerigArg::Infer`, not realising that we never represent inferred types/consts in ambig positions as a `GenericArg::Type/Const`.
+- People may write visitors which check for `GenericArg::Type/Const(TyKind/ConstArgKind::Infer)` and `GenericArg::Infer`, not realising that we never represent inferred types/consts in ambig positions as a `GenericArg::Type/Const`.
 - People may write visitors which check for *only* `TyKind::Infer` and not `ConstArgKind::Infer` forgetting that there are also inferred const arguments (and vice versa).
 
 To make writing HIR visitors less error prone when caring about inferred types/consts we have a relatively complex system:
@@ -60,4 +60,4 @@ This has a number of benefits:
 [ambig_arg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/enum.AmbigArg.html
 [visit_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/intravisit/trait.Visitor.html#method.visit_ty
 [visit_const_arg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/intravisit/trait.Visitor.html#method.visit_const_arg
-[visit_infer]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/intravisit/trait.Visitor.html#method.visit_infer
\ No newline at end of file
+[visit_infer]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/intravisit/trait.Visitor.html#method.visit_infer
diff --git a/src/implementing_new_features.md b/src/implementing_new_features.md
index 5d0e875cb..00bce8599 100644
--- a/src/implementing_new_features.md
+++ b/src/implementing_new_features.md
@@ -1,146 +1,90 @@
 # Implementing new language features
 
-<!-- toc -->
+When you want to implement a new significant feature in the compiler, you need to go through this process to make sure everything goes smoothly.
 
-When you want to implement a new significant feature in the compiler,
-you need to go through this process to make sure everything goes
-smoothly.
+**NOTE: This section is for *language* features, not *library* features, which use [a different process].**
 
-**NOTE: this section is for *language* features, not *library* features,
-which use [a different process].**
-
-See also [the Rust Language Design Team's procedures][lang-propose] for
-proposing changes to the language.
+See also [the Rust Language Design Team's procedures][lang-propose] for proposing changes to the language.
 
 [a different process]: ./stability.md
 [lang-propose]: https://lang-team.rust-lang.org/how_to/propose.html
 
 ## The @rfcbot FCP process
 
-When the change is small and uncontroversial, then it can be done
-with just writing a PR and getting an r+ from someone who knows that
-part of the code. However, if the change is potentially controversial,
-it would be a bad idea to push it without consensus from the rest
-of the team (both in the "distributed system" sense to make sure
-you don't break anything you don't know about, and in the social
-sense to avoid PR fights).
-
-If such a change seems to be too small to require a full formal RFC process
-(e.g., a small standard library addition, a big refactoring of the code, a
-"technically-breaking" change, or a "big bugfix" that basically amounts to a
-small feature) but is still too controversial or big to get by with a single r+,
-you can propose a final comment period (FCP). Or, if you're not on the relevant
-team (and thus don't have @rfcbot permissions), ask someone who is to start one;
-unless they have a concern themselves, they should.
-
-Again, the FCP process is only needed if you need consensus – if you
-don't think anyone would have a problem with your change, it's OK to
-get by with only an r+. For example, it is OK to add or modify
-unstable command-line flags or attributes without an FCP for
-compiler development or standard library use, as long as you don't
-expect them to be in wide use in the nightly ecosystem.
-Some teams have lighter weight processes that they use in scenarios
-like this; for example, the compiler team recommends
-filing a Major Change Proposal ([MCP][mcp]) as a lightweight way to
-garner support and feedback without requiring full consensus.
+When the change is small, uncontroversial, non-breaking, and does not affect the stable language in any user-observable ways or add any new unstable features, then it can be done with just writing a PR and getting an r+ from someone who knows that part of the code. However, if not, more must be done. Even for compiler-internal work, it would be a bad idea to push a controversial change without consensus from the rest of the team (both in the "distributed system" sense to make sure you don't break anything you don't know about, and in the social sense to avoid PR fights).
+
+For changes that need the consensus of a team, we us the process of proposing a final comment period (FCP). If you're not on the relevant team (and thus don't have @rfcbot permissions), ask someone who is to start one; unless they have a concern themselves, they should.
+
+The FCP process is only needed if you need consensus – if no processes require consensus for your change and you don't think anyone would have a problem with it, it's OK to rely on only an r+. For example, it is OK to add or modify unstable command-line flags or attributes in the reserved compiler-internal `rustc_` namespace without an FCP for compiler development or standard library use, as long as you don't expect them to be in wide use in the nightly ecosystem. Some teams have lighter weight processes that they use in scenarios like this; for example, the compiler team recommends filing a Major Change Proposal ([MCP][mcp]) as a lightweight way to garner support and feedback without requiring full consensus.
 
 [mcp]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#how-do-i-submit-an-mcp
 
-You don't need to have the implementation fully ready for r+ to propose an FCP,
-but it is generally a good idea to have at least a proof
-of concept so that people can see what you are talking about.
+You don't need to have the implementation fully ready for r+ to propose an FCP, but it is generally a good idea to have at least a proof of concept so that people can see what you are talking about.
 
-When an FCP is proposed, it requires all members of the team to sign off the
-FCP. After they all do so, there's a 10-day-long "final comment period" (hence
-the name) where everybody can comment, and if no concerns are raised, the
-PR/issue gets FCP approval.
+When an FCP is proposed, it requires all members of the team to sign off on the FCP. After they all do so, there's a 10-day-long "final comment period" (hence the name) where everybody can comment, and if no concerns are raised, the PR/issue gets FCP approval.
 
 ## The logistics of writing features
 
-There are a few "logistic" hoops you might need to go through in
-order to implement a feature in a working way.
+There are a few "logistical" hoops you might need to go through in order to implement a feature in a working way.
 
 ### Warning Cycles
 
-In some cases, a feature or bugfix might break some existing programs
-in some edge cases. In that case, you might want to do a crater run
-to assess the impact and possibly add a future-compatibility lint,
-similar to those used for
-[edition-gated lints](diagnostics.md#edition-gated-lints).
+In some cases, a feature or bugfix might break some existing programs in some edge cases. In that case, you'll want to do a crater run to assess the impact and possibly add a future-compatibility lint, similar to those used for [edition-gated lints](diagnostics.md#edition-gated-lints).
 
 ### Stability
 
-We [value the stability of Rust]. Code that works and runs on stable
-should (mostly) not break. Because of that, we don't want to release
-a feature to the world with only team consensus and code review -
-we want to gain real-world experience on using that feature on nightly,
-and we might want to change the feature based on that experience.
-
-To allow for that, we must make sure users don't accidentally depend
-on that new feature - otherwise, especially if experimentation takes
-time or is delayed and the feature takes the trains to stable,
-it would end up de facto stable and we'll not be able to make changes
-in it without breaking people's code.
-
-The way we do that is that we make sure all new features are feature
-gated - they can't be used without enabling a feature gate
-(`#[feature(foo)]`), which can't be done in a stable/beta compiler.
-See the [stability in code] section for the technical details.
-
-Eventually, after we gain enough experience using the feature,
-make the necessary changes, and are satisfied, we expose it to
-the world using the stabilization process described [here].
-Until then, the feature is not set in stone: every part of the
-feature can be changed, or the feature might be completely
-rewritten or removed. Features are not supposed to gain tenure
-by being unstable and unchanged for a year.
+We [value the stability of Rust]. Code that works and runs on stable should (mostly) not break. Because of that, we don't want to release a feature to the world with only team consensus and code review - we want to gain real-world experience on using that feature on nightly, and we might want to change the feature based on that experience.
+
+To allow for that, we must make sure users don't accidentally depend on that new feature - otherwise, especially if experimentation takes time or is delayed and the feature takes the trains to stable, it would end up de facto stable and we'll not be able to make changes in it without breaking people's code.
+
+The way we do that is that we make sure all new features are feature gated - they can't be used without enabling a feature gate (`#[feature(foo)]`), which can't be done in a stable/beta compiler. See the [stability in code] section for the technical details.
+
+Eventually, after we gain enough experience using the feature, make the necessary changes, and are satisfied, we expose it to the world using the stabilization process described [here]. Until then, the feature is not set in stone: every part of the feature can be changed, or the feature might be completely rewritten or removed. Features do not gain tenure by being unstable and unchanged for long periods of time.
 
 ###  Tracking Issues
 
-To keep track of the status of an unstable feature, the
-experience we get while using it on nightly, and of the
-concerns that block its stabilization, every feature-gate
-needs a tracking issue. General discussions about the feature should be done on the tracking issue.
+To keep track of the status of an unstable feature, the experience we get while using it on
+nightly, and of the concerns that block its stabilization, every feature-gate needs a tracking
+issue. When creating issues and PRs related to the feature, reference this tracking issue, and when there are updates about the feature's progress, post those to the tracking issue.
 
-For features that have an RFC, you should use the RFC's
-tracking issue for the feature.
+For features that are part of an accept RFC or approved lang experiment, use the tracking issue for that.
 
-For other features, you'll have to make a tracking issue
-for that feature. The issue title should be "Tracking issue
-for YOUR FEATURE". Use the ["Tracking Issue" issue template][template].
+For other features, create a tracking issue for that feature. The issue title should be "Tracking issue for YOUR FEATURE". Use the ["Tracking Issue" issue template][template].
 
 [template]: https://github.com/rust-lang/rust/issues/new?template=tracking_issue.md
 
+### Lang experiments
+
+To land in the compiler, features that have user-visible effects on the language (even unstable ones) must either be part of an accepted RFC or an approved [lang experiment].
+
+To propose a new lang experiment, open an issue in `rust-lang/rust` that describes the motivation and the intended solution. If it's accepted, this issue will become the tracking issue for the experiment, so use the tracking issue [template] while also including these other details. Nominate the issue for the lang team and CC `@rust-lang/lang` and `@rust-lang/lang-advisors`. When the experiment is approved, the tracking issue will be marked as `B-experimental`.
+
+Feature flags related to a lang experiment must be marked as `incomplete` until an RFC is accepted for the feature.
+
+[lang experiment]: https://lang-team.rust-lang.org/how_to/experiment.html
+
 ##  Stability in code
 
-The below steps needs to be followed in order to implement
-a new unstable feature:
+The below steps needs to be followed in order to implement a new unstable feature:
 
-1. Open a [tracking issue] -
-   if you have an RFC, you can use the tracking issue for the RFC.
+1. Open or identify the [tracking issue]. For features that are part of an accept RFC or approved lang experiment, use the tracking issue for that.
 
-   The tracking issue should be labeled with at least `C-tracking-issue`.
-   For a language feature, a label `F-feature_name` should be added as well.
+   Label the tracking issue with `C-tracking-issue` and the relevant `F-feature_name` label (adding that label if needed).
 
-1. Pick a name for the feature gate (for RFCs, use the name
-   in the RFC).
+1. Pick a name for the feature gate (for RFCs, use the name in the RFC).
 
 1. Add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block.
 
    Note that this block must be in alphabetical order.
 
-1. Add a feature gate declaration to `rustc_feature/src/unstable.rs` in the unstable
-   `declare_features` block.
+1. Add a feature gate declaration to `rustc_feature/src/unstable.rs` in the unstable `declare_features` block.
 
    ```rust ignore
    /// description of feature
    (unstable, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number))
    ```
 
-   If you haven't yet
-   opened a tracking issue (e.g. because you want initial feedback on whether the feature is likely
-   to be accepted), you can temporarily use `None` - but make sure to update it before the PR is
-   merged!
+   If you haven't yet opened a tracking issue (e.g. because you want initial feedback on whether the feature is likely to be accepted), you can temporarily use `None` - but make sure to update it before the PR is merged!
 
    For example:
 
@@ -149,9 +93,7 @@ a new unstable feature:
    (unstable, non_ascii_idents, "CURRENT_RUSTC_VERSION", Some(55467), None),
    ```
 
-   Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features`
-   lint]
-   by setting their type to `incomplete`:
+   Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features` lint] by setting their type to `incomplete`:
 
    [`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features
 
@@ -160,42 +102,27 @@ a new unstable feature:
    (incomplete, deref_patterns, "CURRENT_RUSTC_VERSION", Some(87121), None),
    ```
 
-   To avoid [semantic merge conflicts], please use `CURRENT_RUSTC_VERSION` instead of `1.70` or
-   another explicit version number.
+   Feature flags related to a lang experiment must be marked as `incomplete` until an RFC is accepted for the feature.
+
+   To avoid [semantic merge conflicts], use `CURRENT_RUSTC_VERSION` instead of `1.70` or another explicit version number.
 
    [semantic merge conflicts]: https://bors.tech/essay/2017/02/02/pitch/
 
-1. Prevent usage of the new feature unless the feature gate is set.
-   You can check it in most places in the compiler using the
-   expression `tcx.features().$feature_name()`
+1. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the expression `tcx.features().$feature_name()`.
+
+    If the feature gate is not set, you should either maintain the pre-feature behavior or raise an error, depending on what makes sense. Errors should generally use [`rustc_session::parse::feature_err`]. For an example of adding an error, see [#81015].
 
-    If the feature gate is not set, you should either maintain
-    the pre-feature behavior or raise an error, depending on
-    what makes sense. Errors should generally use [`rustc_session::parse::feature_err`].
-    For an example of adding an error, see [#81015].
+   For features introducing new syntax, pre-expansion gating should be used instead. During parsing, when the new syntax is parsed, the symbol must be inserted to the current crate's [`GatedSpans`] via `self.sess.gated_span.gate(sym::my_feature, span)`.
 
-   For features introducing new syntax, pre-expansion gating should be used instead.
-   During parsing, when the new syntax is parsed, the symbol must be inserted to the
-   current crate's [`GatedSpans`] via `self.sess.gated_span.gate(sym::my_feature, span)`. 
-   
-   After being inserted to the gated spans, the span must be checked in the 
-   [`rustc_ast_passes::feature_gate::check_crate`] function, which actually denies
-   features. Exactly how it is gated depends on the exact type of feature, but most 
-   likely will use the `gate_all!()` macro. 
+   After being inserted to the gated spans, the span must be checked in the [`rustc_ast_passes::feature_gate::check_crate`] function, which actually denies features. Exactly how it is gated depends on the exact type of feature, but most likely will use the `gate_all!()` macro.
 
-1. Add a test to ensure the feature cannot be used without
-   a feature gate, by creating `tests/ui/feature-gates/feature-gate-$feature_name.rs`.
-   You can generate the corresponding `.stderr` file by running `./x test 
-tests/ui/feature-gates/ --bless`.
+1. Add a test to ensure the feature cannot be used without a feature gate, by creating `tests/ui/feature-gates/feature-gate-$feature_name.rs`. You can generate the corresponding `.stderr` file by running `./x test tests/ui/feature-gates/ --bless`.
 
-1. Add a section to the unstable book, in
-   `src/doc/unstable-book/src/language-features/$feature_name.md`.
+1. Add a section to the unstable book, in `src/doc/unstable-book/src/language-features/$feature_name.md`.
 
-1. Write a lot of tests for the new feature, preferably in `tests/ui/$feature_name/`.
-   PRs without tests will not be accepted!
+1. Write a lot of tests for the new feature, preferably in `tests/ui/$feature_name/`. PRs without tests will not be accepted!
 
-1. Get your PR reviewed and land it. You have now successfully
-   implemented a feature in Rust!
+1. Get your PR reviewed and land it. You have now successfully implemented a feature in Rust!
 
 [`GatedSpans`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.GatedSpans.html
 [#81015]: https://github.com/rust-lang/rust/pull/81015
@@ -206,3 +133,42 @@ tests/ui/feature-gates/ --bless`.
 [here]: ./stabilization_guide.md
 [tracking issue]: #tracking-issues
 [add-feature-gate]: ./feature-gates.md#adding-a-feature-gate
+
+## Call for testing
+
+Once the implementation is complete, the feature will be available to nightly users but not yet part of stable Rust. This is a good time to write a blog post on [the main Rust blog][rust-blog] and issue a "call for testing".
+
+Some earlier such blog posts include:
+
+1. [The push for GATs stabilization](https://blog.rust-lang.org/2021/08/03/GATs-stabilization-push/)
+2. [Changes to `impl Trait` in Rust 2024](https://blog.rust-lang.org/2024/09/05/impl-trait-capture-rules.html)
+3. [Async Closures MVP: Call for Testing!](https://blog.rust-lang.org/inside-rust/2024/08/09/async-closures-call-for-testing/)
+
+Alternatively, [*This Week in Rust*][twir] has a [section][twir-cft] for this. One example of this having been used is:
+
+- [Call for testing on boolean literals as cfg predicates](https://github.com/rust-lang/rust/issues/131204#issuecomment-2569314526)
+
+Which option to choose might depend on how significant the language change is, though note that the [*This Week in Rust*][twir] section might be less visible than a dedicated post on the main Rust blog.
+
+## Polishing
+
+Giving users a polished experience means more than just implementing the feature in rustc. We need to think about all of the tools and resources that we ship. This work includes:
+
+- Documenting the language feature in the [Rust Reference][reference].
+- Extending [`rustfmt`] to format any new syntax (if applicable).
+- Extending [`rust-analyzer`] (if applicable). The extent of this work can depend on the nature of the language feature, as some features don't need to be blocked on *full* support.
+   - When a language feature degrades the user experience simply by existing before support is implemented in [`rust-analyzer`], that may lead the lang team to raise a blocking concern.
+   - Examples of such might include new syntax that [`rust-analyzer`] can't parse or type inference changes it doesn't understand when those lead to bogus diagnostics.
+
+## Stabilization
+
+The final step in the feature lifecycle is [stabilization][stab], which is when the feature becomes available to all Rust users. At this point, backward incompatible changes are generally no longer permitted (see the lang team's [defined semver policies](https://rust-lang.github.io/rfcs/1122-language-semver.html) for details). To learn more about stabilization, see the [stabilization guide][stab].
+
+
+[stab]: ./stabilization_guide.md
+[rust-blog]: https://github.com/rust-lang/blog.rust-lang.org/
+[twir]: https://github.com/rust-lang/this-week-in-rust
+[twir-cft]: https://this-week-in-rust.org/blog/2025/01/22/this-week-in-rust-583/#calls-for-testing
+[`rustfmt`]: https://github.com/rust-lang/rustfmt
+[`rust-analyzer`]: https://github.com/rust-lang/rust-analyzer
+[reference]: https://github.com/rust-lang/reference
diff --git a/src/llvm-coverage-instrumentation.md b/src/llvm-coverage-instrumentation.md
index 28e0e7a90..288b90f33 100644
--- a/src/llvm-coverage-instrumentation.md
+++ b/src/llvm-coverage-instrumentation.md
@@ -1,7 +1,5 @@
 # LLVM source-based code coverage
 
-<!-- toc -->
-
 `rustc` supports detailed source-based code and test coverage analysis
 with a command line option (`-C instrument-coverage`) that instruments Rust
 libraries and binaries with additional instructions and data, at compile time.
@@ -117,7 +115,7 @@ human-readable coverage report.
 > directive, so they will be skipped if the profiler runtime has not been
 > [enabled in `bootstrap.toml`](#recommended-configtoml-settings).
 
-Finally, the [`tests/codegen/instrument-coverage/testprog.rs`] test compiles a simple Rust program
+Finally, the [`tests/codegen-llvm/instrument-coverage/testprog.rs`] test compiles a simple Rust program
 with `-C instrument-coverage` and compares the compiled program's LLVM IR to
 expected LLVM IR instructions and structured data for a coverage-enabled
 program, including various checks for Coverage Map-related metadata and the LLVM
@@ -136,4 +134,4 @@ and `mir-opt` tests can be refreshed by running:
 [`tests/coverage`]: https://github.com/rust-lang/rust/tree/master/tests/coverage
 [`src/tools/coverage-dump`]: https://github.com/rust-lang/rust/tree/master/src/tools/coverage-dump
 [`tests/coverage-run-rustdoc`]: https://github.com/rust-lang/rust/tree/master/tests/coverage-run-rustdoc
-[`tests/codegen/instrument-coverage/testprog.rs`]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/coverage/instrument_coverage.rs
+[`tests/codegen-llvm/instrument-coverage/testprog.rs`]: https://github.com/rust-lang/rust/blob/master/tests/mir-opt/coverage/instrument_coverage.rs
diff --git a/src/macro-expansion.md b/src/macro-expansion.md
index a90f71700..54d6d2b4e 100644
--- a/src/macro-expansion.md
+++ b/src/macro-expansion.md
@@ -1,7 +1,5 @@
 # Macro expansion
 
-<!-- toc -->
-
 Rust has a very powerful macro system. In the previous chapter, we saw how
 the parser sets aside macros to be expanded (using temporary [placeholders]).
 This chapter is about the process of expanding those macros iteratively until
diff --git a/src/mir/construction.md b/src/mir/construction.md
index f2559a22b..8360d9ff1 100644
--- a/src/mir/construction.md
+++ b/src/mir/construction.md
@@ -1,7 +1,5 @@
 # MIR construction
 
-<!-- toc -->
-
 The lowering of [HIR] to [MIR] occurs for the following (probably incomplete)
 list of items:
 
diff --git a/src/mir/dataflow.md b/src/mir/dataflow.md
index 85e57dd83..970e61196 100644
--- a/src/mir/dataflow.md
+++ b/src/mir/dataflow.md
@@ -1,7 +1,5 @@
 # Dataflow Analysis
 
-<!-- toc -->
-
 If you work on the MIR, you will frequently come across various flavors of
 [dataflow analysis][wiki]. `rustc` uses dataflow to find uninitialized
 variables, determine what variables are live across a generator `yield`
diff --git a/src/mir/drop-elaboration.md b/src/mir/drop-elaboration.md
index 3b321fd44..4da612c83 100644
--- a/src/mir/drop-elaboration.md
+++ b/src/mir/drop-elaboration.md
@@ -1,7 +1,5 @@
 # Drop elaboration
 
-<!-- toc -->
-
 ## Dynamic drops
 
 According to the [reference][reference-drop]:
diff --git a/src/mir/index.md b/src/mir/index.md
index f355875aa..8ba5f3ac8 100644
--- a/src/mir/index.md
+++ b/src/mir/index.md
@@ -1,7 +1,5 @@
 # The MIR (Mid-level IR)
 
-<!-- toc -->
-
 MIR is Rust's _Mid-level Intermediate Representation_. It is
 constructed from [HIR](../hir.html). MIR was introduced in
 [RFC 1211]. It is a radically simplified form of Rust that is used for
diff --git a/src/name-resolution.md b/src/name-resolution.md
index 719ebce85..2e96382f7 100644
--- a/src/name-resolution.md
+++ b/src/name-resolution.md
@@ -1,7 +1,5 @@
 # Name resolution
 
-<!-- toc -->
-
 In the previous chapters, we saw how the [*Abstract Syntax Tree* (`AST`)][ast]
 is built with all macros expanded. We saw how doing that requires doing some
 name resolution to resolve imports and macro names. In this chapter, we show
diff --git a/src/normalization.md b/src/normalization.md
index eb0962a41..53e20f1c0 100644
--- a/src/normalization.md
+++ b/src/normalization.md
@@ -1,7 +1,5 @@
 # Aliases and Normalization
 
-<!-- toc -->
-
 ## Aliases
 
 In Rust there are a number of types that are considered equal to some "underlying" type, for example inherent associated types, trait associated types, free type aliases (`type Foo = u32`), and opaque types (`-> impl RPIT`). We consider such types to be "aliases", alias types are represented by the [`TyKind::Alias`][tykind_alias] variant, with the kind of alias tracked by the [`AliasTyKind`][aliaskind] enum.
diff --git a/src/offload/installation.md b/src/offload/installation.md
index 8cfec44ec..b376e962f 100644
--- a/src/offload/installation.md
+++ b/src/offload/installation.md
@@ -6,9 +6,9 @@ In the future, `std::offload` should become available in nightly builds for user
 
 First you need to clone and configure the Rust repository:
 ```bash
-git clone --depth=1 git@github.com:rust-lang/rust.git
+git clone git@github.com:rust-lang/rust
 cd rust
-./configure --enable-llvm-link-shared --release-channel=nightly --enable-llvm-assertions --enable-offload --enable-enzyme --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs
+./configure --enable-llvm-link-shared --release-channel=nightly --enable-llvm-assertions --enable-llvm-offload --enable-llvm-enzyme --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs
 ```
 
 Afterwards you can build rustc using:
@@ -26,7 +26,7 @@ rustup toolchain install nightly # enables -Z unstable-options
 
 ## Build instruction for LLVM itself
 ```bash
-git clone --depth=1 git@github.com:llvm/llvm-project.git 
+git clone git@github.com:llvm/llvm-project
 cd llvm-project
 mkdir build
 cd build
@@ -40,7 +40,7 @@ This gives you a working LLVM build.
 ## Testing
 run
 ```
-./x test --stage 1 tests/codegen/gpu_offload
+./x test --stage 1 tests/codegen-llvm/gpu_offload
 ```
 
 ## Usage
diff --git a/src/overview.md b/src/overview.md
index 8a1a22fad..378d8c445 100644
--- a/src/overview.md
+++ b/src/overview.md
@@ -1,7 +1,5 @@
 # Overview of the compiler
 
-<!-- toc -->
-
 This chapter is about the overall process of compiling a program -- how
 everything fits together.
 
@@ -323,6 +321,10 @@ the name `'tcx`, which means that something is tied to the lifetime of the
 
 [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
 
+For more information about queries in the compiler, see [the queries chapter][queries].
+
+[queries]: ./query.md
+
 ### `ty::Ty`
 
 Types are really important in Rust, and they form the core of a lot of compiler
diff --git a/src/panic-implementation.md b/src/panic-implementation.md
index 468190ffc..dba3f2146 100644
--- a/src/panic-implementation.md
+++ b/src/panic-implementation.md
@@ -1,7 +1,5 @@
 # Panicking in Rust
 
-<!-- toc -->
-
 ## Step 1: Invocation of the `panic!` macro.
 
 There are actually two panic macros - one defined in `core`, and one defined in `std`.
diff --git a/src/profile-guided-optimization.md b/src/profile-guided-optimization.md
index d279786ac..4e3dadd40 100644
--- a/src/profile-guided-optimization.md
+++ b/src/profile-guided-optimization.md
@@ -1,7 +1,5 @@
 # Profile-guided optimization
 
-<!-- toc -->
-
 `rustc` supports doing profile-guided optimization (PGO).
 This chapter describes what PGO is and how the support for it is
 implemented in `rustc`.
@@ -132,7 +130,7 @@ There is also a [codegen test][codegen-test] that checks that some expected
 instrumentation artifacts show up in LLVM IR.
 
 [rmake-tests]: https://github.com/rust-lang/rust/tree/master/tests/run-make
-[codegen-test]: https://github.com/rust-lang/rust/blob/master/tests/codegen/pgo-instrumentation.rs
+[codegen-test]: https://github.com/rust-lang/rust/blob/master/tests/codegen-llvm/pgo-instrumentation.rs
 
 ## Additional information
 
diff --git a/src/queries/incremental-compilation-in-detail.md b/src/queries/incremental-compilation-in-detail.md
index 18e0e25c5..46e38832e 100644
--- a/src/queries/incremental-compilation-in-detail.md
+++ b/src/queries/incremental-compilation-in-detail.md
@@ -1,7 +1,5 @@
 # Incremental compilation in detail
 
-<!-- toc -->
-
 The incremental compilation scheme is, in essence, a surprisingly
 simple extension to the overall query system. It relies on the fact that:
 
diff --git a/src/queries/incremental-compilation.md b/src/queries/incremental-compilation.md
index 6e5b4e8cc..731ff3287 100644
--- a/src/queries/incremental-compilation.md
+++ b/src/queries/incremental-compilation.md
@@ -1,7 +1,5 @@
 # Incremental compilation
 
-<!-- toc -->
-
 The incremental compilation scheme is, in essence, a surprisingly
 simple extension to the overall query system. We'll start by describing
 a slightly simplified variant of the real thing – the "basic algorithm" –
diff --git a/src/queries/query-evaluation-model-in-detail.md b/src/queries/query-evaluation-model-in-detail.md
index 444e20bc5..c1a4373f7 100644
--- a/src/queries/query-evaluation-model-in-detail.md
+++ b/src/queries/query-evaluation-model-in-detail.md
@@ -1,7 +1,5 @@
 # The Query Evaluation Model in detail
 
-<!-- toc -->
-
 This chapter provides a deeper dive into the abstract model queries are built on.
 It does not go into implementation details but tries to explain
 the underlying logic. The examples here, therefore, have been stripped down and
diff --git a/src/queries/salsa.md b/src/queries/salsa.md
index 1a7b7fa9a..dc7160edc 100644
--- a/src/queries/salsa.md
+++ b/src/queries/salsa.md
@@ -1,7 +1,5 @@
 # How Salsa works
 
-<!-- toc -->
-
 This chapter is based on the explanation given by Niko Matsakis in this
 [video](https://www.youtube.com/watch?v=_muY4HjSqVw) about
 [Salsa](https://github.com/salsa-rs/salsa). To find out more you may
diff --git a/src/query.md b/src/query.md
index 0ca1b360a..8377a7b2f 100644
--- a/src/query.md
+++ b/src/query.md
@@ -1,7 +1,5 @@
 # Queries: demand-driven compilation
 
-<!-- toc -->
-
 As described in [Overview of the compiler], the Rust compiler
 is still (as of <!-- date-check --> July 2021) transitioning from a
 traditional "pass-based" setup to a "demand-driven" system. The compiler query
diff --git a/src/rustdoc-internals.md b/src/rustdoc-internals.md
index 0234d4a92..4affbafe4 100644
--- a/src/rustdoc-internals.md
+++ b/src/rustdoc-internals.md
@@ -1,7 +1,5 @@
 # Rustdoc Internals
 
-<!-- toc -->
-
 This page describes [`rustdoc`]'s passes and modes. For an overview of `rustdoc`,
 see the ["Rustdoc overview" chapter](./rustdoc.md).
 
diff --git a/src/rustdoc-internals/rustdoc-test-suite.md b/src/rustdoc-internals/rustdoc-test-suite.md
index b05318ce9..3ec5ebd79 100644
--- a/src/rustdoc-internals/rustdoc-test-suite.md
+++ b/src/rustdoc-internals/rustdoc-test-suite.md
@@ -20,7 +20,7 @@ Internally, [`compiletest`] invokes the supplementary checker script [`htmldocck
 
 Directives to HtmlDocCk are assertions that place constraints on the generated HTML.
 They look similar to those given to `compiletest` in that they take the form of `//@` comments
-but ultimately, they are completey distinct and processed by different programs.
+but ultimately, they are completely distinct and processed by different programs.
 
 [XPath] is used to query parts of the HTML document tree.
 
@@ -55,6 +55,9 @@ Similar to shell commands,
 directives can extend across multiple lines if their last char is `\`.
 In this case, the start of the next line should be `//`, with no `@`.
 
+Similar to compiletest directives, besides a space you can also use a colon `:` to separate
+the directive name and the arguments, however a space is preferred for HtmlDocCk directives.
+
 Use the special string `{{channel}}` in XPaths, `PATTERN` arguments and [snapshot files](#snapshot)
 if you'd like to refer to the URL `https://doc.rust-lang.org/CHANNEL` where `CHANNEL` refers to the
 current release channel (e.g, `stable` or `nightly`).
diff --git a/src/rustdoc-internals/search.md b/src/rustdoc-internals/search.md
index 350643111..beff0a94c 100644
--- a/src/rustdoc-internals/search.md
+++ b/src/rustdoc-internals/search.md
@@ -7,8 +7,6 @@ in the crates in the doc bundle, and the second reads
 it, turns it into some in-memory structures, and
 scans them linearly to search.
 
-<!-- toc -->
-
 ## Search index format
 
 `search.js` calls this Raw, because it turns it into
diff --git a/src/rustdoc.md b/src/rustdoc.md
index 52ae48c37..9290fcd3b 100644
--- a/src/rustdoc.md
+++ b/src/rustdoc.md
@@ -9,8 +9,6 @@ For more details about how rustdoc works, see the
 
 [Rustdoc internals]: ./rustdoc-internals.md
 
-<!-- toc -->
-
 `rustdoc` uses `rustc` internals (and, of course, the standard library), so you
 will have to build the compiler and `std` once before you can build `rustdoc`.
 
diff --git a/src/sanitizers.md b/src/sanitizers.md
index 664b4feac..29d9056c1 100644
--- a/src/sanitizers.md
+++ b/src/sanitizers.md
@@ -76,7 +76,7 @@ implementation:
 ## Testing sanitizers
 
 Sanitizers are validated by code generation tests in
-[`tests/codegen/sanitize*.rs`][test-cg] and end-to-end functional tests in
+[`tests/codegen-llvm/sanitize*.rs`][test-cg] and end-to-end functional tests in
 [`tests/ui/sanitizer/`][test-ui] directory.
 
 Testing sanitizer functionality requires the sanitizer runtimes (built when
@@ -85,7 +85,7 @@ sanitizer. When sanitizer is unsupported on given target, sanitizers tests will
 be ignored. This behaviour is controlled by compiletest `needs-sanitizer-*`
 directives.
 
-[test-cg]: https://github.com/rust-lang/rust/tree/master/tests/codegen
+[test-cg]: https://github.com/rust-lang/rust/tree/master/tests/codegen-llvm
 [test-ui]: https://github.com/rust-lang/rust/tree/master/tests/ui/sanitizer
 
 ## Enabling sanitizer on a new target
diff --git a/src/serialization.md b/src/serialization.md
index 47667061e..8eb37bbe2 100644
--- a/src/serialization.md
+++ b/src/serialization.md
@@ -75,7 +75,7 @@ impl<D: Decoder> Decodable<D> for MyStruct {
 
 rustc has a lot of [arena allocated types].
 Deserializing these types isn't possible without access to the arena that they need to be allocated on.
-The [`TyDecoder`] and [`TyEncoder`] traits are supertraits of [`Decoder`] and [`Encoder`] that allow access to a [`TyCtxt`].
+The [`TyDecoder`] and [`TyEncoder`] traits are subtraits of [`Decoder`] and [`Encoder`] that allow access to a [`TyCtxt`].
 
 Types which contain `arena` allocated types can then bound the type parameter of their
 [`Encodable`] and [`Decodable`] implementations with these traits.
diff --git a/src/solve/candidate-preference.md b/src/solve/candidate-preference.md
new file mode 100644
index 000000000..896052947
--- /dev/null
+++ b/src/solve/candidate-preference.md
@@ -0,0 +1,427 @@
+# Candidate preference
+
+There are multiple ways to prove `Trait` and `NormalizesTo` goals. Each such option is called a [`Candidate`]. If there are multiple applicable candidates, we prefer some candidates over others. We store the relevant information in their [`CandidateSource`].
+
+This preference may result in incorrect inference or region constraints and would therefore be unsound during coherence. Because of this, we simply try to merge all candidates in coherence.
+
+## `Trait` goals
+
+Trait goals merge their applicable candidates in [`fn merge_trait_candidates`]. This document provides additional details and references to explain *why* we've got the current preference rules.
+
+### `CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))`
+
+Trivial builtin impls are builtin impls which are known to be always applicable for well-formed types. This means that if one exists, using another candidate should never have fewer constraints. We currently only consider `Sized` - and `MetaSized` - impls to be trivial.
+
+This is necessary to prevent a lifetime error for the following pattern
+
+```rust
+trait Trait<T>: Sized {}
+impl<'a> Trait<u32> for &'a str {}
+impl<'a> Trait<i32> for &'a str {}
+fn is_sized<T: Sized>(_: T) {}
+fn foo<'a, 'b, T>(x: &'b str)
+where
+    &'a str: Trait<T>,
+{
+    // Elaborating the `&'a str: Trait<T>` where-bound results in a
+    // `&'a str: Sized` where-bound. We do not want to prefer this
+    // over the builtin impl. 
+    is_sized(x);
+}
+```
+
+This preference is incorrect in case the builtin impl has a nested goal which relies on a non-param where-clause
+```rust
+struct MyType<'a, T: ?Sized>(&'a (), T);
+fn is_sized<T>() {}
+fn foo<'a, T: ?Sized>()
+where
+    (MyType<'a, T>,): Sized,
+    MyType<'static, T>: Sized,
+{
+    // The where-bound is trivial while the builtin `Sized` impl for tuples
+    // requires proving `MyType<'a, T>: Sized` which can only be proven by
+    // using the where-clause, adding an unnecessary `'static` constraint.
+    is_sized::<(MyType<'a, T>,)>();
+    //~^ ERROR lifetime may not live long enough
+}
+```
+
+### `CandidateSource::ParamEnv`
+
+Once there's at least one *non-global* `ParamEnv` candidate, we prefer *all* `ParamEnv` candidates over other candidate kinds.
+A where-bound is global if it is not higher-ranked and doesn't contain any generic parameters. It may contain `'static`.
+
+We try to apply where-bounds over other candidates as users tends to have the most control over them, so they can most easily
+adjust them in case our candidate preference is incorrect.
+
+#### Preference over `Impl` candidates
+
+This is necessary to avoid region errors in the following example
+
+```rust
+trait Trait<'a> {}
+impl<T> Trait<'static> for T {}
+fn impls_trait<'a, T: Trait<'a>>() {}
+fn foo<'a, T: Trait<'a>>() {
+    impls_trait::<'a, T>();
+}
+```
+
+We also need this as shadowed impls can result in currently ambiguous solver cycles: [trait-system-refactor-initiative#76]. Without preference we'd be forced to fail with ambiguity
+errors if the where-bound results in region constraints to avoid incompleteness.
+```rust
+trait Super {
+    type SuperAssoc;
+}
+
+trait Trait: Super<SuperAssoc = Self::TraitAssoc> {
+    type TraitAssoc;
+}
+
+impl<T, U> Trait for T
+where
+    T: Super<SuperAssoc = U>,
+{
+    type TraitAssoc = U;
+}
+
+fn overflow<T: Trait>() {
+    // We can use the elaborated `Super<SuperAssoc = Self::TraitAssoc>` where-bound
+    // to prove the where-bound of the `T: Trait` implementation. This currently results in
+    // overflow. 
+    let x: <T as Trait>::TraitAssoc;
+}
+```
+
+This preference causes a lot of issues. See [#24066]. Most of the
+issues are caused by prefering where-bounds over impls even if the where-bound guides type inference:
+```rust
+trait Trait<T> {
+    fn call_me(&self, x: T) {}
+}
+impl<T> Trait<u32> for T {}
+impl<T> Trait<i32> for T {}
+fn bug<T: Trait<U>, U>(x: T) {
+    x.call_me(1u32);
+    //~^ ERROR mismatched types
+}
+```
+However, even if we only apply this preference if the where-bound doesn't guide inference, it may still result
+in incorrect lifetime constraints:
+```rust
+trait Trait<'a> {}
+impl<'a> Trait<'a> for &'a str {}
+fn impls_trait<'a, T: Trait<'a>>(_: T) {}
+fn foo<'a, 'b>(x: &'b str)
+where
+    &'a str: Trait<'b>
+{
+    // Need to prove `&'x str: Trait<'b>` with `'b: 'x`.
+    impls_trait::<'b, _>(x);
+    //~^ ERROR lifetime may not live long enough
+}
+```
+
+#### Preference over `AliasBound` candidates
+
+This is necessary to avoid region errors in the following example
+```rust
+trait Bound<'a> {}
+trait Trait<'a> {
+    type Assoc: Bound<'a>;
+}
+
+fn impls_bound<'b, T: Bound<'b>>() {}
+fn foo<'a, 'b, 'c, T>()
+where
+    T: Trait<'a>,
+    for<'hr> T::Assoc: Bound<'hr>,
+{
+    impls_bound::<'b, T::Assoc>();
+    impls_bound::<'c, T::Assoc>();
+}
+```
+It can also result in unnecessary constraints
+```rust
+trait Bound<'a> {}
+trait Trait<'a> {
+    type Assoc: Bound<'a>;
+}
+
+fn impls_bound<'b, T: Bound<'b>>() {}
+fn foo<'a, 'b, T>()
+where
+    T: for<'hr> Trait<'hr>,
+    <T as Trait<'b>>::Assoc: Bound<'a>,
+{
+    // Using the where-bound for `<T as Trait<'a>>::Assoc: Bound<'a>`
+    // unnecessarily equates `<T as Trait<'a>>::Assoc` with the
+    // `<T as Trait<'b>>::Assoc` from the env.
+    impls_bound::<'a, <T as Trait<'a>>::Assoc>();
+    // For a `<T as Trait<'b>>::Assoc: Bound<'b>` the self type of the
+    // where-bound matches, but the arguments of the trait bound don't.
+    impls_bound::<'b, <T as Trait<'b>>::Assoc>();
+}
+```
+
+#### Why no preference for global where-bounds
+
+Global where-bounds are either fully implied by an impl or unsatisfiable. If they are unsatisfiable, we don't really care what happens. If a where-bound is fully implied then using the impl to prove the trait goal cannot result in additional constraints. For trait goals this is only useful for where-bounds which use `'static`:
+
+```rust
+trait A {
+    fn test(&self);
+}
+
+fn foo(x: &dyn A)
+where
+    dyn A + 'static: A, // Using this bound would lead to a lifetime error.
+{
+    x.test();
+}
+```
+More importantly, by using impls here we prevent global where-bounds from shadowing impls when normalizing associated types. There are no known issues from preferring impls over global where-bounds.
+
+#### Why still consider global where-bounds
+
+Given that we just use impls even if there exists a global where-bounds, you may ask why we don't just ignore these global where-bounds entirely: we use them to weaken the inference guidance from non-global where-bounds.
+
+Without a global where-bound, we currently prefer non-global where bounds even though there would be an applicable impl as well. By adding a non-global where-bound, this unnecessary inference guidance is disabled, allowing the following to compile:
+```rust
+fn check<Color>(color: Color)
+where
+    Vec: Into<Color> + Into<f32>,
+{
+    let _: f32 = Vec.into();
+    // Without the global `Vec: Into<f32>`  bound we'd
+    // eagerly use the non-global `Vec: Into<Color>` bound
+    // here, causing this to fail.
+}
+
+struct Vec;
+impl From<Vec> for f32 {
+    fn from(_: Vec) -> Self {
+        loop {}
+    }
+}
+```
+
+### `CandidateSource::AliasBound`
+
+We prefer alias-bound candidates over impls. We currently use this preference to guide type inference, causing the following to compile. I personally don't think this preference is desirable 🤷
+```rust
+pub trait Dyn {
+    type Word: Into<u64>;
+    fn d_tag(&self) -> Self::Word;
+    fn tag32(&self) -> Option<u32> {
+        self.d_tag().into().try_into().ok()
+        // prove `Self::Word: Into<?0>` and then select a method
+        // on `?0`, needs eager inference.
+    }
+}
+```
+```rust
+fn impl_trait() -> impl Into<u32> {
+    0u16
+}
+
+fn main() {
+    // There are two possible types for `x`:
+    // - `u32` by using the "alias bound" of `impl Into<u32>`
+    // - `impl Into<u32>`, i.e. `u16`, by using `impl<T> From<T> for T`
+    //
+    // We infer the type of `x` to be `u32` even though this is not
+    // strictly necessary and can even lead to surprising errors.
+    let x = impl_trait().into();
+    println!("{}", std::mem::size_of_val(&x));
+}
+```
+This preference also avoids ambiguity due to region constraints, I don't know whether people rely on this in practice.
+```rust
+trait Bound<'a> {}
+impl<T> Bound<'static> for T {}
+trait Trait<'a> {
+    type Assoc: Bound<'a>;
+}
+
+fn impls_bound<'b, T: Bound<'b>>() {}
+fn foo<'a, T: Trait<'a>>() {
+    // Should we infer this to `'a` or `'static`.
+    impls_bound::<'_, T::Assoc>();
+}
+```
+
+### `CandidateSource::BuiltinImpl(BuiltinImplSource::Object(_))`
+
+We prefer builtin trait object impls over user-written impls. This is **unsound** and should be remoed in the future. See [#57893](https://github.com/rust-lang/rust/issues/57893) and [#141347](https://github.com/rust-lang/rust/pull/141347) for more details.
+
+## `NormalizesTo` goals
+
+The candidate preference behavior during normalization is implemented in [`fn assemble_and_merge_candidates`].
+
+### Where-bounds shadow impls
+
+Normalization of associated items does not consider impls if the corresponding trait goal has been proven via a `ParamEnv` or `AliasBound` candidate.
+This means that for where-bounds which do not constrain associated types, the associated types remain *rigid*.
+
+This is necessary to avoid unnecessary region constraints from applying impls.
+```rust
+trait Trait<'a> {
+    type Assoc;
+}
+impl Trait<'static> for u32 {
+    type Assoc = u32;
+}
+
+fn bar<'b, T: Trait<'b>>() -> T::Assoc { todo!() }
+fn foo<'a>()
+where
+    u32: Trait<'a>,
+{
+    // Normalizing the return type would use the impl, proving
+    // the `T: Trait` where-bound would use the where-bound, resulting
+    // in different region constraints.
+    bar::<'_, u32>();
+}
+```
+
+### We always consider `AliasBound` candidates
+
+In case the where-bound does not specify the associated item, we consider `AliasBound` candidates instead of treating the alias as rigid, even though the trait goal was proven via a `ParamEnv` candidate.
+
+```rust
+trait Super {
+    type Assoc;
+}
+trait Bound {
+    type Assoc: Super<Assoc = u32>;
+}
+trait Trait: Super {}
+
+// Elaborating the environment results in a `T::Assoc: Super` where-bound.
+// This where-bound must not prevent normalization via the `Super<Assoc = u32>`
+// item bound.
+fn heck<T: Bound<Assoc: Trait>>(x: <T::Assoc as Super>::Assoc) -> u32 {
+    x
+}
+```
+Using such an alias can result in additional region constraints, cc [#133044].
+```rust
+trait Bound<'a> {
+    type Assoc;
+}
+trait Trait {
+    type Assoc: Bound<'static, Assoc = u32>;
+}
+
+fn heck<'a, T: Trait<Assoc: Bound<'a>>>(x: <T::Assoc as Bound<'a>>::Assoc) {
+    // Normalizing the associated type requires `T::Assoc: Bound<'static>` as it
+    // uses the `Bound<'static>` alias-bound instead of keeping the alias rigid.
+    drop(x);
+}
+```
+
+### We prefer `ParamEnv` candidates over `AliasBound`
+
+While we use `AliasBound` candidates if the where-bound does not specify the associated type, in case it does, we prefer the where-bound.
+This is necessary for the following example:
+```rust
+// Make sure we prefer the `I::IntoIterator: Iterator<Item = ()>`
+// where-bound over the `I::Intoiterator: Iterator<Item = I::Item>`
+// alias-bound.
+
+trait Iterator {
+    type Item;
+}
+
+trait IntoIterator {
+    type Item;
+    type IntoIter: Iterator<Item = Self::Item>;
+}
+
+fn normalize<I: Iterator<Item = ()>>() {}
+
+fn foo<I>()
+where
+    I: IntoIterator,
+    I::IntoIter: Iterator<Item = ()>,
+{
+    // We need to prefer the `I::IntoIterator: Iterator<Item = ()>`
+    // where-bound over the `I::Intoiterator: Iterator<Item = I::Item>`
+    // alias-bound.
+    normalize::<I::IntoIter>();
+}
+```
+
+### We always consider where-bounds
+
+Even if the trait goal was proven via an impl, we still prefer `ParamEnv` candidates, if any exist.
+
+#### We prefer "orphaned" where-bounds
+
+We add "orphaned" `Projection` clauses into the `ParamEnv` when normalizing item bounds of GATs and RPITIT in `fn check_type_bounds`.
+We need to prefer these `ParamEnv` candidates over impls and other where-bounds. 
+```rust
+#![feature(associated_type_defaults)]
+trait Foo {
+    // We should be able to prove that `i32: Baz<Self>` because of
+    // the impl below, which requires that `Self::Bar<()>: Eq<i32>`
+    // which is true, because we assume `for<T> Self::Bar<T> = i32`.
+    type Bar<T>: Baz<Self> = i32;
+}
+trait Baz<T: ?Sized> {}
+impl<T: Foo + ?Sized> Baz<T> for i32 where T::Bar<()>: Eq<i32> {}
+trait Eq<T> {}
+impl<T> Eq<T> for T {}
+```
+
+I don't fully understand the cases where this preference is actually necessary and haven't been able to exploit this in fun ways yet, but 🤷
+
+#### We prefer global where-bounds over impls
+
+This is necessary for the following to compile. I don't know whether anything relies on it in practice 🤷
+```rust
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+
+fn foo<T>(x: T) -> <u32 as Id>::This
+where
+    u32: Id<This = T>,
+{
+    x
+}
+```
+This means normalization can result in additional region constraints, cc [#133044].
+```rust
+trait Trait {
+    type Assoc;
+}
+
+impl Trait for &u32 {
+    type Assoc = u32;
+}
+
+fn trait_bound<T: Trait>() {}
+fn normalize<T: Trait<Assoc = u32>>() {}
+
+fn foo<'a>()
+where
+    &'static u32: Trait<Assoc = u32>,
+{
+    trait_bound::<&'a u32>(); // ok, proven via impl
+    normalize::<&'a u32>(); // error, proven via where-bound
+}
+```
+
+[`Candidate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/solve/assembly/struct.Candidate.html
+[`CandidateSource`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_next_trait_solver/solve/enum.CandidateSource.html
+[`fn merge_trait_candidates`]: https://github.com/rust-lang/rust/blob/e3ee7f7aea5b45af3b42b5e4713da43876a65ac9/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs#L1342-L1424
+[`fn assemble_and_merge_candidates`]: https://github.com/rust-lang/rust/blob/e3ee7f7aea5b45af3b42b5e4713da43876a65ac9/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs#L920-L1003
+[trait-system-refactor-initiative#76]: https://github.com/rust-lang/trait-system-refactor-initiative/issues/76
+[#24066]: https://github.com/rust-lang/rust/issues/24066
+[#133044]: https://github.com/rust-lang/rust/issues/133044
\ No newline at end of file
diff --git a/src/solve/invariants.md b/src/solve/invariants.md
index fd12b1957..8ec15f339 100644
--- a/src/solve/invariants.md
+++ b/src/solve/invariants.md
@@ -4,17 +4,15 @@ FIXME: This file talks about invariants of the type system as a whole, not only
 
 There are a lot of invariants - things the type system guarantees to be true at all times -
 which are desirable or expected from other languages and type systems. Unfortunately, quite
-a few of them do not hold in Rust right now. This is either a fundamental to its design or
-caused by bugs and something that may change in the future.
+a few of them do not hold in Rust right now. This is either fundamental to its design or
+caused by bugs, and something that may change in the future.
 
-It is important to know about the things you can assume while working on - and with - the
+It is important to know about the things you can assume while working on, and with, the
 type system, so here's an incomplete and unofficial list of invariants of
 the core type system:
 
-- ✅: this invariant mostly holds, with some weird exceptions, you can rely on it outside
-of these cases
-- ❌: this invariant does not hold, either due to bugs or by design, you must not rely on
-it for soundness or have to be incredibly careful when doing so
+- ✅: this invariant mostly holds, with some weird exceptions or current bugs
+- ❌: this invariant does not hold, and is unlikely to do so in the future; do not rely on it for soundness or have to be incredibly careful when doing so
 
 ### `wf(X)` implies `wf(normalize(X))` ✅
 
@@ -23,20 +21,23 @@ well-formed after normalizing said aliases. We rely on this as
 otherwise we would have to re-check for well-formedness for these
 types.
 
+This currently does not hold due to a type system unsoundness: [#84533](https://github.com/rust-lang/rust/issues/84533).
+
 ### Structural equality modulo regions implies semantic equality ✅
 
 If you have a some type and equate it to itself after replacing any regions with unique
 inference variables in both the lhs and rhs, the now potentially structurally different
 types should still be equal to each other.
 
-Needed to prevent goals from succeeding in HIR typeck and then failing in MIR borrowck.
-If this invariant is broken MIR typeck ends up failing with an ICE.
+This is needed to prevent goals from succeeding in HIR typeck and then failing in MIR borrowck.
+If this invariant is broken, MIR typeck ends up failing with an ICE.
 
 ### Applying inference results from a goal does not change its result ❌
 
 TODO: this invariant is formulated in a weird way and needs to be elaborated.
 Pretty much: I would like this check to only fail if there's a solver bug:
-https://github.com/rust-lang/rust/blob/2ffeb4636b4ae376f716dc4378a7efb37632dc2d/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs#L391-L407
+<https://github.com/rust-lang/rust/blob/2ffeb4636b4ae376f716dc4378a7efb37632dc2d/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs#L391-L407>.
+We should readd this check and see where it breaks :3
 
 If we prove some goal/equate types/whatever, apply the resulting inference constraints,
 and then redo the original action, the result should be the same.
@@ -73,82 +74,99 @@ Many of the currently known unsound issues end up relying on this invariant bein
 It is however very difficult to imagine a sound type system without this invariant, so
 the issue is that the invariant is broken, not that we incorrectly rely on it.
 
-### Generic goals and their instantiations have the same result ✅
+### The type system is complete ❌
+
+The type system is not complete.
+It often adds unnecessary inference constraints, and errors even though the goal could hold.
+
+- method selection
+- opaque type inference
+- handling type outlives constraints
+- preferring `ParamEnv` candidates over `Impl` candidates during candidate selection
+in the trait solver
+
+### Goals keep their result from HIR typeck afterwards ✅
+
+Having a goal which succeeds during HIR typeck but fails when being reevaluated during MIR borrowck causes ICE, e.g. [#140211](https://github.com/rust-lang/rust/issues/140211).
 
-Pretty much: If we successfully typecheck a generic function concrete instantiations
-of that function should also typeck. We should not get errors post-monomorphization.
-We can however get overflow errors at that point.
+Having a goal which succeeds during HIR typeck but fails after being instantiated is unsound, e.g. [#140212](https://github.com/rust-lang/rust/issues/140212).
 
-TODO: example for overflow error post-monomorphization
+It is interesting that we allow some incompleteness in the trait solver while still maintaining this limitation. It would be nice if there was a clear way to separate the "allowed incompleteness" from behavior which would break this invariant.
+
+#### Normalization must not change results
 
 This invariant is relied on to allow the normalization of generic aliases. Breaking
-it can easily result in unsoundness, e.g. [#57893](https://github.com/rust-lang/rust/issues/57893)
+it can easily result in unsoundness, e.g. [#57893](https://github.com/rust-lang/rust/issues/57893).
+
+#### Goals may still overflow after instantiation
+
+This happens they start to hit the recursion limit.
+We also have diverging aliases which are scuffed.
+It's unclear how these should be handled :3
 
 ### Trait goals in empty environments are proven by a unique impl ✅
 
 If a trait goal holds with an empty environment, there should be a unique `impl`,
 either user-defined or builtin, which is used to prove that goal. This is
-necessary to select a unique method.
+necessary to select unique methods and associated items.
 
-We do however break this invariant in few cases, some of which are due to bugs,
-some by design:
+We do however break this invariant in a few cases, some of which are due to bugs, some by design:
 - *marker traits* are allowed to overlap as they do not have associated items
 - *specialization* allows specializing impls to overlap with their parent
 - the builtin trait object trait implementation can overlap with a user-defined impl:
-[#57893]
+[#57893](https://github.com/rust-lang/rust/issues/57893)
 
-### The type system is complete ❌
-
-The type system is not complete, it often adds unnecessary inference constraints, and errors
-even though the goal could hold.
-
-- method selection
-- opaque type inference
-- handling type outlives constraints
-- preferring `ParamEnv` candidates over `Impl` candidates during candidate selection
-in the trait solver
 
 #### The type system is complete during the implicit negative overlap check in coherence ✅
 
-For more on overlap checking: [coherence]
+For more on overlap checking, see [Coherence chapter].
 
-During the implicit negative overlap check in coherence we must never return *error* for
-goals which can be proven. This would allow for overlapping impls with potentially different
-associated items, breaking a bunch of other invariants.
+During the implicit negative overlap check in coherence,
+we must never return *error* for goals which can be proven.
+This would allow for overlapping impls with potentially different associated items,
+breaking a bunch of other invariants.
 
 This invariant is currently broken in many different ways while actually something we rely on.
 We have to be careful as it is quite easy to break:
 - generalization of aliases
 - generalization during subtyping binders (luckily not exploitable in coherence)
 
-### Trait solving must be (free) lifetime agnostic ✅
+### Trait solving must not depend on lifetimes being different ✅
+
+If a goal holds with lifetimes being different, it must also hold with these lifetimes being the same. We otherwise get post-monomorphization errors during codegen or unsoundness due to invalid vtables.
 
-Trait solving during codegen should have the same result as during typeck. As we erase
-all free regions during codegen we must not rely on them during typeck. A noteworthy example
-is special behavior for `'static`.
+We could also just get inconsistent behavior when first proving a goal with different lifetimes which are later constrained to be equal.
+
+### Trait solving in bodies must not depend on lifetimes being equal ✅
 
 We also have to be careful with relying on equality of regions in the trait solver.
 This is fine for codegen, as we treat all erased regions as equal. We can however
 lose equality information from HIR to MIR typeck.
 
-The new solver "uniquifies regions" during canonicalization, canonicalizing `u32: Trait<'x, 'x>`
-as `exists<'0, '1> u32: Trait<'0, '1>`, to make it harder to rely on this property.
+This currently does not hold with the new solver: [trait-system-refactor-initiative#27](https://github.com/rust-lang/trait-system-refactor-initiative/issues/27).
 
 ### Removing ambiguity makes strictly more things compile ❌
 
 Ideally we *should* not rely on ambiguity for things to compile.
 Not doing that will cause future improvements to be breaking changes.
 
-Due to *incompleteness* this is not the case and improving inference can result in inference
-changes, breaking existing projects.
+Due to *incompleteness* this is not the case,
+and improving inference can result in inference changes, breaking existing projects.
 
 ### Semantic equality implies structural equality ✅
 
 Two types being equal in the type system must mean that they have the
 same `TypeId` after instantiating their generic parameters with concrete
-arguments. This currently does not hold: [#97156].
+arguments. We can otherwise use their different `TypeId`s to impact trait selection.
+
+We lookup types using structural equality during codegen, but this shouldn't necessarily be unsound
+- may result in redundant method codegen or backend type check errors?
+- we also rely on it in CTFE assertions
+
+### Semantically different types have different `TypeId`s ✅
+
+Semantically different `'static` types need different `TypeId`s to avoid transmutes,
+for example `for<'a> fn(&'a str)` vs `fn(&'static str)` must have a different `TypeId`.
+
 
-[#57893]: https://github.com/rust-lang/rust/issues/57893
-[#97156]: https://github.com/rust-lang/rust/issues/97156
-[#114936]: https://github.com/rust-lang/rust/issues/114936
-[coherence]:  ../coherence.md
+[coherence chapter]: ../coherence.md
diff --git a/src/stability.md b/src/stability.md
index 230925252..c26d34273 100644
--- a/src/stability.md
+++ b/src/stability.md
@@ -6,8 +6,6 @@ APIs to use unstable APIs internally in the rustc standard library.
 **NOTE**: this section is for *library* features, not *language* features. For instructions on
 stabilizing a language feature see [Stabilizing Features](./stabilization_guide.md).
 
-<!-- toc -->
-
 ## unstable
 
 The `#[unstable(feature = "foo", issue = "1234", reason = "lorem ipsum")]`
@@ -183,4 +181,7 @@ the `deprecated_in_future` lint is triggered which is default `allow`, but most
 of the standard library raises it to a warning with
 `#![warn(deprecated_in_future)]`.
 
+## unstable_feature_bound
+The `#[unstable_feature_bound(foo)]` attribute can be used together with `#[unstable]` attribute to mark an `impl` of stable type and stable trait as unstable. In std/core, an item annotated with `#[unstable_feature_bound(foo)]` can only be used by another item that is also annotated with `#[unstable_feature_bound(foo)]`. Outside of std/core, using an item with `#[unstable_feature_bound(foo)]` requires the feature to be enabled with `#![feature(foo)]` attribute on the crate. Currently, only `impl`s and free functions can be annotated with `#[unstable_feature_bound]`.
+
 [blog]: https://www.ralfj.de/blog/2018/07/19/const.html
diff --git a/src/stabilization_guide.md b/src/stabilization_guide.md
index f875c6874..e399930fc 100644
--- a/src/stabilization_guide.md
+++ b/src/stabilization_guide.md
@@ -1,120 +1,64 @@
 # Request for stabilization
 
-**NOTE**: this page is about stabilizing *language* features.
-For stabilizing *library* features, see [Stabilizing a library feature].
+**NOTE**: This page is about stabilizing *language* features. For stabilizing *library* features, see [Stabilizing a library feature].
 
 [Stabilizing a library feature]: ./stability.md#stabilizing-a-library-feature
 
-Once an unstable feature has been well-tested with no outstanding
-concern, anyone may push for its stabilization. It involves the
-following steps:
+Once an unstable feature has been well-tested with no outstanding concerns, anyone may push for its stabilization, though involving the people who have worked on it is prudent. Follow these steps:
 
-<!-- toc -->
+## Write an RFC, if needed
 
-## Documentation PRs
+If the feature was part of a [lang experiment], the lang team generally will want to first accept an RFC before stabilization.
 
-<a id="updating-documentation"></a>
+[lang experiment]: https://lang-team.rust-lang.org/how_to/experiment.html
 
-If any documentation for this feature exists, it should be
-in the [`Unstable Book`], located at [`src/doc/unstable-book`].
-If it exists, the page for the feature gate should be removed.
+## Documentation PRs
 
-If there was documentation there, integrating it into the
-existing documentation is needed.
+<a id="updating-documentation"></a>
 
-If there wasn't documentation there, it needs to be added.
+The feature might be documented in the [`Unstable Book`], located at [`src/doc/unstable-book`]. Remove the page for the feature gate if it exists. Integrate any useful parts of that documentation in other places.
 
-Places that may need updated documentation:
+Places that may need updated documentation include:
 
-- [The Reference]: This must be updated, in full detail.
-- [The Book]: This may or may not need updating, depends.
-    If you're not sure, please open an issue on this repository
-    and it can be discussed.
-- standard library documentation: As needed. Language features
-    often don't need this, but if it's a feature that changes
-    how good examples are written, such as when `?` was added
-    to the language, updating examples is important.
-- [Rust by Example]: As needed.
+- [The Reference]: This must be updated, in full detail, and a member of the lang-docs team must review and approve the PR before the stabilization can be merged.
+- [The Book]: This is updated as needed. If you're not sure, please open an issue on this repository and it can be discussed.
+- Standard library documentation: This is updated as needed. Language features often don't need this, but if it's a feature that changes how idiomatic examples are written, such as when `?` was added to the language, updating these in the library documentation is important. Review also the keyword documentation and ABI documentation in the standard library, as these sometimes needs updates for language changes.
+- [Rust by Example]: This is updated as needed.
 
-Prepare PRs to update documentation involving this new feature
-for repositories mentioned above. Maintainers of these repositories
-will keep these PRs open until the whole stabilization process
-has completed. Meanwhile, we can proceed to the next step.
+Prepare PRs to update documentation involving this new feature for the repositories mentioned above. Maintainers of these repositories will keep these PRs open until the whole stabilization process has completed. Meanwhile, we can proceed to the next step.
 
 ## Write a stabilization report
 
-Find the tracking issue of the feature, and create a short
-stabilization report. Essentially this would be a brief summary
-of the feature plus some links to test cases showing it works
-as expected, along with a list of edge cases that came up
-and were considered. This is a minimal "due diligence" that
-we do before stabilizing.
+Author a stabilization report using the [template found in this repository][srt].
 
-The report should contain:
+The stabilization reports summarizes:
 
-- A summary, showing examples (e.g. code snippets) what is
-  enabled by this feature.
-- Links to test cases in our test suite regarding this feature
-  and describe the feature's behavior on encountering edge cases.
-- Links to the documentations (the PRs we have made in the
-  previous steps).
-- Any other relevant information.
-- The resolutions of any unresolved questions if the stabilization
-  is for an RFC.
+- The main design decisions and deviations since the RFC was accepted, including both decisions that were FCP'd or otherwise accepted by the language team as well as those being presented to the lang team for the first time.
+    - Often, the final stabilized language feature has significant design deviations from the original RFC. That's OK, but these deviations must be highlighted and explained carefully.
+- The work that has been done since the RFC was accepted, acknowledging the main contributors that helped drive the language feature forward.
 
-Examples of stabilization reports can be found in
-[rust-lang/rust#44494][report1] and [rust-lang/rust#28237][report2] (these links
-will bring you directly to the comment containing the stabilization report).
+The [*Stabilization Template*][srt] includes a series of questions that aim to surface connections between this feature and lang's subteams (e.g. types, opsem, lang-docs, etc.) and to identify items that are commonly overlooked.
 
-[report1]: https://github.com/rust-lang/rust/issues/44494#issuecomment-360191474
-[report2]: https://github.com/rust-lang/rust/issues/28237#issuecomment-363374130
+[srt]: ./stabilization_report_template.md
 
-## FCP
-
-If any member of the team responsible for tracking this
-feature agrees with stabilizing this feature, they will
-start the FCP (final-comment-period) process by commenting
-
-```text
-@rfcbot fcp merge
-```
-
-The rest of the team members will review the proposal. If the final
-decision is to stabilize, we proceed to do the actual code modification.
+The stabilization report is typically posted as the main comment on the stabilization PR (see the next section).
 
 ## Stabilization PR
 
-*This is for stabilizing language features.  If you are stabilizing a library
-feature, see [the stabilization chapter of the std dev guide][std-guide-stabilization] instead.*
-
-Once we have decided to stabilize a feature, we need to have
-a PR that actually makes that stabilization happen. These kinds
-of PRs are a great way to get involved in Rust, as they take
-you on a little tour through the source code.
-
-Here is a general guide to how to stabilize a feature --
-every feature is different, of course, so some features may
-require steps beyond what this guide talks about.
+Every feature is different, and some may require steps beyond what this guide discusses.
 
-Note: Before we stabilize any feature, it's the rule that it
-should appear in the documentation.
+Before the stabilization will be considered by the lang team, there must be a complete PR to the Reference describing the feature, and before the stabilization PR will be merged, this PR must have been reviewed and approved by the lang-docs team.
 
 ### Updating the feature-gate listing
 
-There is a central listing of unstable feature-gates in
-[`compiler/rustc_feature/src/unstable.rs`]. Search for the `declare_features!`
-macro. There should be an entry for the feature you are aiming
-to stabilize, something like (this example is taken from
-[rust-lang/rust#32409]:
+There is a central listing of unstable feature-gates in [`compiler/rustc_feature/src/unstable.rs`]. Search for the `declare_features!`  macro. There should be an entry for the feature you are aiming to stabilize, something like (this example is taken from [rust-lang/rust#32409]:
 
 ```rust,ignore
 // pub(restricted) visibilities (RFC 1422)
 (unstable, pub_restricted, "CURRENT_RUSTC_VERSION", Some(32409)),
 ```
 
-The above line should be moved to [`compiler/rustc_feature/src/accepted.rs`].
-Entries in the `declare_features!` call are sorted, so find the correct place.
-When it is done, it should look like:
+The above line should be moved to [`compiler/rustc_feature/src/accepted.rs`]. Entries in the `declare_features!` call are sorted, so find the correct place. When it is done, it should look like:
 
 ```rust,ignore
 // pub(restricted) visibilities (RFC 1422)
@@ -122,54 +66,31 @@ When it is done, it should look like:
 // note that we changed this
 ```
 
-(Even though you will encounter version numbers in the file of past changes,
-you should not put the rustc version you expect your stabilization to happen in,
-but instead `CURRENT_RUSTC_VERSION`)
+(Even though you will encounter version numbers in the file of past changes, you should not put the rustc version you expect your stabilization to happen in, but instead use `CURRENT_RUSTC_VERSION`.)
 
 ### Removing existing uses of the feature-gate
 
-Next search for the feature string (in this case, `pub_restricted`)
-in the codebase to find where it appears. Change uses of
-`#![feature(XXX)]` from the `std` and any rustc crates (this includes test folders
-under `library/` and `compiler/` but not the toplevel `tests/` one) to be
-`#![cfg_attr(bootstrap, feature(XXX))]`. This includes the feature-gate
-only for stage0, which is built using the current beta (this is
-needed because the feature is still unstable in the current beta).
+Next, search for the feature string (in this case, `pub_restricted`) in the codebase to find where it appears. Change uses of `#![feature(XXX)]` from the `std` and any rustc crates (this includes test folders under `library/` and `compiler/` but not the toplevel `tests/` one) to be `#![cfg_attr(bootstrap, feature(XXX))]`. This includes the feature-gate only for stage0, which is built using the current beta (this is needed because the feature is still unstable in the current beta).
 
-Also, remove those strings from any tests (e.g. under `tests/`). If there are tests
-specifically targeting the feature-gate (i.e., testing that the
-feature-gate is required to use the feature, but nothing else),
-simply remove the test.
+Also, remove those strings from any tests (e.g. under `tests/`). If there are tests specifically targeting the feature-gate (i.e., testing that the feature-gate is required to use the feature, but nothing else), simply remove the test.
 
 ### Do not require the feature-gate to use the feature
 
-Most importantly, remove the code which flags an error if the
-feature-gate is not present (since the feature is now considered
-stable). If the feature can be detected because it employs some
-new syntax, then a common place for that code to be is in the
-same `compiler/rustc_ast_passes/src/feature_gate.rs`.
-For example, you might see code like this:
+Most importantly, remove the code which flags an error if the feature-gate is not present (since the feature is now considered stable). If the feature can be detected because it employs some new syntax, then a common place for that code to be is in `compiler/rustc_ast_passes/src/feature_gate.rs`. For example, you might see code like this:
 
 ```rust,ignore
-gate_feature_post!(&self, pub_restricted, span,
- "`pub(restricted)` syntax is experimental");
+gate_all!(pub_restricted, "`pub(restricted)` syntax is experimental");
 ```
 
-This `gate_feature_post!` macro prints an error if the
-`pub_restricted` feature is not enabled. It is not needed
-now that `#[pub_restricted]` is stable.
+This `gate_feature_post!` macro prints an error if the `pub_restricted` feature is not enabled. It is not needed now that `#[pub_restricted]` is stable.
 
 For more subtle features, you may find code like this:
 
 ```rust,ignore
-if self.tcx.sess.features.borrow().pub_restricted { /* XXX */ }
+if self.tcx.features().async_fn_in_dyn_trait() { /* XXX */ }
 ```
 
-This `pub_restricted` field (obviously named after the feature)
-would ordinarily be false if the feature flag is not present
-and true if it is. So transform the code to assume that the field
-is true. In this case, that would mean removing the `if` and
-leaving just the `/* XXX */`.
+This `pub_restricted` field (named after the feature) would ordinarily be false if the feature flag is not present and true if it is. So transform the code to assume that the field is true. In this case, that would mean removing the `if` and leaving just the `/* XXX */`.
 
 ```rust,ignore
 if self.tcx.sess.features.borrow().pub_restricted { /* XXX */ }
@@ -194,3 +115,40 @@ if something { /* XXX */ }
 [Rust by Example]: https://github.com/rust-lang/rust-by-example
 [`Unstable Book`]: https://doc.rust-lang.org/unstable-book/index.html
 [`src/doc/unstable-book`]: https://github.com/rust-lang/rust/tree/master/src/doc/unstable-book
+
+## Team nominations
+
+When opening the stabilization PR, CC the lang team and its advisors (`@rust-lang/lang @rust-lang/lang-advisors`) and any other teams to whom the feature is relevant, e.g.:
+
+- `@rust-lang/types`, for type system interactions.
+- `@rust-lang/opsem`, for interactions with unsafe code.
+- `@rust-lang/compiler`, for implementation robustness.
+- `@rust-lang/libs-api`, for changes to the standard library API or its guarantees.
+- `@rust-lang/lang-docs`, for questions about how this should be documented in the Reference.
+
+After the stabilization PR is opened with the stabilization report, wait a bit for any immediate comments. When such comments "simmer down" and you feel the PR is ready for consideration by the lang team, [nominate the PR](https://lang-team.rust-lang.org/how_to/nominate.html) to get it on the agenda for consideration in an upcoming lang meeting.
+
+If you are not a `rust-lang` organization member, you can ask your assigned reviewer to CC the relevant teams on your behalf.
+
+## Propose FCP on the PR
+
+After the lang team and other relevant teams review the stabilization, and after you have answered any questions they may have had, a member of one of the teams may propose to accept the stabilization by commenting:
+
+```text
+@rfcbot fcp merge
+```
+
+Once enough team members have reviewed, the PR will move into a "final comment period" (FCP). If no new concerns are raised, this period will complete and the PR can be merged after implementation review in the usual way.
+
+## Reviewing and merging stabilizations
+
+On a stabilization, before giving it the `r+`, ensure that the PR:
+
+- Matches what the team proposed for stabilization and what is documented in the Reference PR.
+- Includes any changes the team decided to request along the way in order to resolve or avoid concerns.
+- Is otherwise exactly what is described in the stabilization report and in any relevant RFCs or prior lang FCPs.
+- Does not expose on stable behaviors other than those specified, accepted for stabilization, and documented in the Reference.
+- Has sufficient tests to convincingly demonstrate these things.
+- Is accompanied by a PR to the Reference than has been reviewed and approved by a member of lang-docs.
+
+In particular, when reviewing the PR, keep an eye out for any user-visible details that the lang team failed to consider and specify. If you find one, describe it and nominate the PR for the lang team.
diff --git a/src/stabilization_report_template.md b/src/stabilization_report_template.md
new file mode 100644
index 000000000..793f7d7e4
--- /dev/null
+++ b/src/stabilization_report_template.md
@@ -0,0 +1,277 @@
+# Stabilization report template
+
+## What is this?
+
+This is a template for [stabilization reports](./stabilization_guide.md) of **language features**. The questions aim to solicit the details most often needed. These details help reviewers to identify potential problems upfront. Not all parts of the template will apply to every stabilization. If a question doesn't apply, explain briefly why.
+
+Copy everything after the separator and edit it as Markdown. Replace each *TODO* with your answer.
+
+---
+
+# Stabilization report
+
+## Summary
+
+> Remind us what this feature is and what value it provides. Tell the story of what led up to this stabilization.
+>
+> E.g., see:
+>
+> - [Stabilize AFIT/RPITIT](https://web.archive.org/web/20250329190642/https://github.com/rust-lang/rust/pull/115822)
+> - [Stabilize RTN](https://web.archive.org/web/20250321214601/https://github.com/rust-lang/rust/pull/138424)
+> - [Stabilize ATPIT](https://web.archive.org/web/20250124214256/https://github.com/rust-lang/rust/pull/120700)
+> - [Stabilize opaque type precise capturing](https://web.archive.org/web/20250312173538/https://github.com/rust-lang/rust/pull/127672)
+
+*TODO*
+
+Tracking:
+
+- *TODO* (Link to tracking issue.)
+
+Reference PRs:
+
+- *TODO* (Link to Reference PRs.)
+
+cc @rust-lang/lang @rust-lang/lang-advisors
+
+### What is stabilized
+
+> Describe each behavior being stabilized and give a short example of code that will now be accepted.
+
+```rust
+todo!()
+```
+
+### What isn't stabilized
+
+> Describe any parts of the feature not being stabilized. Talk about what we might want to do later and what doors are being left open for that. If what we're not stabilizing might lead to surprises for users, talk about that in particular.
+
+## Design
+
+### Reference
+
+> What updates are needed to the Reference? Link to each PR. If the Reference is missing content needed for describing this feature, discuss that.
+
+- *TODO*
+
+### RFC history
+
+> What RFCs have been accepted for this feature?
+
+- *TODO*
+
+### Answers to unresolved questions
+
+> What questions were left unresolved by the RFC? How have they been answered? Link to any relevant lang decisions.
+
+*TODO*
+
+### Post-RFC changes
+
+> What other user-visible changes have occurred since the RFC was accepted? Describe both changes that the lang team accepted (and link to those decisions) as well as changes that are being presented to the team for the first time in this stabilization report.
+
+*TODO*
+
+### Key points
+
+> What decisions have been most difficult and what behaviors to be stabilized have proved most contentious? Summarize the major arguments on all sides and link to earlier documents and discussions.
+
+*TODO*
+
+### Nightly extensions
+
+> Are there extensions to this feature that remain unstable? How do we know that we are not accidentally committing to those?
+
+*TODO*
+
+### Doors closed
+
+> What doors does this stabilization close for later changes to the language? E.g., does this stabilization make any other RFCs, lang experiments, or known in-flight proposals more difficult or impossible to do later?
+
+## Feedback
+
+### Call for testing
+
+> Has a "call for testing" been done? If so, what feedback was received?
+
+*TODO*
+
+### Nightly use
+
+> Do any known nightly users use this feature? Counting instances of `#![feature(FEATURE_NAME)]` on GitHub with grep might be informative.
+
+*TODO*
+
+## Implementation
+
+### Major parts
+
+> Summarize the major parts of the implementation and provide links into the code and to relevant PRs.
+>
+> See, e.g., this breakdown of the major parts of async closures:
+>
+> - <https://rustc-dev-guide.rust-lang.org/coroutine-closures.html>
+
+*TODO*
+
+### Coverage
+
+> Summarize the test coverage of this feature.
+>
+> Consider what the "edges" of this feature are. We're particularly interested in seeing tests that assure us about exactly what nearby things we're not stabilizing. Tests should of course comprehensively demonstrate that the feature works. Think too about demonstrating the diagnostics seen when common mistakes are made and the feature is used incorrectly.
+>
+> Within each test, include a comment at the top describing the purpose of the test and what set of invariants it intends to demonstrate. This is a great help to our review.
+>
+> Describe any known or intentional gaps in test coverage.
+>
+> Contextualize and link to test folders and individual tests.
+
+*TODO*
+
+### Outstanding bugs
+
+> What outstanding bugs involve this feature? List them. Should any block the stabilization? Discuss why or why not.
+
+*TODO*
+
+- *TODO*
+- *TODO*
+- *TODO*
+
+### Outstanding FIXMEs
+
+> What FIXMEs are still in the code for that feature and why is it OK to leave them there?
+
+*TODO*
+
+### Tool changes
+
+> What changes must be made to our other tools to support this feature. Has this work been done? Link to any relevant PRs and issues.
+
+- [ ] rustfmt
+  - *TODO*
+- [ ] rust-analyzer
+  - *TODO*
+- [ ] rustdoc (both JSON and HTML)
+  - *TODO*
+- [ ] cargo
+  - *TODO*
+- [ ] clippy
+  - *TODO*
+- [ ] rustup
+  - *TODO*
+- [ ] docs.rs
+  - *TODO*
+
+*TODO*
+
+### Breaking changes
+
+> If this stabilization represents a known breaking change, link to the crater report, the analysis of the crater report, and to all PRs we've made to ecosystem projects affected by this breakage. Discuss any limitations of what we're able to know about or to fix.
+
+*TODO*
+
+Crater report:
+
+- *TODO*
+
+Crater analysis:
+
+- *TODO*
+
+PRs to affected crates:
+
+- *TODO*
+- *TODO*
+- *TODO*
+
+## Type system, opsem
+
+### Compile-time checks
+
+> What compilation-time checks are done that are needed to prevent undefined behavior?
+>
+> Link to tests demonstrating that these checks are being done.
+
+*TODO*
+
+- *TODO*
+- *TODO*
+- *TODO*
+
+### Type system rules
+
+> What type system rules are enforced for this feature and what is the purpose of each?
+
+*TODO*
+
+### Sound by default?
+
+> Does the feature's implementation need specific checks to prevent UB, or is it sound by default and need specific opt-in to perform the dangerous/unsafe operations? If it is not sound by default, what is the rationale?
+
+*TODO*
+
+### Breaks the AM?
+
+> Can users use this feature to introduce undefined behavior, or use this feature to break the abstraction of Rust and expose the underlying assembly-level implementation? Describe this if so.
+
+*TODO*
+
+## Common interactions
+
+### Temporaries
+
+> Does this feature introduce new expressions that can produce temporaries? What are the scopes of those temporaries?
+
+*TODO*
+
+### Drop order
+
+> Does this feature raise questions about the order in which we should drop values? Talk about the decisions made here and how they're consistent with our earlier decisions.
+
+*TODO*
+
+### Pre-expansion / post-expansion
+
+> Does this feature raise questions about what should be accepted pre-expansion (e.g. in code covered by `#[cfg(false)]`) versus what should be accepted post-expansion? What decisions were made about this?
+
+*TODO*
+
+### Edition hygiene
+
+> If this feature is gated on an edition, how do we decide, in the context of the edition hygiene of tokens, whether to accept or reject code. E.g., what token do we use to decide?
+
+*TODO*
+
+### SemVer implications
+
+> Does this feature create any new ways in which library authors must take care to prevent breaking downstreams when making minor-version releases? Describe these. Are these new hazards "major" or "minor" according to [RFC 1105](https://rust-lang.github.io/rfcs/1105-api-evolution.html)?
+
+*TODO*
+
+### Exposing other features
+
+> Are there any other unstable features whose behavior may be exposed by this feature in any way? What features present the highest risk of that?
+
+*TODO*
+
+## History
+
+> List issues and PRs that are important for understanding how we got here.
+
+- *TODO*
+- *TODO*
+- *TODO*
+
+## Acknowledgments
+
+> Summarize contributors to the feature by name for recognition and so that those people are notified about the stabilization. Does anyone who worked on this *not* think it should be stabilized right now? We'd like to hear about that if so.
+
+*TODO*
+
+## Open items
+
+> List any known items that have not yet been completed and that should be before this is stabilized.
+
+- [ ] *TODO*
+- [ ] *TODO*
+- [ ] *TODO*
diff --git a/src/test-implementation.md b/src/test-implementation.md
index e906dd29f..f09d73631 100644
--- a/src/test-implementation.md
+++ b/src/test-implementation.md
@@ -1,7 +1,5 @@
 # The `#[test]` attribute
 
-<!-- toc -->
-
 
 
 Many Rust programmers rely on a built-in attribute called `#[test]`. All
diff --git a/src/tests/adding.md b/src/tests/adding.md
index 895eabfbd..e5c26bef1 100644
--- a/src/tests/adding.md
+++ b/src/tests/adding.md
@@ -1,7 +1,5 @@
 # Adding new tests
 
-<!-- toc -->
-
 **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 master but pass
 after the PR. These tests are really useful for preventing us from repeating the
diff --git a/src/tests/compiletest.md b/src/tests/compiletest.md
index ded30234e..4980ed845 100644
--- a/src/tests/compiletest.md
+++ b/src/tests/compiletest.md
@@ -1,7 +1,5 @@
 # Compiletest
 
-<!-- toc -->
-
 ## Introduction
 
 `compiletest` is the main test harness of the Rust test suite. It allows test
@@ -29,7 +27,7 @@ on if or how to run the test, what behavior to expect, and more. See
 [directives](directives.md) and the test suite documentation below for more details
 on these annotations.
 
-See the [Adding new tests](adding.md) and [Best practies](best-practices.md)
+See the [Adding new tests](adding.md) and [Best practices](best-practices.md)
 chapters for a tutorial on creating a new test and advice on writing a good
 test, and the [Running tests](running.md) chapter on how to run the test suite.
 
@@ -68,7 +66,7 @@ The following test suites are available, with links for more information:
 | [`pretty`](#pretty-printer-tests)         | Check pretty printing                                                                                               |
 | [`incremental`](#incremental-tests)       | Check incremental compilation behavior                                                                              |
 | [`debuginfo`](#debuginfo-tests)           | Check debuginfo generation running debuggers                                                                        |
-| [`codegen`](#codegen-tests)               | Check code generation                                                                                               |
+| [`codegen-*`](#codegen-tests)             | Check code generation                                                                                               |
 | [`codegen-units`](#codegen-units-tests)   | Check codegen unit partitioning                                                                                     |
 | [`assembly`](#assembly-tests)             | Check assembly output                                                                                               |
 | [`mir-opt`](#mir-opt-tests)               | Check MIR generation and optimizations                                                                              |
@@ -290,7 +288,7 @@ For example, `./x test tests/debuginfo -- --debugger gdb` will only test GDB com
 
 ### Codegen tests
 
-The tests in [`tests/codegen`] test LLVM code generation. They compile the test
+The tests in [`tests/codegen-llvm`] test LLVM code generation. They compile the test
 with the `--emit=llvm-ir` flag to emit LLVM IR. They then run the LLVM
 [FileCheck] tool. The test is annotated with various `// CHECK` comments to
 check the generated code. See the [FileCheck] documentation for a tutorial and
@@ -301,13 +299,13 @@ See also the [assembly tests](#assembly-tests) for a similar set of tests.
 If you need to work with `#![no_std]` cross-compiling tests, consult the
 [`minicore` test auxiliary](./minicore.md) chapter.
 
-[`tests/codegen`]: https://github.com/rust-lang/rust/tree/master/tests/codegen
+[`tests/codegen-llvm`]: https://github.com/rust-lang/rust/tree/master/tests/codegen-llvm
 [FileCheck]: https://llvm.org/docs/CommandGuide/FileCheck.html
 
 
 ### Assembly tests
 
-The tests in [`tests/assembly`] test LLVM assembly output. They compile the test
+The tests in [`tests/assembly-llvm`] test LLVM assembly output. They compile the test
 with the `--emit=asm` flag to emit a `.s` file with the assembly output. They
 then run the LLVM [FileCheck] tool.
 
@@ -324,7 +322,7 @@ See also the [codegen tests](#codegen-tests) for a similar set of tests.
 If you need to work with `#![no_std]` cross-compiling tests, consult the
 [`minicore` test auxiliary](./minicore.md) chapter.
 
-[`tests/assembly`]: https://github.com/rust-lang/rust/tree/master/tests/assembly
+[`tests/assembly-llvm`]: https://github.com/rust-lang/rust/tree/master/tests/assembly-llvm
 
 
 ### Codegen-units tests
diff --git a/src/tests/directives.md b/src/tests/directives.md
index 839076b80..f4ba9a044 100644
--- a/src/tests/directives.md
+++ b/src/tests/directives.md
@@ -1,7 +1,5 @@
 # Compiletest directives
 
-<!-- toc -->
-
 <!--
 FIXME(jieyouxu) completely revise this chapter.
 -->
@@ -52,6 +50,8 @@ not be exhaustive. Directives can generally be found by browsing the
 
 ### Auxiliary builds
 
+See [Building auxiliary crates](compiletest.html#building-auxiliary-crates)
+
 | Directive             | Explanation                                                                                           | Supported test suites | Possible values                               |
 |-----------------------|-------------------------------------------------------------------------------------------------------|-----------------------|-----------------------------------------------|
 | `aux-bin`             | Build a aux binary, made available in `auxiliary/bin` relative to test directory                      | All except `run-make` | Path to auxiliary `.rs` file                  |
@@ -59,10 +59,9 @@ not be exhaustive. Directives can generally be found by browsing the
 | `aux-crate`           | Like `aux-build` but makes available as extern prelude                                                | All except `run-make` | `<extern_prelude_name>=<path/to/aux/file.rs>` |
 | `aux-codegen-backend` | Similar to `aux-build` but pass the compiled dylib to `-Zcodegen-backend` when building the main file | `ui-fulldeps`         | Path to codegen backend file                  |
 | `proc-macro`          | Similar to `aux-build`, but for aux forces host and don't use `-Cprefer-dynamic`[^pm].                | All except `run-make` | Path to auxiliary proc-macro `.rs` file       |
-| `build-aux-docs`      | Build docs for auxiliaries as well                                                                    | All except `run-make` | N/A                                           |
+| `build-aux-docs`      | Build docs for auxiliaries as well.  Note that this only works with `aux-build`, not `aux-crate`.     | All except `run-make` | N/A                                           |
 
-[^pm]: please see the Auxiliary proc-macro section in the
-    [compiletest](./compiletest.md) chapter for specifics.
+[^pm]: please see the [Auxiliary proc-macro section](compiletest.html#auxiliary-proc-macro) in the compiletest chapter for specifics.
 
 ### Controlling outcome expectations
 
@@ -75,8 +74,10 @@ expectations](ui.md#controlling-passfail-expectations).
 | `check-fail`                | Building (no codegen) should fail           | `ui`, `crashes`                           | N/A             |
 | `build-pass`                | Building should pass                        | `ui`, `crashes`, `codegen`, `incremental` | N/A             |
 | `build-fail`                | Building should fail                        | `ui`, `crashes`                           | N/A             |
-| `run-pass`                  | Running the test binary should pass         | `ui`, `crashes`, `incremental`            | N/A             |
-| `run-fail`                  | Running the test binary should fail         | `ui`, `crashes`                           | N/A             |
+| `run-pass`                  | Program must exit with code `0`             | `ui`, `crashes`, `incremental`            | N/A             |
+| `run-fail`                  | Program must exit with code `1..=127`       | `ui`, `crashes`                           | N/A             |
+| `run-crash`                 | Program must crash                          | `ui`                                      | N/A             |
+| `run-fail-or-crash`         | Program must `run-fail` or `run-crash`      | `ui`                                      | N/A             |
 | `ignore-pass`               | Ignore `--pass` flag                        | `ui`, `crashes`, `codegen`, `incremental` | N/A             |
 | `dont-check-failure-status` | Don't check exact failure status (i.e. `1`) | `ui`, `incremental`                       | N/A             |
 | `failure-status`            | Check                                       | `ui`, `crashes`                           | Any `u16`       |
@@ -203,6 +204,8 @@ settings:
   on `wasm32-unknown-unknown` target because the target does not support the
   `proc-macro` crate type.
 - `needs-target-std` — ignores if target platform does not have std support.
+- `ignore-backends` — ignores the listed backends, separated by whitespace characters.
+- `needs-backends` — only runs the test if current codegen backend is listed.
 
 The following directives will check LLVM support:
 
@@ -289,13 +292,12 @@ See [Pretty-printer](compiletest.md#pretty-printer-tests).
 
 - `no-auto-check-cfg` — disable auto check-cfg (only for `--check-cfg` tests)
 - [`revisions`](compiletest.md#revisions) — compile multiple times
-- [`unused-revision-names`](compiletest.md#ignoring-unused-revision-names) -
-      suppress tidy checks for mentioning unknown revision names
 -[`forbid-output`](compiletest.md#incremental-tests) — incremental cfail rejects
       output pattern
 - [`should-ice`](compiletest.md#incremental-tests) — incremental cfail should
       ICE
 - [`reference`] — an annotation linking to a rule in the reference
+- `disable-gdb-pretty-printers` — disable gdb pretty printers for debuginfo tests
 
 [`reference`]: https://github.com/rust-lang/reference/blob/master/docs/authoring.md#test-rule-annotations
 
@@ -311,6 +313,17 @@ test suites that use those tools:
 - `llvm-cov-flags` adds extra flags when running LLVM's `llvm-cov` tool.
   - Used by [coverage tests](compiletest.md#coverage-tests) in `coverage-run` mode.
 
+### Tidy specific directives
+
+The following directives control how the [tidy script](../conventions.md#formatting)
+verifies tests.
+
+- `ignore-tidy-target-specific-tests` disables checking that the appropriate
+  LLVM component is required (via a `needs-llvm-components` directive) when a
+  test is compiled for a specific target (via the `--target` flag in a
+  `compile-flag` directive).
+- [`unused-revision-names`](compiletest.md#ignoring-unused-revision-names) -
+      suppress tidy checks for mentioning unknown revision names.
 
 ## Substitutions
 
@@ -345,7 +358,7 @@ described below:
   - Example: `x86_64-unknown-linux-gnu`
 
 See
-[`tests/ui/commandline-argfile.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui/argfile/commandline-argfile.rs)
+[`tests/ui/argfile/commandline-argfile.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui/argfile/commandline-argfile.rs)
 for an example of a test that uses this substitution.
 
 [output normalization]: ui.md#normalization
diff --git a/src/tests/docker.md b/src/tests/docker.md
index 032da1ca1..ae0939842 100644
--- a/src/tests/docker.md
+++ b/src/tests/docker.md
@@ -6,12 +6,12 @@ need to install Docker on a Linux, Windows, or macOS system (typically Linux
 will be much faster than Windows or macOS because the latter use virtual
 machines to emulate a Linux environment).
 
-Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. If you want to run a CI job locally in the simplest way possible, you can use a provided helper Python script that tries to replicate what happens on CI as closely as possible:
+Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. If you want to run a CI job locally in the simplest way possible, you can use a provided helper `citool` that tries to replicate what happens on CI as closely as possible:
 
 ```bash
-python3 src/ci/github-actions/ci.py run-local <job-name>
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>
 # For example:
-python3 src/ci/github-actions/ci.py run-local dist-x86_64-linux-alt
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local dist-x86_64-linux-alt
 ```
 
 If the above script does not work for you, you would like to have more control of the Docker image execution, or you want to understand what exactly happens during Docker job execution, then continue reading below.
@@ -53,15 +53,6 @@ Some additional notes about using the interactive mode:
   containers. With the container name, run `docker exec -it <CONTAINER>
   /bin/bash` where `<CONTAINER>` is the container name like `4ba195e95cef`.
 
-The approach described above is a relatively low-level interface for running the Docker images
-directly. If you want to run a full CI Linux job locally with Docker, in a way that is as close to CI as possible, you can use the following command:
-
-```bash
-cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>
-# For example:
-cargo run --manifest-path src/ci/citool/Cargo.toml run-local dist-x86_64-linux-alt
-```
-
 [Docker]: https://www.docker.com/
 [`src/ci/docker`]: https://github.com/rust-lang/rust/tree/master/src/ci/docker
 [`src/ci/docker/run.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/docker/run.sh
diff --git a/src/tests/intro.md b/src/tests/intro.md
index 84f99e946..b90c16d60 100644
--- a/src/tests/intro.md
+++ b/src/tests/intro.md
@@ -1,7 +1,5 @@
 # Testing the compiler
 
-<!-- toc -->
-
 The Rust project runs a wide variety of different tests, orchestrated by the
 build system (`./x test`). This section gives a brief overview of the different
 testing tools. Subsequent chapters dive into [running tests](running.md) and
@@ -116,7 +114,9 @@ This requires building all of the documentation, which might take a while.
 `distcheck` verifies that the source distribution tarball created by the build
 system will unpack, build, and run all tests.
 
-> Example: `./x test distcheck`
+```console
+./x test distcheck
+```
 
 ### Tool tests
 
diff --git a/src/tests/misc.md b/src/tests/misc.md
index c0288b3dd..39f881748 100644
--- a/src/tests/misc.md
+++ b/src/tests/misc.md
@@ -9,7 +9,7 @@ for testing:
 
 - `RUSTC_BOOTSTRAP=1` will "cheat" and bypass usual stability checking, allowing
   you to use unstable features and cli flags on a stable `rustc`.
-- `RUSTC_BOOTSTRAP=-1` will force a given `rustc` to pretend that is a stable
+- `RUSTC_BOOTSTRAP=-1` will force a given `rustc` to pretend it is a stable
   compiler, even if it's actually a nightly `rustc`. This is useful because some
   behaviors of the compiler (e.g. diagnostics) can differ depending on whether
   the compiler is nightly or not.
diff --git a/src/tests/running.md b/src/tests/running.md
index 6526fe9c2..317b65f98 100644
--- a/src/tests/running.md
+++ b/src/tests/running.md
@@ -1,7 +1,5 @@
 # Running tests
 
-<!-- toc -->
-
 You can run the entire test collection using `x`. But note that running the
 *entire* test collection is almost never what you want to do during local
 development because it takes a really long time. For local development, see the
@@ -344,7 +342,6 @@ coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]).
 > **TODO**
 >
 > - Is there any support for using an iOS emulator?
-> - It's also unclear to me how the wasm or asm.js tests are run.
 
 [armhf-gnu]: https://github.com/rust-lang/rust/tree/master/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
 [QEMU]: https://www.qemu.org/
@@ -352,6 +349,28 @@ coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]).
 [remote-test-server]: https://github.com/rust-lang/rust/tree/master/src/tools/remote-test-server
 [src/bootstrap/src/core/build_steps/test.rs]: https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/test.rs
 
+## Testing tests on wasi (wasm32-wasip1)
+
+Some tests are specific to wasm targets.
+To run theste tests, you have to pass `--target wasm32-wasip1` to `x test`.
+Additionally, you need the wasi sdk.
+Follow the install instructions from the [wasi sdk repository] to get a sysroot on your computer.
+On the [wasm32-wasip1 target support page] a minimum version is specified that your sdk must be able to build.
+Some cmake commands that take a while and give a lot of very concerning c++ warnings...
+Then, in `bootstrap.toml`, point to the sysroot like so:
+
+```
+[target.wasm32-wasip1]
+wasi-root = "<wasi-sdk location>/build/sysroot/install/share/wasi-sysroot"
+```
+
+In my case I git-cloned it next to my rust folder, so it was `../wasi-sdk/build/....`
+Now, tests should just run, you don't have to set up anything else.
+
+[wasi sdk repository]: https://github.com/WebAssembly/wasi-sdk
+[wasm32-wasip1 target support page]: https://github.com/rust-lang/rust/blob/master/src/doc/rustc/src/platform-support/wasm32-wasip1.md#building-the-target.
+
+
 ## Running rustc_codegen_gcc tests
 
 First thing to know is that it only supports linux x86_64 at the moment. We will
diff --git a/src/tests/suggest-tests.md b/src/tests/suggest-tests.md
deleted file mode 100644
index 663e8a5af..000000000
--- a/src/tests/suggest-tests.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Suggest tests tool
-
-This chapter is about the internals of and contribution instructions for the
-`suggest-tests` tool. For a high-level overview of the tool, see [this
-section](../building/suggested.md#x-suggest). This tool is currently in a beta
-state and is tracked by [this](https://github.com/rust-lang/rust/issues/109933)
-issue on Github. Currently the number of tests it will suggest are very limited
-in scope, we are looking to expand this (contributions welcome!).
-
-## Internals
-
-The tool is defined in a separate crate
-([`src/tools/suggest-tests`](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests))
-which outputs suggestions which are parsed by a shim in bootstrap
-([`src/bootstrap/src/core/build_steps/suggest.rs`](https://github.com/rust-lang/rust/blob/master/src/bootstrap/src/core/build_steps/suggest.rs)).
-The only notable thing the bootstrap shim does is (when invoked with the `--run`
-flag) use bootstrap's internal mechanisms to create a new `Builder` and uses it
-to invoke the suggested commands. The `suggest-tests` crate is where the fun
-happens, two kinds of suggestions are defined: "static" and "dynamic"
-suggestions.
-
-### Static suggestions
-
-Defined
-[here](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/static_suggestions.rs).
-Static suggestions are simple: they are just
-[globs](https://crates.io/crates/glob) which map to a `x` command. In
-`suggest-tests`, this is implemented with a simple `macro_rules` macro.
-
-### Dynamic suggestions
-
-Defined
-[here](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/dynamic_suggestions.rs).
-These are more complicated than static suggestions and are implemented as
-functions with the following signature: `fn(&Path) -> Vec<Suggestion>`. In other
-words, each suggestion takes a path to a modified file and (after running
-arbitrary Rust code) can return any number of suggestions, or none. Dynamic
-suggestions are useful for situations where fine-grained control over
-suggestions is needed. For example, modifications to the `compiler/xyz/` path
-should trigger the `x test compiler/xyz` suggestion. In the future, dynamic
-suggestions might even read file contents to determine if (what) tests should
-run.
-
-## Adding a suggestion
-
-The following steps should serve as a rough guide to add suggestions to
-`suggest-tests` (very welcome!):
-
-1. Determine the rules for your suggestion. Is it simple and operates only on a
-   single path or does it match globs? Does it need fine-grained control over
-   the resulting command or does "one size fit all"?
-2. Based on the previous step, decide if your suggestion should be implemented
-   as either static or dynamic.
-3. Implement the suggestion. If it is dynamic then a test is highly recommended,
-   to verify that your logic is correct and to give an example of the
-   suggestion. See the
-   [tests.rs](https://github.com/rust-lang/rust/blob/master/src/tools/suggest-tests/src/tests.rs)
-   file.
-4. Open a PR implementing your suggestion. **(TODO: add example PR)**
diff --git a/src/tests/ui.md b/src/tests/ui.md
index 4fce5838b..25dd5814c 100644
--- a/src/tests/ui.md
+++ b/src/tests/ui.md
@@ -1,7 +1,5 @@
 # UI tests
 
-<!-- toc -->
-
 UI tests are a particular [test suite](compiletest.md#test-suites) of
 compiletest.
 
@@ -25,9 +23,9 @@ If you need to work with `#![no_std]` cross-compiling tests, consult the
 
 ## General structure of a test
 
-A test consists of a Rust source file located anywhere in the `tests/ui`
-directory, but they should be placed in a suitable sub-directory. For example,
-[`tests/ui/hello.rs`] is a basic hello-world test.
+A test consists of a Rust source file located in the `tests/ui` directory.
+**Tests must be placed in the appropriate subdirectory** based on their purpose
+and testing category - placing tests directly in `tests/ui` is not permitted.
 
 Compiletest will use `rustc` to compile the test, and compare the output against
 the expected output which is stored in a `.stdout` or `.stderr` file located
@@ -46,8 +44,6 @@ pass/fail expectations](#controlling-passfail-expectations).
 By default, a test is built as an executable binary. If you need a different
 crate type, you can use the `#![crate_type]` attribute to set it as needed.
 
-[`tests/ui/hello.rs`]: https://github.com/rust-lang/rust/blob/master/tests/ui/hello.rs
-
 ## Output comparison
 
 UI tests store the expected output from the compiler in `.stderr` and `.stdout`
@@ -309,7 +305,9 @@ fn main((ؼ
 
 Use `//~?` to match an error without line information.
 `//~?` is precise and will not match errors if their line information is available.
-It should be preferred to using `error-pattern`, which is imprecise and non-exhaustive.
+It should be preferred over `//@ error-pattern`
+for tests wishing to match against compiler diagnostics,
+due to `//@ error-pattern` being imprecise and non-exhaustive.
 
 ```rust,ignore
 //@ compile-flags: --print yyyy
@@ -319,8 +317,8 @@ It should be preferred to using `error-pattern`, which is imprecise and non-exha
 
 ### `error-pattern`
 
-The `error-pattern` [directive](directives.md) can be used for runtime messages, which don't
-have a specific span, or in exceptional cases, for compile time messages.
+The `error-pattern` [directive](directives.md) can be used for runtime messages which don't
+have a specific span, or, in exceptional cases, for compile time messages.
 
 Let's think about this test:
 
@@ -347,8 +345,6 @@ fn main() {
 }
 ```
 
-Use of `error-pattern` is not recommended in general.
-
 For strict testing of compile time output, try to use the line annotations `//~` as much as
 possible, including `//~?` annotations for diagnostics without spans.
 
@@ -359,7 +355,8 @@ Some of the compiler messages can stay uncovered by annotations in this mode.
 
 For checking runtime output, `//@ check-run-results` may be preferable.
 
-Only use `error-pattern` if none of the above works.
+Only use `error-pattern` if none of the above works, such as when finding a
+specific string pattern in a runtime panic output.
 
 Line annotations `//~` and `error-pattern` are compatible and can be used in the same test.
 
@@ -448,7 +445,7 @@ even run the resulting program. Just add one of the following
   - `//@ build-pass` — compilation and linking should succeed but do
     not run the resulting binary.
   - `//@ run-pass` — compilation should succeed and running the resulting
-    binary should also succeed.
+    binary should make it exit with code 0 which indicates success.
 - Fail directives:
   - `//@ check-fail` — compilation should fail (the codegen phase is skipped).
     This is the default for UI tests.
@@ -457,10 +454,20 @@ even run the resulting program. Just add one of the following
     - First time is to ensure that the compile succeeds without the codegen phase
     - Second time is to ensure that the full compile fails
   - `//@ run-fail` — compilation should succeed, but running the resulting
-    binary should fail.
-
-For `run-pass` and `run-fail` tests, by default the output of the program itself
-is not checked.
+    binary should make it exit with a code in the range `1..=127` which
+    indicates regular failure. On targets without unwind support, crashes
+    are also accepted.
+  - `//@ run-crash` — compilation should succeed, but running the resulting
+    binary should fail with a crash. Crashing is defined as "not exiting with
+    a code in the range `0..=127`". Example on Linux: Termination by `SIGABRT`
+    or `SIGSEGV`. Example on Windows: Exiting with the code for
+    `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`).
+  - `//@ run-fail-or-crash` — compilation should succeed, but running the
+    resulting binary should either `run-fail` or `run-crash`. Useful if a test
+    crashes on some targets but just fails on others.
+
+For `run-pass`. `run-fail`, `run-crash` and `run-fail-or-crash` tests, by
+default the output of the program itself is not checked.
 
 If you want to check the output of running the program, include the
 `check-run-results` directive. This will check for a `.run.stderr` and
diff --git a/src/thir.md b/src/thir.md
index 73d09ad80..3d3dafaef 100644
--- a/src/thir.md
+++ b/src/thir.md
@@ -1,7 +1,5 @@
 # The THIR
 
-<!-- toc -->
-
 The THIR ("Typed High-Level Intermediate Representation"), previously called HAIR for
 "High-Level Abstract IR", is another IR used by rustc that is generated after
 [type checking]. It is (as of <!-- date-check --> January 2024) used for
diff --git a/src/tracing.md b/src/tracing.md
index 0cfdf306e..5e5b81fc6 100644
--- a/src/tracing.md
+++ b/src/tracing.md
@@ -1,7 +1,5 @@
 # Using tracing to debug the compiler
 
-<!-- toc -->
-
 The compiler has a lot of [`debug!`] (or `trace!`) calls, which print out logging information
 at many points. These are very useful to at least narrow down the location of
 a bug if not to find it entirely, or just to orient yourself as to why the
diff --git a/src/traits/goals-and-clauses.md b/src/traits/goals-and-clauses.md
index 40fd4581b..2884ca5a0 100644
--- a/src/traits/goals-and-clauses.md
+++ b/src/traits/goals-and-clauses.md
@@ -1,7 +1,5 @@
 # Goals and clauses
 
-<!-- toc -->
-
 In logic programming terms, a **goal** is something that you must
 prove and a **clause** is something that you know is true. As
 described in the [lowering to logic](./lowering-to-logic.html)
diff --git a/src/traits/lowering-to-logic.md b/src/traits/lowering-to-logic.md
index 1248d4346..cc8b3bf80 100644
--- a/src/traits/lowering-to-logic.md
+++ b/src/traits/lowering-to-logic.md
@@ -1,7 +1,5 @@
 # Lowering to logic
 
-<!-- toc -->
-
 The key observation here is that the Rust trait system is basically a
 kind of logic, and it can be mapped onto standard logical inference
 rules. We can then look for solutions to those inference rules in a
diff --git a/src/traits/resolution.md b/src/traits/resolution.md
index c62b05936..ccb2b0426 100644
--- a/src/traits/resolution.md
+++ b/src/traits/resolution.md
@@ -1,7 +1,5 @@
 # Trait resolution (old-style)
 
-<!-- toc -->
-
 This chapter describes the general process of _trait resolution_ and points out
 some non-obvious things.
 
diff --git a/src/ty.md b/src/ty.md
index 767ac3fdb..4055f475e 100644
--- a/src/ty.md
+++ b/src/ty.md
@@ -1,7 +1,5 @@
 # The `ty` module: representing types
 
-<!-- toc -->
-
 The `ty` module defines how the Rust compiler represents types internally. It also defines the
 *typing context* (`tcx` or `TyCtxt`), which is the central data structure in the compiler.
 
diff --git a/src/ty_module/instantiating_binders.md b/src/ty_module/instantiating_binders.md
index e3f091ca4..0d1108c72 100644
--- a/src/ty_module/instantiating_binders.md
+++ b/src/ty_module/instantiating_binders.md
@@ -77,7 +77,7 @@ This end result is incorrect as we had two separate binders introducing their ow
 
 While in theory we could make this work it would be quite involved and more complex than the current setup, we would have to:
 - "rewrite" bound variables to have a higher `DebruijnIndex` whenever instantiating a `Binder`/`EarlyBinder` with a `Bound` ty/const/region 
-- When inferring an inference variable to a bound var, if that bound var is from a binder enterred after creating the infer var, we would have to lower the `DebruijnIndex` of the var.
+- When inferring an inference variable to a bound var, if that bound var is from a binder entered after creating the infer var, we would have to lower the `DebruijnIndex` of the var.
 - Separately track what binder an inference variable was created inside of, also what the innermost binder it can name parameters from (currently we only have to track the latter)
 - When resolving inference variables rewrite any bound variables according to the current binder depth of the infcx
 - Maybe more (while writing this list items kept getting added so it seems naive to think this is exhaustive)
diff --git a/src/type-inference.md b/src/type-inference.md
index 888eb2439..2243205f1 100644
--- a/src/type-inference.md
+++ b/src/type-inference.md
@@ -1,7 +1,5 @@
 # Type inference
 
-<!-- toc -->
-
 Type inference is the process of automatic detection of the type of an
 expression.
 
diff --git a/src/typing_parameter_envs.md b/src/typing_parameter_envs.md
index e21bc5155..db15467a4 100644
--- a/src/typing_parameter_envs.md
+++ b/src/typing_parameter_envs.md
@@ -1,7 +1,5 @@
 # Typing/Parameter Environments
 
-<!-- toc -->
-
 ## Typing Environments
 
 When interacting with the type system there are a few variables to consider that can affect the results of trait solving. The set of in-scope where clauses, and what phase of the compiler type system operations are being performed in (the [`ParamEnv`][penv] and [`TypingMode`][tmode] structs respectively).
diff --git a/src/variance.md b/src/variance.md
index ad4fa4adf..7aa014071 100644
--- a/src/variance.md
+++ b/src/variance.md
@@ -1,7 +1,5 @@
 # Variance of type and lifetime parameters
 
-<!-- toc -->
-
 For a more general background on variance, see the [background] appendix.
 
 [background]: ./appendix/background.html
diff --git a/src/walkthrough.md b/src/walkthrough.md
index 48b3f8bb1..b4c337934 100644
--- a/src/walkthrough.md
+++ b/src/walkthrough.md
@@ -1,7 +1,5 @@
 # Walkthrough: a typical contribution
 
-<!-- toc -->
-
 There are _a lot_ of ways to contribute to the Rust compiler, including fixing
 bugs, improving performance, helping design features, providing feedback on
 existing features, etc. This chapter does not claim to scratch the surface.
diff --git a/triagebot.toml b/triagebot.toml
index b3f4c2d28..3ac5d57a5 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -62,9 +62,6 @@ allow-unauthenticated = [
 # Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html
 [issue-links]
 
-# Automatically close and reopen PRs made by bots to run CI on them
-[bot-pull-requests]
-
 [behind-upstream]
 days-threshold = 7
 
