From 76323c8c596877d72ab3727aac13708dceb29ca7 Mon Sep 17 00:00:00 2001 From: Jynn Nelson Date: Fri, 17 Apr 2026 11:07:32 +0200 Subject: [PATCH 01/57] [draft] Link to proposed LLM policy --- src/doc/rustc-dev-guide/src/about-this-guide.md | 3 ++- src/doc/rustc-dev-guide/src/contributing.md | 6 ++++++ src/doc/rustc-dev-guide/src/getting-started.md | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 4dc453a2042de..57f6e676866d8 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -72,6 +72,7 @@ You might also find the following sites useful: - [rustc API docs] -- rustdoc documentation for the compiler, devtools, and internal tools - [Forge] -- contains documentation about Rust infrastructure, team procedures, and more +- `rust-lang/rust`'s [LLM policy] - [compiler-team] -- the home-base for the Rust compiler team, with description of the team procedures, active working groups, and the team calendar. - [std-dev-guide] -- a similar guide for developing the standard library. @@ -93,7 +94,7 @@ You might also find the following sites useful: For example, searching for `* -> vec` should find all functions that return a `Vec`. _Hint:_ Find more tips and keyboard shortcuts by typing `?` on any Rustdoc page! - +[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html [rustc dev guide]: about-this-guide.md [gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here [stddocs]: https://doc.rust-lang.org/std diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 7f4779515b13c..05685d9f2fa58 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -517,6 +517,12 @@ This is used for [RFCs], issues, and pull requests. [rfcbot]: https://github.com/anp/rfcbot-rs/ [RFCs]: https://github.com/rust-lang/rfcs +## LLM policy + +See [Forge][LLM policy]. + +[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html + ## Helpful links and information This section has moved to the ["About this guide"] chapter. diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index a5da912aa4c4d..12167347d44ef 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -48,6 +48,8 @@ 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. +See also [our LLM policy](https://forge.rust-lang.org/policies/llm-usage.html). + ### Experts Not all `t-compiler` members are experts on all parts of `rustc`; From f32e5d87873a76facca83f917091b6971f90cabd Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 23 May 2026 06:41:40 +0200 Subject: [PATCH 02/57] add guidance for working with LLMs --- src/doc/rustc-dev-guide/src/SUMMARY.md | 1 + src/doc/rustc-dev-guide/src/llm-guidance.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/doc/rustc-dev-guide/src/llm-guidance.md diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 9a9861186011d..29a259130d395 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -50,6 +50,7 @@ - [About the compiler team](./compiler-team.md) - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) +- [Running LLMs](./llm-guidance.md) - [Walkthrough: a typical contribution](./walkthrough.md) - [Implementing new language features](./implementing-new-features.md) - [Stability guarantees](./stability-guarantees.md) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md new file mode 100644 index 0000000000000..1e668d1624174 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -0,0 +1,15 @@ +# Running LLMs + +This is a non-binding list of suggestions for working with LLMs. +This is not our moderation policy; see [Forge][LLM policy]. + +## Review bots + +- If a more reliable tool, such as a linter or formatter, already exists for the language you're writing, we strongly suggest using that tool instead of or in addition to the LLM. +- Configure LLM review tools to reduce false positives and excessive focus on trivialities, as these are common, exhausting failure modes. + +## LLM-authored code + +- We recommend, but do not require, using a second LLM for adversarial local review before publishing your changes. + +[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html From e07d7cc69fd3fd7bf6c62f20f4f85c51f8fe97da Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 6 Jun 2026 13:16:48 +0200 Subject: [PATCH 03/57] Suggest using an LLM to generate tools, rather than making the LLM the tool --- src/doc/rustc-dev-guide/src/llm-guidance.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index 1e668d1624174..b93b3c6d52ec5 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -7,9 +7,13 @@ This is not our moderation policy; see [Forge][LLM policy]. - If a more reliable tool, such as a linter or formatter, already exists for the language you're writing, we strongly suggest using that tool instead of or in addition to the LLM. - Configure LLM review tools to reduce false positives and excessive focus on trivialities, as these are common, exhausting failure modes. +- Wherever possible, ask an LLM to *generate a linter*, which you then tell it to run. + This both saves on token costs, and allows people who are not using an LLM to run the analysis. ## LLM-authored code - We recommend, but do not require, using a second LLM for adversarial local review before publishing your changes. +- Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. + You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. [LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html From baf98d4b9ed078def5c58b4dd1dd098daa357e67 Mon Sep 17 00:00:00 2001 From: jyn Date: Thu, 11 Jun 2026 17:58:39 +0200 Subject: [PATCH 04/57] add note that LLMs prefer their own output --- src/doc/rustc-dev-guide/src/llm-guidance.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index b93b3c6d52ec5..d76f819fb9f30 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -9,6 +9,7 @@ This is not our moderation policy; see [Forge][LLM policy]. - Configure LLM review tools to reduce false positives and excessive focus on trivialities, as these are common, exhausting failure modes. - Wherever possible, ask an LLM to *generate a linter*, which you then tell it to run. This both saves on token costs, and allows people who are not using an LLM to run the analysis. +- Note that LLMs sometimes demonstrate a preference for LLM output, particularly output from the same model. ## LLM-authored code From 32c4dcb73668043e42ffcb9fcd55b7c716ed5282 Mon Sep 17 00:00:00 2001 From: jyn Date: Thu, 18 Jun 2026 02:01:10 +0200 Subject: [PATCH 05/57] extend llm guidance --- src/doc/rustc-dev-guide/src/llm-guidance.md | 52 ++++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index d76f819fb9f30..bbb12bd0e37f1 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -1,20 +1,60 @@ -# Running LLMs +# Working with LLMs This is a non-binding list of suggestions for working with LLMs. This is not our moderation policy; see [Forge][LLM policy]. -## Review bots +[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html + +## Automated checks and LLM review - If a more reliable tool, such as a linter or formatter, already exists for the language you're writing, we strongly suggest using that tool instead of or in addition to the LLM. - Configure LLM review tools to reduce false positives and excessive focus on trivialities, as these are common, exhausting failure modes. - Wherever possible, ask an LLM to *generate a linter*, which you then tell it to run. This both saves on token costs, and allows people who are not using an LLM to run the analysis. -- Note that LLMs sometimes demonstrate a preference for LLM output, particularly output from the same model. +- LLMs sometimes prefer LLM-generated output, particularly output from the same + model. Treat LLM review as advisory, and do not rely on the model that + produced a change as its only reviewer. -## LLM-authored code +## Writing LLM-created code -- We recommend, but do not require, using a second LLM for adversarial local review before publishing your changes. +- We recommend, but do not require, using a different model for adversarial + local review before publishing your changes. This does not replace human + self-review. - Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. -[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html +[`ast-grep`]: https://astgrep.com/ + +## Reviewing LLM-created code + +Point people to [#llm-mentoring](https://rust-lang.zulipchat.com/#narrow/channel/606558-llm-mentoring/) liberally. +Deal with low-quality PRs by closing the PR and asking the author to follow the "solicited" rule in the Forge policy. +Deal with borderline PRs by asking the author to do work that shows they're paying attention; it's ok to ask for that work before you've put much time into review yourself. +For example, ask them to reproduce the bug, explain the change in their own +words, identify relevant edge cases, or add or justify tests. + +If you find yourself suggesting the same fixes on multiple PRs, +consider adding them to the dev-guide. + +## Disclosure guidelines + +Disclose the *extent* and *purpose* of your LLM use. +We don't care which model you used, but we do care whether you used the LLM to +implement the idea or to come up with it. +Write the disclosure yourself. You may use an LLM to privately review a +disclosure you have written, but not to draft or rewrite it. + +**Good** examples: + +> LLM disclosure: I wrote the three commits by hand after viewing profiling data. I used an LLM to review the commits before submitting. The LLM identified that ImplString::is_negative was no longer used, so I removed that field by hand. + +> Created with the help of Claude Code, which: +> - traced the missing cache hits to the unconditional return(pass) by inspecting Fastly vs CloudFront headers, +> - reviewed the git history to understand why the snippet was added, and +> - made the VCL change. + +**Bad** examples: + +> 🤖 Generated with Claude Code + +> Co-Authored-By: Claude Opus 4.6 (1M context) From 2685feceadb5712acd93184038dbbe60a3b038d4 Mon Sep 17 00:00:00 2001 From: jyn Date: Tue, 28 Jul 2026 13:54:01 +0200 Subject: [PATCH 06/57] extend LLM guidance with a summary of the policy --- src/doc/rustc-dev-guide/src/llm-guidance.md | 135 ++++++++++++++++---- 1 file changed, 109 insertions(+), 26 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index bbb12bd0e37f1..5426f6f8944d1 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -1,10 +1,70 @@ # Working with LLMs -This is a non-binding list of suggestions for working with LLMs. -This is not our moderation policy; see [Forge][LLM policy]. +This is a list of guidelines for working with LLMs, as well as a summary of the moderation policy. +This is not the policy itself; see [Forge][LLM policy]. +If the two conflict, Forge is canonical. [LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html +## Writing LLM-created code + +### Rules + +Before anything else, you **must** find a reviewer who volunteers to review your PR. +LLM PRs without an assigned reviewer will be closed. + +Disclose your use of LLMs, following the disclosure guidelines below. +Write the disclosure yourself. +You may use an LLM to privately review a disclosure you have written, but not to draft or rewrite it. + +You may *not* use an LLM to write doc-comments, `// SAFETY` comments, diagnostics, or soundness-critical code. +If you don't know what counts as soundness-critical, discuss it with your reviewer. + +**Write your own PR description and comments**. +LLM-created PR descriptions are banned. +LLM-created Github comments are banned. +We want to hear from you, not from your agent. + +### Guidelines + +Start with one PR at a time. +We understand it's easy to be excited about contributing to Rust, but your PRs are not only a gift but a responsibility for the reviewers. +Go slow. + +Avoid E-easy and E-mentor issues. +Those are intended for people to get familiar with the project, not for LLMs. + +Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. +You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. + +Read the documentation. Strive for quality. Review your own PR before opening it: +Does it make sense? Can you tell what the goal of the PR is? Does it achieve that goal? + +We recommend using a different model for adversarial local review before publishing your changes. +This does not replace human self-review. + +[`ast-grep`]: https://astgrep.com/ + +#### Disclosure guidelines + +Disclose the *extent* and *purpose* of your LLM use. +We don't care which model you used, but we do care whether you used the LLM to implement the idea or to come up with it. + +**Good** examples: + +> LLM disclosure: I wrote the three commits by hand after viewing profiling data. I used an LLM to review the commits before submitting. The LLM identified that `ImplString::is_negative` was no longer used, so I removed that field by hand. + +> Created with the help of Claude Code, which: +> - traced the missing cache hits to the unconditional `return(pass)` by inspecting Fastly vs CloudFront headers, +> - reviewed the git history to understand why the snippet was added, and +> - made the VCL change. + +**Bad** examples: + +> 🤖 Generated with Claude Code + +> Co-Authored-By: Claude Opus 4.6 (1M context) + ## Automated checks and LLM review - If a more reliable tool, such as a linter or formatter, already exists for the language you're writing, we strongly suggest using that tool instead of or in addition to the LLM. @@ -15,20 +75,25 @@ This is not our moderation policy; see [Forge][LLM policy]. model. Treat LLM review as advisory, and do not rely on the model that produced a change as its only reviewer. -## Writing LLM-created code +## Reviewing LLM-created code -- We recommend, but do not require, using a different model for adversarial - local review before publishing your changes. This does not replace human - self-review. -- Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. - You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. +First, add the new `ai-assisted` label to the PR. -[`ast-grep`]: https://astgrep.com/ +### Rules -## Reviewing LLM-created code +We expect everyone to follow the new policy, not just authors. +That means it is **your responsibility** to check whether an `ai-assisted` PR touches an area that's disallowed by the policy. +You may request that the author redo it without LLM-generated code, in which case this section doesn't apply. + +The following areas are currently banned: +- Code that affects soundness. If the author is not obviously experienced in the domain, you are required to close the PR. +- Diagnostics. All user-facing diagnostics must be human-written. +- Docs. All public doc-comments, and all `SAFETY` comments, must be human-written. + +### Guidelines Point people to [#llm-mentoring](https://rust-lang.zulipchat.com/#narrow/channel/606558-llm-mentoring/) liberally. -Deal with low-quality PRs by closing the PR and asking the author to follow the "solicited" rule in the Forge policy. +Deal with low-quality PRs by closing the PR and asking the author to follow the policy. Deal with borderline PRs by asking the author to do work that shows they're paying attention; it's ok to ask for that work before you've put much time into review yourself. For example, ask them to reproduce the bug, explain the change in their own words, identify relevant edge cases, or add or justify tests. @@ -36,25 +101,43 @@ words, identify relevant edge cases, or add or justify tests. If you find yourself suggesting the same fixes on multiple PRs, consider adding them to the dev-guide. -## Disclosure guidelines +#### Missing disclosure -Disclose the *extent* and *purpose* of your LLM use. -We don't care which model you used, but we do care whether you used the LLM to -implement the idea or to come up with it. -Write the disclosure yourself. You may use an LLM to privately review a -disclosure you have written, but not to draft or rewrite it. +If you see a PR that is "obviously" LLM-created without disclosing that use, you have the option—but not the responsibility—to close it unilaterally. -**Good** examples: +We suggest using the following wording: -> LLM disclosure: I wrote the three commits by hand after viewing profiling data. I used an LLM to review the commits before submitting. The LLM identified that ImplString::is_negative was no longer used, so I removed that field by hand. +> This PR appears to be LLM-generated without disclosing use of an LLM, +> so I am going to close this PR. +> You are welcome to open additional PRs as long as they follow our [policy][forge-page]. +> For more information, see [#llm-mentoring] on Zulip. -> Created with the help of Claude Code, which: -> - traced the missing cache hits to the unconditional return(pass) by inspecting Fastly vs CloudFront headers, -> - reviewed the git history to understand why the snippet was added, and -> - made the VCL change. +Examples of "obvious" LLM tells are: +- PR descriptions that are completely wrong/don't match the code. +- PR descriptions that state the exact tests that were run (e.g. `./x test --stage 1 tests/ui/.rs`) or useless tests such as `git diff --check`. +- Responses to reviewer questions that fall into one of the above categories. -**Bad** examples: +You do not have an obligation to detect LLM-created PRs; +you don't need to play detective. -> 🤖 Generated with Claude Code +PR templates will have a "Did you use an LLM?" question so that this rarely comes up. +If the author deleted the question without answering it, you can close the PR, no questions asked. -> Co-Authored-By: Claude Opus 4.6 (1M context) +#### Missing solicited reviewer + +If the PR discloses use, but does not assign a reviewer following the [experiment guidelines], you can close it similarly: + +> You've opened an LLM-generated PR, but it's in the normal review queue, which breaks our [policy][experiment guidelines]. +> I am going to close this PR. +> Please do not re-open it until you find a project member who has volunteered to review it. +> For more information, see [#llm-mentoring] on Zulip. + +#### Missing tests, low-quality, or not self-reviewed + +If a PR is clearly not ready for review, you do not have to review it. +It's ok to simply skim the PR and tell the author "you need to add tests before I can review this". +If you notice on your skim that the PR is clearly the wrong approach, it's ok to close the PR and tell the author to talk with you in the [#llm-mentoring] channel before opening a new PR. + +[experiment guidelines]: https://forge.rust-lang.org/policies/llm-usage.html#experiment-llm-created-code-changes-intended-for-review +[#llm-mentoring]: https://rust-lang.zulipchat.com/join/rlfvpemsaacs3pfi6kwqnqjb/ +[forge-page]: https://forge.rust-lang.org/policies/llm-usage.html From 7da7cd027e177b488f06328a493a4e518e4909ac Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 09:04:02 +0200 Subject: [PATCH 07/57] flesh out author guidance --- src/doc/rustc-dev-guide/src/llm-guidance.md | 27 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index 5426f6f8944d1..aff7197463634 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -11,7 +11,8 @@ If the two conflict, Forge is canonical. ### Rules Before anything else, you **must** find a reviewer who volunteers to review your PR. -LLM PRs without an assigned reviewer will be closed. +LLM-created PRs without an assigned reviewer will be closed. +If you do not know where to find a reviewer, see [#llm-mentoring] on Zulip. Disclose your use of LLMs, following the disclosure guidelines below. Write the disclosure yourself. @@ -27,6 +28,8 @@ We want to hear from you, not from your agent. ### Guidelines +#### Before you write code + Start with one PR at a time. We understand it's easy to be excited about contributing to Rust, but your PRs are not only a gift but a responsibility for the reviewers. Go slow. @@ -34,15 +37,33 @@ Go slow. Avoid E-easy and E-mentor issues. Those are intended for people to get familiar with the project, not for LLMs. +#### While working + +When fixing a bug, reproduce the bug *before* fixing it. +Write a test that fails, fix the bug, then verify the test now succeeds. +Otherwise, you don't know that you were testing the right thing. + Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. -Read the documentation. Strive for quality. Review your own PR before opening it: +#### Before opening a PR + +Review your own PR before opening it: Does it make sense? Can you tell what the goal of the PR is? Does it achieve that goal? +Run tests to verify your change works. +Do NOT report which tests you ran in the PR description; +that's useless to us, since CI will run them anyway. + +You must review diagnostic snapshots; don't simply `--bless` them away. + We recommend using a different model for adversarial local review before publishing your changes. This does not replace human self-review. +You must understand and be able to explain your own change and its edge cases. +Asking the LLM can be a starting point but is not sufficient. +You are responsible for your own code; you cannot disclaim responsibility to your agent. + [`ast-grep`]: https://astgrep.com/ #### Disclosure guidelines @@ -92,7 +113,7 @@ The following areas are currently banned: ### Guidelines -Point people to [#llm-mentoring](https://rust-lang.zulipchat.com/#narrow/channel/606558-llm-mentoring/) liberally. +Point people to [#llm-mentoring] liberally. Deal with low-quality PRs by closing the PR and asking the author to follow the policy. Deal with borderline PRs by asking the author to do work that shows they're paying attention; it's ok to ask for that work before you've put much time into review yourself. For example, ask them to reproduce the bug, explain the change in their own From 500f94c222e814442984ef9271d0194dcd22314b Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 09:04:10 +0200 Subject: [PATCH 08/57] more author guidance; cross-references --- src/doc/rustc-dev-guide/src/llm-guidance.md | 37 +++++++++++++++---- .../src/tests/best-practices.md | 2 +- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index aff7197463634..183e81c10f50b 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -18,7 +18,8 @@ Disclose your use of LLMs, following the disclosure guidelines below. Write the disclosure yourself. You may use an LLM to privately review a disclosure you have written, but not to draft or rewrite it. -You may *not* use an LLM to write doc-comments, `// SAFETY` comments, diagnostics, or soundness-critical code. +You may *not* use an LLM to write doc-comments, `// SAFETY` comments, diagnostic wording, or soundness-critical code. +Write them yourself instead. If you don't know what counts as soundness-critical, discuss it with your reviewer. **Write your own PR description and comments**. @@ -37,11 +38,21 @@ Go slow. Avoid E-easy and E-mentor issues. Those are intended for people to get familiar with the project, not for LLMs. +Determine whether this is a *useful* and *well-scoped* change. +For example: + +- Search for related issues and PRs. +- Find relevant code, tests, git history, and Zulip discussion. +- If this is a cross-cutting change, consult the "cross-cutting" section of [the contributing docs](./contributing.md#pull-requests). +- Make the smallest change that fixes the problem. + Do not combine it with unrelated refactors or cleanups. + #### While working -When fixing a bug, reproduce the bug *before* fixing it. -Write a test that fails, fix the bug, then verify the test now succeeds. -Otherwise, you don't know that you were testing the right thing. +When fixing a bug, verify that your test fails before and succeeds after your change. +Consult [adding new tests](./tests/adding.md) and [best practices](./tests/best-practices.md) for test procedures. +Tests are absolutely required; either existing tests or new tests you write. +Untested LLM PRs will not be merged. Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. @@ -51,19 +62,31 @@ You may use an LLM for generating the instructions for that tool, but you should Review your own PR before opening it: Does it make sense? Can you tell what the goal of the PR is? Does it achieve that goal? -Run tests to verify your change works. +[Run tests](tests/running.md) to verify your change works. Do NOT report which tests you ran in the PR description; that's useless to us, since CI will run them anyway. -You must review diagnostic snapshots; don't simply `--bless` them away. +You must [review diagnostic snapshots](tests/adding.md#step-4-review-the-output); +don't simply `--bless` them away. We recommend using a different model for adversarial local review before publishing your changes. This does not replace human self-review. +#### Understand your own change + You must understand and be able to explain your own change and its edge cases. Asking the LLM can be a starting point but is not sufficient. You are responsible for your own code; you cannot disclaim responsibility to your agent. +Some questions that you should be able to answer: + +- What is the original bug? When does it happen? How severe is it? What causes it? +- Why is this the right fix? Are there other fixes possible? What are their advantages or disadvantages? +- Are there any edge cases? Does your code handle them? +- What behavior is *unchanged*? What test establishes that? +- Why does your test trigger the bug? +- What are you still not certain about? + [`ast-grep`]: https://astgrep.com/ #### Disclosure guidelines @@ -107,7 +130,7 @@ That means it is **your responsibility** to check whether an `ai-assisted` PR to You may request that the author redo it without LLM-generated code, in which case this section doesn't apply. The following areas are currently banned: -- Code that affects soundness. If the author is not obviously experienced in the domain, you are required to close the PR. +- Code that affects soundness. If the author is not an org member who is experienced in the domain, you are required to close the PR. - Diagnostics. All user-facing diagnostics must be human-written. - Docs. All public doc-comments, and all `SAFETY` comments, must be human-written. diff --git a/src/doc/rustc-dev-guide/src/tests/best-practices.md b/src/doc/rustc-dev-guide/src/tests/best-practices.md index b6daffa6683c0..4e6f40c4b78e6 100644 --- a/src/doc/rustc-dev-guide/src/tests/best-practices.md +++ b/src/doc/rustc-dev-guide/src/tests/best-practices.md @@ -140,7 +140,7 @@ A good rule of thumb is non-trivial things exercised in the test deserves some explanation to help other contributors to understand. This may include remarks on: -- How an ICE can get triggered if it's quite elaborate. +- How an ICE or bug can get triggered if it's quite elaborate. - Related issues and tests (e.g. this test is like another test but is kept separate because...). - Platform-specific behaviors. From ac6af3961c651b0c0bb81c889ec2203d04caae67 Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 10:30:18 +0200 Subject: [PATCH 09/57] change tone from policy to mentorship --- src/doc/rustc-dev-guide/src/llm-guidance.md | 56 ++++++++++++++------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index 183e81c10f50b..175b3d1e3848c 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -8,18 +8,35 @@ If the two conflict, Forge is canonical. ## Writing LLM-created code +LLMs are a valuable tool, but one that is easy to misuse. +The main risks are **overwhelming volume** and **lack of understanding**. +When writing your PR, keep in mind that there is a person on the other end who needs to review and understand your change. +Help us out by making your change small, targeted, and easy to review. + +Keep in mind this quote: + +> Programs must be written for people to read, and only incidentally for machines to execute. +> — Harold Abelson and Gerald Jay Sussman, [*Structure and Interpretation of Computer Programs*][sicp] + +[sicp]: https://web.mit.edu/6.001/6.037/sicp.pdf + ### Rules -Before anything else, you **must** find a reviewer who volunteers to review your PR. -LLM-created PRs without an assigned reviewer will be closed. -If you do not know where to find a reviewer, see [#llm-mentoring] on Zulip. +Before anything else, find a reviewer who volunteers to review your PR. +If you do not know where to find a reviewer, ask in [#llm-mentoring] on Zulip. +Your first message should say: + +- your relevant experience, so we can find an issue that's suitable for you +- which problem (or kind of problem) you want to work on +- (optional) ideas you have so far for a solution +- (optional) how you expect to test your solution Disclose your use of LLMs, following the disclosure guidelines below. Write the disclosure yourself. You may use an LLM to privately review a disclosure you have written, but not to draft or rewrite it. -You may *not* use an LLM to write doc-comments, `// SAFETY` comments, diagnostic wording, or soundness-critical code. -Write them yourself instead. +Write your own doc-comments, `// SAFETY` comments, diagnostic wording, and soundness-critical code. +As before, you can use an LLM to review your work, but not to write it from scratch. If you don't know what counts as soundness-critical, discuss it with your reviewer. **Write your own PR description and comments**. @@ -32,11 +49,11 @@ We want to hear from you, not from your agent. #### Before you write code Start with one PR at a time. -We understand it's easy to be excited about contributing to Rust, but your PRs are not only a gift but a responsibility for the reviewers. +Your PRs are not only a gift but a responsibility for reviewers. Go slow. -Avoid E-easy and E-mentor issues. -Those are intended for people to get familiar with the project, not for LLMs. +Do not use an LLM for `E-easy` issues; those are meant for you to write the code yourself. +Ask first before working on an `E-mentor` issue; mentors may not want to work with LLM-generated code. Determine whether this is a *useful* and *well-scoped* change. For example: @@ -63,22 +80,24 @@ Review your own PR before opening it: Does it make sense? Can you tell what the goal of the PR is? Does it achieve that goal? [Run tests](tests/running.md) to verify your change works. -Do NOT report which tests you ran in the PR description; -that's useless to us, since CI will run them anyway. +Do NOT report which UI tests you ran in the PR description; +that's noise, since CI will run them anyway. +If you did manual testing or benchmarking, do report that, +but note that all LLM PRs must have automated tests. -You must [review diagnostic snapshots](tests/adding.md#step-4-review-the-output); +[Review diagnostic snapshots](tests/adding.md#step-4-review-the-output); don't simply `--bless` them away. We recommend using a different model for adversarial local review before publishing your changes. -This does not replace human self-review. +You're still responsible for reviewing your own changes yourself. #### Understand your own change -You must understand and be able to explain your own change and its edge cases. -Asking the LLM can be a starting point but is not sufficient. -You are responsible for your own code; you cannot disclaim responsibility to your agent. +We want you to understand and be able to explain your own change and its edge cases. +Asking the LLM can be a starting point but it's not the same as explaining it yourself. -Some questions that you should be able to answer: +Try explaining your change to yourself before opening the PR. +For example, ask yourself: - What is the original bug? When does it happen? How severe is it? What causes it? - Why is this the right fix? Are there other fixes possible? What are their advantages or disadvantages? @@ -87,6 +106,9 @@ Some questions that you should be able to answer: - Why does your test trigger the bug? - What are you still not certain about? +It's ok to be uncertain and to ask for help. +We would much rather help you because you're not sure than have you guess wrong and then have to reverse-engineer where you went wrong. + [`ast-grep`]: https://astgrep.com/ #### Disclosure guidelines @@ -138,7 +160,7 @@ The following areas are currently banned: Point people to [#llm-mentoring] liberally. Deal with low-quality PRs by closing the PR and asking the author to follow the policy. -Deal with borderline PRs by asking the author to do work that shows they're paying attention; it's ok to ask for that work before you've put much time into review yourself. +Deal with borderline PRs by asking the author to put in the work themselves rather than offloading it to you. For example, ask them to reproduce the bug, explain the change in their own words, identify relevant edge cases, or add or justify tests. From ef9670cfc89d846eeb98eed61fa38948606dad0b Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 11:44:43 +0200 Subject: [PATCH 10/57] add "maintainable code" section --- src/doc/rustc-dev-guide/src/llm-guidance.md | 43 +++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index 175b3d1e3848c..d186df8779436 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -10,8 +10,9 @@ If the two conflict, Forge is canonical. LLMs are a valuable tool, but one that is easy to misuse. The main risks are **overwhelming volume** and **lack of understanding**. -When writing your PR, keep in mind that there is a person on the other end who needs to review and understand your change. -Help us out by making your change small, targeted, and easy to review. +When writing your PR, keep in mind that there is a person on the other end who needs to review and understand your change, +and that other people in the project will need to read your code for years to come. +Help us out by making your change small, targeted, and high-quality. Keep in mind this quote: @@ -49,7 +50,7 @@ We want to hear from you, not from your agent. #### Before you write code Start with one PR at a time. -Your PRs are not only a gift but a responsibility for reviewers. +Keep your changes small enough that you and your reviewer can understand every part of them. Go slow. Do not use an LLM for `E-easy` issues; those are meant for you to write the code yourself. @@ -74,11 +75,45 @@ Untested LLM PRs will not be merged. Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. +Work in small steps. +Run tests after every meaningful change, so you know where you first went wrong. +Do not write all your code at once; that will make it very hard to know what broke. +Ideally, commit your changes in [small atomic commits] as you go. + +Verify your understanding against the existing code, documentation, and tests. +You can get better advice from your LLM by telling *it* to read the relevant materials. +Do not rely on the LLM as a source of truth. + +[small atomic commits](https://github.blog/developer-skills/github/write-better-commits-build-better-projects/#%e2%9a%9b%ef%b8%8f-resize-and-stabilize-the-commits) + +#### Write maintainable code + +Treat generated code as a *draft*, not a final product. + +Follow the style of surrounding code. +Use existing helpers and avoid duplicating logic or validation. + +Represent data in [one normalized place](https://react.dev/learn/choosing-the-state-structure); +trying to keep data in sync between two different places is a code smell. + +When practical, [make invalid states unrepresentable](https://kentcdodds.com/blog/make-impossible-states-impossible), [not just checked at construction time](https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/). + +Write comments that say *why* you have done a thing, not *what* you have done. +It's ok to go into detail about non-obvious bugs. + +Preserve existing behavior. +Consider platform differences and error cases. + #### Before opening a PR Review your own PR before opening it: Does it make sense? Can you tell what the goal of the PR is? Does it achieve that goal? +Remove outdated or prototyping code and debugging. + +Re-read the whole diff, *not* just your conversation with the agent. +Your reviewer is going to see your code, not your conversation. + [Run tests](tests/running.md) to verify your change works. Do NOT report which UI tests you ran in the PR description; that's noise, since CI will run them anyway. @@ -102,6 +137,8 @@ For example, ask yourself: - What is the original bug? When does it happen? How severe is it? What causes it? - Why is this the right fix? Are there other fixes possible? What are their advantages or disadvantages? - Are there any edge cases? Does your code handle them? +- Does the code have existing [invariants](https://brooker.co.za/blog/2023/07/28/ds-testing.html)? + Did you preserve those invariants? - What behavior is *unchanged*? What test establishes that? - Why does your test trigger the bug? - What are you still not certain about? From cebbf10814b33518523e751d6c0b10572affd499 Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 11:45:16 +0200 Subject: [PATCH 11/57] split authoring and reviewing sections --- src/doc/rustc-dev-guide/src/SUMMARY.md | 4 +- .../rustc-dev-guide/src/llm-guidance/index.md | 10 ++ .../src/llm-guidance/reviewing.md | 76 +++++++++++++ .../writing.md} | 106 ++---------------- 4 files changed, 100 insertions(+), 96 deletions(-) create mode 100644 src/doc/rustc-dev-guide/src/llm-guidance/index.md create mode 100644 src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md rename src/doc/rustc-dev-guide/src/{llm-guidance.md => llm-guidance/writing.md} (59%) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 29a259130d395..d082f6e253175 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -50,7 +50,9 @@ - [About the compiler team](./compiler-team.md) - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) -- [Running LLMs](./llm-guidance.md) +- [Running LLMs](./llm-guidance/index.md) + - [Writing code with LLMs](./llm-guidance/writing.md) + - [Reviewing code with LLMs](./llm-guidance/reviewing.md) - [Walkthrough: a typical contribution](./walkthrough.md) - [Implementing new language features](./implementing-new-features.md) - [Stability guarantees](./stability-guarantees.md) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/index.md b/src/doc/rustc-dev-guide/src/llm-guidance/index.md new file mode 100644 index 0000000000000..3709e7ead854c --- /dev/null +++ b/src/doc/rustc-dev-guide/src/llm-guidance/index.md @@ -0,0 +1,10 @@ +# Working with LLMs + +This section is a list of guidelines for working with LLMs, as well as a summary of the moderation policy. +This is not the policy itself; see [Forge][LLM policy]. +If the two conflict, Forge is canonical. + +If you are writing code using an LLM, see [Writing LLM-created code](./writing.md). +If you are reviewing LLM-created code, or reviewing using an LLM, see [Reviewing with LLMs](./reviewing.md). + +[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md new file mode 100644 index 0000000000000..4feab70ec3dcc --- /dev/null +++ b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md @@ -0,0 +1,76 @@ +## Using an LLM to review code + +- If a more reliable tool, such as a linter or formatter, already exists for the language you're writing, we strongly suggest using that tool instead of or in addition to the LLM. +- Configure LLM review tools to reduce false positives and excessive focus on trivialities, as these are common, exhausting failure modes. +- Wherever possible, ask an LLM to *generate a linter*, which you then tell it to run. + This both saves on token costs, and allows people who are not using an LLM to run the analysis. +- LLMs sometimes prefer LLM-generated output, particularly output from the same + model. Treat LLM review as advisory, and do not rely on the model that + produced a change as its only reviewer. + +## Reviewing LLM-created code + +First, add the new `ai-assisted` label to the PR. + +### Rules + +We expect everyone to follow the new policy, not just authors. +That means it is **your responsibility** to check whether an `ai-assisted` PR touches an area that's disallowed by the policy. +You may request that the author redo it without LLM-generated code, in which case this section doesn't apply. + +The following areas are currently banned: +- Code that affects soundness. If the author is not an org member who is experienced in the domain, you are required to close the PR. +- Diagnostics. All user-facing diagnostics must be human-written. +- Docs. All public doc-comments, and all `SAFETY` comments, must be human-written. + +### Guidelines + +Point people to [#llm-mentoring] liberally. +Deal with low-quality PRs by closing the PR and asking the author to follow the policy. +Deal with borderline PRs by asking the author to put in the work themselves rather than offloading it to you. +For example, ask them to reproduce the bug, explain the change in their own +words, identify relevant edge cases, or add or justify tests. + +If you find yourself suggesting the same fixes on multiple PRs, +consider adding them to the dev-guide. + +#### Missing disclosure + +If you see a PR that is "obviously" LLM-created without disclosing that use, you have the option—but not the responsibility—to close it unilaterally. + +We suggest using the following wording: + +> This PR appears to be LLM-generated without disclosing use of an LLM, +> so I am going to close this PR. +> You are welcome to open additional PRs as long as they follow our [policy][forge-page]. +> For more information, see [#llm-mentoring] on Zulip. + +Examples of "obvious" LLM tells are: +- PR descriptions that are completely wrong/don't match the code. +- PR descriptions that state the exact tests that were run (e.g. `./x test --stage 1 tests/ui/.rs`) or useless tests such as `git diff --check`. +- Responses to reviewer questions that fall into one of the above categories. + +You do not have an obligation to detect LLM-created PRs; +you don't need to play detective. + +PR templates will have a "Did you use an LLM?" question so that this rarely comes up. +If the author deleted the question without answering it, you can close the PR, no questions asked. + +#### Missing solicited reviewer + +If the PR discloses use, but does not assign a reviewer following the [experiment guidelines], you can close it similarly: + +> You've opened an LLM-generated PR, but it's in the normal review queue, which breaks our [policy][experiment guidelines]. +> I am going to close this PR. +> Please do not re-open it until you find a project member who has volunteered to review it. +> For more information, see [#llm-mentoring] on Zulip. + +#### Missing tests, low-quality, or not self-reviewed + +If a PR is clearly not ready for review, you do not have to review it. +It's ok to simply skim the PR and tell the author "you need to add tests before I can review this". +If you notice on your skim that the PR is clearly the wrong approach, it's ok to close the PR and tell the author to talk with you in the [#llm-mentoring] channel before opening a new PR. + +[experiment guidelines]: https://forge.rust-lang.org/policies/llm-usage.html#experiment-llm-created-code-changes-intended-for-review +[#llm-mentoring]: https://rust-lang.zulipchat.com/join/rlfvpemsaacs3pfi6kwqnqjb/ +[forge-page]: https://forge.rust-lang.org/policies/llm-usage.html diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md similarity index 59% rename from src/doc/rustc-dev-guide/src/llm-guidance.md rename to src/doc/rustc-dev-guide/src/llm-guidance/writing.md index d186df8779436..c4ed09bc65936 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -1,12 +1,4 @@ -# Working with LLMs - -This is a list of guidelines for working with LLMs, as well as a summary of the moderation policy. -This is not the policy itself; see [Forge][LLM policy]. -If the two conflict, Forge is canonical. - -[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html - -## Writing LLM-created code +# Writing LLM-created code LLMs are a valuable tool, but one that is easy to misuse. The main risks are **overwhelming volume** and **lack of understanding**. @@ -20,8 +12,9 @@ Keep in mind this quote: > — Harold Abelson and Gerald Jay Sussman, [*Structure and Interpretation of Computer Programs*][sicp] [sicp]: https://web.mit.edu/6.001/6.037/sicp.pdf +[#llm-mentoring]: https://rust-lang.zulipchat.com/join/rlfvpemsaacs3pfi6kwqnqjb/ -### Rules +## Rules Before anything else, find a reviewer who volunteers to review your PR. If you do not know where to find a reviewer, ask in [#llm-mentoring] on Zulip. @@ -45,9 +38,9 @@ LLM-created PR descriptions are banned. LLM-created Github comments are banned. We want to hear from you, not from your agent. -### Guidelines +## Guidelines -#### Before you write code +### Before you write code Start with one PR at a time. Keep your changes small enough that you and your reviewer can understand every part of them. @@ -65,7 +58,7 @@ For example: - Make the smallest change that fixes the problem. Do not combine it with unrelated refactors or cleanups. -#### While working +### While working When fixing a bug, verify that your test fails before and succeeds after your change. Consult [adding new tests](./tests/adding.md) and [best practices](./tests/best-practices.md) for test procedures. @@ -84,9 +77,9 @@ Verify your understanding against the existing code, documentation, and tests. You can get better advice from your LLM by telling *it* to read the relevant materials. Do not rely on the LLM as a source of truth. -[small atomic commits](https://github.blog/developer-skills/github/write-better-commits-build-better-projects/#%e2%9a%9b%ef%b8%8f-resize-and-stabilize-the-commits) +[small atomic commits]: https://github.blog/developer-skills/github/write-better-commits-build-better-projects/#%e2%9a%9b%ef%b8%8f-resize-and-stabilize-the-commits -#### Write maintainable code +### Write maintainable code Treat generated code as a *draft*, not a final product. @@ -104,7 +97,7 @@ It's ok to go into detail about non-obvious bugs. Preserve existing behavior. Consider platform differences and error cases. -#### Before opening a PR +### Before opening a PR Review your own PR before opening it: Does it make sense? Can you tell what the goal of the PR is? Does it achieve that goal? @@ -126,7 +119,7 @@ don't simply `--bless` them away. We recommend using a different model for adversarial local review before publishing your changes. You're still responsible for reviewing your own changes yourself. -#### Understand your own change +### Understand your own change We want you to understand and be able to explain your own change and its edge cases. Asking the LLM can be a starting point but it's not the same as explaining it yourself. @@ -148,7 +141,7 @@ We would much rather help you because you're not sure than have you guess wrong [`ast-grep`]: https://astgrep.com/ -#### Disclosure guidelines +### Disclosure guidelines Disclose the *extent* and *purpose* of your LLM use. We don't care which model you used, but we do care whether you used the LLM to implement the idea or to come up with it. @@ -167,80 +160,3 @@ We don't care which model you used, but we do care whether you used the LLM to i > 🤖 Generated with Claude Code > Co-Authored-By: Claude Opus 4.6 (1M context) - -## Automated checks and LLM review - -- If a more reliable tool, such as a linter or formatter, already exists for the language you're writing, we strongly suggest using that tool instead of or in addition to the LLM. -- Configure LLM review tools to reduce false positives and excessive focus on trivialities, as these are common, exhausting failure modes. -- Wherever possible, ask an LLM to *generate a linter*, which you then tell it to run. - This both saves on token costs, and allows people who are not using an LLM to run the analysis. -- LLMs sometimes prefer LLM-generated output, particularly output from the same - model. Treat LLM review as advisory, and do not rely on the model that - produced a change as its only reviewer. - -## Reviewing LLM-created code - -First, add the new `ai-assisted` label to the PR. - -### Rules - -We expect everyone to follow the new policy, not just authors. -That means it is **your responsibility** to check whether an `ai-assisted` PR touches an area that's disallowed by the policy. -You may request that the author redo it without LLM-generated code, in which case this section doesn't apply. - -The following areas are currently banned: -- Code that affects soundness. If the author is not an org member who is experienced in the domain, you are required to close the PR. -- Diagnostics. All user-facing diagnostics must be human-written. -- Docs. All public doc-comments, and all `SAFETY` comments, must be human-written. - -### Guidelines - -Point people to [#llm-mentoring] liberally. -Deal with low-quality PRs by closing the PR and asking the author to follow the policy. -Deal with borderline PRs by asking the author to put in the work themselves rather than offloading it to you. -For example, ask them to reproduce the bug, explain the change in their own -words, identify relevant edge cases, or add or justify tests. - -If you find yourself suggesting the same fixes on multiple PRs, -consider adding them to the dev-guide. - -#### Missing disclosure - -If you see a PR that is "obviously" LLM-created without disclosing that use, you have the option—but not the responsibility—to close it unilaterally. - -We suggest using the following wording: - -> This PR appears to be LLM-generated without disclosing use of an LLM, -> so I am going to close this PR. -> You are welcome to open additional PRs as long as they follow our [policy][forge-page]. -> For more information, see [#llm-mentoring] on Zulip. - -Examples of "obvious" LLM tells are: -- PR descriptions that are completely wrong/don't match the code. -- PR descriptions that state the exact tests that were run (e.g. `./x test --stage 1 tests/ui/.rs`) or useless tests such as `git diff --check`. -- Responses to reviewer questions that fall into one of the above categories. - -You do not have an obligation to detect LLM-created PRs; -you don't need to play detective. - -PR templates will have a "Did you use an LLM?" question so that this rarely comes up. -If the author deleted the question without answering it, you can close the PR, no questions asked. - -#### Missing solicited reviewer - -If the PR discloses use, but does not assign a reviewer following the [experiment guidelines], you can close it similarly: - -> You've opened an LLM-generated PR, but it's in the normal review queue, which breaks our [policy][experiment guidelines]. -> I am going to close this PR. -> Please do not re-open it until you find a project member who has volunteered to review it. -> For more information, see [#llm-mentoring] on Zulip. - -#### Missing tests, low-quality, or not self-reviewed - -If a PR is clearly not ready for review, you do not have to review it. -It's ok to simply skim the PR and tell the author "you need to add tests before I can review this". -If you notice on your skim that the PR is clearly the wrong approach, it's ok to close the PR and tell the author to talk with you in the [#llm-mentoring] channel before opening a new PR. - -[experiment guidelines]: https://forge.rust-lang.org/policies/llm-usage.html#experiment-llm-created-code-changes-intended-for-review -[#llm-mentoring]: https://rust-lang.zulipchat.com/join/rlfvpemsaacs3pfi6kwqnqjb/ -[forge-page]: https://forge.rust-lang.org/policies/llm-usage.html From 7cef419c671a6a89cfa17d580ed9f77983253c8f Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 11:57:35 +0200 Subject: [PATCH 12/57] be more clear about what i mean around linters --- src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md index 4feab70ec3dcc..7bb722195f37c 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md @@ -1,13 +1,20 @@ +# Reviewing with LLMs + ## Using an LLM to review code - If a more reliable tool, such as a linter or formatter, already exists for the language you're writing, we strongly suggest using that tool instead of or in addition to the LLM. - Configure LLM review tools to reduce false positives and excessive focus on trivialities, as these are common, exhausting failure modes. -- Wherever possible, ask an LLM to *generate a linter*, which you then tell it to run. +- Wherever possible, ask an LLM to *generate or configure a linter*, which you then tell it to run. This both saves on token costs, and allows people who are not using an LLM to run the analysis. + For example, if you have a codebase-specific wrapper around command spawning, + rather than getting an LLM to look for places where you should use the wrapper, + [configure clippy to disallow `Command::new`][disallowed-methods]. - LLMs sometimes prefer LLM-generated output, particularly output from the same model. Treat LLM review as advisory, and do not rely on the model that produced a change as its only reviewer. +[disallowed-methods]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods + ## Reviewing LLM-created code First, add the new `ai-assisted` label to the PR. From 49d14d6e73105eb67a5b159a72b4f9b46b9a24e0 Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 12:07:00 +0200 Subject: [PATCH 13/57] add more links --- src/doc/rustc-dev-guide/src/llm-guidance/writing.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index c4ed09bc65936..8366b5c79d08c 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -55,9 +55,11 @@ For example: - Search for related issues and PRs. - Find relevant code, tests, git history, and Zulip discussion. - If this is a cross-cutting change, consult the "cross-cutting" section of [the contributing docs](./contributing.md#pull-requests). -- Make the smallest change that fixes the problem. +- [Make the smallest change that fixes the problem][small-cls]. Do not combine it with unrelated refactors or cleanups. +[small-cls]: https://google.github.io/eng-practices/review/developer/small-cls.html + ### While working When fixing a bug, verify that your test fails before and succeeds after your change. @@ -91,9 +93,11 @@ trying to keep data in sync between two different places is a code smell. When practical, [make invalid states unrepresentable](https://kentcdodds.com/blog/make-impossible-states-impossible), [not just checked at construction time](https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/). -Write comments that say *why* you have done a thing, not *what* you have done. +[Write comments that say *why*][mit-comment-style] you have done a thing, not *what* you have done. It's ok to go into detail about non-obvious bugs. +[mit-comment-style]: https://mitcommlab.mit.edu/broad/commkit/coding-and-comment-style/ + Preserve existing behavior. Consider platform differences and error cases. From 4fb41b1ebbab56949fa1a1e01dc053b68305cdec Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 12:16:40 +0200 Subject: [PATCH 14/57] move correctness suggestions to a better chapter --- src/doc/rustc-dev-guide/src/conventions.md | 24 +++++++++++++++++++ .../src/llm-guidance/writing.md | 17 +------------ 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md index 0440fb0c5e736..f30921f35bc38 100644 --- a/src/doc/rustc-dev-guide/src/conventions.md +++ b/src/doc/rustc-dev-guide/src/conventions.md @@ -141,6 +141,30 @@ if foo { If you want to leave a note in the codebase, use `// FIXME` instead. +### Follow the style of surrounding code. + +Use existing helpers and avoid duplicating logic or validation. + +### Represent data in [one normalized place](https://react.dev/learn/choosing-the-state-structure) + +Trying to keep data in sync between two different places is a code smell. + +### Make invalid states unrepresentable + +When practical, [make invalid states unrepresentable](https://kentcdodds.com/blog/make-impossible-states-impossible), [not just checked at construction time](https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/). + +### Write useful comments + +[Write comments that say *why*][mit-comment-style] you have done a thing, not *what* you have done. +It's ok to go into detail about non-obvious bugs. + +[mit-comment-style]: https://mitcommlab.mit.edu/broad/commkit/coding-and-comment-style/ + +### Preserve existing behavior. + +Consider platform differences and error cases. +Look for relevant tests that exercise the edge cases. + ## Using crates from crates.io diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index 8366b5c79d08c..3a35896712bb8 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -84,22 +84,7 @@ Do not rely on the LLM as a source of truth. ### Write maintainable code Treat generated code as a *draft*, not a final product. - -Follow the style of surrounding code. -Use existing helpers and avoid duplicating logic or validation. - -Represent data in [one normalized place](https://react.dev/learn/choosing-the-state-structure); -trying to keep data in sync between two different places is a code smell. - -When practical, [make invalid states unrepresentable](https://kentcdodds.com/blog/make-impossible-states-impossible), [not just checked at construction time](https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/). - -[Write comments that say *why*][mit-comment-style] you have done a thing, not *what* you have done. -It's ok to go into detail about non-obvious bugs. - -[mit-comment-style]: https://mitcommlab.mit.edu/broad/commkit/coding-and-comment-style/ - -Preserve existing behavior. -Consider platform differences and error cases. +Follow the [correctness conventions](../conventions.md#cc). ### Before opening a PR From 6b52bdaaa3448458dc1b98e0ab7200a704671fa1 Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 12:23:16 +0200 Subject: [PATCH 15/57] address Sasha's review comments --- .../rustc-dev-guide/src/about-this-guide.md | 3 +- .../src/llm-guidance/reviewing.md | 42 +++++++++++++++---- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 57f6e676866d8..cc98ad7b2bf4c 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -72,7 +72,7 @@ You might also find the following sites useful: - [rustc API docs] -- rustdoc documentation for the compiler, devtools, and internal tools - [Forge] -- contains documentation about Rust infrastructure, team procedures, and more -- `rust-lang/rust`'s [LLM policy] +- [`rust-lang/rust`]'s [LLM policy] - [compiler-team] -- the home-base for the Rust compiler team, with description of the team procedures, active working groups, and the team calendar. - [std-dev-guide] -- a similar guide for developing the standard library. @@ -114,3 +114,4 @@ You might also find the following sites useful: [std-dev-guide]: https://std-dev-guide.rust-lang.org/ [rust-analyzer book]: https://rust-analyzer.github.io/book/ [z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler +[`rust-lang/rust`]: https://github.com/rust-lang/rust/ diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md index 7bb722195f37c..44ae4b9e6c2af 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md @@ -28,7 +28,22 @@ You may request that the author redo it without LLM-generated code, in which cas The following areas are currently banned: - Code that affects soundness. If the author is not an org member who is experienced in the domain, you are required to close the PR. - Diagnostics. All user-facing diagnostics must be human-written. -- Docs. All public doc-comments, and all `SAFETY` comments, must be human-written. +- Docs. All public doc-comments, and all `// SAFETY` comments, must be human-written. + +"Code that affects soundness" is both broader and narrower than it sounds. +It's broader because almost all of the compiler is relevant to soundness; +it's narrower because there's quite a lot of rust-lang/rust that isn't the compiler +(library, bootstrap, compiletest, rustdoc, CI, ...). + +If in doubt, we suggest this criteria: +Do not allow LLM-generated code for parts of the compiler where [wrong code does not look wrong][joel-wrong]. +Ultimately, this is up to your judgement as a reviewer. + +[joel-wrong]: https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/ + +You are still expected to respect your [r+ rights](../compiler-team.html#r-rights). +Please do not merge PRs unless you are confident in that part of that code, +even if the maintainer does not wish to review LLM PRs. ### Guidelines @@ -47,10 +62,14 @@ If you see a PR that is "obviously" LLM-created without disclosing that use, you We suggest using the following wording: -> This PR appears to be LLM-generated without disclosing use of an LLM, -> so I am going to close this PR. -> You are welcome to open additional PRs as long as they follow our [policy][forge-page]. -> For more information, see [#llm-mentoring] on Zulip. +```markdown +This PR appears to be LLM-generated without disclosing use of an LLM, so I am going to close this PR. +You are welcome to open additional PRs as long as they follow our [policy][forge-page]. +For more information, see [#llm-mentoring] on Zulip. + +[#llm-mentoring]: https://rust-lang.zulipchat.com/join/rlfvpemsaacs3pfi6kwqnqjb/ +[forge-page]: https://forge.rust-lang.org/policies/llm-usage.html +``` Examples of "obvious" LLM tells are: - PR descriptions that are completely wrong/don't match the code. @@ -67,10 +86,15 @@ If the author deleted the question without answering it, you can close the PR, n If the PR discloses use, but does not assign a reviewer following the [experiment guidelines], you can close it similarly: -> You've opened an LLM-generated PR, but it's in the normal review queue, which breaks our [policy][experiment guidelines]. -> I am going to close this PR. -> Please do not re-open it until you find a project member who has volunteered to review it. -> For more information, see [#llm-mentoring] on Zulip. +```markdown +You've opened an LLM-generated PR, but it's in the normal review queue, which breaks our [policy][experiment guidelines]. +I am going to close this PR. +Please do not re-open it until you find a project member who has volunteered to review it. +For more information, see [#llm-mentoring] on Zulip. + +[#llm-mentoring]: https://rust-lang.zulipchat.com/join/rlfvpemsaacs3pfi6kwqnqjb/ +[forge-page]: https://forge.rust-lang.org/policies/llm-usage.html +``` #### Missing tests, low-quality, or not self-reviewed From ff5a4a4829acb9567309f3b10658eef276a7e02d Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 12:38:23 +0200 Subject: [PATCH 16/57] fix links --- src/doc/rustc-dev-guide/src/llm-guidance/writing.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index 3a35896712bb8..4ea43ae008519 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -34,9 +34,9 @@ As before, you can use an LLM to review your work, but not to write it from scra If you don't know what counts as soundness-critical, discuss it with your reviewer. **Write your own PR description and comments**. +We want to hear from you, not from your agent. LLM-created PR descriptions are banned. LLM-created Github comments are banned. -We want to hear from you, not from your agent. ## Guidelines @@ -54,7 +54,7 @@ For example: - Search for related issues and PRs. - Find relevant code, tests, git history, and Zulip discussion. -- If this is a cross-cutting change, consult the "cross-cutting" section of [the contributing docs](./contributing.md#pull-requests). +- If this is a cross-cutting change, consult the "cross-cutting" section of [the contributing docs](../contributing.md#pull-requests). - [Make the smallest change that fixes the problem][small-cls]. Do not combine it with unrelated refactors or cleanups. @@ -63,7 +63,7 @@ For example: ### While working When fixing a bug, verify that your test fails before and succeeds after your change. -Consult [adding new tests](./tests/adding.md) and [best practices](./tests/best-practices.md) for test procedures. +Consult [adding new tests](../tests/adding.md) and [best practices](../tests/best-practices.md) for test procedures. Tests are absolutely required; either existing tests or new tests you write. Untested LLM PRs will not be merged. @@ -96,13 +96,13 @@ Remove outdated or prototyping code and debugging. Re-read the whole diff, *not* just your conversation with the agent. Your reviewer is going to see your code, not your conversation. -[Run tests](tests/running.md) to verify your change works. +[Run tests](../tests/running.md) to verify your change works. Do NOT report which UI tests you ran in the PR description; that's noise, since CI will run them anyway. If you did manual testing or benchmarking, do report that, but note that all LLM PRs must have automated tests. -[Review diagnostic snapshots](tests/adding.md#step-4-review-the-output); +[Review diagnostic snapshots](../tests/adding.md#step-4-review-the-output); don't simply `--bless` them away. We recommend using a different model for adversarial local review before publishing your changes. @@ -148,4 +148,4 @@ We don't care which model you used, but we do care whether you used the LLM to i > 🤖 Generated with Claude Code -> Co-Authored-By: Claude Opus 4.6 (1M context) +> `Co-Authored-By: Claude Opus 4.6 (1M context) ` From df4f543804601e3660bc4cc74eaadc379f139ee5 Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 12:47:39 +0200 Subject: [PATCH 17/57] tweaks --- src/doc/rustc-dev-guide/src/conventions.md | 17 ++++++++++++----- .../src/llm-guidance/writing.md | 19 ++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md index f30921f35bc38..023db80481e78 100644 --- a/src/doc/rustc-dev-guide/src/conventions.md +++ b/src/doc/rustc-dev-guide/src/conventions.md @@ -141,15 +141,15 @@ if foo { If you want to leave a note in the codebase, use `// FIXME` instead. -### Follow the style of surrounding code. +### Follow the style of surrounding code Use existing helpers and avoid duplicating logic or validation. -### Represent data in [one normalized place](https://react.dev/learn/choosing-the-state-structure) +### [Avoid duplicated sources of truth](https://react.dev/learn/choosing-the-state-structure) Trying to keep data in sync between two different places is a code smell. -### Make invalid states unrepresentable +### Use types to enforce invariants When practical, [make invalid states unrepresentable](https://kentcdodds.com/blog/make-impossible-states-impossible), [not just checked at construction time](https://lexi-lambda.github.io/blog/2020/11/01/names-are-not-type-safety/). @@ -160,11 +160,16 @@ It's ok to go into detail about non-obvious bugs. [mit-comment-style]: https://mitcommlab.mit.edu/broad/commkit/coding-and-comment-style/ -### Preserve existing behavior. +### Preserve existing behavior Consider platform differences and error cases. Look for relevant tests that exercise the edge cases. +### Work in small steps + +Work in small, independently testable steps. +Run the relevant tests after every meaningful change, so you know where you first went wrong. + ## Using crates from crates.io @@ -183,11 +188,13 @@ you rename a method, then put that rename into its own commit, along with the renames of all the uses. **More commits is usually better.** If you are doing a large change, -it's almost always better to break it up into smaller steps that can be independently understood. +it's almost always better to break it up into smaller steps that can be [independently understood][atomic commits]. The one thing to be aware of is that if you introduce some code following one strategy, then change it dramatically (versus adding to it) in a later commit, that 'back-and-forth' can be confusing. +[atomic commits]: https://github.blog/developer-skills/github/write-better-commits-build-better-projects/#%e2%9a%9b%ef%b8%8f-resize-and-stabilize-the-commits + **Format liberally.** While only the final commit of a PR must be correctly formatted, it is both easier to review and less noisy to format each commit individually using `./x fmt`. diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index 4ea43ae008519..c3115e602be0d 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -70,21 +70,26 @@ Untested LLM PRs will not be merged. Mass renames or rewrites should *strongly* prefer using a proper syntax rewrite tool, such as [`ast-grep`]. You may use an LLM for generating the instructions for that tool, but you should be very cautious about performing the rewrite directly with an LLM. -Work in small steps. -Run tests after every meaningful change, so you know where you first went wrong. -Do not write all your code at once; that will make it very hard to know what broke. -Ideally, commit your changes in [small atomic commits] as you go. +Consider [performance] as you write. + +[performance]: ../contributing.md#performance + +Think before adding dependencies; +consult our [guidance for new dependencies][crates-io]. + +[crates-io]: ../crates-io.md Verify your understanding against the existing code, documentation, and tests. You can get better advice from your LLM by telling *it* to read the relevant materials. Do not rely on the LLM as a source of truth. -[small atomic commits]: https://github.blog/developer-skills/github/write-better-commits-build-better-projects/#%e2%9a%9b%ef%b8%8f-resize-and-stabilize-the-commits - ### Write maintainable code Treat generated code as a *draft*, not a final product. -Follow the [correctness conventions](../conventions.md#cc). +Follow our [correctness and maintainability conventions](../conventions.md#cc). + +Avoid unnecessary abstractions and compatibility layers. +Rustc does not have a stable API; you do not need to preserve backwards compatibility for internal compiler APIs. ### Before opening a PR From beca161c45390f06345e61d96564ae1a4f3168cd Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 29 Jul 2026 12:54:54 +0200 Subject: [PATCH 18/57] headings --- .../rustc-dev-guide/src/llm-guidance/writing.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index c3115e602be0d..aaf37b030cf62 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -16,6 +16,8 @@ Keep in mind this quote: ## Rules +### Before you write code + Before anything else, find a reviewer who volunteers to review your PR. If you do not know where to find a reviewer, ask in [#llm-mentoring] on Zulip. Your first message should say: @@ -25,14 +27,21 @@ Your first message should say: - (optional) ideas you have so far for a solution - (optional) how you expect to test your solution -Disclose your use of LLMs, following the disclosure guidelines below. -Write the disclosure yourself. -You may use an LLM to privately review a disclosure you have written, but not to draft or rewrite it. +Mentors are here to help. +Talking to them early helps you avoid wasted work. + +### While working Write your own doc-comments, `// SAFETY` comments, diagnostic wording, and soundness-critical code. As before, you can use an LLM to review your work, but not to write it from scratch. If you don't know what counts as soundness-critical, discuss it with your reviewer. +### When opening a PR + +Disclose your use of LLMs, following the disclosure guidelines below. +Write the disclosure yourself. +You may use an LLM to privately review a disclosure you have written, but not to draft or rewrite it. + **Write your own PR description and comments**. We want to hear from you, not from your agent. LLM-created PR descriptions are banned. From a2d28afb2840a40664e87414a9fbcd755598638f Mon Sep 17 00:00:00 2001 From: jyn Date: Thu, 30 Jul 2026 23:43:40 +0200 Subject: [PATCH 19/57] don't treat model names as a good example of disclosure --- src/doc/rustc-dev-guide/src/llm-guidance/writing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index aaf37b030cf62..6719b5e786002 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -153,7 +153,7 @@ We don't care which model you used, but we do care whether you used the LLM to i > LLM disclosure: I wrote the three commits by hand after viewing profiling data. I used an LLM to review the commits before submitting. The LLM identified that `ImplString::is_negative` was no longer used, so I removed that field by hand. -> Created with the help of Claude Code, which: +> Created with the help of an LLM, which: > - traced the missing cache hits to the unconditional `return(pass)` by inspecting Fastly vs CloudFront headers, > - reviewed the git history to understand why the snippet was added, and > - made the VCL change. From daafdb59851981953989d2e44ba614510d125186 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 1 Aug 2026 17:42:49 -0700 Subject: [PATCH 20/57] Document `./x build --timings` --- .../src/building/bootstrapping/what-bootstrapping-does.md | 2 +- src/doc/rustc-dev-guide/src/profiling.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md index 0623d176403e4..011afa2de948c 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md @@ -372,7 +372,7 @@ Finally, `MAGIC_EXTRA_RUSTFLAGS` bypasses the - `RUSTDOCFLAGS`, `RUSTDOCFLAGS_BOOTSTRAP` and `RUSTDOCFLAGS_NOT_BOOTSTRAP` are analogous to `RUSTFLAGS`, but for `rustdoc`. -- `CARGOFLAGS` will pass arguments to cargo itself (e.g. `--timings`). +- `CARGOFLAGS` will pass arguments to cargo itself. `CARGOFLAGS_BOOTSTRAP` and `CARGOFLAGS_NOT_BOOTSTRAP` work analogously to `RUSTFLAGS_BOOTSTRAP`. - `--test-args` will pass arguments through to the test runner. For `tests/ui`, diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index 66eabe7d8c930..ed4e15e9c0851 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -19,7 +19,7 @@ Depending on what you're trying to measure, there are several different approach - If you want a nice visual representation of the compile times of your crate graph, you can use [cargo's `--timings` flag](https://doc.rust-lang.org/nightly/cargo/reference/timings.html), e.g. `cargo build --timings`. - You can use this flag on the compiler itself with `CARGOFLAGS="--timings" ./x build` + You can use this flag on the compiler itself with `./x build compiler --timings` - If you want to profile memory usage, you can use various tools depending on what operating system you are using. From fbaa0345dd6433b3503bbc548fe8ee5839c7e239 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 2 Aug 2026 12:43:20 +0200 Subject: [PATCH 21/57] document that commit messages must be human-authored --- src/doc/rustc-dev-guide/src/llm-guidance/writing.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index 6719b5e786002..6af83fd4246cb 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -100,6 +100,11 @@ Follow our [correctness and maintainability conventions](../conventions.md#cc). Avoid unnecessary abstractions and compatibility layers. Rustc does not have a stable API; you do not need to preserve backwards compatibility for internal compiler APIs. +### Commit structure + +See ["How to structure your PR"](../contributing.md#er). +Commit messages must be authored by you, not your LLM. + ### Before opening a PR Review your own PR before opening it: From 77a8b9f863422da6ae1c6c54774eec9240d4a7b9 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Wed, 5 Aug 2026 19:37:32 +0200 Subject: [PATCH 22/57] move index file up to make external links to ".../llm-guidance.html" work --- .../src/{llm-guidance/index.md => llm-guidance.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/doc/rustc-dev-guide/src/{llm-guidance/index.md => llm-guidance.md} (100%) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/index.md b/src/doc/rustc-dev-guide/src/llm-guidance.md similarity index 100% rename from src/doc/rustc-dev-guide/src/llm-guidance/index.md rename to src/doc/rustc-dev-guide/src/llm-guidance.md From 142707e1162b2dd0bf5837741b387962f49fb5c8 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Wed, 5 Aug 2026 19:45:37 +0200 Subject: [PATCH 23/57] Update relative links --- src/doc/rustc-dev-guide/src/SUMMARY.md | 2 +- src/doc/rustc-dev-guide/src/llm-guidance.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 32dc0051a9de1..09960ae453df1 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -52,7 +52,7 @@ - [About the compiler team](./compiler-team.md) - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.md) -- [Running LLMs](./llm-guidance/index.md) +- [Running LLMs](./llm-guidance.md) - [Writing code with LLMs](./llm-guidance/writing.md) - [Reviewing code with LLMs](./llm-guidance/reviewing.md) - [Walkthrough: a typical contribution](./walkthrough.md) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance.md b/src/doc/rustc-dev-guide/src/llm-guidance.md index 3709e7ead854c..c1b34362d2f47 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance.md @@ -4,7 +4,7 @@ This section is a list of guidelines for working with LLMs, as well as a summary This is not the policy itself; see [Forge][LLM policy]. If the two conflict, Forge is canonical. -If you are writing code using an LLM, see [Writing LLM-created code](./writing.md). -If you are reviewing LLM-created code, or reviewing using an LLM, see [Reviewing with LLMs](./reviewing.md). +If you are writing code using an LLM, see [Writing LLM-created code](llm-guidance/writing.md). +If you are reviewing LLM-created code, or reviewing using an LLM, see [Reviewing with LLMs](llm-guidance/reviewing.md). [LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html From a669f67baa9374bf5662941e6d05b2fe43b3dd5b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 6 Aug 2026 14:56:34 +0200 Subject: [PATCH 24/57] derive(Diagnostic): #[note] etc also work on bool fields --- .../rustc-dev-guide/src/diagnostics/diagnostic-structs.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index 9631ccc083243..6a450909eb8a4 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -135,12 +135,12 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { - `code = "..."` (_Optional_) - Specifies the error code. - `#[note("message")]` (_Optional_) - - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ + - _Applied to struct or struct fields of type `Span`, `Option<()>`, `bool`, or `()`._ - Adds a note subdiagnostic. - Value is the note's message. - If applied to a `Span` field, creates a spanned note. - `#[help("message")]` (_Optional_) - - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ + - _Applied to struct or struct fields of type `Span`, `Option<()>`, `bool`, or `()`._ - Adds a help subdiagnostic. - Value is the help message. - If applied to a `Span` field, creates a spanned help. @@ -149,7 +149,7 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { - Adds a label subdiagnostic. - Value is the label's message. - `#[warning("message")]` (_Optional_) - - _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._ + - _Applied to struct or struct fields of type `Span`, `Option<()>`, `bool`, or `()`._ - Adds a warning subdiagnostic. - Value is the warning's message. - `#[suggestion{,_hidden,_short,_verbose}("message", code = "...", applicability = "...")]` From 7ed549afe60527f0741a1f6a6d4ce250c21946e5 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 10 Aug 2026 04:40:01 +0000 Subject: [PATCH 25/57] Prepare for merging from rust-lang/rust This updates the rust-version file to 969b803cbe1d4499f841ae0a49c637d8c70a0458. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 1a74dff9d23d8..5e795b08df4a2 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -da86f4d0726be475afbbffe40cb2f65741c51ad3 +969b803cbe1d4499f841ae0a49c637d8c70a0458 From 25c1ae6c7652e04abdca92c739d2af315ff419c6 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Mon, 10 Aug 2026 08:13:56 -0700 Subject: [PATCH 26/57] stability.md: add missing brackets to `unstable_removed` attribute --- src/doc/rustc-dev-guide/src/stability.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index f80dc48cd4c28..3aebc860bc5c5 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -217,7 +217,7 @@ Currently, the items that can be annotated with `#[unstable_feature_bound]` are: ## renamed and removed features Unstable features can get renamed and removed. If you rename a feature, you can add `old_name = "old_name"` to the `#[unstable]` attribute. -If you remove a feature, the `#!unstable_removed(feature = "foo", reason = "brief description", link = "link", since = "1.90.0")` +If you remove a feature, the `#![unstable_removed(feature = "foo", reason = "brief description", link = "link", since = "1.90.0")]` attribute should be used to produce a good error message for users of the removed feature. The `link` field can be used to link to the most relevant information on the removal of the feature such as a GitHub issue, comment or PR. From 0ece90b62b45988cd01ce0a95e317ea2796304de Mon Sep 17 00:00:00 2001 From: Fallible <118682743+fallible-algebra@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:32:41 +0100 Subject: [PATCH 27/57] Add assumptions on binders shorthand to the glossary --- src/doc/rustc-dev-guide/src/appendix/glossary.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 527da87b7b7e1..486238c86fc71 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -6,6 +6,7 @@ Term | Meaning arena, arena allocation | An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info. AFIDT | Short for _async function in `dyn Trait`_. See also [AFIT](#afit). AFIT | Short for _async function in trait_. They desugar to [RPITITs](#rpitit). + Assbind | Short for ["Assumptions on Binders"](https://github.com/rust-lang/project-assumptions-on-binders) (See: [Zulip thread](https://rust-lang.zulipchat.com/#narrow/channel/260443-project-const-generics/topic/talkies.3F.20in.20this.20economy/near/615646513)). AST | The _abstract syntax tree_ (an [IR](#ir)) produced by the parser; reflects the surface / user syntax very closely. APIT | Short for _argument-position `impl Trait`_. Also known as universial `impl Trait` (as opposed to existential) or anonymous type parameter. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#anonymous-type-parameters)). ATPIT | Short for _associated-type-position `impl Trait`_. Also known as [ITIAT](#itiat). From 98cb632c2ea8f715458eb49cd367bd44765bc10e Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Tue, 11 Aug 2026 17:59:24 +0000 Subject: [PATCH 28/57] Prepare for merging from rust-lang/rust This updates the rust-version file to e64c8a664d9da54fc239cd4404cbf67f0d624326. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 5e795b08df4a2..6a21f4bf92e28 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -969b803cbe1d4499f841ae0a49c637d8c70a0458 +e64c8a664d9da54fc239cd4404cbf67f0d624326 From 9b06d77a4685ca554486457fbbe70aa75c9fbf93 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 11 Aug 2026 20:05:39 +0200 Subject: [PATCH 29/57] fix attribute links --- .../rustc-dev-guide/src/hir/attribute-parsing.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md b/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md index fd0ddc7210711..bc0240faec661 100644 --- a/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md +++ b/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md @@ -5,15 +5,15 @@ Inert attributes are parsed during AST lowering to the HIR, while active attribu For more information about the difference, see [the page about attributes][attributes_page]. During [AST lowering][lowering], inert attributes are converted from an unparsed `TokenStream` to a parsed representation. -The parsed form [is defined][hir_attrs] in the `rustc_hir` crate, and the parsers [are defined][attr_parsing] in the `rustc_attr_parsing` crate. +The parsed form is defined in the [`rustc_attr_ir`][attrs] crate, and the parsers are defined in the [`rustc_attr_parsing`][attr_parsing] crate. ## A step by step guide of adding a new inert attribute parser 1. Add the attribute name to the [BUILTIN_ATTRIBUTES]. This list defines the set of inert attributes. -2. Add a variant to `AttributeKind` in the [hir definition of attributes][hir_attrs]. +2. Add a variant to [`AttributeKind`] in the [definition of attributes][attrs]. This will define the parsed form of the attribute that the attribute parser will produce. -3. Add your variant to the match in `rustc_hir/attrs/encode_cross_crate.rs`, which should return whether your attribute should be visible in dependent crates. +3. Add your variant to the match in `rustc_attr_ir/encode_cross_crate.rs`, which should return whether your attribute should be visible in dependent crates. This is usually `No` for codegen related attributes, and `Yes` for analysis related attributes. 4. Create a new struct in `rustc_attr_parsing/attributes/*.rs` that will hold the state for your attribute parser. For most parsers, this will be an empty struct. @@ -57,9 +57,9 @@ This macro can be used in the following ways: * `find_attr!(tcx, , Variant(...))` to find an attribute on a def id. * `find_attr!(tcx, , Variant(...))` to find an attribute on a HIR id. * `find_attr!(tcx, crate, Variant(...))` to find an attribute on the current crate. -* `find_attr!(attrs, Variant(...))` to find an attribute in attrs, a `&[hir::Attribute]`. +* `find_attr!(attrs, Variant(...))` to find an attribute in attrs, a `&[rustc_attr_ir::Attribute]`. -`Variant` is a pattern matching one of the `AttributeKind` variants, and can take one of the following shapes: +`Variant` is a pattern matching one of the [`AttributeKind`] variants, and can take one of the following shapes: * `find_attr!(..., Variant)` will return a boolean representing whether the attribute is present. * `find_attr!(..., Variant(a, b, _) => (a, b))` will return the value after the `=>`, constructed from fields bound by the pattern. @@ -74,10 +74,11 @@ In other words, we expect attributes parsed with `parse_limited` to be reparsed [attributes_page]: ../attributes.md [lowering]: ./lowering.md -[hir_attrs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/attrs/index.html +[attrs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_ir/index.html [attr_parsing]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/ [attribute_parsers]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/context/static.ATTRIBUTE_PARSERS.html [builtin_attributes]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_feature/builtin_attrs/static.BUILTIN_ATTRIBUTES.html [template!]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/macro.template.html -[find_attr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/macro.find_attr.html +[find_attr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_ir/macro.find_attr.html [parse_limited]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/interface/struct.AttributeParser.html#method.parse_limited +[`AttributeKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_ir/enum.AttributeKind.html \ No newline at end of file From 761241c8eb07ed404c530aa2a5e89aa087bc799f Mon Sep 17 00:00:00 2001 From: Fallible <118682743+fallible-algebra@users.noreply.github.com> Date: Wed, 12 Aug 2026 13:41:45 +0100 Subject: [PATCH 30/57] Add preferred assumptions on binders shorthand to the glossary Removing the old one as it would otherwise be highly-visible and was already deprecated --- src/doc/rustc-dev-guide/src/appendix/glossary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index 486238c86fc71..0ddb65a2e2b20 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -3,10 +3,10 @@ Term | Meaning -----------------------------------------------|-------- 1-ZST | A *one-aligned [zero-sized type](#zst)*. A type of size zero with an [alignment][size-align] of one. +abby | Short for [_assumptions on binders_](https://github.com/rust-lang/project-assumptions-on-binders). Alternatively: `a-bi`, though this is very close to ABI. arena, arena allocation | An _arena_ is a large memory buffer from which other memory allocations are made. This style of allocation is called _arena allocation_. See [this chapter](../memory.md) for more info. AFIDT | Short for _async function in `dyn Trait`_. See also [AFIT](#afit). AFIT | Short for _async function in trait_. They desugar to [RPITITs](#rpitit). - Assbind | Short for ["Assumptions on Binders"](https://github.com/rust-lang/project-assumptions-on-binders) (See: [Zulip thread](https://rust-lang.zulipchat.com/#narrow/channel/260443-project-const-generics/topic/talkies.3F.20in.20this.20economy/near/615646513)). AST | The _abstract syntax tree_ (an [IR](#ir)) produced by the parser; reflects the surface / user syntax very closely. APIT | Short for _argument-position `impl Trait`_. Also known as universial `impl Trait` (as opposed to existential) or anonymous type parameter. ([see the reference](https://doc.rust-lang.org/reference/types/impl-trait.html#anonymous-type-parameters)). ATPIT | Short for _associated-type-position `impl Trait`_. Also known as [ITIAT](#itiat). From 5cdd04f8b63567da014a749cbb6c922fc5792a38 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Wed, 12 Aug 2026 22:11:48 +0200 Subject: [PATCH 31/57] Fix mentions of "`ai-assisted`" label in llm guidance docs The actual label we created is called `llm-assisted` now. --- src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md index 44ae4b9e6c2af..d78bdf60db1e3 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md @@ -17,12 +17,12 @@ ## Reviewing LLM-created code -First, add the new `ai-assisted` label to the PR. +First, add the new `llm-assisted` label to the PR. ### Rules We expect everyone to follow the new policy, not just authors. -That means it is **your responsibility** to check whether an `ai-assisted` PR touches an area that's disallowed by the policy. +That means it is **your responsibility** to check whether an `llm-assisted` PR touches an area that's disallowed by the policy. You may request that the author redo it without LLM-generated code, in which case this section doesn't apply. The following areas are currently banned: From adc30eb1ccf74a92d0460d48a7f46de2ffda4739 Mon Sep 17 00:00:00 2001 From: Alejandra Gonzalez Date: Thu, 23 Jul 2026 21:19:24 +0200 Subject: [PATCH 32/57] Add `feedable` query modifier --- .../src/queries/incremental-compilation-in-detail.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md index b6bac0fea3ef3..823090c24ade3 100644 --- a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md +++ b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md @@ -485,6 +485,12 @@ respect to incremental compilation: be cached to disk for "local" keys, because values for external crates should be loadable from crate metadata instead. + - `feedable` - The query is not actually a function, but its own arena type. This + is done to declare an arena, "feed" the information + to store at a later point in the compilation (for example, when we actually have a + `Crate` object available), and then retrieve it as any other crate. Thus, function + definitions for these queries do not exist. + [mod]: ../query.html#adding-a-new-kind-of-query @@ -553,4 +559,4 @@ See for more information. [query-model]: ./query-evaluation-model-in-detail.html -[try_mark_green]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/dep_graph/graph.rs.html +[try_mark_green]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/dep_graph/graph.rs.html \ No newline at end of file From 6a823d31d29994a994ee54124730d44610cd2dfe Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:34:51 +0200 Subject: [PATCH 33/57] sembr src/queries/incremental-compilation-in-detail.md --- .../src/queries/incremental-compilation-in-detail.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md index 823090c24ade3..71a48c3e377fc 100644 --- a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md +++ b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md @@ -485,11 +485,11 @@ respect to incremental compilation: be cached to disk for "local" keys, because values for external crates should be loadable from crate metadata instead. - - `feedable` - The query is not actually a function, but its own arena type. This - is done to declare an arena, "feed" the information + - `feedable` - The query is not actually a function, but its own arena type. + This is done to declare an arena, "feed" the information to store at a later point in the compilation (for example, when we actually have a - `Crate` object available), and then retrieve it as any other crate. Thus, function - definitions for these queries do not exist. + `Crate` object available), and then retrieve it as any other crate. + Thus, function definitions for these queries do not exist. [mod]: ../query.html#adding-a-new-kind-of-query @@ -559,4 +559,4 @@ See for more information. [query-model]: ./query-evaluation-model-in-detail.html -[try_mark_green]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/dep_graph/graph.rs.html \ No newline at end of file +[try_mark_green]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/dep_graph/graph.rs.html From fa6c1ba66dc4de0da7eb006d837065d085a26919 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:35:19 +0200 Subject: [PATCH 34/57] align --- .../src/queries/incremental-compilation-in-detail.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md index 71a48c3e377fc..28618cbb082a0 100644 --- a/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md +++ b/src/doc/rustc-dev-guide/src/queries/incremental-compilation-in-detail.md @@ -487,10 +487,10 @@ respect to incremental compilation: - `feedable` - The query is not actually a function, but its own arena type. This is done to declare an arena, "feed" the information - to store at a later point in the compilation (for example, when we actually have a - `Crate` object available), and then retrieve it as any other crate. - Thus, function definitions for these queries do not exist. - + to store at a later point in the compilation (for example, when we actually have a + `Crate` object available), and then retrieve it as any other crate. + Thus, function definitions for these queries do not exist. + [mod]: ../query.html#adding-a-new-kind-of-query From 66cf60318a721a4afdf1d8364bbc98874e847bbe Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:42:21 +0200 Subject: [PATCH 35/57] sembr src/llm-guidance/reviewing.md --- .../rustc-dev-guide/src/llm-guidance/reviewing.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md index d78bdf60db1e3..439b1d809e706 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/reviewing.md @@ -9,8 +9,8 @@ For example, if you have a codebase-specific wrapper around command spawning, rather than getting an LLM to look for places where you should use the wrapper, [configure clippy to disallow `Command::new`][disallowed-methods]. -- LLMs sometimes prefer LLM-generated output, particularly output from the same - model. Treat LLM review as advisory, and do not rely on the model that +- LLMs sometimes prefer LLM-generated output, particularly output from the same model. + Treat LLM review as advisory, and do not rely on the model that produced a change as its only reviewer. [disallowed-methods]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-methods @@ -26,9 +26,12 @@ That means it is **your responsibility** to check whether an `llm-assisted` PR t You may request that the author redo it without LLM-generated code, in which case this section doesn't apply. The following areas are currently banned: -- Code that affects soundness. If the author is not an org member who is experienced in the domain, you are required to close the PR. -- Diagnostics. All user-facing diagnostics must be human-written. -- Docs. All public doc-comments, and all `// SAFETY` comments, must be human-written. +- Code that affects soundness. + If the author is not an org member who is experienced in the domain, you are required to close the PR. +- Diagnostics. + All user-facing diagnostics must be human-written. +- Docs. + All public doc-comments, and all `// SAFETY` comments, must be human-written. "Code that affects soundness" is both broader and narrower than it sounds. It's broader because almost all of the compiler is relevant to soundness; From 3aba612b6b1ab8bd34b076e2dbbd62f9e3436d47 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:43:54 +0200 Subject: [PATCH 36/57] sembr src/llm-guidance/writing.md --- .../src/llm-guidance/writing.md | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md index 6af83fd4246cb..3cbdf3d2b849c 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -107,8 +107,9 @@ Commit messages must be authored by you, not your LLM. ### Before opening a PR -Review your own PR before opening it: -Does it make sense? Can you tell what the goal of the PR is? Does it achieve that goal? +Review your own PR before opening it: Does it make sense? +Can you tell what the goal of the PR is? +Does it achieve that goal? Remove outdated or prototyping code and debugging. @@ -135,12 +136,19 @@ Asking the LLM can be a starting point but it's not the same as explaining it yo Try explaining your change to yourself before opening the PR. For example, ask yourself: -- What is the original bug? When does it happen? How severe is it? What causes it? -- Why is this the right fix? Are there other fixes possible? What are their advantages or disadvantages? -- Are there any edge cases? Does your code handle them? +- What is the original bug? + When does it happen? + How severe is it? + What causes it? +- Why is this the right fix? + Are there other fixes possible? + What are their advantages or disadvantages? +- Are there any edge cases? + Does your code handle them? - Does the code have existing [invariants](https://brooker.co.za/blog/2023/07/28/ds-testing.html)? Did you preserve those invariants? -- What behavior is *unchanged*? What test establishes that? +- What behavior is *unchanged*? + What test establishes that? - Why does your test trigger the bug? - What are you still not certain about? From b011266b95d5dd5bce22b5114b7b1afe2a808799 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:44:45 +0200 Subject: [PATCH 37/57] sembr src/opaque-types-type-alias-impl-trait.md --- .../src/opaque-types-type-alias-impl-trait.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md b/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md index 9f20bfc708dce..239f30843ee67 100644 --- a/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md +++ b/src/doc/rustc-dev-guide/src/opaque-types-type-alias-impl-trait.md @@ -10,8 +10,8 @@ This is expressed by using `impl Trait` within type aliases, for example: type Foo = impl Bar; ``` -This declares an opaque type named `Foo`, of which the only information is that -it implements `Bar`. Therefore, any of `Bar`'s interface can be used on a `Foo`, +This declares an opaque type named `Foo`, of which the only information is that it implements `Bar`. +Therefore, any of `Bar`'s interface can be used on a `Foo`, but nothing else (regardless of whether the concrete type implements any other traits). Since there needs to be a concrete background type, @@ -53,12 +53,11 @@ fn foo() -> Foo { ## Defining use site(s) Currently only the return value of a function can be a defining use site -of an opaque type (and only if the return type of that function contains -the opaque type). +of an opaque type (and only if the return type of that function contains the opaque type). The defining use of an opaque type can be any code *within* the parent -of the opaque type definition. This includes any siblings of the -opaque type and all children of the siblings. +of the opaque type definition. +This includes any siblings of the opaque type and all children of the siblings. The initiative for *"not causing fatal brain damage to developers due to accidentally running infinite loops in their brain while trying to @@ -68,7 +67,8 @@ of opaque types to be defining use sites. ### Associated opaque types Associated opaque types can be defined by any other associated item -on the same trait `impl` or a child of these associated items. For instance: +on the same trait `impl` or a child of these associated items. +For instance: ```rust,ignore trait Baz { From c47f10a86512a281ff785d00c8111c5358ed2731 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:45:30 +0200 Subject: [PATCH 38/57] sembr src/hir/attribute-parsing.md --- src/doc/rustc-dev-guide/src/hir/attribute-parsing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md b/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md index bc0240faec661..fb544a680fa8f 100644 --- a/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md +++ b/src/doc/rustc-dev-guide/src/hir/attribute-parsing.md @@ -81,4 +81,4 @@ In other words, we expect attributes parsed with `parse_limited` to be reparsed [template!]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/macro.template.html [find_attr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_ir/macro.find_attr.html [parse_limited]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_parsing/interface/struct.AttributeParser.html#method.parse_limited -[`AttributeKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_ir/enum.AttributeKind.html \ No newline at end of file +[`AttributeKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_attr_ir/enum.AttributeKind.html From e8d39b87aeff31b0845ce83055e7c077d837e9fa Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:46:14 +0200 Subject: [PATCH 39/57] sembr src/diagnostics/error-guaranteed.md --- .../src/diagnostics/error-guaranteed.md | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md b/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md index d0ff775da80e6..950e36ef33178 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md @@ -1,32 +1,31 @@ # `ErrorGuaranteed` -The previous sections have been about the error message that a user of the -compiler sees. But emitting an error can also have a second important side -effect within the compiler source code: it generates an -[`ErrorGuaranteed`][errorguar]. +The previous sections have been about the error message that a user of the compiler sees. +But emitting an error can also have a second important side +effect within the compiler source code: it generates an [`ErrorGuaranteed`][errorguar]. `ErrorGuaranteed` is a zero-sized type that is unconstructable outside of the -[`rustc_errors`][rerrors] crate. It is generated whenever an error is reported +[`rustc_errors`][rerrors] crate. +It is generated whenever an error is reported to the user, so that if your compiler code ever encounters a value of type -`ErrorGuaranteed`, the compilation is _statically guaranteed to fail_. This is -useful for avoiding unsoundness bugs because you can statically check that an +`ErrorGuaranteed`, the compilation is _statically guaranteed to fail_. +This is useful for avoiding unsoundness bugs because you can statically check that an error code path leads to a failure. There are some important considerations about the usage of `ErrorGuaranteed`: -* It does _not_ convey information about the _kind_ of error. For example, the - error may be due (indirectly) to a delayed bug or other compiler error. +* It does _not_ convey information about the _kind_ of error. + For example, the error may be due (indirectly) to a delayed bug or other compiler error. Thus, you should not rely on - `ErrorGuaranteed` when deciding whether to emit an error, or what kind of error - to emit. + `ErrorGuaranteed` when deciding whether to emit an error, or what kind of error to emit. * `ErrorGuaranteed` should not be used to indicate that a compilation _will - emit_ an error in the future. It should be used to indicate that an error - _has already been_ emitted -- that is, the [`emit()`][emit] function has - already been called. For example, if we detect that a future part of the + emit_ an error in the future. + It should be used to indicate that an error + _has already been_ emitted -- that is, the [`emit()`][emit] function has already been called. + For example, if we detect that a future part of the compiler will error, we _cannot_ use `ErrorGuaranteed` unless we first emit an error or delayed bug ourselves. -Thankfully, in most cases, it should be statically impossible to abuse -`ErrorGuaranteed`. +Thankfully, in most cases, it should be statically impossible to abuse `ErrorGuaranteed`. [errorguar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.ErrorGuaranteed.html [rerrors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html From 8b93983071028fa8f3cd387e9653e91eb11fffa5 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:49:46 +0200 Subject: [PATCH 40/57] improve src/stability.md --- .../src/diagnostics/error-guaranteed.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md b/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md index 950e36ef33178..0e9fa1ca057ac 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/error-guaranteed.md @@ -1,10 +1,11 @@ # `ErrorGuaranteed` + The previous sections have been about the error message that a user of the compiler sees. But emitting an error can also have a second important side -effect within the compiler source code: it generates an [`ErrorGuaranteed`][errorguar]. +effect within the compiler source code: it generates an [`ErrorGuaranteed`]. `ErrorGuaranteed` is a zero-sized type that is unconstructable outside of the -[`rustc_errors`][rerrors] crate. +[`rustc_errors`] crate. It is generated whenever an error is reported to the user, so that if your compiler code ever encounters a value of type `ErrorGuaranteed`, the compilation is _statically guaranteed to fail_. @@ -21,12 +22,12 @@ There are some important considerations about the usage of `ErrorGuaranteed`: emit_ an error in the future. It should be used to indicate that an error _has already been_ emitted -- that is, the [`emit()`][emit] function has already been called. - For example, if we detect that a future part of the + For example, if we detect that a future part of the compiler will error, we _cannot_ use `ErrorGuaranteed` unless we first emit an error or delayed bug ourselves. Thankfully, in most cases, it should be statically impossible to abuse `ErrorGuaranteed`. -[errorguar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.ErrorGuaranteed.html -[rerrors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html +[`ErrorGuaranteed`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.ErrorGuaranteed.html +[`rustc_errors`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html [emit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/diagnostic/struct.Diag.html#method.emit From 6bf26fb840dd9fc6ec5543c77ee58a903bbc09d3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:50:29 +0200 Subject: [PATCH 41/57] sembr src/debuginfo/testing.md --- src/doc/rustc-dev-guide/src/debuginfo/testing.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/debuginfo/testing.md b/src/doc/rustc-dev-guide/src/debuginfo/testing.md index 7aec83aa97ac6..293a5d2a5cfbc 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/testing.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/testing.md @@ -1,7 +1,7 @@ # Testing -The debug info test suite is undergoing a substantial rewrite. This section will be filled out as -the rewrite makes progress. +The debug info test suite is undergoing a substantial rewrite. +This section will be filled out as the rewrite makes progress. Please see [this tracking issue][148483] for more information. From 24b66a7f94a34655ee1b792a8cda39c1b4ff71c4 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:50:58 +0200 Subject: [PATCH 42/57] sembr src/tests/stdlib-semver-check.md --- .../src/tests/stdlib-semver-check.md | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md b/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md index 60923d57cceef..7fbd531bf9b44 100644 --- a/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md +++ b/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md @@ -1,21 +1,32 @@ # Standard library semantic versioning breakage check -The `x86_64-gnu-stdlib-semver-check` job runs the [`cargo-semver-checks`][csc] (c-s-c) tool on the standard library (`core`, `alloc` and `std`) in order to find potential unintended semantic versioning (semver) breakages. It does so by analyzing the rustdoc JSON output (from the `rust-docs-json` component) of the parent merge commit, and the current commit being merged. When it runs, one of five things can happen: +The `x86_64-gnu-stdlib-semver-check` job runs the [`cargo-semver-checks`][csc] (c-s-c) tool on the standard library (`core`, `alloc` and `std`) in order to find potential unintended semantic versioning (semver) breakages. +It does so by analyzing the rustdoc JSON output (from the `rust-docs-json` component) of the parent merge commit, and the current commit being merged. +When it runs, one of five things can happen: 1. Everything proceeds correctly, c-s-c does not find any breakage. -2. The rustdoc JSON version was bumped recently, and c-s-c cannot handle it yet. This case will result in the test ending with a success, and printing a warning that c-s-c needs to be updated. Once c-s-c releases a version that supports the new JSON format, it should go to 1. again. +2. The rustdoc JSON version was bumped recently, and c-s-c cannot handle it yet. + This case will result in the test ending with a success, and printing a warning that c-s-c needs to be updated. + Once c-s-c releases a version that supports the new JSON format, it should go to 1. again. - We currently install the latest released version of c-s-c in this job, so its version does not need to be updated manually in the `rust-lang/rust` repository. -3. c-s-c detects a breakage, but it is a false positive. In this case, please report the false positive to [this][semver-topic] Zulip channel, and [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). -4. c-s-c detects a real breakage, and it helped you find unintended beakage. Yay! In this case, please consider reporting the success to [this][semver-topic] Zulip channel. -5. c-s-c detects a real breakage, but you want to land it anyway (maybe it is an edge case that was FCPed). In that case, [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). +3. c-s-c detects a breakage, but it is a false positive. + In this case, please report the false positive to [this][semver-topic] Zulip channel, and [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). +4. c-s-c detects a real breakage, and it helped you find unintended beakage. + Yay! + In this case, please consider reporting the success to [this][semver-topic] Zulip channel. +5. c-s-c detects a real breakage, but you want to land it anyway (maybe it is an edge case that was FCPed). + In that case, [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). ## Bumping the stdlib semver stamp file -If you want to let CI pass on a PR where c-s-c detects breakage (whether it is real or not), you have to modify the `src/bootstrap/stdlib-semver-check-stamp` file. Please update the PR number in which you modify this file at the bottom of the file. This will ensure that the test will stay green, regardless of what c-s-c detects. +If you want to let CI pass on a PR where c-s-c detects breakage (whether it is real or not), you have to modify the `src/bootstrap/stdlib-semver-check-stamp` file. +Please update the PR number in which you modify this file at the bottom of the file. +This will ensure that the test will stay green, regardless of what c-s-c detects. ## Running the check manually -You can manually run the semver check locally using `./x test std-semver-check --set rust.stdlib-semver-baseline=${PARENT}`, where `PARENT` is a commit SHA against which you want to compare the in-tree stdlib. If you do not specify it, bootstrap will select the latest upstream commit that it finds in your local git history. +You can manually run the semver check locally using `./x test std-semver-check --set rust.stdlib-semver-baseline=${PARENT}`, where `PARENT` is a commit SHA against which you want to compare the in-tree stdlib. +If you do not specify it, bootstrap will select the latest upstream commit that it finds in your local git history. [semver-topic]: https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/Breakages.20detected.20by.20cargo-semver-checks/with/615570111 [csc]: https://github.com/obi1kenobi/cargo-semver-checks From fd1d77ffeccfe3314905fc5293b7c2b66c293d01 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:56:04 +0200 Subject: [PATCH 43/57] improve tests/stdlib-semver-check.md --- src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md b/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md index 7fbd531bf9b44..b560568811d48 100644 --- a/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md +++ b/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md @@ -10,10 +10,10 @@ When it runs, one of five things can happen: Once c-s-c releases a version that supports the new JSON format, it should go to 1. again. - We currently install the latest released version of c-s-c in this job, so its version does not need to be updated manually in the `rust-lang/rust` repository. 3. c-s-c detects a breakage, but it is a false positive. - In this case, please report the false positive to [this][semver-topic] Zulip channel, and [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). + In this case, please report the false positive to [this Zulip topic][semver-topic], and [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). 4. c-s-c detects a real breakage, and it helped you find unintended beakage. Yay! - In this case, please consider reporting the success to [this][semver-topic] Zulip channel. + In this case, please consider reporting the success to [this Zulip topic][semver-topic]. 5. c-s-c detects a real breakage, but you want to land it anyway (maybe it is an edge case that was FCPed). In that case, [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). From c490377e3c13bcfb2eaf4034be04fb1f480ecac0 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:57:19 +0200 Subject: [PATCH 44/57] reflow --- .../src/tests/stdlib-semver-check.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md b/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md index b560568811d48..af1116f69e75b 100644 --- a/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md +++ b/src/doc/rustc-dev-guide/src/tests/stdlib-semver-check.md @@ -6,11 +6,14 @@ When it runs, one of five things can happen: 1. Everything proceeds correctly, c-s-c does not find any breakage. 2. The rustdoc JSON version was bumped recently, and c-s-c cannot handle it yet. - This case will result in the test ending with a success, and printing a warning that c-s-c needs to be updated. + This case will result in the test ending with a success, + and printing a warning that c-s-c needs to be updated. Once c-s-c releases a version that supports the new JSON format, it should go to 1. again. - - We currently install the latest released version of c-s-c in this job, so its version does not need to be updated manually in the `rust-lang/rust` repository. + - We currently install the latest released version of c-s-c in this job,r + so its version does not need to be updated manually in the `rust-lang/rust` repository. 3. c-s-c detects a breakage, but it is a false positive. - In this case, please report the false positive to [this Zulip topic][semver-topic], and [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). + In this case, please report the false positive to [this Zulip topic][semver-topic], +and [bump the stamp file](#bumping-the-stdlib-semver-stamp-file). 4. c-s-c detects a real breakage, and it helped you find unintended beakage. Yay! In this case, please consider reporting the success to [this Zulip topic][semver-topic]. @@ -19,14 +22,17 @@ When it runs, one of five things can happen: ## Bumping the stdlib semver stamp file -If you want to let CI pass on a PR where c-s-c detects breakage (whether it is real or not), you have to modify the `src/bootstrap/stdlib-semver-check-stamp` file. +If you want to let CI pass on a PR where c-s-c detects breakage (whether it is real or not), +you have to modify the `src/bootstrap/stdlib-semver-check-stamp` file. Please update the PR number in which you modify this file at the bottom of the file. This will ensure that the test will stay green, regardless of what c-s-c detects. ## Running the check manually -You can manually run the semver check locally using `./x test std-semver-check --set rust.stdlib-semver-baseline=${PARENT}`, where `PARENT` is a commit SHA against which you want to compare the in-tree stdlib. -If you do not specify it, bootstrap will select the latest upstream commit that it finds in your local git history. +You can manually run the semver check locally using `./x test std-semver-check --set rust.stdlib-semver-baseline=${PARENT}`, +where `PARENT` is a commit SHA against which you want to compare the in-tree stdlib. +If you do not specify it, +bootstrap will select the latest upstream commit that it finds in your local git history. [semver-topic]: https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/Breakages.20detected.20by.20cargo-semver-checks/with/615570111 [csc]: https://github.com/obi1kenobi/cargo-semver-checks From cda814cbcb341e1ade7c68e0bc2dbdded27fb5d2 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 11:58:11 +0200 Subject: [PATCH 45/57] sembr src/profile-guided-optimization.md --- .../src/profile-guided-optimization.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/profile-guided-optimization.md b/src/doc/rustc-dev-guide/src/profile-guided-optimization.md index f8a07813a10eb..191d612b45a60 100644 --- a/src/doc/rustc-dev-guide/src/profile-guided-optimization.md +++ b/src/doc/rustc-dev-guide/src/profile-guided-optimization.md @@ -1,8 +1,7 @@ # Profile-guided optimization `rustc` supports doing profile-guided optimization (PGO). -This chapter describes what PGO is and how the support for it is -implemented in `rustc`. +This chapter describes what PGO is and how the support for it is implemented in `rustc`. ## What is profiled-guided optimization? @@ -35,13 +34,13 @@ LLVM actually [supports multiple forms][clang-pgo] of PGO: itself during optimization passes. `rustc` supports only the last approach, IR-level instrumentation, mainly -because it is almost exclusively implemented in LLVM and needs little -maintenance on the Rust side. Fortunately, it is also the most modern approach, +because it is almost exclusively implemented in LLVM and needs little maintenance on the Rust side. +Fortunately, it is also the most modern approach, yielding the best results. So, we are dealing with an instrumentation-based approach, i.e. profiling data -is generated by a specially instrumented version of the program that's being -optimized. Instrumentation-based PGO has two components: a compile-time +is generated by a specially instrumented version of the program that's being optimized. +Instrumentation-based PGO has two components: a compile-time component and run-time component, and one needs to understand the overall workflow to see how they interact. @@ -89,8 +88,8 @@ runtime are not removed [by marking the with the right export level][pgo-gen-sym #### Compile binaries where optimizations make use of profiling data In the final step of the workflow described above, the program is compiled -again, with the compiler using the gathered profiling data in order to drive -optimization decisions. `rustc` again leaves most of the work to LLVM here, +again, with the compiler using the gathered profiling data in order to drive optimization decisions. +`rustc` again leaves most of the work to LLVM here, basically [just telling][pgo-use-passmanager] the LLVM `PassManagerBuilder` where the profiling data can be found: @@ -112,8 +111,7 @@ to generate profiling data, and collecting and persisting this profiling data needs some infrastructure in place. In the case of LLVM, these runtime components are implemented in -[compiler-rt][compiler-rt-profile] and statically linked into any instrumented -binaries. +[compiler-rt][compiler-rt-profile] and statically linked into any instrumented binaries. The `rustc` version of this can be found in `library/profiler_builtins` which basically packs the C code from `compiler-rt` into a Rust crate. From 28ff895a8ae84949f03c9f5cc758b03c6b9d9a54 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:11:33 +0200 Subject: [PATCH 46/57] improve profile-guided-optimization.md --- .../src/profile-guided-optimization.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/profile-guided-optimization.md b/src/doc/rustc-dev-guide/src/profile-guided-optimization.md index 191d612b45a60..52c197162993f 100644 --- a/src/doc/rustc-dev-guide/src/profile-guided-optimization.md +++ b/src/doc/rustc-dev-guide/src/profile-guided-optimization.md @@ -111,24 +111,24 @@ to generate profiling data, and collecting and persisting this profiling data needs some infrastructure in place. In the case of LLVM, these runtime components are implemented in -[compiler-rt][compiler-rt-profile] and statically linked into any instrumented binaries. +[compiler-rt] and statically linked into any instrumented binaries. The `rustc` version of this can be found in `library/profiler_builtins` which basically packs the C code from `compiler-rt` into a Rust crate. In order for `profiler_builtins` to be built, `profiler = true` must be set in `rustc`'s `bootstrap.toml`. -[compiler-rt-profile]: https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/profile +[compiler-rt]: https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/profile ## Testing PGO Since the PGO workflow spans multiple compiler invocations most testing happens -in [run-make tests][rmake-tests] (the relevant tests have `pgo` in their name). -There is also a [codegen test][codegen-test] that checks that some expected +in [run-make tests] (the relevant tests have `pgo` in their name). +There is also a [codegen test] that checks that some expected instrumentation artifacts show up in LLVM IR. -[rmake-tests]: https://github.com/rust-lang/rust/tree/HEAD/tests/run-make -[codegen-test]: https://github.com/rust-lang/rust/blob/HEAD/tests/codegen-llvm/pgo-instrumentation.rs +[run-make tests]: https://github.com/rust-lang/rust/tree/HEAD/tests/run-make +[codegen test]: https://github.com/rust-lang/rust/blob/HEAD/tests/codegen-llvm/pgo-instrumentation.rs ## Additional information From eee684e6e05d0978054a8233f7fe24a37aa35d71 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:12:42 +0200 Subject: [PATCH 47/57] sembr src/guides/editions.md --- .../rustc-dev-guide/src/guides/editions.md | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/guides/editions.md b/src/doc/rustc-dev-guide/src/guides/editions.md index 535d82f8403b4..435aa12339b99 100644 --- a/src/doc/rustc-dev-guide/src/guides/editions.md +++ b/src/doc/rustc-dev-guide/src/guides/editions.md @@ -23,8 +23,8 @@ supports comparisons for doing range checks, such as `span.edition() >= Edition: ### Adding a new edition Adding a new edition mainly involves adding a variant to the [`Edition`] enum and then fixing -everything that is broken. See [#94461](https://github.com/rust-lang/rust/pull/94461) for an -example. +everything that is broken. +See [#94461](https://github.com/rust-lang/rust/pull/94461) for an example. ### Features and Edition stability @@ -35,7 +35,8 @@ When adding a new feature, there are two options you can choose for how to handl future edition: - Just check the edition of the span like `span.at_least_rust_20xx()` (see [Edition hygiene]) or the - [`Session::edition`]. This will implicitly depend on the stability of the edition itself to + [`Session::edition`]. + This will implicitly depend on the stability of the edition itself to indicate that your feature is available. - Place your new behavior behind a [feature gate]. @@ -71,7 +72,8 @@ There are a few different options for doing feature checks: or just remove the feature check altogether and just check `span.at_least_rust_20xx()`. If you need to do the feature gating in multiple places, consider placing the check in a single -function so that there will only be a single place to update. For example: +function so that there will only be a single place to update. +For example: ```rust,ignore // An example from Edition 2021 disjoint closure captures. @@ -93,7 +95,8 @@ Within [`Lexer`], tokens can be modified based on edition-specific behavior. For example, C-String literals like `c"foo"` are split into multiple tokens in editions before 2021. This is also where things like reserved prefixes are handled for the 2021 edition. -Edition-specific parsing is relatively rare. One example is `async fn` which checks the span of the +Edition-specific parsing is relatively rare. +One example is `async fn` which checks the span of the token to determine if it is the 2015 edition, and emits an error in that case. This can only be done if the syntax was already invalid. @@ -190,7 +193,9 @@ When a user runs `cargo fix --edition`, cargo will pass the `--force-warn rust-2 flag to force all of these lints to appear during the edition migration. Cargo also passes `--cap-lints=allow` so that no other lints interfere with the edition migration. -Make sure that the example code sets the correct edition. The example should illustrate the previous edition, and show what the migration warning would look like. For example, this lint for a 2024 migration shows an example in 2021: +Make sure that the example code sets the correct edition. +The example should illustrate the previous edition, and show what the migration warning would look like. +For example, this lint for a 2024 migration shows an example in 2021: ```rust,ignore declare_lint! { @@ -245,14 +250,16 @@ afterwards. This should generally be used sparingly, as there are other options: - Small impact stylistic changes unrelated to an edition can just make the lint `Warn` on all - editions. If you want people to adopt a different way to write things, then go ahead and commit to + editions. + If you want people to adopt a different way to write things, then go ahead and commit to having it show up for all projects. Beware that if a new warn-by-default lint hits many projects, it can be very disruptive and frustrating for users. - Change the new style to be a hard error in the new edition, and use a [migration lint] to - automatically convert projects to the new style. For example, + automatically convert projects to the new style. + For example, [`ellipsis_inclusive_range_patterns`] is a hard error in 2021, and warns in all previous editions. Beware that these cannot be added after the edition stabilizes. @@ -354,11 +361,22 @@ In general it is recommended to avoid these special cases except for very high v Updating the edition of the standard library itself roughly involves the following process: - Wait until the newly stabilized edition has reached beta and the bootstrap compiler has been updated. -- Apply migration lints. This can be an involved process since some code is in external submodules[^std-submodules], and the standard library makes heavy use of conditional compilation. Also, running `cargo fix --edition` can be impractical on the standard library itself. One approach is to individually add `#![warn(...)]` at the top of each crate for each lint, run `./x check library`, apply the migrations, remove the `#![warn(...)]` and commit each migration separately. You'll likely need to run `./x check` with `--target` for many different targets to get full coverage (otherwise you'll likely spend days or weeks getting CI to pass)[^ed-docker]. See also the [advanced migration guide] for more tips. - - Apply migrations to [`backtrace-rs`]. [Example for 2024](https://github.com/rust-lang/backtrace-rs/pull/700). Note that this doesn't update the edition of the crate itself because that is published independently on crates.io, and that would otherwise restrict the minimum Rust version. Consider adding some `#![deny()]` attributes to avoid regressions until its edition gets updated. - - Apply migrations to [`stdarch`], and update its edition, and formatting. [Example for 2024](https://github.com/rust-lang/stdarch/pull/1710). +- Apply migration lints. + This can be an involved process since some code is in external submodules[^std-submodules], and the standard library makes heavy use of conditional compilation. + Also, running `cargo fix --edition` can be impractical on the standard library itself. + One approach is to individually add `#![warn(...)]` at the top of each crate for each lint, run `./x check library`, apply the migrations, remove the `#![warn(...)]` and commit each migration separately. + You'll likely need to run `./x check` with `--target` for many different targets to get full coverage (otherwise you'll likely spend days or weeks getting CI to pass)[^ed-docker]. + See also the [advanced migration guide] for more tips. + - Apply migrations to [`backtrace-rs`]. + [Example for 2024](https://github.com/rust-lang/backtrace-rs/pull/700). + Note that this doesn't update the edition of the crate itself because that is published independently on crates.io, and that would otherwise restrict the minimum Rust version. + Consider adding some `#![deny()]` attributes to avoid regressions until its edition gets updated. + - Apply migrations to [`stdarch`], and update its edition, and formatting. + [Example for 2024](https://github.com/rust-lang/stdarch/pull/1710). - Post PRs to update the backtrace and stdarch submodules, and wait for those to land. - - Apply migration lints to the standard library crates, and update their edition. I recommend working one crate at a time starting with `core`. [Example for 2024](https://github.com/rust-lang/rust/pull/138162). + - Apply migration lints to the standard library crates, and update their edition. + I recommend working one crate at a time starting with `core`. + [Example for 2024](https://github.com/rust-lang/rust/pull/138162). [^std-submodules]: This will hopefully change in the future to pull these submodules into `rust-lang/rust`. [^ed-docker]: You'll also likely need to do a lot of testing for different targets, and this is where [docker testing](../tests/docker.md) comes in handy. @@ -376,7 +394,8 @@ After the edition team has given the go-ahead, the process for stabilizing an ed - Hunt and find any document that refers to edition by number, and update it: - [`--edition` flag](https://github.com/rust-lang/rust/blob/HEAD/src/doc/rustc/src/command-line-arguments.md#--edition-specify-the-edition-to-use) - [Rustdoc attributes](https://github.com/rust-lang/rust/blob/HEAD/src/doc/rustdoc/src/write-documentation/documentation-tests.md#attributes) -- Clean up any tests that use the `//@ edition` header to remove the `-Zunstable-options` flag to ensure they are indeed stable. Note: Ideally this should be automated, see [#133582]. +- Clean up any tests that use the `//@ edition` header to remove the `-Zunstable-options` flag to ensure they are indeed stable. + Note: Ideally this should be automated, see [#133582]. - Bless any tests that change. - Update `lint-docs` to default to the new edition. From e8fe604d3f364dfc4281e8278f2a114df42021a6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:19:09 +0200 Subject: [PATCH 48/57] not a blog post --- src/doc/rustc-dev-guide/src/guides/editions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/guides/editions.md b/src/doc/rustc-dev-guide/src/guides/editions.md index 435aa12339b99..e5f8d38912a09 100644 --- a/src/doc/rustc-dev-guide/src/guides/editions.md +++ b/src/doc/rustc-dev-guide/src/guides/editions.md @@ -375,7 +375,7 @@ Updating the edition of the standard library itself roughly involves the followi [Example for 2024](https://github.com/rust-lang/stdarch/pull/1710). - Post PRs to update the backtrace and stdarch submodules, and wait for those to land. - Apply migration lints to the standard library crates, and update their edition. - I recommend working one crate at a time starting with `core`. + It is recommended to work one crate at a time, starting with `core`. [Example for 2024](https://github.com/rust-lang/rust/pull/138162). [^std-submodules]: This will hopefully change in the future to pull these submodules into `rust-lang/rust`. From 5d82d7ec74655fe768a90569aa27a069d0eb2173 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:20:21 +0200 Subject: [PATCH 49/57] sembr src/incrcomp-debugging.md --- .../rustc-dev-guide/src/incrcomp-debugging.md | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/incrcomp-debugging.md b/src/doc/rustc-dev-guide/src/incrcomp-debugging.md index 8207b81665aa7..35fb6d6846611 100644 --- a/src/doc/rustc-dev-guide/src/incrcomp-debugging.md +++ b/src/doc/rustc-dev-guide/src/incrcomp-debugging.md @@ -2,16 +2,16 @@ ## Testing the dependency graph -There are various ways to write tests against the dependency graph. The -simplest mechanisms are the `#[rustc_if_this_changed]` and -`#[rustc_then_this_would_need]` annotations. These are used in [ui] tests to test +There are various ways to write tests against the dependency graph. + The simplest mechanisms are the `#[rustc_if_this_changed]` and +`#[rustc_then_this_would_need]` annotations. +These are used in [ui] tests to test whether the expected set of paths exist in the dependency graph. [`tests/ui/dep-graph/dep-graph-caller-callee.rs`]: https://github.com/rust-lang/rust/blob/HEAD/tests/ui/dep-graph/dep-graph-caller-callee.rs [ui]: tests/ui.html -As an example, see [`tests/ui/dep-graph/dep-graph-caller-callee.rs`], or the -tests below. +As an example, see [`tests/ui/dep-graph/dep-graph-caller-callee.rs`], or the tests below. ```rust,ignore #[rustc_if_this_changed] @@ -45,15 +45,15 @@ code we test, but is meaningful from the point of view of the test itself. ### Dumping the graph -The compiler is also capable of dumping the dependency graph for your -debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The -graph will be dumped to `dep_graph.{txt,dot}` in the current -directory. You can override the filename with the `RUST_DEP_GRAPH` -environment variable. +The compiler is also capable of dumping the dependency graph for your debugging pleasure. +To do so, pass the `-Z dump-dep-graph` flag. +The graph will be dumped to `dep_graph.{txt,dot}` in the current +directory. + You can override the filename with the `RUST_DEP_GRAPH` environment variable. -Frequently, though, the full dep graph is quite overwhelming and not -particularly helpful. Therefore, the compiler also allows you to filter -the graph. You can filter in three ways: +Frequently, though, the full dep graph is quite overwhelming and not particularly helpful. +Therefore, the compiler also allows you to filter the graph. +You can filter in three ways: 1. All edges originating in a particular set of nodes (usually a single node). 2. All edges reaching a particular set of nodes. @@ -69,15 +69,15 @@ source_filter -> target_filter // nodes in between source_filter and target_filt ``` `source_filter` and `target_filter` are a `&`-separated list of strings. -A node is considered to match a filter if all of those strings appear in its -label. So, for example: +A node is considered to match a filter if all of those strings appear in its label. +So, for example: ```text RUST_DEP_GRAPH_FILTER='-> TypeckTables' ``` -would select the predecessors of all `TypeckTables` nodes. Usually though you -want the `TypeckTables` node for some particular fn, so you might write: +would select the predecessors of all `TypeckTables` nodes. +Usually though you want the `TypeckTables` node for some particular fn, so you might write: ```text RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar' @@ -87,36 +87,35 @@ This will select only the predecessors of `TypeckTables` nodes for functions with `bar` in their name. Perhaps you are finding that when you change `foo` you need to re-type-check -`bar`, but you don't think you should have to. In that case, you might do: +`bar`, but you don't think you should have to. +In that case, you might do: ```text RUST_DEP_GRAPH_FILTER='Hir & foo -> TypeckTables & bar' ``` This will dump out all the nodes that lead from `Hir(foo)` to -`TypeckTables(bar)`, from which you can (hopefully) see the source -of the erroneous edge. +`TypeckTables(bar)`, from which you can (hopefully) see the source of the erroneous edge. ### Tracking down incorrect edges Sometimes, after you dump the dependency graph, you will find some -path that should not exist, but you will not be quite sure how it came -to be. **When the compiler is built with debug assertions,** it can -help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE` -environment variable to a filter. Every edge created in the dep-graph +path that should not exist, but you will not be quite sure how it came to be. +**When the compiler is built with debug assertions,** it can help you track that down. +Simply set the `RUST_FORBID_DEP_GRAPH_EDGE` environment variable to a filter. +Every edge created in the dep-graph will be tested against that filter – if it matches, a `bug!` is reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`). -The syntax for these filters is the same as described in the previous -section. However, note that this filter is applied to every **edge** -and doesn't handle longer paths in the graph, unlike the previous -section. +The syntax for these filters is the same as described in the previous section. +However, note that this filter is applied to every **edge** +and doesn't handle longer paths in the graph, unlike the previous section. Example: You find that there is a path from the `Hir` of `foo` to the type -check of `bar` and you don't think there should be. You dump the -dep-graph as described in the previous section and open `dep-graph.txt` +check of `bar` and you don't think there should be. +You dump the dep-graph as described in the previous section and open `dep-graph.txt` to see something like: ```text @@ -124,6 +123,7 @@ Hir(foo) -> Collect(bar) Collect(bar) -> TypeckTables(bar) ``` -That first edge looks suspicious to you. So you set -`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and -then observe the backtrace. Voila, bug fixed! +That first edge looks suspicious to you. +So you set `RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and +then observe the backtrace. +Voila, bug fixed! From 5f249e400cd710607c1901e9c361be291f7e1a5a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:23:52 +0200 Subject: [PATCH 50/57] whitespace --- src/doc/rustc-dev-guide/src/incrcomp-debugging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/incrcomp-debugging.md b/src/doc/rustc-dev-guide/src/incrcomp-debugging.md index 35fb6d6846611..8b5b889bc6af3 100644 --- a/src/doc/rustc-dev-guide/src/incrcomp-debugging.md +++ b/src/doc/rustc-dev-guide/src/incrcomp-debugging.md @@ -49,7 +49,7 @@ The compiler is also capable of dumping the dependency graph for your debugging To do so, pass the `-Z dump-dep-graph` flag. The graph will be dumped to `dep_graph.{txt,dot}` in the current directory. - You can override the filename with the `RUST_DEP_GRAPH` environment variable. +You can override the filename with the `RUST_DEP_GRAPH` environment variable. Frequently, though, the full dep graph is quite overwhelming and not particularly helpful. Therefore, the compiler also allows you to filter the graph. From 84fb23fa0c2f5eb2a6f776c23c82ece238ea1f3a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:24:32 +0200 Subject: [PATCH 51/57] sembr src/memory.md --- src/doc/rustc-dev-guide/src/memory.md | 45 +++++++++++++++------------ 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md index 24e7205a3565b..ca79160064d3b 100644 --- a/src/doc/rustc-dev-guide/src/memory.md +++ b/src/doc/rustc-dev-guide/src/memory.md @@ -27,30 +27,33 @@ The [`CtxtInterners`] type contains a bunch of maps of interned types and the ar ### Example: `ty::TyKind` Taking the example of [`ty::TyKind`] which represents a type in the compiler (you -can read more [here](./ty.md)). Each time we want to construct a type, the -compiler doesn’t naively allocate from the buffer. Instead, we check if that -type was already constructed. If it was, we just get the same pointer we had -before, otherwise we make a fresh pointer. With this schema if we want to know -if two types are the same, all we need to do is compare the pointers which is -efficient. [`ty::TyKind`] should never be constructed on the stack, and it would be unusable -if done so. -You always allocate them from this arena and you always intern them so they are -unique. +can read more [here](./ty.md)). + Each time we want to construct a type, the compiler doesn’t naively allocate from the buffer. + Instead, we check if that type was already constructed. +If it was, we just get the same pointer we had before, otherwise we make a fresh pointer. +With this schema if we want to know +if two types are the same, all we need to do is compare the pointers which is efficient. +[`ty::TyKind`] should never be constructed on the stack, and it would be unusable if done so. +You always allocate them from this arena and you always intern them so they are unique. At the beginning of the compilation we make a buffer and each time we need to allocate a type we use -some of this memory buffer. If we run out of space we get another one. The lifetime of that buffer -is `'tcx`. Our types are tied to that lifetime, so when compilation finishes all the memory related +some of this memory buffer. +If we run out of space we get another one. +The lifetime of that buffer is `'tcx`. +Our types are tied to that lifetime, so when compilation finishes all the memory related to that buffer is freed and our `'tcx` references would be invalid. In addition to types, there are a number of other arena-allocated data structures that you can -allocate, and which are found in this module. Here are a few examples: +allocate, and which are found in this module. +Here are a few examples: - [`GenericArgs`], allocated with [`mk_args`] – this will intern a slice of types, often used to specify the values to be substituted for generics args (e.g. `HashMap` would be represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). - [`TraitRef`], typically passed by value – a **trait reference** consists of a reference to a trait along with its various type parameters (including `Self`), like `i32: Display` (here, the def-id - would reference the `Display` trait, and the args would contain `i32`). Note that `def-id` is + would reference the `Display` trait, and the args would contain `i32`). + Note that `def-id` is defined and discussed in depth in the [`AdtDef and DefId`][adtdefid] section. - [`Predicate`] defines something the trait system has to prove (see [traits] module). @@ -69,9 +72,9 @@ represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). ## The `tcx` and how it uses lifetimes -The typing context (`tcx`) is the central data structure in the compiler. It is the context that -you use to perform all manner of queries. The `struct` [`TyCtxt`] defines a reference to this shared -context: +The typing context (`tcx`) is the central data structure in the compiler. +It is the context that you use to perform all manner of queries. +The `struct` [`TyCtxt`] defines a reference to this shared context: ```rust,ignore tcx: TyCtxt<'tcx> @@ -80,7 +83,8 @@ tcx: TyCtxt<'tcx> // arena lifetime ``` -As you can see, the `TyCtxt` type takes a lifetime parameter. When you see a reference with a +As you can see, the `TyCtxt` type takes a lifetime parameter. +When you see a reference with a lifetime like `'tcx`, you know that it refers to arena-allocated data (or data that lives as long as the arenas, anyhow). @@ -91,14 +95,15 @@ the arenas, anyhow). The Rust compiler is a fairly large program containing lots of big data structures (e.g. the [Abstract Syntax Tree (AST)][ast], [High-Level Intermediate Representation (`HIR`)][hir], and the type system) and as such, arenas and -references are heavily relied upon to minimize unnecessary memory use. This +references are heavily relied upon to minimize unnecessary memory use. +This manifests itself in the way people can plug into the compiler (i.e. the [driver](./rustc-driver/intro.md)), preferring a "push"-style API (callbacks) instead of the more Rust-ic "pull" style (think the `Iterator` trait). Thread-local storage and interning are used a lot through the compiler to reduce -duplication while also preventing a lot of the ergonomic issues due to many -pervasive lifetimes. The [`rustc_middle::ty::tls`][tls] module is used to access these +duplication while also preventing a lot of the ergonomic issues due to many pervasive lifetimes. +The [`rustc_middle::ty::tls`][tls] module is used to access these thread-locals, although you should rarely need to touch it. [ast]: ./ast-validation.md From 0b6995a5fe7c5754a936957155880ecb054111cd Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:32:35 +0200 Subject: [PATCH 52/57] improve memory.md --- src/doc/rustc-dev-guide/src/memory.md | 31 ++++++++++++--------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/memory.md b/src/doc/rustc-dev-guide/src/memory.md index ca79160064d3b..6056f09ab2593 100644 --- a/src/doc/rustc-dev-guide/src/memory.md +++ b/src/doc/rustc-dev-guide/src/memory.md @@ -28,20 +28,20 @@ The [`CtxtInterners`] type contains a bunch of maps of interned types and the ar Taking the example of [`ty::TyKind`] which represents a type in the compiler (you can read more [here](./ty.md)). - Each time we want to construct a type, the compiler doesn’t naively allocate from the buffer. - Instead, we check if that type was already constructed. +Each time we want to construct a type, the compiler doesn’t naively allocate from the buffer. +Instead, we check if that type was already constructed. If it was, we just get the same pointer we had before, otherwise we make a fresh pointer. -With this schema if we want to know -if two types are the same, all we need to do is compare the pointers which is efficient. +With this schema, if we want to know if two types are the same, +all we need to do is compare the pointers, which is efficient. [`ty::TyKind`] should never be constructed on the stack, and it would be unusable if done so. You always allocate them from this arena and you always intern them so they are unique. At the beginning of the compilation we make a buffer and each time we need to allocate a type we use some of this memory buffer. -If we run out of space we get another one. +If we run out of space, we get another one. The lifetime of that buffer is `'tcx`. -Our types are tied to that lifetime, so when compilation finishes all the memory related -to that buffer is freed and our `'tcx` references would be invalid. +Our types are tied to that lifetime, so when compilation finishes, +all the memory related to that buffer is freed, and our `'tcx` references would be invalid. In addition to types, there are a number of other arena-allocated data structures that you can allocate, and which are found in this module. @@ -53,18 +53,16 @@ represented as a slice `&'tcx [tcx.types.i32, tcx.types.u32]`). - [`TraitRef`], typically passed by value – a **trait reference** consists of a reference to a trait along with its various type parameters (including `Self`), like `i32: Display` (here, the def-id would reference the `Display` trait, and the args would contain `i32`). - Note that `def-id` is - defined and discussed in depth in the [`AdtDef and DefId`][adtdefid] section. + Note that `def-id` is defined and discussed in depth in the [`AdtDef and DefId`] section. - [`Predicate`] defines something the trait system has to prove (see [traits] module). [`GenericArgs`]: ./ty-module/generic-arguments.md#the-genericargs-type -[adtdefid]: ./ty-module/generic-arguments.md#adtdef-and-defid [`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html [`AdtDef` and `DefId`]: ./ty.md#adts-representation [`def-id`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html [`GenericArgs`]: ./generic_arguments.html#GenericArgs [`mk_args`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.mk_args -[adtdefid]: ./ty-module/generic-arguments.md#adtdef-and-defid +[`AdtDef and DefId`]: ./ty-module/generic-arguments.md#adtdef-and-defid [`Predicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Predicate.html [`TraitRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html [`ty::TyKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.TyKind.html @@ -84,9 +82,8 @@ tcx: TyCtxt<'tcx> ``` As you can see, the `TyCtxt` type takes a lifetime parameter. -When you see a reference with a -lifetime like `'tcx`, you know that it refers to arena-allocated data (or data that lives as long as -the arenas, anyhow). +When you see a reference with a lifetime like `'tcx`, +you know that it refers to arena-allocated data (or data that lives as long as the arenas, anyhow). [`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html @@ -96,9 +93,9 @@ The Rust compiler is a fairly large program containing lots of big data structures (e.g. the [Abstract Syntax Tree (AST)][ast], [High-Level Intermediate Representation (`HIR`)][hir], and the type system) and as such, arenas and references are heavily relied upon to minimize unnecessary memory use. -This -manifests itself in the way people can plug into the compiler (i.e. the -[driver](./rustc-driver/intro.md)), preferring a "push"-style API (callbacks) instead +This manifests itself in the way people can plug into the compiler +(i.e. the [driver](./rustc-driver/intro.md)), +preferring a "push"-style API (callbacks) instead of the more Rust-ic "pull" style (think the `Iterator` trait). Thread-local storage and interning are used a lot through the compiler to reduce From ac129e99b031a04bf4e1cb4153ddfbf17de413b1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:34:20 +0200 Subject: [PATCH 53/57] sembr src/return-position-impl-trait-in-trait.md --- .../return-position-impl-trait-in-trait.md | 141 +++++++++--------- 1 file changed, 67 insertions(+), 74 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md index d87b97a8612cb..605a70cac90c0 100644 --- a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md +++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md @@ -7,8 +7,8 @@ GAT either on the trait side or impl side. RPITIT was originally implemented in [#101224], which added support for async fn in trait (AFIT), since the implementation for RPITIT came for -free as a part of implementing AFIT which had been RFC'd previously. It -was then RFC'd independently in [RFC 3425], which was recently approved +free as a part of implementing AFIT which had been RFC'd previously. +It was then RFC'd independently in [RFC 3425], which was recently approved by T-lang. ## How does it work? @@ -21,12 +21,13 @@ This doc is ordered mostly via the compilation pipeline: ### AST lowering -AST lowering for RPITITs is almost the same as lowering RPITs. We -still lower them as +AST lowering for RPITITs is almost the same as lowering RPITs. +We still lower them as [`hir::ItemKind::OpaqueTy`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html). The two differences are that: -We record `in_trait` for the opaque. This will signify that the opaque +We record `in_trait` for the opaque. +This will signify that the opaque is an RPITIT for HIR ty lowering, diagnostics that deal with HIR, etc. We record `lifetime_mapping`s for the opaque type, described below. @@ -34,11 +35,12 @@ We record `lifetime_mapping`s for the opaque type, described below. #### Aside: Opaque lifetime duplication *All opaques* (not just RPITITs) end up duplicating their captured -lifetimes into new lifetime parameters local to the opaque. The main -reason we do this is because RPITs need to be able to "reify"[^1] any -captured late-bound arguments, or make them into early-bound ones. This -is so they can be used as generic args for the opaque, and later to -instantiate hidden types. Since we don't know which lifetimes are early- +lifetimes into new lifetime parameters local to the opaque. +The main reason we do this is because RPITs need to be able to "reify"[^1] any +captured late-bound arguments, or make them into early-bound ones. +This is so they can be used as generic args for the opaque, and later to +instantiate hidden types. +Since we don't know which lifetimes are early- or late-bound during AST lowering, we just do this for all lifetimes. [^1]: This is compiler-errors terminology, I'm not claiming it's accurate :^) @@ -49,15 +51,13 @@ duplicated lifetimes in an additional field, [`OpaqueTy::lifetime_mapping`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.OpaqueTy.html#structfield.lifetime_mapping). We use this lifetime mapping later on in `clauses_of` to install bounds that enforce equality between these duplicated lifetimes and -their source lifetimes in order to properly typecheck these GATs, which -will be discussed below. +their source lifetimes in order to properly typecheck these GATs, which will be discussed below. ##### Note It may be better if we were able to lower without duplicates and for -that I think we would need to stop distinguishing between early and late -bound lifetimes. So we would need a solution like [Account for -late-bound lifetimes in generics +that I think we would need to stop distinguishing between early and late bound lifetimes. +So we would need a solution like [Account for late-bound lifetimes in generics #103448](https://github.com/rust-lang/rust/pull/103448) and then also a PR similar to [Inherit function lifetimes for impl-trait #103449](https://github.com/rust-lang/rust/pull/103449). @@ -66,12 +66,12 @@ PR similar to [Inherit function lifetimes for impl-trait The main change to HIR ty lowering is that we lower `hir::TyKind::OpaqueDef` for an RPITIT to a projection instead of an opaque, using a newly -synthesized def-id for a new associated type in the trait. We'll -describe how exactly we get this def-id in the next section. +synthesized def-id for a new associated type in the trait. +We'll describe how exactly we get this def-id in the next section. This means that any time we call `lower_ty` on the RPITIT, we end up -getting a projection back instead of an opaque. This projection can then -be normalized to the right value -- either the original opaque if we're +getting a projection back instead of an opaque. +This projection can then be normalized to the right value -- either the original opaque if we're in the trait, or the inferred type of the RPITIT if we're in an impl. #### Lowering to synthetic associated types @@ -84,18 +84,15 @@ trait side and impl side for RPITITs that show up in methods. When `tcx.associated_item_def_ids(trait_def_id)` is called on a trait to gather all of the trait's associated types, the query previously just returned the def-ids of the HIR items that are children of the trait. -After [#112988], additionally, for each method in the trait, we add the -def-ids returned by +After [#112988], additionally, for each method in the trait, we add the def-ids returned by `tcx.associated_types_for_impl_traits_in_associated_fn(trait_method_def_id)`, which walks through each trait method, gathers any RPITITs that show up -in the signature, and then calls -`associated_type_for_impl_trait_in_trait` for each RPITIT, which +in the signature, and then calls `associated_type_for_impl_trait_in_trait` for each RPITIT, which synthesizes a new associated type. ##### Lowering RPITITs in impls -Similarly, along with the impl's HIR items, for each impl method, we -additionally add all of the +Similarly, along with the impl's HIR items, for each impl method, we additionally add all of the `associated_types_for_impl_traits_in_associated_fn` for the impl method. This calls `associated_type_for_impl_trait_in_impl`, which will synthesize an associated type definition for each RPITIT that comes from @@ -107,11 +104,10 @@ We use query feeding ([`TyCtxtAt::create_def`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/query/plumbing/struct.TyCtxtAt.html#method.create_def)) to synthesize a new def-id for the synthetic GATs for each RPITIT. -Locally, most of rustc's queries match on the HIR of an item to compute -their values. Since the RPITIT doesn't really have HIR associated with +Locally, most of rustc's queries match on the HIR of an item to compute their values. +Since the RPITIT doesn't really have HIR associated with it, or at least not HIR that corresponds to an associated type, we must -compute many queries eagerly and -[feed](https://github.com/rust-lang/rust/pull/104940) them, like +compute many queries eagerly and [feed](https://github.com/rust-lang/rust/pull/104940) them, like `opt_def_kind`, `associated_item`, `visibility`, and`defaultness`. The values for most of these queries is obvious, since the RPITIT @@ -124,19 +120,18 @@ document the interesting ones of those below: ##### `generics_of` for the trait -The GAT for an RPITIT conceptually inherits the same generics as the -RPIT it comes from. However, instead of having the method as the -generics' parent, the trait is the parent. +The GAT for an RPITIT conceptually inherits the same generics as the RPIT it comes from. +However, instead of having the method as the generics' parent, the trait is the parent. Currently we get away with taking the RPIT's generics and method generics and flattening them both into a new generics list, preserving -the def-id of each of the parameters. (This may cause issues with -def-ids having the wrong parents, but in the worst case this will cause -diagnostics issues. If this ends up being an issue, we can synthesize +the def-id of each of the parameters. +(This may cause issues with def-ids having the wrong parents, but in the worst case this will cause +diagnostics issues. +If this ends up being an issue, we can synthesize new def-ids for generic params whose parent is the GAT.) -
- An illustrated example +
An illustrated example ```rust trait Foo { @@ -158,9 +153,10 @@ trait Foo { ##### `generics_of` for the impl -The generics for an impl's GAT are a bit more interesting. They are -composed of RPITIT's own generics (from the trait definition), appended -onto the impl's methods generics. This has the same issue as above, +The generics for an impl's GAT are a bit more interesting. +They are composed of RPITIT's own generics (from the trait definition), appended +onto the impl's methods generics. +This has the same issue as above, where the generics for the GAT have parameters whose def-ids have the wrong parent, but this should only cause issues in diagnostics. @@ -172,9 +168,8 @@ perhaps by a interested new contributor. Some queries rely on computing information that would result in cycles if we were to feed them eagerly, like `explicit_clauses_of`. -Therefore we defer to the `clauses_of` provider to return the right -value for our RPITIT's GAT. We do this by detecting early on in the -query if the associated type is synthetic by using +Therefore we defer to the `clauses_of` provider to return the right value for our RPITIT's GAT. +We do this by detecting early on in the query if the associated type is synthetic by using [`opt_rpitit_info`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.opt_rpitit_info), which returns `Some` if the associated type is synthetic. @@ -200,8 +195,8 @@ both on the trait and impl side. Additionally, we install "bidirectional outlives" predicates. Specifically, we add region-outlives clauses in both directions for each captured early-bound lifetime that constrains it to be equal to the -duplicated early-bound lifetime that results from lowering. This is best -illustrated in an example: +duplicated early-bound lifetime that results from lowering. +This is best illustrated in an example: ```rust trait Foo<'a> { @@ -226,8 +221,8 @@ trait Foo<'a> { ##### `assumed_wf_types` The GATs in both the trait and impl inherit the `assumed_wf_types` of -the trait method that defines the RPITIT. This is to make sure that the -following code is well formed when lowered. +the trait method that defines the RPITIT. +This is to make sure that the following code is well formed when lowered. ```rust trait Foo { @@ -247,8 +242,7 @@ trait FooDesugared { Because `assumed_wf_types` is only defined for local def ids, in order to properly implement `assumed_wf_types` for impls of foreign traits -with RPITs, we need to encode the assumed wf types of RPITITs in an -extern query +with RPITs, we need to encode the assumed wf types of RPITITs in an extern query [`assumed_wf_types_for_rpitit`](https://github.com/rust-lang/rust/blob/a17c7968b727d8413801961fc4e89869b6ab00d3/compiler/rustc_ty_utils/src/implied_bounds.rs#L14). ### Typechecking @@ -259,8 +253,8 @@ The RPITIT inference algorithm is implemented in [`collect_return_position_impl_trait_in_trait_tys`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/check/compare_impl_item/fn.collect_return_position_impl_trait_in_trait_tys.html). **High-level:** Given a impl method and a trait method, we take the -trait method and instantiate each RPITIT in the signature with an infer -var. We then equate this trait method signature with the impl method +trait method and instantiate each RPITIT in the signature with an infer var. +We then equate this trait method signature with the impl method signature, and process all obligations that fall out in order to infer the type of all of the RPITITs in the method. @@ -268,8 +262,7 @@ The method is also responsible for making sure that the hidden types for each RPITIT actually satisfy the bounds of the `impl Trait`, i.e. that if we infer `impl Trait = Foo`, that `Foo: Trait` holds. -
- An example... +
An example... ```rust #![feature(return_position_impl_trait_in_trait)] @@ -287,16 +280,16 @@ impl Foo for () { ``` We end up with the trait signature that looks like `fn() -> ?0`, and -nested obligations `?0: Deref`, `?1: Sized`. The impl -signature is `fn() -> Box`. +nested obligations `?0: Deref`, `?1: Sized`. +The impl signature is `fn() -> Box`. Equating these signatures gives us `?0 = Box`, which then after processing the obligation `Box: Deref` gives us `?1 = String`, and the other obligation `String: Sized` evaluates to true. By the end of the algorithm, we end up with a mapping between associated -type def-ids to concrete types inferred from the signature. We can then -use this mapping to implement `type_of` for the synthetic associated +type def-ids to concrete types inferred from the signature. +We can then use this mapping to implement `type_of` for the synthetic associated types in the impl, since this mapping describes the type that should come after the `=` in `type Assoc = ...` for each RPITIT.
@@ -305,17 +298,17 @@ come after the `=` in `type Assoc = ...` for each RPITIT. Since `collect_return_position_impl_trait_in_trait_tys` does fulfillment and region resolution, we must provide it `assumed_wf_types` so that we can prove -region obligations with the same expected implied bounds as -`compare_method_clause_entailment` does. +region obligations with the same expected implied bounds as `compare_method_clause_entailment` does. Since the return type of a method is understood to be one of the assumed WF types, and we eagerly fold the return type with inference variables to do opaque type inference, after opaque type inference, the return type will -resolve to contain the hidden types of the RPITITs. this would mean that the +resolve to contain the hidden types of the RPITITs. +this would mean that the hidden types of the RPITITs would be assumed to be well-formed without having -independently proven that they are. This resulted in a -[subtle unsoundness bug](https://github.com/rust-lang/rust/pull/116072). In -order to prevent this cyclic reasoning, we instead replace the hidden types of +independently proven that they are. +This resulted in a [subtle unsoundness bug](https://github.com/rust-lang/rust/pull/116072). +In order to prevent this cyclic reasoning, we instead replace the hidden types of the RPITITs in the return type of the method with *placeholders*, which lead to no implied well-formedness bounds. @@ -331,12 +324,13 @@ trait Foo { } ``` -requires one interesting hack. We need to install a projection predicate +requires one interesting hack. +We need to install a projection predicate into the param-env of `Foo::bar` allowing us to assume that the RPITIT's -GAT normalizes to the RPITIT's opaque type. This relies on the -observation that a trait method and RPITIT's GAT will always be "in -sync". That is, one will only ever be overridden if the other one is as -well. +GAT normalizes to the RPITIT's opaque type. +This relies on the observation that a trait method and RPITIT's GAT will always be "in +sync". +That is, one will only ever be overridden if the other one is as well. Compare this to a similar desugaring of the code above, which would fail because we cannot rely on this same assumption: @@ -355,8 +349,7 @@ trait Foo { ``` Failing because a down-stream impl could theoretically provide an -implementation for `RPITIT` without providing an implementation of -`bar`: +implementation for `RPITIT` without providing an implementation of `bar`: ```text error[E0308]: mismatched types @@ -390,8 +383,8 @@ WF-checking the GAT as if it were a regular GAT. The "default trait methods" described above does not interact well with specialization, because we only install those projection bounds in trait -default methods, and not in impl methods. Given that specialization is -already pretty busted, I won't go into detail, but it's currently a bug +default methods, and not in impl methods. +Given that specialization is already pretty busted, I won't go into detail, but it's currently a bug tracked in: * `tests/ui/impl-trait/in-trait/specialization-broken.rs` @@ -414,8 +407,8 @@ fn test<'a, 'b, T: Foo>() -> bool { ``` This is because we can't relate `::Rpitit<'a>` and `::Rpitit<'b>`, even if they don't capture their lifetime. If we were -using regular opaque types, this would work, because they would be +Foo>::Rpitit<'b>`, even if they don't capture their lifetime. +If we were using regular opaque types, this would work, because they would be bivariant in that lifetime parameter: ```rust #![feature(return_position_impl_trait_in_trait)] From b4f722c6c7853d84c61a347e40116bce89c1aa3a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 12:49:30 +0200 Subject: [PATCH 54/57] was 3 years ago --- .../rustc-dev-guide/src/return-position-impl-trait-in-trait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md index 605a70cac90c0..a256dbcd49eeb 100644 --- a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md +++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md @@ -8,7 +8,7 @@ GAT either on the trait side or impl side. RPITIT was originally implemented in [#101224], which added support for async fn in trait (AFIT), since the implementation for RPITIT came for free as a part of implementing AFIT which had been RFC'd previously. -It was then RFC'd independently in [RFC 3425], which was recently approved +It was then RFC'd independently in [RFC 3425], which was then approved by T-lang. ## How does it work? From 8f7fc506b5e2a1b9030e4e00045175a45614a86e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 13:11:14 +0200 Subject: [PATCH 55/57] reflow --- .../return-position-impl-trait-in-trait.md | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md index a256dbcd49eeb..39453d1358647 100644 --- a/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md +++ b/src/doc/rustc-dev-guide/src/return-position-impl-trait-in-trait.md @@ -27,8 +27,8 @@ We still lower them as The two differences are that: We record `in_trait` for the opaque. -This will signify that the opaque -is an RPITIT for HIR ty lowering, diagnostics that deal with HIR, etc. +This will signify that the opaque is an RPITIT for HIR ty lowering, +diagnostics that deal with HIR, etc. We record `lifetime_mapping`s for the opaque type, described below. @@ -40,8 +40,8 @@ The main reason we do this is because RPITs need to be able to "reify"[^1] any captured late-bound arguments, or make them into early-bound ones. This is so they can be used as generic args for the opaque, and later to instantiate hidden types. -Since we don't know which lifetimes are early- -or late-bound during AST lowering, we just do this for all lifetimes. +Since we don't know which lifetimes are early- or late-bound during AST lowering, +we just do this for all lifetimes. [^1]: This is compiler-errors terminology, I'm not claiming it's accurate :^) @@ -304,9 +304,8 @@ Since the return type of a method is understood to be one of the assumed WF types, and we eagerly fold the return type with inference variables to do opaque type inference, after opaque type inference, the return type will resolve to contain the hidden types of the RPITITs. -this would mean that the -hidden types of the RPITITs would be assumed to be well-formed without having -independently proven that they are. +This would mean that the hidden types of the RPITITs would be assumed to be well-formed +without having independently proven that they are. This resulted in a [subtle unsoundness bug](https://github.com/rust-lang/rust/pull/116072). In order to prevent this cyclic reasoning, we instead replace the hidden types of the RPITITs in the return type of the method with *placeholders*, which lead @@ -314,7 +313,7 @@ to no implied well-formedness bounds. #### Default trait body -Type-checking a default trait body, like: +Type-checking a default trait body like the following requires one interesting hack. ```rust trait Foo { @@ -324,12 +323,10 @@ trait Foo { } ``` -requires one interesting hack. We need to install a projection predicate into the param-env of `Foo::bar` allowing us to assume that the RPITIT's GAT normalizes to the RPITIT's opaque type. -This relies on the observation that a trait method and RPITIT's GAT will always be "in -sync". +This relies on the observation that a trait method and RPITIT's GAT will always be "in sync". That is, one will only ever be overridden if the other one is as well. Compare this to a similar desugaring of the code above, which would fail From 499d68c4d4034df2f8687d4479bb90b726d79151 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 13:11:52 +0200 Subject: [PATCH 56/57] sembr src/traits/implied-bounds.md --- .../src/traits/implied-bounds.md | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md index 732f6e81465b2..4fa64fdb99199 100644 --- a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md @@ -3,13 +3,15 @@ We currently add implied region bounds to avoid explicit annotations. e.g. `fn foo<'a, T>(x: &'a T)` can freely assume that `T: 'a` holds without specifying it. -There are two kinds of implied bounds: explicit and implicit. Explicit implied bounds +There are two kinds of implied bounds: explicit and implicit. +Explicit implied bounds get added to the `fn clauses_of` of the relevant item while implicit ones are handled... well... implicitly. ## explicit implied bounds -The explicit implied bounds are computed in [`fn inferred_outlives_of`]. Only ADTs and +The explicit implied bounds are computed in [`fn inferred_outlives_of`]. +Only ADTs and lazy type aliases have explicit implied bounds which are computed via a fixpoint algorithm in the [`fn inferred_outlives_crate`] query. @@ -18,12 +20,14 @@ This function computes the outlives bounds for each component of the field using separate implementation. For ADTs, trait objects, and associated types the initially required clauses are -computed in [`fn check_explicit_clauses`]. This simply uses `fn explicit_clauses_of` -without elaborating them. +computed in [`fn check_explicit_clauses`]. +This simply uses `fn explicit_clauses_of` without elaborating them. -Region clauses are added via [`fn insert_outlives_clause`]. This function takes +Region clauses are added via [`fn insert_outlives_clause`]. +This function takes an outlives clause, decomposes it and adds the components as explicit clauses only -if the outlived region is a region parameter. [It does not add `'static` requirements][nostatic]. +if the outlived region is a region parameter. +[It does not add `'static` requirements][nostatic]. [`fn inferred_outlives_of`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/mod.rs#L20 @@ -40,7 +44,8 @@ requirements of impls and functions as explicit predicates. ### using implicit implied bounds as assumptions -These bounds are not added to the `ParamEnv` of the affected item itself. For lexical +These bounds are not added to the `ParamEnv` of the affected item itself. +For lexical region resolution they are added using [`fn OutlivesEnvironment::from_normalized_bounds`]. Similarly, during MIR borrowck we add them using [`fn UniversalRegionRelationsBuilder::add_implied_bounds`]. @@ -50,8 +55,8 @@ Outside of MIR borrowck we add the outlives requirements for the types returned [`fn assumed_wf_types`] query. The assumed outlives constraints for implicit bounds are computed using the -[`fn implied_outlives_bounds`] query. This directly -[extracts the required outlives bounds from `fn wf::obligations`][boundsfromty]. +[`fn implied_outlives_bounds`] query. +This directly [extracts the required outlives bounds from `fn wf::obligations`][boundsfromty]. MIR borrowck adds the outlives constraints for both the normalized and unnormalized types, lexical region resolution [only uses the unnormalized types][notnorm]. @@ -67,11 +72,13 @@ lexical region resolution [only uses the unnormalized types][notnorm]. ### proving implicit implied bounds As the implicit implied bounds are not included in `fn clauses_of` we have to -separately make sure they actually hold. We generally handle this by checking that +separately make sure they actually hold. +We generally handle this by checking that all used types are well formed by emitting `WellFormed` predicates. We cannot emit `WellFormed` predicates when instantiating impls, as this would result -in - currently often inductive - trait solver cycles. We also do not emit constraints +in - currently often inductive - trait solver cycles. +We also do not emit constraints involving higher ranked regions as we're lacking the implied bounds from their binder. This results in multiple unsoundnesses: From 9ac8fe6cf9efd51241bdd58b80ed0b80e37eea64 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 13 Aug 2026 13:15:19 +0200 Subject: [PATCH 57/57] improve traits/implied-bounds.md --- .../src/traits/implied-bounds.md | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md index 4fa64fdb99199..3b4072394e787 100644 --- a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md @@ -4,16 +4,14 @@ We currently add implied region bounds to avoid explicit annotations. e.g. `fn foo<'a, T>(x: &'a T)` can freely assume that `T: 'a` holds without specifying it. There are two kinds of implied bounds: explicit and implicit. -Explicit implied bounds -get added to the `fn clauses_of` of the relevant item while implicit ones are -handled... well... implicitly. +Explicit implied bounds get added to the `fn clauses_of` of the relevant item, +while implicit ones are handled, well... implicitly. ## explicit implied bounds The explicit implied bounds are computed in [`fn inferred_outlives_of`]. -Only ADTs and -lazy type aliases have explicit implied bounds which are computed via a fixpoint algorithm -in the [`fn inferred_outlives_crate`] query. +Only ADTs and lazy type aliases have explicit implied bounds +which are computed via a fixpoint algorithm in the [`fn inferred_outlives_crate`] query. We use [`fn insert_required_clauses_to_be_wf`] on all fields of all ADTs in the crate. This function computes the outlives bounds for each component of the field using a @@ -24,8 +22,8 @@ computed in [`fn check_explicit_clauses`]. This simply uses `fn explicit_clauses_of` without elaborating them. Region clauses are added via [`fn insert_outlives_clause`]. -This function takes -an outlives clause, decomposes it and adds the components as explicit clauses only +This function takes an outlives clause, +decomposes it, and adds the components as explicit clauses only if the outlived region is a region parameter. [It does not add `'static` requirements][nostatic]. @@ -45,8 +43,8 @@ requirements of impls and functions as explicit predicates. ### using implicit implied bounds as assumptions These bounds are not added to the `ParamEnv` of the affected item itself. -For lexical -region resolution they are added using [`fn OutlivesEnvironment::from_normalized_bounds`]. +For lexical region resolution, +they are added using [`fn OutlivesEnvironment::from_normalized_bounds`]. Similarly, during MIR borrowck we add them using [`fn UniversalRegionRelationsBuilder::add_implied_bounds`]. @@ -74,12 +72,12 @@ lexical region resolution [only uses the unnormalized types][notnorm]. As the implicit implied bounds are not included in `fn clauses_of` we have to separately make sure they actually hold. We generally handle this by checking that -all used types are well formed by emitting `WellFormed` predicates. +all used types are well-formed by emitting `WellFormed` predicates. We cannot emit `WellFormed` predicates when instantiating impls, as this would result in - currently often inductive - trait solver cycles. -We also do not emit constraints -involving higher ranked regions as we're lacking the implied bounds from their binder. +We also do not emit constraints involving higher ranked regions +as we're lacking the implied bounds from their binder. This results in multiple unsoundnesses: - by using subtyping: [#25860]