diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index 804839b0f5c2e..5ff245b168b07 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: BASE_SHA: ${{ github.event.pull_request.base.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 with: # linkcheck needs the base commit. fetch-depth: 0 @@ -54,13 +54,19 @@ jobs: - name: Install Dependencies if: steps.mdbook-cache.outputs.cache-hit != 'true' run: | - cargo install mdbook --version ${{ env.MDBOOK_VERSION }} - cargo install mdbook-linkcheck2 --version ${{ env.MDBOOK_LINKCHECK2_VERSION }} - cargo install mdbook-mermaid --version ${{ env.MDBOOK_MERMAID_VERSION }} + cargo install --locked mdbook --version ${{ env.MDBOOK_VERSION }} + cargo install --locked mdbook-linkcheck2 --version ${{ env.MDBOOK_LINKCHECK2_VERSION }} + cargo install --locked mdbook-mermaid --version ${{ env.MDBOOK_MERMAID_VERSION }} - name: Check build run: ENABLE_LINKCHECK=1 mdbook build + - name: Check build with link checking disabled + run: | + output=$(mktemp) + mdbook build 2>&1 | tee "$output" + ! grep -F "Broken pipe" "$output" + - name: Save cached Linkcheck id: cache-linkcheck-save if: ${{ !cancelled() && github.event_name == 'schedule' }} diff --git a/src/doc/rustc-dev-guide/.github/workflows/date-check.yml b/src/doc/rustc-dev-guide/.github/workflows/date-check.yml index e26dec6ce25dd..fb7ff3bc04b11 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/date-check.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/date-check.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@v5 + uses: actions/checkout@v7 - name: Ensure Rust is up-to-date run: | diff --git a/src/doc/rustc-dev-guide/README.md b/src/doc/rustc-dev-guide/README.md index 59d6719c71cbd..86aba86ab8ed9 100644 --- a/src/doc/rustc-dev-guide/README.md +++ b/src/doc/rustc-dev-guide/README.md @@ -1,19 +1,18 @@ [![CI](https://github.com/rust-lang/rustc-dev-guide/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-lang/rustc-dev-guide/actions/workflows/ci.yml) +## About the `rustc-dev-guide` + This is a collaborative effort to build a guide that explains how rustc works. The aim of the guide is to help new contributors get oriented to rustc, as well as to help more experienced folks in figuring out some new part of the compiler that they haven't worked on before. -You may also find the [rustc API docs] useful. - -Note that these are not intended as a guide; it's recommended that you search -for the docs you're looking for instead of reading them top to bottom. +For more information, see [About This Guide](./src/about-this-guide.md). For documentation on developing the standard library, see [`std-dev-guide`](https://std-dev-guide.rust-lang.org/). -### Contributing to the guide +## Contributing to the guide The guide is useful today, but it has a lot of work still to go. @@ -24,35 +23,28 @@ Just post a comment on the issue you would like to work on to make sure that we accidentally duplicate work. If you think something is missing, please open an issue about it! -**In general, if you don't know how the compiler works, that is not a -problem!** In that case, what we will do is to schedule a bit of time -for you to talk with someone who **does** know the code, or who wants -to pair with you and figure it out. -Then you can work on writing up what you learned. - -In general, when writing about a particular part of the compiler's code, we -recommend that you link to the relevant parts of the [rustc API docs]. +See below for instructions on [writing new docs](#editing-the-guide). The guide has a much lower bar for what it takes for a PR to be merged. Check out the forge documentation for [our policy][forge_policy]. [forge_policy]: https://forge.rust-lang.org/rustc-dev-guide/index.html#review-policy -### Build Instructions +## Build Instructions To build a local static HTML site, install [`mdbook`](https://github.com/rust-lang/mdBook) with: ``` -cargo install mdbook mdbook-linkcheck2 mdbook-mermaid +cargo install --locked mdbook mdbook-linkcheck2 mdbook-mermaid ``` and execute the following command in the root of the repository: ``` -mdbook build --open +mdbook serve --open ``` -The build files are found in the `book/html` directory. +For a one-off build, you can use `mdbook build`. ### Link Validations @@ -65,11 +57,46 @@ following example. ENABLE_LINKCHECK=1 mdbook serve ``` -## Synchronizing josh subtree with rustc +## Editing the guide + +### Where to start + +**In general, if you don't know how the compiler works, that is not a +problem!** In that case, what we will do is to schedule a bit of time +for you to talk with someone who **does** know the code, or who wants +to pair with you and figure it out. +Then you can work on writing up what you learned. + +### Layout + +The dev-guide is organized as a normal [mdBook](https://rust-lang.github.io/mdBook/): +It has a `src/SUMMARY.md` table of contents, which links to individual pages under `src/`. +Configuration lives in `book.toml`. +Images are in `src/img`. +The build files are found in the `book/html` directory. + +**NOTE: if you do not add a page to SUMMARY.md, it will not be shown!** + +### While writing + +See the guide itself for instructions on [writing new docs]. + +[writing new docs]: src/contributing-to-guide.md + +## Maintaining the guide + +### CI + +Various tools are kept under `ci/`. +Check links with `mdbook-linkcheck2 --standalone`. +Check semantic line breaks with `cargo run --manifest-path ci/sembr/Cargo.toml src`. +Triage `` annotations with `cargo run --manifest-path ci/date-check/Cargo.toml .`. + +You can test those tools with `cargo test --manifest-path ci//Cargo.toml`. + +### Synchronizing josh subtree with rustc This repository is linked to `rust-lang/rust` as a [josh](https://josh-project.github.io/josh/intro.html) subtree. You can use the [rustc-josh-sync](https://github.com/rust-lang/josh-sync) tool to perform synchronization. You can find a guide on how to perform the synchronization [here](./src/external-repos.md#synchronizing-a-josh-subtree). - -[rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml index 1ded7aba10f96..a78cf231d00d3 100644 --- a/src/doc/rustc-dev-guide/book.toml +++ b/src/doc/rustc-dev-guide/book.toml @@ -96,3 +96,4 @@ warning-policy = "error" "/ty_module/instantiating_binders.html" = "/ty-module/instantiating-binders.html" "/ty_module/param_ty_const_regions.html" = "/ty-module/param-ty-const-regions.html" "/typing_parameter_envs.html" = "typing-parameter-envs.html" +"/walkthrough.html" = "walkthroughs/test.html" diff --git a/src/doc/rustc-dev-guide/ci/linkcheck.sh b/src/doc/rustc-dev-guide/ci/linkcheck.sh index 867b427eafbbe..ae0373f911fda 100755 --- a/src/doc/rustc-dev-guide/ci/linkcheck.sh +++ b/src/doc/rustc-dev-guide/ci/linkcheck.sh @@ -11,6 +11,9 @@ set_github_token() { if [ -z "$ENABLE_LINKCHECK" ] ; then echo "Skipping link check." + # mdBook writes the render context to extensions over stdin. + # Discard it so mdBook doesn't warn about a broken pipe. + cat > /dev/null exit 0 fi diff --git a/src/doc/rustc-dev-guide/ci/sembr/Cargo.lock b/src/doc/rustc-dev-guide/ci/sembr/Cargo.lock index 36a50dec5a70a..3436c860a7ab6 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/Cargo.lock +++ b/src/doc/rustc-dev-guide/ci/sembr/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -28,15 +28,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -63,25 +63,25 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "bstr" -version = "1.12.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" dependencies = [ "memchr", - "serde", + "serde_core", ] [[package]] name = "clap" -version = "4.5.51" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -89,9 +89,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.51" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ "heck", "proc-macro2", @@ -113,21 +113,21 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -135,24 +135,24 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "globset" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" dependencies = [ "aho-corasick", "bstr", @@ -169,9 +169,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "ignore" -version = "0.4.25" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f" dependencies = [ "crossbeam-deque", "globset", @@ -191,15 +191,15 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "log" -version = "0.4.28" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "once_cell_polyfill" @@ -209,27 +209,27 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -239,9 +239,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -250,9 +250,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "same-file" @@ -273,29 +273,20 @@ dependencies = [ "regex", ] -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", -] - [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", @@ -310,9 +301,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.110" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" dependencies = [ "proc-macro2", "quote", @@ -321,9 +312,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "utf8parse" diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 954c1536e32b0..83094681e9cc4 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -11,8 +11,8 @@ use regex::Regex; struct Cli { /// File or directory to check path: PathBuf, - #[arg(long)] /// Modify files that do not comply + #[arg(long)] overwrite: bool, /// Applies to lines that are to be split #[arg(long, default_value_t = 100)] @@ -40,22 +40,19 @@ fn main() -> Result<()> { continue; } let path = entry.into_path(); - if let Some(extension) = path.extension() { - if extension != "md" { - continue; - } - let old = fs::read_to_string(&path)?; - let new = comply(&old); - if new == old { - compliant.push(path.clone()); - } else { - if cli.overwrite { - fs::write(&path, lengthen_lines(&new, cli.line_length_limit))?; - made_compliant.push(path.clone()); - } else { - not_compliant.push(path.clone()); - } - } + let Some(extension) = path.extension() else { continue }; + if extension != "md" { + continue; + } + let old = fs::read_to_string(&path)?; + let new = comply(&old); + if new == old { + compliant.push(path.clone()); + } else if cli.overwrite { + fs::write(&path, lengthen_lines(&new, cli.line_length_limit))?; + made_compliant.push(path.clone()); + } else { + not_compliant.push(path.clone()); } } if !compliant.is_empty() { @@ -78,8 +75,8 @@ fn display(header: &str, paths: &[PathBuf]) { } } -fn ignore(line: &str, in_code_block: bool) -> bool { - in_code_block +fn ignore(line: &str) -> bool { + REGEX_IGNORE_LINK_TARGETS.is_match(line) || line.to_lowercase().contains("e.g.") || line.to_lowercase().contains("n.b.") || line.contains(" etc.") @@ -91,7 +88,6 @@ fn ignore(line: &str, in_code_block: bool) -> bool { || line.trim_start().starts_with('>') || line.starts_with('#') || line.trim().is_empty() - || REGEX_IGNORE_LINK_TARGETS.is_match(line) } fn comply(content: &str) -> String { @@ -107,7 +103,7 @@ fn comply(content: &str) -> String { in_code_block = !in_code_block; continue; } - if ignore(&line, in_code_block) { + if in_code_block || ignore(&line) { continue; } if REGEX_SPLIT.is_match(&line) { @@ -150,21 +146,24 @@ fn lengthen_lines(content: &str, limit: usize) -> String { in_code_block = !in_code_block; continue; } - if line.trim_start().starts_with("") { in_html_div = false; continue; } + if line.trim_start().starts_with("") { continue; } - if ignore(line, in_code_block) || REGEX_SPLIT.is_match(line) { + if ignore(line) || REGEX_SPLIT.is_match(line) { continue; } let Some(next_line) = content.get(n + 1) else { @@ -173,7 +172,7 @@ fn lengthen_lines(content: &str, limit: usize) -> String { if next_line.trim_start().starts_with("```") { continue; } - if ignore(next_line, in_code_block) + if ignore(next_line) || REGEX_LIST_ENTRY.is_match(next_line) || REGEX_IGNORE_END.is_match(line) { @@ -257,6 +256,7 @@ short sentences
a bit of text inside
+
preserve next line 1. one @@ -288,6 +288,7 @@ do not split short sentences
a bit of text inside
+
preserve next line 1. one @@ -322,3 +323,17 @@ fn should_pass() { let original = "if you see `input isn't interesting! verify interesting-ness test`."; assert_eq!(original, comply(original)); } + +#[test] +#[ignore] +fn split_on_comma() { + let original = " +Because of canonicalization of regions and +inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. +"; + let expected = " +Because of canonicalization of regions and inference variables, +encountering a cycle doesn't mean that we would get an infinite proof tree. +"; + assert_eq!(expected, lengthen_lines(original, 100)) +} diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 2f175e966812d..7b170626619e4 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -2c39ff499469be916d4e45506d1afed69bbaddb7 +da5114692c9ebe46b869488c5f34f92eb10b98c1 diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md index 920fad617943a..7c4ffe7b05a18 100644 --- a/src/doc/rustc-dev-guide/src/SUMMARY.md +++ b/src/doc/rustc-dev-guide/src/SUMMARY.md @@ -51,19 +51,22 @@ # Contributing to Rust - [Contribution procedures](./contributing.md) +- [PR lifecycle](./pr-lifecycle.md) +- [Writing rustc-dev-guide documentation](./contributing-to-guide.md) - [About the compiler team](./compiler-team.md) - [Using Git](./git.md) - [Mastering @rustbot](./rustbot.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) +- [Walkthrough: adding a new test](./walkthroughs/test.md) - [Implementing new language features](./implementing-new-features.md) - [Stability guarantees](./stability-guarantees.md) - [Stability attributes](./stability.md) - [Stabilizing language features](./stabilization-guide.md) - [Stabilization report template](./stabilization-report-template.md) - [Feature Gates](./feature-gates.md) +- [Walkthrough: a new language feature, from design to stabilization](./walkthroughs/lang-feature.md) - [Coding conventions](./conventions.md) - [Procedures for breaking changes](./bug-fix-procedure.md) - [Using external repositories](./external-repos.md) @@ -275,4 +278,6 @@ [Appendix E: Bibliography](./appendix/bibliography.md) +[Appendix F: Reading club sessions](./appendix/reading-club.md) + [Appendix Z: HumorRust](./appendix/humorust.md) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 651c8a539e265..8928bbaa44aad 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -5,6 +5,9 @@ This guide is meant to help document how rustc – the Rust compiler – works, as well as to help new contributors get involved in rustc development. +Note that this guide is intended as a reference; it's recommended that you search +for the docs you're looking for instead of reading them top to bottom. + There are several parts to this guide: 1. [Building and debugging `rustc`][p1]: @@ -32,7 +35,7 @@ There are several parts to this guide: There are a few of these with different information, including a glossary. [p1]: ./building/how-to-build-and-run.md -[p2]: ./contributing.md +[p2]: ./getting-started.md [p3]: ./building/bootstrapping/intro.md [p4]: ./part-2-intro.md [p5]: ./part-3-intro.md @@ -58,7 +61,7 @@ Even better, open a PR with a correction! If you do contribute to the guide, please see the corresponding [subsection on writing documentation in this guide]. -[subsection on writing documentation in this guide]: contributing.md#contributing-to-rustc-dev-guide +[subsection on writing documentation in this guide]: contributing-to-guide.md > “‘All conditioned things are impermanent’ — > when one sees this with wisdom, one turns away from suffering.” diff --git a/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md b/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md index 0bd4c6eb13398..6911b21544add 100644 --- a/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md +++ b/src/doc/rustc-dev-guide/src/appendix/compiler-lecture.md @@ -2,11 +2,29 @@ These are videos where various experts explain different parts of the compiler: -## General +## Compiler architecture +- [September 2022: Bootstrapping: The once and future compiler](https://www.youtube.com/watch?v=oUIjG-y4zaA) +- [November 2024: Rust compiler overview](https://www.youtube.com/watch?v=8E7I0EGRXo0) +- [June 2025: (Almost) everything you should know about the compiler frontend](https://www.youtube.com/watch?v=aFG5KtpEynk) +- [October 2025: Stable MIR: Fork the Rust compiler pipeline and go beyond](https://www.youtube.com/watch?v=lfi2pCOaGGk) +- [November 2025: How Rust compiles](https://www.youtube.com/watch?v=G1g6Me1FHmE) + +## Contributing and compiler tooling - [January 2019: Tom Tromey discusses debugging support in rustc](https://www.youtube.com/watch?v=elBxMRSNYr4) +- [May 2021: Peeking at compiler-internal data (for fun and profit)](https://www.youtube.com/watch?v=SKmd5A-1cSE) +- [September 2021: Hacking rustc: Contributing to the compiler](https://www.youtube.com/watch?v=9H9SO2u6Q20) +- [October 2022: Rustc Explore](https://www.youtube.com/playlist?list=PL85XCvVPmGQj3-MujOJ0jcoSqQ6Yi6Rkk) +- [September 2025: How doctests work](https://www.youtube.com/watch?v=NmgNi6kFXZI) +- [June 2026: Compilers are just programs: Fixing a bug in the Rust compiler](https://www.youtube.com/watch?v=osTwwllrgeA) +- [June 2026: Out-of-tree access to compiler state](https://www.youtube.com/watch?v=ExxxtADP-t8) + +## Performance and compiler testing - [June 2019: Responsive compilers - Nicholas Matsakis - PLISS 2019](https://www.youtube.com/watch?v=N6b44kMS6OM) - [June 2019: Things I Learned (TIL) - Nicholas Matsakis - PLISS 2019](https://www.youtube.com/watch?v=LIYkT3p5gTs) -- [October 2022: Rustc Explore](https://www.youtube.com/playlist?list=PL85XCvVPmGQj3-MujOJ0jcoSqQ6Yi6Rkk) +- [November 2024: The current state and future of Rust compiler performance](https://www.youtube.com/watch?v=Lye2xeJ3O5w) +- [March 2025: Rustlantis: Randomized differential testing of the Rust compiler](https://www.youtube.com/watch?v=0jqI8M1xzj4) +- [June 2026: Precise, consistent, and reliable code coverage](https://www.youtube.com/watch?v=P9lmSc4oLFs) +- [June 2026: Rethinking the incremental system in between compilation types](https://www.youtube.com/watch?v=aRwK5dbJy3Y) ## Rust Analyzer - [January 2019: How Salsa Works](https://www.youtube.com/watch?v=_muY4HjSqVw) @@ -22,6 +40,7 @@ These are videos where various experts explain different parts of the compiler: - [February 2019: Universes and Lifetimes](https://www.youtube.com/watch?v=iV1Z0xYXkck) - [April 2019: Representing types in rustc](https://www.youtube.com/watch?v=c01TsOsr3-c) - [March 2019: RFC #2229 Disjoint Field Capture plan](https://www.youtube.com/watch?v=UTXOptVMuIc) +- [December 2025: `-Znext-solver`: What, why, and when](https://www.youtube.com/watch?v=HUVjZyANCjM) ## Closures - [October 2018: closures and upvar capture](https://www.youtube.com/watch?v=fMopdkn5-Xw) @@ -37,9 +56,11 @@ These are videos where various experts explain different parts of the compiler: ## Polonius - [March 2019: Polonius-rustc walkthrough](https://www.youtube.com/watch?v=i5KdU0ieb_A) - [May 2019: Polonius WG: Initialization and move tracking](https://www.youtube.com/watch?v=ilv9V-328HI) +- [March 2025: The first six years in the development of Polonius](https://www.youtube.com/watch?v=ThvFHval7Gk) ## Miri - [March 2019: oli-obk on miri and constant evaluation](https://www.youtube.com/watch?v=5Pm2C1YXrvM) +- [June 2026: FFI in Miri at 8,000 segfaults per second](https://www.youtube.com/watch?v=9X-ngiKo_Y0) ## Async - [February 2019: async-await implementation plans](https://www.youtube.com/watch?v=xe2_whJWBC0) @@ -47,4 +68,5 @@ These are videos where various experts explain different parts of the compiler: ## Code Generation - [January 2019: Cranelift](https://www.youtube.com/watch?v=9OIA7DTFQWU) +- [December 2024: Rust unlinked: A journey through rustc, linkers, symbols, and static libraries](https://www.youtube.com/watch?v=I0JvqbRCI2U) - [December 2024: LLVM Developers' Meeting - Rust ❤️ LLVM](https://www.youtube.com/watch?v=Kqz-umsAnk8) diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md index e8f22bdf2fb15..18ddf069fd684 100644 --- a/src/doc/rustc-dev-guide/src/appendix/glossary.md +++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md @@ -18,6 +18,7 @@ Term | Meaning codegen unit | When we produce LLVM IR, we group the Rust code into a number of codegen units (sometimes abbreviated as CGUs). Each of these units is processed by LLVM independently from one another, enabling parallelism. They are also the unit of incremental re-use. ([see more](../backend/codegen.md)) completeness | A technical term in type theory, it means that every type-safe program also type-checks. Having both soundness and completeness is very hard, and usually soundness is more important. (see "soundness"). control-flow graph, CFG | A representation of the control-flow of a program; see [the background chapter for more](./background.md#cfg) +CTA | A _checked type alias_, a type alias that gets "properly" represented as an alias in the [middle ty IR](#middle-ty-ir); contrary to (unchecked) type aliases whose reference sites get expanded to the underlying aliased type (the RHS of the type alias after instantiation) during HIR ty lowering, its reference sites get [lowered](#lowering) to an [`AliasTy`]. CTFE | Short for _compile-time function evaluation_, this is the ability of the compiler to evaluate `const fn`s at compile time. This is part of the compiler's constant evaluation system. ([see more](../const-eval.md)) `cx` | We tend to use _cx_ as an abbreviation for _context_. See also `tcx`, `infcx`, etc. `ctxt` | We also use _ctxt_ as an abbreviation for _context_, e.g. [`TyCtxt`](#TyCtxt). See also [cx](#cx) or [tcx](#tcx). @@ -57,7 +58,7 @@ Term | Meaning late-bound lifetime | A lifetime / region that is substituted at its call site. Bound in a HRTB and substituted by specific functions in the compiler, such as `liberate_late_bound_regions`. Contrast with **early-bound lifetime**. ([see more](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/region_kind/enum.RegionKind.html#bound-regions)) local crate | The crate currently being compiled. This is in contrast to "upstream crates" which refer to dependencies of the local crate. lowering | The act of converting a higher-level [IR](#ir) to a lower-level one. E.g., AST lowering (from [AST](#ast) to [HIR](#hir)) or HIR ty lowering (from HIR to [middle ty IR](#middle-ty-ir)). -LTA | A _lazy type alias_, a type alias that gets "properly" represented as an alias in the [middle ty IR](#middle-ty-ir); contrary to (eager) type aliases whose reference sites get expanded to the underlying aliased type (the RHS of the type alias after instantiation) during HIR ty lowering, its reference sites get [lowered](#lowering) to an [`AliasTy`]. +LTA 👎 | Short for _lazy type alias_. **Renamed to [CTA](#cta)**. LTO | Short for *link-time optimizations*, this is a set of optimizations offered by LLVM that occur just before the final binary is linked. These include optimizations like removing functions that are never used in the final program, for example. _ThinLTO_ is a variant of LTO that aims to be a bit more scalable and efficient, but possibly sacrifices some optimizations. You may also read issues in the Rust repo about "FatLTO", which is the loving nickname given to non-Thin LTO. LLVM documentation: [here][lto] and [here][thinlto]. [LLVM] | (actually not an acronym :P) an open-source compiler backend. It accepts LLVM IR and outputs native binaries. Various languages (e.g. Rust) can then implement a compiler front-end that outputs LLVM IR and use LLVM to compile to all the platforms LLVM supports. memoization | The process of storing the results of (pure) computations (such as pure function calls) to avoid having to repeat them in the future. This is typically a trade-off between execution speed and memory usage. @@ -120,7 +121,7 @@ See also . [RFC 2515]: https://rust-lang.github.io/rfcs/2515-type_alias_impl_trait.html [RFC 3425]: https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html [TLS]: https://llvm.org/docs/LangRef.html#thread-local-storage-models -[`AliasTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.AliasTy.html +[`AliasTy`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/type.AliasTy.html [`Span`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html [`generic_const_items`]: https://github.com/rust-lang/rust/issues/113521 [`min_generic_const_items`]: https://github.com/rust-lang/rust/issues/132980 diff --git a/src/doc/rustc-dev-guide/src/appendix/reading-club.md b/src/doc/rustc-dev-guide/src/appendix/reading-club.md new file mode 100644 index 0000000000000..ec71ad21018b2 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/appendix/reading-club.md @@ -0,0 +1,29 @@ +# Reading club sessions + +The dev-guide is large, dense, and often written by subject-matter-experts. +Occasionally, maintainers and anyone else who's interested will read through existing chapters to try and understand them. +This appendex indexes those Zulip discussions. + +- [February 26, 2024: Compiler architecture, queries, bootstrap, serialization, and rustdoc][2024-02-26] +- [March 11, 2024: Bootstrap deep dive][2024-03-11] +- [April 8, 2024: Syntax and the AST, initial discussion][2024-04-08] +- [April 17, 2024: Syntax, the AST, parsing, expansion, and name resolution][2024-04-17] +- [May 2, 2024: HIR and THIR][2024-05-02] +- [May 29, 2024: MIR][2024-05-29] +- [November 20, 2024: Compiler identifiers, closure capture, inline assembly, and guide organization][2024-11-20] +- [December 4, 2024: Generic parameters and early- and late-bound parameters][2024-12-04] +- [March 19, 2025: Diagnostics and lints][2025-03-19] + +For plans and general discussion, see the +[reading club coordination topic][coordination]. + +[2024-02-26]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202023.2E02.2E26.20chapters.2022.20to.2030/near/423399948 +[2024-03-11]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202024.2E03.2E11.20bootstrap.20deep.20dive/near/425836705 +[2024-04-08]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202024.2E04.2E08.20chapters.2033.20to.2036.20.28AST.29/near/431960099 +[2024-04-17]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202024.2E04.2E17.20chapters.2033.20to.2036.20.28AST.29/near/433844859 +[2024-05-02]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202024.2E05.2E02.20chapter.2037.20.28HIR.29/near/436739663 +[2024-05-29]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202024.2E05.2E02.20chapter.2039.20.28MIR.29/near/441283239 +[2024-11-20]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202024.2E11.2E20.20chapter.2040.20to.2042/near/483537033 +[2024-12-04]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202024.2E12.2E04.20chapter.2042.20to.2043/near/486144956 +[2025-03-19]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/.5Breading.20club.5D.202025.2E03.2E19.20chapter.2043/near/506795838 +[coordination]: https://rust-lang.zulipchat.com/#narrow/channel/196385-t-compiler.2Fwg-rustc-dev-guide/topic/Rustc.20dev.20guide.20reading.20club diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 896fa20df26b1..4cd664b306ce0 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -71,7 +71,7 @@ use the `RUSTFLAGS` environment variable (e.g. `RUSTFLAGS='--emit=llvm-ir'`). This causes rustc to spit out LLVM IR into the target directory. `cargo llvm-ir [options] path` spits out the LLVM IR for a particular function at `path`. -(`cargo install cargo-asm` installs `cargo asm` and `cargo llvm-ir`). +(`cargo install --locked cargo-asm` installs `cargo asm` and `cargo llvm-ir`). `--build-type=debug` emits code for debug builds. There are also other useful options. Also, debug info in LLVM IR can clutter the output a lot: diff --git a/src/doc/rustc-dev-guide/src/borrow-check/type-check.md b/src/doc/rustc-dev-guide/src/borrow-check/type-check.md index 69456d870eaa9..2c1058a13881b 100644 --- a/src/doc/rustc-dev-guide/src/borrow-check/type-check.md +++ b/src/doc/rustc-dev-guide/src/borrow-check/type-check.md @@ -1,17 +1,35 @@ # The MIR type-check -A key component of the borrow check is the -[MIR type-check](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/type_check/index.html). -This check walks the MIR and does a complete "type check" -- the same -kind you might find in any other language. In the process of doing -this type-check, we also uncover the region constraints that apply to -the program. + -TODO -- elaborate further? Maybe? :) +"Canonical" type checking (ignoring lifetimes) for Rust happens in the HIR. +Despite this, we also do a [type checking pass in MIR][type_check]. + +The MIR is our fully-typed intermediate representation, the types of all items and the contents of their bodies are known by this point and by constructing the MIR we know its types are correct. +The reason to do a type checking pass on this already-typed, already-checked IR is to accumulate information about lifetimes[^lifetimes] for borrow checking. +See: [`borrowck_collect_region_constraints`][borrowck_collect_region_constraints]. + +[^lifetimes]: AKA regions AKA loans. + +Doing this additional type checking pass on it also allows us to check our working: +If something fails in MIR type checking that passed in HIR type checking, something has gone wrong. + +Maintaining "MIR type checking should succeed if HIR type checking succeeds" is nontrivial. +One major reason for this is that type checking MIR involves erasing the existing lifetimes and replacing them with new unconstrained lifetime variables, while in HIR lifetimes get inferred but not checked. +In this way, HIR type checking and MIR type checking each work with subtly different information. + +The erase-and-re-infer strategy in MIR is called [Region Uniquification](#region-uniquification). + +## Region Uniquification + +TODO: Talk more about Region Uniquification and any still-existing use of it. + +[borrowck_collect_region_constraints]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_borrowck/fn.borrowck_collect_region_constraints.html +[type_check]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_borrowck/type_check/fn.type_check.html ## User types -At the start of MIR type-check, we replace all regions in the body with new unconstrained regions. +At the start of MIR type checking, we replace all regions in the body with new unconstrained regions. However, this would cause us to accept the following program: ```rust fn foo<'a>(x: &'a u32) { @@ -37,7 +55,8 @@ We replace all inference variables with existential bound variables instead. Something like `let x: Vec<_>` would therefore result in `exists UserType::Ty(Vec)`. A pattern like `let Foo(x): Foo<&'a u32>` has a user type `Foo<&'a u32>` but -the actual type of `x` should only be `&'a u32`. For this, we use a [`UserTypeProjection`][proj]. +the actual type of `x` should only be `&'a u32`. +For this, we use a [`UserTypeProjection`][proj]. In the MIR, we deal with user types in two slightly different ways. @@ -50,15 +69,15 @@ Here `T_x` only has to be a subtype of the user type, so we instead use [`StatementKind::AscribeUserType`][stmt] for that. Note that we do not directly use the user type as the MIR typechecker -doesn't really deal with type and const inference variables. We instead store the final -[`inferred_type`][inf] from the HIR type-checker. During MIR typeck, we then replace its regions -with new nll inference vars and relate it with the actual `UserType` to get the correct region -constraints again. +doesn't really deal with type and const inference variables. +We instead store the final [`inferred_type`][inf] from the HIR type-checker. +During MIR typeck, we then replace its regions with new nll inference vars +and relate it with the actual `UserType` to get the correct region constraints again. -After the MIR type-check, all user type annotations get discarded, as they aren't needed anymore. +After the MIR type-check, all user type annotations get discarded as they aren't needed anymore. [annot]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CanonicalUserTypeAnnotation.html [proj]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.UserTypeProjection.html [decl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.LocalDecl.html [stmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.StatementKind.html#variant.AscribeUserType -[inf]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CanonicalUserTypeAnnotation.html#structfield.inferred_ty \ No newline at end of file +[inf]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.CanonicalUserTypeAnnotation.html#structfield.inferred_ty diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index 026a42907493f..881f8eaa0cbf3 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -48,3 +48,36 @@ like the standard library (std) or the compiler (rustc). NOTE: The documentation for the compiler is found at [this link]. [this link]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ + +## Contributing documentation + +Documentation improvements are very welcome. +The source of `doc.rust-lang.org` +is located in [`src/doc`] in the tree, and standard API documentation is generated +from the source code itself (e.g. [`library/std/src/lib.rs`][std-root]). +Documentation pull requests function in the same way as other pull requests. + +[`src/doc`]: https://github.com/rust-lang/rust/tree/HEAD/src/doc +[std-root]: https://github.com/rust-lang/rust/blob/HEAD/library/std/src/lib.rs#L1 + +To find documentation-related issues, use the [A-docs label]. + +You can find documentation style guidelines in [RFC 1574]. + +To build the standard library documentation, use `x doc --stage 1 library --open`. +To build the documentation for a book (e.g. the unstable book), use `x doc src/doc/unstable-book`. +Results should appear in `build/host/doc`, as well as automatically open in your default browser. +See [Building Documentation](#building-documentation) for more +information. + +You can also use `rustdoc` directly to check small fixes. +For example, `rustdoc src/doc/reference.md` will render reference to `doc/reference.html`. +The CSS might be messed up, but you can verify that the HTML is right. + +Please notice that we don't accept typography/spellcheck fixes to **internal documentation** +as it's usually not worth the churn or the review time. +Examples of internal documentation are code comments and rustc API docs. +However, feel free to fix those if accompanied by other improvements in the same PR. + +[A-docs label]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs +[RFC 1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index e9bcfb34e03d4..3144655f31f04 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -152,10 +152,10 @@ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #### Running bootstrap slightly more conveniently There is a binary that wraps bootstrap called `x`. -All it does is run `./x`, but it can be installed system-wide and run from any subdirectory of a checkout. +It runs `./x`, and can be installed system-wide and run from any subdirectory of a checkout. It also looks up the appropriate version of Python to use and avoids depending on which shell you're currently using. -You can install it with `cargo install --path src/tools/x`. +You can install it with `cargo install --locked --path src/tools/x`. ## Create a `bootstrap.toml` diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md index f10f7ae1c2659..65539ee49f4dd 100644 --- a/src/doc/rustc-dev-guide/src/building/optimized-build.md +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -31,11 +31,11 @@ Enabling LTO on Linux has [produced] speed-ups by up to 10%. ## Memory allocator Using a different memory allocator for `rustc` can provide significant performance benefits. -If you want to enable the `jemalloc` allocator, you can set the `rust.override-allocator` option to `jemalloc` +If you want to enable the `jemalloc` allocator, you can set the `build.allocator` option to `jemalloc` in `bootstrap.toml`: ```toml -rust.override-allocator = "jemalloc" +build.allocator = "jemalloc" ``` > Note that this option is currently only supported for Linux and macOS targets. diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 0b0cabaca6616..01869dfdc3f75 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -90,11 +90,13 @@ Running `./x setup editor` will prompt you to create a project-local LSP config file for one of the supported editors. You can also create the config file as a step of running `./x setup`. -### Using a separate build directory for rust-analyzer +### Using a shared build directory for rust-analyzer -By default, when rust-analyzer runs a check or format command, it will share -the same build directory as manual command-line builds. -This can be inconvenient for two reasons: +By default, when rust-analyzer runs a bootstrap command, +it will use a separate build directory from manual command-line builds. +You can override this your generated LSP config file if you want to save disk space. + +However, this is not recommended: - Each build will lock the build directory and force the other to wait, so it becomes impossible to run command-line builds while rust-analyzer is running commands in the background. @@ -102,18 +104,6 @@ This can be inconvenient for two reasons: artifacts due to conflicting compiler flags or other settings, forcing additional rebuilds in some cases. -To avoid these problems: -- Add `--build-dir=build-rust-analyzer` to all of the custom `x` commands in - your editor's rust-analyzer configuration. - (Feel free to choose a different directory name if desired.) -- Modify the `rust-analyzer.rustfmt.overrideCommand` setting so that it points - to the copy of `rustfmt` in that other build directory. -- Modify the `rust-analyzer.procMacro.server` setting so that it points to the - copy of `rust-analyzer-proc-macro-srv` in that other build directory. - -Using separate build directories for command-line builds and rust-analyzer -requires extra disk space. - ### Visual Studio Code Selecting `vscode` in `./x setup editor` will prompt you to create a diff --git a/src/doc/rustc-dev-guide/src/contributing-to-guide.md b/src/doc/rustc-dev-guide/src/contributing-to-guide.md new file mode 100644 index 0000000000000..43b9d5868b029 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/contributing-to-guide.md @@ -0,0 +1,82 @@ +# Writing rustc-dev-guide documentation + +Contributions to the [rustc-dev-guide] are always welcome, and can be made directly at +[the rust-lang/rustc-dev-guide repo][rdgrepo]. +The issue tracker in that repo is also a great way to find things that need doing. +There are issues for beginners and advanced compiler devs alike! + +Just a few things to keep in mind: + +[rustc API docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle + +- When writing about a particular part of the compiler's code, we + recommend that you link to the relevant parts of the [rustc API docs]. + +- Use sentence case for chapter and section titles. + +- Use dashes (`-`) to separate words in file names. + +- Links within the guide should use `.md` relative links, not `.html` links. + CI will enforce this. + +- Please try to avoid overly long lines and use semantic line breaks (where you break the line after each sentence). + This makes it easier to review diffs, since they avoid reflowing other unrelated prose. + There is no strict limit on line lengths; + let the sentence or part of the sentence flow to its proper end on the same line. + + You can use a tool in ci/sembr to help with this. + Its help output can be seen with this command: + + ```console + cargo run --manifest-path ci/sembr/Cargo.toml -- --help + ``` + +- When contributing text to the guide, please contextualize the information with some time period + and/or a reason so that the reader knows how much to trust the information. + Aim to provide a reasonable amount of context, and consider including: + + - A reason for why the text may be out of date other than "change", + as change is a constant across the project. + + - The date the comment was added, e.g. instead of writing _"Currently, ..."_ + or _"As of now, ..."_, consider adding the date, in one of the following formats: + - Jan 2021 + - January 2021 + - jan 2021 + - january 2021 + + There is a CI action (in `.github/workflows/date-check.yml`) + that generates a monthly report showing those that are over 6 months old + ([example](https://github.com/rust-lang/rustc-dev-guide/issues/2052)). + + For the action to pick the date, add a special annotation before specifying the date: + + ```md + Jul 2026 + ``` + + Example: + + ```md + As of Jul 2026, the foo did the bar. + ``` + + For cases where the date should not be part of the visible rendered output, + use the following instead: + + ```md + + ``` + + - A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide + further explanation for the change process or a way to verify that the information is not + outdated. + +## ⚠️ Note: Where to contribute `rustc-dev-guide` changes + +For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, +see [the rustc-dev-guide team documentation]. + +[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ +[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide +[the rustc-dev-guide team documentation]: https://forge.rust-lang.org/rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index ef6c98cb6d978..7badbee2c8216 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -31,515 +31,48 @@ Trait in return position**. Opening an issue is as easy as following [this link][create an issue] and filling out the fields in the appropriate provided template. -## Bug fixes or "normal" code changes - -For most PRs, no special procedures are needed. -You can just [open a PR], and it will be reviewed, approved, and merged. -This includes most bug fixes, refactorings, and other user-invisible changes. -The next few sections talk about exceptions to this rule. - -Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft PRs]. -Some people prefer to do this so they can get feedback along the -way or share their code with a collaborator. -Others do this so they can utilize -the CI to build and test their PR (e.g. when developing on a slow machine). - -[open a PR]: #pull-requests -[Draft PRs]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ - -## New features - -Rust has strong backwards-compatibility guarantees. -Thus, new features can't just be implemented directly in stable Rust. -Instead, we have 3 release channels: stable, beta, and nightly. -See [The Rust Book] for more details on Rust’s train release model. - -- **Stable**: this is the latest stable release for general usage. -- **Beta**: this is the next release (will be stable within 6 weeks). -- **Nightly**: follows the `main` branch of the repo. - This is the only channel where unstable features are intended to be used, - which happens via opt-in feature gates. - -See [this chapter on implementing new features](./implementing-new-features.md) for more -information. - -[The Rust Book]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html - -### Breaking changes - -Breaking changes have a [dedicated section][Breaking Changes] in the dev-guide. - -### Major changes - -The compiler team has a special process for large changes, whether or not they cause breakage. -This process is called a Major Change Proposal (MCP). -MCP is a relatively lightweight mechanism for getting feedback on large changes to the -compiler (as opposed to a full RFC or a design meeting with the team). - -Example of things that might require MCPs include major refactorings, changes -to important types, or important changes to how the compiler does something, or -smaller user-facing changes. - -**When in doubt, ask [on Zulip]. -It would be a shame to put a lot of work -into a PR that ends up not getting merged!** [See this document][mcpinfo] for more info on MCPs. - -[mcpinfo]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#how-do-i-submit-an-mcp -[on Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler - -### Performance - -Compiler performance is important. -We have put a lot of effort over the last few years into [gradually improving it][perfdash]. - -[perfdash]: https://perf.rust-lang.org/dashboard.html - -If you suspect that your change may cause a performance regression (or -improvement), you can request a "perf run" (and your reviewer may also request one -before approving). -This is yet another bot that will compile a collection of -benchmarks on a compiler with your changes. -The numbers are reported -[here][perf], and you can see a comparison of your changes against the latest `main`. - -> For an introduction to the performance of Rust code in general -> which would also be useful in rustc development, see [The Rust Performance Book]. - -[perf]: https://perf.rust-lang.org -[The Rust Performance Book]: https://nnethercote.github.io/perf-book/ - -## Pull requests - -Pull requests (or PRs for short) are the primary mechanism we use to change Rust. -GitHub itself has some [great documentation][about-pull-requests] on using the Pull Request feature. -We use the ["fork and pull" model][development-models], -where contributors push changes to their personal fork and create pull requests to -bring those changes into the source repository. -We have [a chapter](git.md) on how to use Git when contributing to Rust. - -> **Advice for potentially large, complex, cross-cutting and/or very domain-specific changes** -> -> The compiler reviewers on rotation usually each have areas of the compiler that they know well, -> but also have areas that they are not very familiar with. If your PR contains changes that are -> large, complex, cross-cutting and/or highly domain-specific, it becomes very difficult to find a -> suitable reviewer who is comfortable in reviewing all of the changes in such a PR. This is also -> true if the changes are not only compiler-specific but also contains changes which fall under the -> purview of reviewers from other teams, like the standard library team. [There's a bot][triagebot] -> which notifies the relevant teams and pings people who have setup specific alerts based on the -> files modified. -> -> Before making such changes, you are strongly encouraged to **discuss your proposed changes with -> the compiler team beforehand** (and with other teams that the changes would require approval -> from), and work with the compiler team to see if we can help you **break down a large potentially -> unreviewable PR into a series of smaller more individually reviewable PRs**. -> -> You can communicate with the compiler team by creating a [#t-compiler thread on Zulip][t-compiler] -> to discuss your proposed changes. -> -> Communicating with the compiler team beforehand helps in several ways: -> -> 1. It increases the likelihood of your PRs being reviewed in a timely manner. -> - We can help you identify suitable reviewers *before* you open actual PRs, or help find -> advisors and liaisons to help you navigate the change procedures, or help with running -> try-jobs, perf runs and crater runs as suitable. -> 2. It helps the compiler team track your changes. -> 3. The compiler team can perform vibe checks on your changes early and often, to see if the -> direction of the changes align with what the compiler team prefers to see. -> 4. Helps to avoid situations where you may have invested significant time and effort into large -> changes that the compiler team might not be willing to accept, or finding out very late that the -> changes are in a direction that the compiler team disagrees with. - -[about-pull-requests]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests -[development-models]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#fork-and-pull-model -[t-compiler]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler -[triagebot]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml - -### Keeping your branch up-to-date - -The CI in rust-lang/rust applies your patches directly against current `main`, -not against the commit your branch is based on. -This can lead to unexpected failures -if your branch is outdated, even when there are no explicit merge conflicts. - -Update your branch only when needed: when you have merge conflicts, upstream CI is broken and blocking your green PR, or a maintainer requests it. -Avoid updating an already-green PR under review unless necessary. -During review, make incremental commits to address feedback. -Prefer to squash or rebase only at the end, or when a reviewer requests it. - -When updating, use `git push --force-with-lease` and leave a brief comment explaining what changed. -Some repos prefer merging from `upstream/main` instead of rebasing; -follow the project's conventions. -See [keeping things up to date](git.md#keeping-things-up-to-date) for detailed instructions. - -After rebasing, it's recommended to [run the relevant tests locally](tests/intro.md) to catch any issues before CI runs. - -### r? - -All pull requests are reviewed by another person. -We have a bot, [@rustbot], that will automatically assign a random person -to review your request based on which files you changed. - -If you want to request that a specific person reviews your pull request, you -can add an `r?` to the pull request description or in a comment. -For example, if you want to ask a review by @awesome-reviewer, -add the following to the end of the pull request description: - - r? @awesome-reviewer - -[@rustbot] will then assign the PR to that reviewer instead of a random person. -This is entirely optional. - -You can also assign a random reviewer from a specific team by writing `r? rust-lang/groupname`. -As an example, if you were making a diagnostics change, -you could get a reviewer from the diagnostics team by adding: - - r? rust-lang/diagnostics - -For a full list of possible `groupname`s, -check the `adhoc_groups` section at the [triagebot.toml config file], -or the list of teams in the [rust-lang teams database]. - -### Waiting for reviews - -> NOTE -> -> Pull request reviewers are often working at capacity, -> and many of them are contributing on a volunteer basis. -> In order to minimize review delays, -> pull request authors and assigned reviewers should ensure that the review label -> (`S-waiting-on-review` and `S-waiting-on-author`) stays updated, -> invoking these commands when appropriate: -> -> - `@rustbot author`: -> the review is finished, -> and PR author should check the comments and take action accordingly. -> -> - `@rustbot review`: -> the author is ready for a review, -> and this PR will be queued again in the reviewer's queue. - -Please note that the reviewers are humans, who for the most part work on `rustc` in their free time. -This means that they can take some time to respond and review your PR. -It also means that reviewers can miss some PRs that are assigned to them. - -To try to move PRs forward, the Triage WG regularly goes through all PRs that -are waiting for review and haven't been discussed for at least 2 weeks. -If you don't get a review within 2 weeks, feel free to ask the Triage WG on -Zulip ([#t-release/triage]). -They have knowledge of when to ping, who might be on vacation, etc. - -The reviewer may request some changes using the GitHub code review interface. -They may also request special procedures for some PRs. -See [Crater] and [Breaking Changes] chapters for some examples of such procedures. - -[r?]: https://github.com/rust-lang/rust/pull/78133#issuecomment-712692371 -[#t-release/triage]: https://rust-lang.zulipchat.com/#narrow/stream/242269-t-release.2Ftriage -[Crater]: tests/crater.md - -### CI - -In addition to being reviewed by a human, pull requests are automatically tested, -thanks to continuous integration (CI). -Basically, every time you open and update -a pull request, CI builds the compiler and tests it against the -[compiler test suite], and also performs other tests such as checking that -your pull request is in compliance with Rust's style guidelines. - -Running continuous integration tests allows PR authors to catch mistakes early -without going through a first review cycle, and also helps reviewers stay aware -of the status of a particular pull request. - -Rust has plenty of CI capacity, and you should never have to worry about wasting -computational resources each time you push a change. -It is also perfectly fine -(and even encouraged!) to use the CI to test your changes if it can help your productivity. -In particular, we don't recommend running the full `./x test` suite locally, -since it takes a very long time to execute. -See the [Testing with CI] chapter for using Rust's CI to test your changes. - -[Testing with CI]: tests/ci.md#testing-with-ci - -### r+ - -After someone has reviewed your pull request, they will leave an annotation -on the pull request with an `r+`. -It will look something like this: - - @bors r+ - -This tells [@bors], our lovable integration bot, that your pull request has been approved. -The PR then enters the [merge queue], where [@bors] -will run *all* the tests on *every* platform we support. -If it all works out, [@bors] will merge your code into `main` and close the pull request. - -Depending on the scale of the change, you may see a slightly different form of `r+`: - - @bors r+ rollup - -The additional `rollup` tells [@bors] that this change should always be "rolled up". -Changes that are rolled up are tested and merged alongside other PRs, to speed the process up. -Typically, only small changes that are expected not to conflict -with one another are marked as "always roll up". - -Be patient; -this can take a while and the queue can sometimes be long. -Also, note that PRs are never merged by hand. - -[@rustbot]: https://github.com/rustbot -[@bors]: https://github.com/rust-lang/bors - -### Opening a PR - -You are now ready to file a pull request (PR)? -Great! -Here are a few points you should be aware of. - -All pull requests should be filed against the `main` branch, -unless you know for sure that you should target a different branch. - -Run some style checks before you submit the PR: - - ./x test tidy --bless - -We recommend to make this check before every pull request (and every new commit in a pull request); -you can add [git hooks] before every push to make sure you never forget to make this check. -The CI will also run tidy and will fail if tidy fails. - -Rust follows a _no merge-commit policy_, -meaning that when you encounter merge conflicts, -you are expected to always rebase instead of merging. -For example, -always use rebase when bringing the latest changes from the `main` branch to your feature branch. -If your PR contains merge commits, it will get marked as `has-merge-commits`. -Once you have removed the merge commits, e.g., through an interactive rebase, you -should remove the label again: - - @rustbot label -has-merge-commits - -See [this chapter][labeling] for more details. - -If you encounter merge conflicts or when a reviewer asks you to perform some -changes, your PR will get marked as `S-waiting-on-author`. -When you resolve them, you should use `@rustbot` to mark it as `S-waiting-on-review`: - - @rustbot ready - -GitHub allows [closing issues using keywords][closing-keywords]. -This feature should be used to keep the issue tracker tidy. -However, it is generally preferred -to put the "closes #123" text in the PR description rather than the commit message; -particularly during rebasing, citing the issue number in the commit can "spam" -the issue in question. - -However, if your PR fixes a stable-to-beta or stable-to-stable regression and has -been accepted for a beta and/or stable backport (i.e., it is marked `beta-accepted` -and/or `stable-accepted`), please do *not* use any such keywords since we don't -want the corresponding issue to get auto-closed once the fix lands on `main`. -Please update the PR description while still mentioning the issue somewhere. -For example, you could write `Fixes (after beta backport) #NNN.`. - -As for further actions, please keep a sharp look-out for a PR whose title begins with -`[beta]` or `[stable]` and which backports the PR in question. -When that one gets merged, the relevant issue can be closed. -The closing comment should mention all PRs that were involved. -If you don't have the permissions to close the issue, please -leave a comment on the original PR asking the reviewer to close it for you. - -[labeling]: ./rustbot.md#issue-relabeling -[closing-keywords]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue - -### Reverting a PR - -When a PR leads to miscompile, significant performance regressions, or other critical issues, we may -want to revert that PR with a regression test case. -You can also check out the [revert policy] on -Forge docs (which is mainly targeted for reviewers, but contains useful info for PR authors too). - -If the PR contains huge changes, it can be challenging to revert, making it harder to review -incremental fixes in subsequent updates. -Or if certain code in that PR is heavily depended upon by -subsequent PRs, reverting it can become difficult. - -In such cases, we can identify the problematic code and disable it for some input, as shown in [#128271][#128271]. - -For MIR optimizations, we can also use the `-Zunsound-mir-opt` option to gate the mir-opt, as shown -in [#132356][#132356]. - -[revert policy]: https://forge.rust-lang.org/compiler/reviews.html?highlight=revert#reverts -[#128271]: https://github.com/rust-lang/rust/pull/128271 -[#132356]: https://github.com/rust-lang/rust/pull/132356 - -## External dependencies - -This section has moved to ["Using External Repositories"](./external-repos.md). - -## Writing documentation - -Documentation improvements are very welcome. -The source of `doc.rust-lang.org` -is located in [`src/doc`] in the tree, and standard API documentation is generated -from the source code itself (e.g. [`library/std/src/lib.rs`][std-root]). Documentation pull requests -function in the same way as other pull requests. - -[`src/doc`]: https://github.com/rust-lang/rust/tree/HEAD/src/doc -[std-root]: https://github.com/rust-lang/rust/blob/HEAD/library/std/src/lib.rs#L1 - -To find documentation-related issues, use the [A-docs label]. - -You can find documentation style guidelines in [RFC 1574]. - -To build the standard library documentation, use `x doc --stage 1 library --open`. -To build the documentation for a book (e.g. the unstable book), use `x doc src/doc/unstable-book.` -Results should appear in `build/host/doc`, as well as automatically open in your default browser. -See [Building Documentation](./building/compiler-documenting.md#building-documentation) for more -information. - -You can also use `rustdoc` directly to check small fixes. -For example, `rustdoc src/doc/reference.md` will render reference to `doc/reference.html`. -The CSS might be messed up, but you can verify that the HTML is right. - -Please notice that we don't accept typography/spellcheck fixes to **internal documentation** -as it's usually not worth the churn or the review time. -Examples of internal documentation is code comments and rustc api docs. -However, feel free to fix those if accompanied by other improvements in the same PR. - -### Contributing to rustc-dev-guide - -Contributions to the [rustc-dev-guide] are always welcome, and can be made directly at -[the rust-lang/rustc-dev-guide repo][rdgrepo]. -The issue tracker in that repo is also a great way to find things that need doing. -There are issues for beginners and advanced compiler devs alike! - -Just a few things to keep in mind: - -- Please try to avoid overly long lines and use semantic line breaks (where you break the line after each sentence). - There is no strict limit on line lengths; - let the sentence or part of the sentence flow to its proper end on the same line. - - You can use a tool in ci/sembr to help with this. - Its help output can be seen with this command: - - ```console - cargo run --manifest-path ci/sembr/Cargo.toml -- --help - ``` - -- When contributing text to the guide, please contextualize the information with some time period - and/or a reason so that the reader knows how much to trust the information. - Aim to provide a reasonable amount of context, and consider including: - - - A reason for why the text may be out of date other than "change", - as change is a constant across the project. - - - The date the comment was added, e.g. instead of writing _"Currently, ..."_ - or _"As of now, ..."_, consider adding the date, in one of the following formats: - - Jan 2021 - - January 2021 - - jan 2021 - - january 2021 - - There is a CI action (in `.github/workflows/date-check.yml`) - that generates a monthly report showing those that are over 6 months old - ([example](https://github.com/rust-lang/rustc-dev-guide/issues/2052)). - - For the action to pick the date, add a special annotation before specifying the date: - - ```md - Jul 2026 - ``` - - Example: - - ```md - As of Jul 2026, the foo did the bar. - ``` +[search existing issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue +[create an issue]: https://github.com/rust-lang/rust/issues/new/choose - For cases where the date should not be part of the visible rendered output, - use the following instead: +## Other procedures - ```md - - ``` +Other contribution procedures are documented with the parts of the guide that own them: - - A link to a relevant WG, tracking issue, `rustc` rustdoc page, or similar, that may provide - further explanation for the change process or a way to verify that the information is not - outdated. + + -- Use sentence case for chapter and sections titles. +- For routine changes or large, cross-cutting pull requests, see [normal code changes](getting-started.md#bug-fixes-or-normal-code-changes), [PR lifecycle](./pr-lifecycle.md), and [pull request guidance](getting-started.md#pull-requests). -- Use dashes (`-`) to separate words file names. + + + -#### ⚠️ Note: Where to contribute `rustc-dev-guide` changes +- For new features, major changes, and breaking changes, see [Implementing new language features](implementing-new-features.md) and [Procedures for breaking changes](bug-fix-procedure.md). -For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, -see [the rustc-dev-guide team documentation]. + -## Issue triage +- For performance-sensitive changes, see [Performance testing](tests/perf.md#performance-considerations). -Please see . + -[stable-]: https://github.com/rust-lang/rust/labels?q=stable -[beta-]: https://github.com/rust-lang/rust/labels?q=beta -[I-\*-nominated]: https://github.com/rust-lang/rust/labels?q=nominated -[I-prioritize]: https://github.com/rust-lang/rust/labels/I-prioritize -[tracking issues]: https://github.com/rust-lang/rust/labels/C-tracking-issue -[beta-backport]: https://forge.rust-lang.org/release/backporting.html#beta-backporting-in-rust-langrust -[stable-backport]: https://forge.rust-lang.org/release/backporting.html#stable-backporting-in-rust-langrust -[metabug]: https://github.com/rust-lang/rust/labels/metabug -[regression-]: https://github.com/rust-lang/rust/labels?q=regression -[relnotes]: https://github.com/rust-lang/rust/labels/relnotes -[S-tracking-]: https://github.com/rust-lang/rust/labels?q=s-tracking -[the rustc-dev-guide team documentation]: https://forge.rust-lang.org/rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes +- For compiler documentation, see [Contributing documentation](building/compiler-documenting.md#contributing-documentation). -### rfcbot labels + -[rfcbot] uses its own labels for tracking the process of coordinating -asynchronous decisions, such as approving or rejecting a change. -This is used for [RFCs], issues, and pull requests. +- For issue triage, see [Issue triage](getting-started.md#issue-triage). -| Labels | Color | Description | -|--------|-------|-------------| -| [proposed-final-comment-period] |  Gray | Currently awaiting signoff of all team members in order to enter the final comment period. | -| [disposition-merge] |  Green | Indicates the intent is to merge the change. | -| [disposition-close] |  Red | Indicates the intent is to not accept the change and close it. | -| [disposition-postpone] |  Gray | Indicates the intent is to not accept the change at this time and postpone it to a later date. | -| [final-comment-period] |  Blue | Currently soliciting final comments before merging or closing. | -| [finished-final-comment-period] |  Light Yellow | The final comment period has concluded, and the issue will be merged or closed. | -| [postponed] |  Yellow | The issue has been postponed. | -| [closed] |  Red | The issue has been rejected. | -| [to-announce] |  Gray | Issues that have finished their final-comment-period and should be publicly announced. Note: the rust-lang/rust repository uses this label differently, to announce issues at the triage meetings. | + -[disposition-merge]: https://github.com/rust-lang/rust/labels/disposition-merge -[disposition-close]: https://github.com/rust-lang/rust/labels/disposition-close -[disposition-postpone]: https://github.com/rust-lang/rust/labels/disposition-postpone -[proposed-final-comment-period]: https://github.com/rust-lang/rust/labels/proposed-final-comment-period -[final-comment-period]: https://github.com/rust-lang/rust/labels/final-comment-period -[finished-final-comment-period]: https://github.com/rust-lang/rust/labels/finished-final-comment-period -[postponed]: https://github.com/rust-lang/rfcs/labels/postponed -[closed]: https://github.com/rust-lang/rfcs/labels/closed -[to-announce]: https://github.com/rust-lang/rfcs/labels/to-announce -[rfcbot]: https://github.com/anp/rfcbot-rs/ -[RFCs]: https://github.com/rust-lang/rfcs +- For guidance on LLM usage, see [Running LLMs](llm-guidance.md). -## LLM policy + -See [Forge][LLM policy]. +- For changes to this guide itself, see [Writing rustc-dev-guide documentation](contributing-to-guide.md). -[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html + -## Helpful links and information +- For external dependencies, see [Using external repositories](external-repos.md). -This section has moved to the ["About this guide"] chapter. + -["About this guide"]: about-this-guide.md#other-places-to-find-information -[search existing issues]: https://github.com/rust-lang/rust/issues?q=is%3Aissue -[Breaking Changes]: bug-fix-procedure.md -[triagebot.toml config file]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml -[rust-lang teams database]: https://github.com/rust-lang/team/tree/HEAD/teams -[compiler test suite]: tests/intro.md -[merge queue]: https://bors.rust-lang.org/queue/rust -[git hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks -[A-docs label]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs -[RFC 1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text -[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ -[rdgrepo]: https://github.com/rust-lang/rustc-dev-guide -[create an issue]: https://github.com/rust-lang/rust/issues/new/choose +- For further resources, see [About this guide](about-this-guide.md#other-places-to-find-information). diff --git a/src/doc/rustc-dev-guide/src/debuginfo/intro.md b/src/doc/rustc-dev-guide/src/debuginfo/intro.md index e8c4d11d12b0a..8609d7c472888 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/intro.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/intro.md @@ -86,7 +86,7 @@ accurate, and has useful diagrams. * [pdb-rs](https://github.com/microsoft/pdb-rs/) - A Rust-based PDB reader and writer based on other publicly-available information. Does not guarantee stability or spec compliance. - Also contains `pdbtool`, which can dump PDB files (`cargo install pdbtool`) + Also contains `pdbtool`, which can dump PDB files (`cargo install --locked pdbtool`) * [Debug Interface Access SDK](https://learn.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/getting-started-debug-interface-access-sdk). While it does not document the PDB format directly, details can be gleaned from the interface itself. diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index b143beb9e0648..77b04e683c86d 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -3,52 +3,19 @@ Thank you for your interest in contributing to Rust! There are many ways to contribute, and we appreciate all of them. -If this is your first time contributing, the [walkthrough] chapter can give you a good example of -how a typical contribution would go. +For general information about how to contribute to Rust, +see [Forge](https://forge.rust-lang.org/how-to-start-contributing.html). +The rest of this section is about how to contribute to the compiler specifically. This documentation is _not_ intended to be comprehensive; it is meant to be a quick guide for the most useful things. For more information, see [How to build and run the compiler](building/how-to-build-and-run.md). -[internals]: https://internals.rust-lang.org -[rust-zulip]: https://rust-lang.zulipchat.com -[coc]: https://www.rust-lang.org/policies/code-of-conduct -[walkthrough]: ./walkthrough.md -[Getting Started]: ./getting-started.md +## Finding help -## Asking Questions - -If you have questions, please make a post on the [Rust Zulip server][rust-zulip] or -[internals.rust-lang.org][internals]. -See the [list of teams and working groups][governance] and [the Community page][community] on the -official website for more resources. - -[governance]: https://www.rust-lang.org/governance -[community]: https://www.rust-lang.org/community - -As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. - -The compiler team (or `t-compiler`) usually hangs out in Zulip in -[the #t-compiler channel][z-t-compiler]; -questions about how the compiler works can go in [#t-compiler/help][z-help]. - -[z-t-compiler]: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler -[z-help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp - -**Please ask questions!** A lot of people report feeling that they are "wasting -expert's time", but nobody on `t-compiler` feels this way. -Contributors are important to us. - -Also, if you feel comfortable, prefer public topics, as this means others can -see the questions and answers, and perhaps even integrate them back into this guide :) - -**Tip**: If you're not a native English speaker and feel unsure about writing, try using a translator to help. -But avoid using LLM tools that generate long, complex words. -In daily teamwork, **simple and clear words** are best for easy understanding. -Even small typos or grammar mistakes can make you seem more human, and people connect better with humans. - -See also [our LLM policy](https://forge.rust-lang.org/policies/llm-usage.html). +See also ["Asking +Questions"](https://forge.rust-lang.org/how-to-start-contributing.html#asking-questions). ### Experts @@ -68,18 +35,10 @@ more information about these commits). [map]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml -### Etiquette - -We do ask that you be mindful to include as much useful information as you can -in your question, but we recognize this can be hard if you are unfamiliar with contributing to Rust. - -Just pinging someone without providing any context can be a bit annoying and -just create noise, so we ask that you be mindful of the fact that the -`t-compiler` folks get a lot of pings in a day. ## What should I work on? -The Rust project is quite large and it can be difficult to know which parts of the project need +The `rust` monorepo is quite large and it can be difficult to know which parts need help, or are a good starting place for beginners. Here are some suggested starting places. @@ -91,7 +50,6 @@ See the [Triage] for an explanation of these labels. You can also try filtering the search to areas you're interested in. For example: -- `repo:rust-lang/rust-clippy` will only show clippy issues - `label:T-compiler` will only show issues related to the compiler - `label:A-diagnostics` will only show diagnostic issues @@ -99,7 +57,7 @@ Not all important or beginner work has issue labels. See below for how to find work that isn't labelled. [help-wanted-search]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20org%3Arust-lang%20no%3Aassignee%20label%3AE-easy%2CE-medium%2CE-help-wanted%2CE-mentor%20-label%3AS-blocked%20-linked%3Apr -[Triage]: ./contributing.md#issue-triage +[Triage]: https://forge.rust-lang.org/release/issue-triaging.html ### Recurring work @@ -112,17 +70,6 @@ it's easy to pick up work without a large time commitment: If you find more recurring work, please feel free to add it here! -### Clippy issues - -The [Clippy] project has spent a long time making its contribution process as friendly to newcomers -as possible. -Consider working on it first to get familiar with the process and the compiler internals. - -See [the Clippy contribution guide][clippy-contributing] for instructions on getting started. - -[Clippy]: https://doc.rust-lang.org/clippy/ -[clippy-contributing]: https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md - ### Diagnostic issues Many diagnostic issues are self-contained and don't need detailed background knowledge of the @@ -161,48 +108,79 @@ You can see a list of needs test issues [here][needs-test-issues]. See [std-dev-guide](https://std-dev-guide.rust-lang.org/). -### Contributing code to other Rust projects - -There are a bunch of other projects that you can contribute to outside of the -`rust-lang/rust` repo, including `cargo`, `miri`, `rustup`, and many others. - -These repos might have their own contributing guidelines and procedures. -Many of them are owned by working groups. -For more info, see the documentation in those repos' READMEs. - ### Other ways to contribute -There are a bunch of other ways you can contribute, especially if you don't -feel comfortable jumping straight into the large `rust-lang/rust` codebase. - -The following tasks are doable without much background knowledge but are incredibly helpful: - -- [Writing documentation][wd]: if you are feeling a bit more intrepid, you could try - to read a part of the code and write doc comments for it. - This will help you to learn some part of the compiler while also producing a useful artifact! -- [Triaging issues][triage]: categorizing, replicating, and minimizing issues is very helpful to the Rust maintainers. -- [Working areas][wa]: there are a bunch of working areas on a wide variety - of rust-related things. -- Answer questions on [users.rust-lang.org][users], or on [Stack Overflow][so]. -- Participate in the [RFC process](https://github.com/rust-lang/rfcs). -- Find a [requested community library][community-library], build it, and publish - it to [Crates.io](https://crates.io). - Easier said than done, but very, very valuable! - -[users]: https://users.rust-lang.org/ -[so]: http://stackoverflow.com/questions/tagged/rust -[community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library -[wd]: ./contributing.md#writing-documentation -[wa]: https://forge.rust-lang.org/compiler/working-areas.html -[triage]: ./contributing.md#issue-triage +See [Forge](https://forge.rust-lang.org/how-to-start-contributing.html#how-to-start-contributing-1). ## Cloning and Building See ["How to build and run the compiler"](./building/how-to-build-and-run.md). -## Contributor Procedures - -This section has moved to the ["Contribution Procedures"](./contributing.md) chapter. +## Bug fixes or "normal" code changes + +For most PRs, no special procedures are needed. +You can just [open a PR], and it will be reviewed, approved, and merged. +This includes most bug fixes, refactorings, and other user-invisible changes. +The next few sections talk about exceptions to this rule. + +Also, note that it is perfectly acceptable to open WIP PRs or GitHub [Draft PRs]. +Some people prefer to do this so they can get feedback along the +way or share their code with a collaborator. +Others do this so they can utilize +the CI to build and test their PR (e.g. when developing on a slow machine). + +[open a PR]: git.md#opening-a-pr +[Draft PRs]: https://github.blog/2019-02-14-introducing-draft-pull-requests/ + +## Pull requests + +Pull requests (or PRs for short) are the primary mechanism we use to change Rust. +GitHub itself has some [great documentation][about-pull-requests] on using the Pull Request feature. +We use the ["fork and pull" model][development-models], +where contributors push changes to their personal fork and create pull requests to +bring those changes into the source repository. +We have [a chapter](git.md) on how to use Git when contributing to Rust. + +> **Advice for potentially large, complex, cross-cutting and/or very domain-specific changes** +> +> The compiler reviewers on rotation usually each have areas of the compiler that they know well, +> but also have areas that they are not very familiar with. If your PR contains changes that are +> large, complex, cross-cutting and/or highly domain-specific, it becomes very difficult to find a +> suitable reviewer who is comfortable in reviewing all of the changes in such a PR. This is also +> true if the changes are not only compiler-specific but also contain changes which fall under the +> purview of reviewers from other teams, like the standard library team. [There's a bot][triagebot] +> which notifies the relevant teams and pings people who have set up specific alerts based on the +> files modified. +> +> Before making such changes, you are strongly encouraged to **discuss your proposed changes with +> the compiler team beforehand** (and with other teams that the changes would require approval +> from), and work with the compiler team to see if we can help you **break down a large potentially +> unreviewable PR into a series of smaller more individually reviewable PRs**. +> +> You can communicate with the compiler team by creating a [#t-compiler thread on Zulip][t-compiler] +> to discuss your proposed changes. +> +> Communicating with the compiler team beforehand helps in several ways: +> +> 1. It increases the likelihood of your PRs being reviewed in a timely manner. +> - We can help you identify suitable reviewers *before* you open actual PRs, or help find +> advisors and liaisons to help you navigate the change procedures, or help with running +> try-jobs, perf runs and crater runs as suitable. +> 2. It helps the compiler team track your changes. +> 3. The compiler team can perform vibe checks on your changes early and often, to see if the +> direction of the changes align with what the compiler team prefers to see. +> 4. Helps to avoid situations where you may have invested significant time and effort into large +> changes that the compiler team might not be willing to accept, or finding out very late that the +> changes are in a direction that the compiler team disagrees with. + +[about-pull-requests]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests +[development-models]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#fork-and-pull-model +[t-compiler]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler +[triagebot]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml + +## Issue triage + +Please see . ## Other Resources diff --git a/src/doc/rustc-dev-guide/src/implementing-new-features.md b/src/doc/rustc-dev-guide/src/implementing-new-features.md index 2ff9d6a62e286..947dd9d36d0e5 100644 --- a/src/doc/rustc-dev-guide/src/implementing-new-features.md +++ b/src/doc/rustc-dev-guide/src/implementing-new-features.md @@ -12,6 +12,38 @@ See also [the Rust Language Design Team's procedures][lang-propose] for proposin [a different process]: ./stability.md [lang-propose]: https://lang-team.rust-lang.org/how_to/propose.html +## New features + +Rust has strong backwards-compatibility guarantees. +Thus, new features can't just be implemented directly in stable Rust. +Instead, we have 3 release channels: stable, beta, and nightly. +See [The Rust Book] for more details on Rust’s train release model. + +- **Stable**: this is the latest stable release for general usage. +- **Beta**: this is the next release (will be stable within 6 weeks). +- **Nightly**: follows the `main` branch of the repo. + This is the only channel where unstable features are intended to be used, + which happens via opt-in feature gates. + +[The Rust Book]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html + +### Breaking changes + +Breaking changes have a [dedicated section][Breaking Changes] in the dev-guide. + +### Major changes + +See ["What proposal approval do I need?"](https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#what-proposalapproval-do-i-need) +For a definition of the terms there, see +["Proposals"](https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#proposals). + +**When in doubt, ask [on Zulip]. +It would be a shame to put a lot of work into a PR that ends up not getting merged!** + +[on Zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler + +[Breaking Changes]: bug-fix-procedure.md + ## The @rfcbot FCP process When the change is small, uncontroversial, non-breaking, @@ -226,7 +258,6 @@ The below steps needs to be followed in order to implement a new unstable featur [stability in code]: #stability-in-code [here]: ./stabilization-guide.md [tracking issue]: #tracking-issues -[add-feature-gate]: ./feature-gates.md#adding-a-feature-gate [guidance for compiler flags]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html?highlight=unstable%20flag#compiler-flags [`UnstableOptions`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/options/struct.UnstableOptions.html 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 3cbdf3d2b849c..a352b5459ed4d 100644 --- a/src/doc/rustc-dev-guide/src/llm-guidance/writing.md +++ b/src/doc/rustc-dev-guide/src/llm-guidance/writing.md @@ -45,7 +45,7 @@ You may use an LLM to privately review a disclosure you have written, but not to **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. +LLM-created GitHub comments are banned. ## Guidelines @@ -63,7 +63,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 [pull request guidance](../getting-started.md#pull-requests). - [Make the smallest change that fixes the problem][small-cls]. Do not combine it with unrelated refactors or cleanups. @@ -81,7 +81,7 @@ You may use an LLM for generating the instructions for that tool, but you should Consider [performance] as you write. -[performance]: ../contributing.md#performance +[performance]: ../tests/perf.md#performance-considerations Think before adding dependencies; consult our [guidance for new dependencies][crates-io]. @@ -176,3 +176,9 @@ 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) ` + +## LLM policy + +See [Forge][LLM policy]. + +[LLM policy]: https://forge.rust-lang.org/policies/llm-usage.html diff --git a/src/doc/rustc-dev-guide/src/normalization.md b/src/doc/rustc-dev-guide/src/normalization.md index a8bc9a87d3b4c..05484a672aaf3 100644 --- a/src/doc/rustc-dev-guide/src/normalization.md +++ b/src/doc/rustc-dev-guide/src/normalization.md @@ -214,7 +214,7 @@ and each entry point should only be used in specific parts of the compiler. An additional complication is that the compiler is currently undergoing a transition from the old trait solver to the new trait solver. As part of this transition, our approach to normalization in the compiler has changed somewhat significantly, resulting in some normalization entry points being "old solver only" slated for removal in the long-term once the new solver has stabilized. -The transition can be tracked via the [WG-trait-system-refactor label] on Github. +The transition can be tracked via the [WG-trait-system-refactor label] on GitHub. Here is a rough overview of the different entry points to normalization in the compiler: - `infcx.at.structurally_normalize` diff --git a/src/doc/rustc-dev-guide/src/notification-groups/about.md b/src/doc/rustc-dev-guide/src/notification-groups/about.md index 8d5b7d1278307..d66ad5f7b42a6 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/about.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/about.md @@ -108,3 +108,7 @@ or contributors, and is typically done as part of compiler team triage.** [rustbot]: https://github.com/rust-lang/triagebot/ [`ping`]: https://forge.rust-lang.org/triagebot/pinging.html [`triagebot.toml`]: https://github.com/rust-lang/rust/blob/HEAD/triagebot.toml + +## Adding a notification group + +See [Forge](https://forge.rust-lang.org/compiler/notification-groups.html#creating-a-notification-group). diff --git a/src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md b/src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md index 9acc94a174ed5..1e2389a1a829e 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/gpu-target.md @@ -1,6 +1,6 @@ # GPU target notification group -**Github Label:** None
+**GitHub Label:** None
**Ping command:** `@rustbot ping gpu-target` This notification group deals with linker-related issues and their integration within the compiler. diff --git a/src/doc/rustc-dev-guide/src/pr-lifecycle.md b/src/doc/rustc-dev-guide/src/pr-lifecycle.md new file mode 100644 index 0000000000000..b12c1d6669fa4 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/pr-lifecycle.md @@ -0,0 +1,232 @@ +# PR lifecycle + +## Before review + +### Opening a PR + +You are now ready to file a pull request (PR)? +Great! +Here are a few points you should be aware of. + +All pull requests should be filed against the `main` branch, +unless you know for sure that you should target a different branch. + +Run some style checks before you submit the PR: + + ./x test tidy --bless + +We recommend to make this check before every pull request (and every new commit in a pull request); +you can add [git hooks] before every push to make sure you never forget to make this check. +The CI will also run tidy and will fail if tidy fails. + +### PR description + +GitHub allows [closing issues using keywords][closing-keywords]. +This feature should be used to keep the issue tracker tidy. +However, it is generally preferred +to put the "closes #123" text in the PR description rather than the commit message; +particularly during rebasing, citing the issue number in the commit can "spam" +the issue in question. + +However, if your PR fixes a stable-to-beta or stable-to-stable regression and has +been accepted for a beta and/or stable backport (i.e., it is marked `beta-accepted` +and/or `stable-accepted`), please do *not* use any such keywords since we don't +want the corresponding issue to get auto-closed once the fix lands on `main`. +Please update the PR description while still mentioning the issue somewhere. +For example, you could write `Fixes (after beta backport) #NNN.`. + +[labeling]: ./rustbot.md#issue-relabeling +[closing-keywords]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue + +### CI + +In addition to being reviewed by a human, pull requests are automatically tested, +thanks to continuous integration (CI). +Basically, every time you open and update +a pull request, CI builds the compiler and tests it against the +[compiler test suite], and also performs other tests such as checking that +your pull request is in compliance with Rust's style guidelines. + +Running continuous integration tests allows PR authors to catch mistakes early +without going through a first review cycle, and also helps reviewers stay aware +of the status of a particular pull request. + +Rust has plenty of CI capacity, and you should never have to worry about wasting +computational resources each time you push a change. +It is also perfectly fine +(and even encouraged!) to use the CI to test your changes if it can help your productivity. +In particular, we don't recommend running the full `./x test` suite locally, +since it takes a very long time to execute. +See the [Testing with CI] chapter for using Rust's CI to test your changes. + +[Testing with CI]: tests/ci.md#testing-with-ci + +## PR review + +### r? + +Your PR will be automatically assigned a reviewer. +You can override the reviewer using `r? @username`. +See [PR assignment](https://forge.rust-lang.org/triagebot/pr-assignment.html#usage) for details. + +### Rebasing + +Rust follows a _no merge-commit policy_, +meaning that when you encounter merge conflicts, +you are expected to always rebase instead of merging. +For example, +always use rebase when bringing the latest changes from the `main` branch to your feature branch. +If your PR contains merge commits, it will get marked as `has-merge-commits`. +Once you have removed the merge commits, e.g., through an interactive rebase, you +should remove the label again: + + @rustbot label -has-merge-commits + +See [this chapter][labeling] for more details. + +If you encounter merge conflicts or when a reviewer asks you to perform some +changes, your PR will get marked as `S-waiting-on-author`. +When you resolve them, you should use `@rustbot` to mark it as `S-waiting-on-review`: + + @rustbot ready + +### Keeping your branch up-to-date + +The CI in rust-lang/rust applies your patches directly against current `main`, +not against the commit your branch is based on. +This can lead to unexpected failures +if your branch is outdated, even when there are no explicit merge conflicts. + +Update your branch only when needed: when you have merge conflicts, upstream CI is broken and blocking your green PR, or a maintainer requests it. +Avoid updating an already-green PR under review unless necessary. +During review, make incremental commits to address feedback. +Prefer to squash or rebase only at the end, or when a reviewer requests it. + +When updating, use `git push --force-with-lease` and leave a brief comment explaining what changed. +Some repos prefer merging from `upstream/main` instead of rebasing; +follow the project's conventions. +See [keeping things up to date](git.md#keeping-things-up-to-date) for detailed instructions. + +After rebasing, it's recommended to [run the relevant tests locally](tests/intro.md) to catch any issues before CI runs. + +### Waiting for reviews + +> NOTE +> +> Pull request reviewers are often working at capacity, +> and many of them are contributing on a volunteer basis. +> In order to minimize review delays, +> pull request authors and assigned reviewers should ensure that the review label +> (`S-waiting-on-review` and `S-waiting-on-author`) stays updated, +> invoking these commands when appropriate: +> +> - `@rustbot author`: +> the review is finished, +> and PR author should check the comments and take action accordingly. +> +> - `@rustbot ready`: +> the author is ready for a review, +> and this PR will be queued again in the reviewer's queue. + +Please note that the reviewers are humans, who for the most part work on `rustc` in their free time. +This means that they can take some time to respond and review your PR. +It also means that reviewers can miss some PRs that are assigned to them. + +To try to move PRs forward, the Triage WG regularly goes through all PRs that +are waiting for review and haven't been discussed for at least 2 weeks. +If you don't get a review within 2 weeks, feel free to ask the Triage WG on +Zulip ([#t-release/triage]). +They have knowledge of when to ping, who might be on vacation, etc. + +The reviewer may request some changes using the GitHub code review interface. +They may also request special procedures for some PRs. +See [Crater] and [Breaking Changes] chapters for some examples of such procedures. + +Feel free to ask questions or discuss things you don't understand or disagree with. +However, recognize that the PR won't be merged unless someone on the Rust team approves it. +If a reviewer leave a comment like `r=me after fixing ...`, that means they approve the PR and +you can merge it with comment with `@bors r=reviewer-github-id`(e.g. `@bors r=eddyb`) to merge it +after fixing trivial issues. +Note that `r=someone` requires permission and bors could say +something like "🔑 Insufficient privileges..." when commenting `r=someone`. +In that case, you have to ask the reviewer to revisit your PR. + +There are a couple of things that may happen for some PRs during the review process + +- If the change is substantial enough, the reviewer may request an FCP on the PR. + This gives all members of the appropriate team a chance to review the changes. +- If the change may cause breakage, the reviewer may request a [crater] run. + This compiles the compiler with your changes and then attempts to compile all + crates on crates.io with your modified compiler. + This is a great smoke test + to check if you introduced a change to compiler behavior that affects a large + portion of the ecosystem. +- If the diff of your PR is large or the reviewer is busy, your PR may have + some merge conflicts with other PRs that happen to get merged first. + You should fix these merge conflicts using the normal git procedures. + +[crater]: ./tests/crater.md + +[r?]: https://github.com/rust-lang/rust/pull/78133#issuecomment-712692371 +[#t-release/triage]: https://rust-lang.zulipchat.com/#narrow/stream/242269-t-release.2Ftriage +[Crater]: tests/crater.md + +### r+ + +After someone has reviewed your pull request, they will leave an annotation +on the pull request with an `r+`. +It will look something like this: + + @bors r+ + +This tells [@bors], our lovable integration bot, that your pull request has been approved. +The PR then enters the [merge queue], where [@bors] +will run *all* the tests on *every* platform we support. + +Depending on the scale of the change, you may see a slightly different form of `r+`: + + @bors r+ rollup + +The additional `rollup` tells [@bors] that this change should always be "rolled up". +Changes that are rolled up are tested and merged alongside other PRs, to speed the process up. +Typically, only small changes that are expected not to conflict +with one another are marked as "always roll up". + +Be patient; +this can take a while and the queue can sometimes be long. +Also, note that PRs are never merged by hand. + +If it all works out, [@bors] will merge your code into `main` and close the pull request. +Your code will be in the next nightly compiler :) + +[@rustbot]: https://github.com/rustbot +[@bors]: https://github.com/rust-lang/bors + +## After merge + +### Backports + +As for further actions, please keep a sharp look-out for a PR whose title begins with +`[beta]` or `[stable]` and which backports the PR in question. +When that one gets merged, the relevant issue can be closed. +The closing comment should mention all PRs that were involved. +If you don't have the permissions to close the issue, please +leave a comment on the original PR asking the reviewer to close it for you. + +### Reverting a PR + +See ["Reverts"](https://forge.rust-lang.org/compiler/reviews.html#reverts) on Forge. + +If a PR is large enough that it's hard to revert, it's ok to simply disable the trigger for the +problematic code, as shown in [#128271][#128271]. +For MIR optimizations, we can also use the `-Zunsound-mir-opt` option to gate the mir-opt, as shown +in [#132356][#132356]. + +[#128271]: https://github.com/rust-lang/rust/pull/128271 +[#132356]: https://github.com/rust-lang/rust/pull/132356 + +[Breaking Changes]: bug-fix-procedure.md +[compiler test suite]: tests/intro.md +[merge queue]: https://bors.rust-lang.org/queue/rust +[git hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks + diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index ed4e15e9c0851..bc55c2298f89f 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -41,7 +41,7 @@ It is stored in files with `*.no-opt.bc` extension in LLVM bitcode format. Example usage: ``` -cargo install cargo-llvm-lines +cargo install --locked cargo-llvm-lines # On a normal crate you could now run `cargo llvm-lines`, but `x` isn't normal :P # Do a clean before every run, to not mix in the results from previous runs. diff --git a/src/doc/rustc-dev-guide/src/profiling/with-perf.md b/src/doc/rustc-dev-guide/src/profiling/with-perf.md index dd802d71c0404..b55afed47fbdc 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with-perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with-perf.md @@ -7,7 +7,7 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or - Get a clean checkout of rust-lang/rust - Set the following settings in your `bootstrap.toml`: - `rust.debuginfo-level = 1` - enables line debuginfo - - leave `rust.override-allocator` unset - lets you do memory use profiling with valgrind + - leave `build.allocator` unset - lets you do memory use profiling with valgrind - leave everything else the defaults - Run `./x build` to get a full build - Make a rustup toolchain pointing to that result @@ -54,7 +54,7 @@ In case to avoid the issue of `addr2line xxx/elf: could not read first record` w collected data from `cargo`, you may need use the latest version of `addr2line`: ```bash -cargo install addr2line --features="bin" +cargo install --locked addr2line --features="bin" ``` ### Gathering a perf profile from a `perf.rust-lang.org` test @@ -161,7 +161,7 @@ It's probably easiest to explain by walking through how I would analyze NLL perf You can install perf-focus using `cargo install`: ```bash -cargo install perf-focus +cargo install --locked perf-focus ``` ### Example: How much time is spent in MIR borrowck? diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index e58ea4e3e41e9..471b445c14d5a 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -3,8 +3,8 @@ As described in [Overview of the compiler], the Rust compiler is still (as of July 2021) transitioning from a traditional "pass-based" setup to a "demand-driven" system. -The compiler query system is the key to rustc's demand-driven organization. -The idea is pretty simple. + +The compiler's "query system" is the key to rustc's demand-driven organization. Instead of entirely independent passes (parsing, type-checking, etc.), a set of function-like *queries* compute information about the input source. @@ -21,6 +21,11 @@ Moreover, query execution fits nicely into *incremental computation*; the idea is roughly that, when you invoke a query, the result *may* be returned to you by loading stored data from disk.[^incr-comp-detail] +When we execute a query, +we also discover (at runtime!) what other queries it depends on. +This allows us to construct a **dependency graph** of our crate, +which makes incremental computation sound. + Eventually, we want the entire compiler control-flow to be query driven. There will effectively be one top-level query (`compile`) that will run compilation on a crate; this will in turn demand information about that crate, starting from the *end*. diff --git a/src/doc/rustc-dev-guide/src/rustbot.md b/src/doc/rustc-dev-guide/src/rustbot.md index 11a2404c2aa6e..474c3a654d540 100644 --- a/src/doc/rustc-dev-guide/src/rustbot.md +++ b/src/doc/rustc-dev-guide/src/rustbot.md @@ -7,20 +7,8 @@ Its most interesting features for contributors to `rustc` are issue claiming and ## Issue claiming -`@rustbot` exposes a command that allows anyone to assign an issue to themselves. -If you see an issue you want to work on, you can send the following message as a -comment on the issue at hand: - - @rustbot claim - -This will tell `@rustbot` to assign the issue to you if it has no assignee yet. -Note that because of some GitHub restrictions, you may be assigned indirectly, -i.e. `@rustbot` will assign itself as a placeholder and edit the top comment to -reflect the fact that the issue is now assigned to you. - -If you want to unassign from an issue, `@rustbot` has a different command: - - @rustbot release-assignment +Claim an unassigned issue when you intend to work on it. +See [Issue assignment](https://forge.rust-lang.org/triagebot/issue-assignment.html). ## Issue relabeling diff --git a/src/doc/rustc-dev-guide/src/solve/coinduction.md b/src/doc/rustc-dev-guide/src/solve/coinduction.md index 9753f7539c27a..8e5a09a6cab1e 100644 --- a/src/doc/rustc-dev-guide/src/solve/coinduction.md +++ b/src/doc/rustc-dev-guide/src/solve/coinduction.md @@ -13,7 +13,8 @@ Consider the example of `Vec>>: Debug` which results in the followi - `Vec: Debug` - `u32: Debug` -This tree is finite. But not all goals we would want to hold have finite proof trees, +This tree is finite. +But not all goals we would want to hold have finite proof trees, consider the following example: ```rust @@ -36,7 +37,7 @@ This would result in the following proof tree: - `Box>: Send` - ... -This tree would be infinitely large which is exactly what coinduction is about. +This tree would be infinitely large which is exactly what coinduction is about. > To **inductively** prove a goal you need to provide a finite proof tree for it. > To **coinductively** prove a goal the provided proof tree may be infinite. @@ -44,7 +45,8 @@ This tree would be infinitely large which is exactly what coinduction is about. ## Why is coinduction correct When checking whether some trait goals holds, we're asking "does there exist an `impl` -which satisfies this bound". Even if are infinite chains of nested goals, we still have a +which satisfies this bound". +Even if there are infinite chains of nested goals, we still have a unique `impl` which should be used. ## How to implement coinduction @@ -54,11 +56,13 @@ tree as that would take infinite resources, it still makes sense to think of coi from this perspective. As we cannot check for infinite trees, we instead search for patterns for which we know that -they would result in an infinite proof tree. The currently pattern we detect are (canonical) -cycles. If `T: Send` relies on `T: Send` then it's pretty clear that this will just go on forever. +they would result in an infinite proof tree. +Currently, the pattern we detect are (canonical) cycles. +If `T: Send` relies on `T: Send` then it's pretty clear that this will just go on forever. -With cycles we have to be careful with caching. Because of canonicalization of regions and -inference variables encountering a cycle doesn't mean that we would get an infinite proof tree. +With cycles we have to be careful with caching. +Because of canonicalization of regions and +inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. Looking at the following example: ```rust trait Foo {} @@ -67,18 +71,19 @@ struct Wrapper(T); impl Foo for Wrapper> where Wrapper: Foo -{} +{} ``` Proving `Wrapper: Foo` uses the impl `impl Foo for Wrapper>` which constrains -`?0` to `Wrapper` and then requires `Wrapper: Foo`. Due to canonicalization this would be -detected as a cycle. +`?0` to `Wrapper` and then requires `Wrapper: Foo`. +Due to canonicalization this would be detected as a cycle. The idea to solve is to return a *provisional result* whenever we detect a cycle and repeatedly -retry goals until the *provisional result* is equal to the final result of that goal. We -start out by using `Yes` with no constraints as the result and then update it to the result of +retry goals until the *provisional result* is equal to the final result of that goal. +We start out by using `Yes` with no constraints as the result and then update it to the result of the previous iteration whenever we have to rerun. -TODO: elaborate here. We use the same approach as chalk for coinductive cycles. +TODO: elaborate here. +We use the same approach as chalk for coinductive cycles. Note that the treatment for inductive cycles currently differs by simply returning `Overflow`. See [the relevant chapters][chalk] in the chalk book. @@ -89,7 +94,7 @@ See [the relevant chapters][chalk] in the chalk book. We currently only consider auto-traits, `Sized`, and `WF`-goals to be coinductive. In the future we pretty much intend for all goals to be coinductive. -Lets first elaborate on why allowing more coinductive proofs is even desirable. +Let's first elaborate on why allowing more coinductive proofs is even desirable. ### Recursive data types already rely on coinduction... @@ -111,10 +116,13 @@ impl Clone for List { } ``` -We are using `tail.clone()` in this impl. For this we have to prove `Box>: Clone` -which requires `List: Clone` but that relies on the impl which we are currently checking. -By adding that requirement to the `where`-clauses of the impl, which is what we would -do with [perfect derive], we move that cycle into the trait solver and [get an error][ex1]. +We are using `tail.clone()` in this impl. +For this, we have to prove `Box>: Clone`, +which requires `List: Clone`. +But that relies on the impl which we are currently checking. +By adding that requirement to the `where`-clauses of the impl, +something we would do with [perfect derive], +we move that cycle into the trait solver and [get an error][ex1]. ### Recursive data types @@ -167,8 +175,9 @@ Our trait system currently treats super traits, e.g. `trait Trait: SuperTrait`, by 1) requiring that `SuperTrait` has to hold for all types which implement `Trait`, and 2) assuming `SuperTrait` holds if `Trait` holds. -Relying on 2) while proving 1) is unsound. This can only be observed in case of -coinductive cycles. Without cycles, whenever we rely on 2) we must have also +Relying on 2) while proving 1) is unsound. +This can only be observed in case of coinductive cycles. +Without cycles, whenever we rely on 2) we must have also proven 1) without relying on 2) for the used impl of `Trait`. ```rust @@ -197,10 +206,11 @@ at least the ideas of myself - @lcnr - are all far to complex to be reasonable. #### `normalizes_to` goals and progress -A `normalizes_to` goal represents the requirement that `::Assoc` normalizes -to some `U`. This is achieved by defacto first normalizing `::Assoc` and then -equating the resulting type with `U`. It should be a mapping as each projection should normalize -to exactly one type. By simply allowing infinite proof trees, we would get the following behavior: +A `normalizes_to` goal represents the requirement that `::Assoc` normalizes to some `U`. +This is achieved by defacto first normalizing `::Assoc` and then +equating the resulting type with `U`. +It should be a mapping as each projection should normalize to exactly one type. +By simply allowing infinite proof trees, we would get the following behavior: ```rust trait Trait { @@ -213,7 +223,8 @@ impl Trait for () { ``` If we now compute `normalizes_to(<() as Trait>::Assoc, Vec)`, we would resolve the impl -and get the associated type `<() as Trait>::Assoc`. We then equate that with the expected type, +and get the associated type `<() as Trait>::Assoc`. +We then equate that with the expected type, causing us to check `normalizes_to(<() as Trait>::Assoc, Vec)` again. This just goes on forever, resulting in an infinite proof tree. @@ -223,14 +234,16 @@ This means that `<() as Trait>::Assoc` would be equal to any other type which is **WARNING: THIS IS SUBTLE AND MIGHT BE WRONG** -Unlike trait goals, `normalizes_to` has to be *productive*[^1]. A `normalizes_to` goal -is productive once the projection normalizes to a rigid type constructor, +Unlike trait goals, `normalizes_to` has to be *productive*[^1]. +A `normalizes_to` goal is productive once the projection normalizes to a rigid type constructor, so `<() as Trait>::Assoc` normalizing to `Vec<<() as Trait>::Assoc>` would be productive. -A `normalizes_to` goal has two kinds of nested goals. Nested requirements needed to actually -normalize the projection, and the equality between the normalized projection and the -expected type. Only the equality has to be productive. A branch in the proof tree is productive -if it is either finite, or contains at least one `normalizes_to` where the alias is resolved +A `normalizes_to` goal has two kinds of nested goals. +Nested requirements needed to actually normalize the projection, +and the equality between the normalized projection and the expected type. +Only the equality has to be productive. +A branch in the proof tree is productive if it is either finite, +or contains at least one `normalizes_to` where the alias is resolved to a rigid type constructor. Alternatively, we could simply always treat the equate branch of `normalizes_to` as inductive. diff --git a/src/doc/rustc-dev-guide/src/solve/the-solver.md b/src/doc/rustc-dev-guide/src/solve/the-solver.md index 0e095b55437e0..0151c0482d109 100644 --- a/src/doc/rustc-dev-guide/src/solve/the-solver.md +++ b/src/doc/rustc-dev-guide/src/solve/the-solver.md @@ -1,27 +1,28 @@ # The solver Also consider reading the documentation for [the recursive solver in chalk][chalk] -as it is very similar to this implementation and also talks about limitations of this -approach. +as it is very similar to this implementation and also talks about limitations of this approach. [chalk]: https://rust-lang.github.io/chalk/book/recursive.html ## A rough walkthrough -The entry-point of the solver is `InferCtxtEvalExt::evaluate_root_goal`. This -function sets up the root `EvalCtxt` and then calls `EvalCtxt::evaluate_goal`, +The entry-point of the solver is `InferCtxtEvalExt::evaluate_root_goal`. +This function sets up the root `EvalCtxt` and then calls `EvalCtxt::evaluate_goal`, to actually enter the trait solver. `EvalCtxt::evaluate_goal` handles [canonicalization](./canonicalization.md), caching, -overflow, and solver cycles. Once that is done, it creates a nested `EvalCtxt` with a +overflow, and solver cycles. +Once that is done, it creates a nested `EvalCtxt` with a separate local `InferCtxt` and calls `EvalCtxt::compute_goal`, which is responsible for the -'actual solver behavior'. We match on the `PredicateKind`, delegating to a separate function -for each one. +'actual solver behavior'. +We match on the `PredicateKind`, delegating to a separate function for each one. For trait goals, such a `Vec: Clone`, `EvalCtxt::compute_trait_goal` has to collect all the possible ways this goal can be proven via -`EvalCtxt::assemble_and_evaluate_candidates`. Each candidate is handled in -a separate "probe", to not leak inference constraints to the other candidates. +`EvalCtxt::assemble_and_evaluate_candidates`. +Each candidate is handled in a separate "probe", +to not leak inference constraints to the other candidates. We then try to merge the assembled candidates via `EvalCtxt::merge_candidates`. @@ -30,10 +31,10 @@ We then try to merge the assembled candidates via `EvalCtxt::merge_candidates`. ### `EvalCtxt::add_goal` To prove nested goals, we don't directly call `EvalCtxt::compute_goal`, but instead -add the goal to the `EvalCtxt` with `EvalCtxt::all_goal`. We then prove all nested -goals together in either `EvalCtxt::try_evaluate_added_goals` or -`EvalCtxt::evaluate_added_goals_and_make_canonical_response`. This allows us to handle -inference constraints from later goals. +add the goal to the `EvalCtxt` with `EvalCtxt::add_goal`. +We then prove all nested goals together in either `EvalCtxt::try_evaluate_added_goals` or +`EvalCtxt::evaluate_added_goals_and_make_canonical_response`. +This allows us to handle inference constraints from later goals. E.g. if we have both `?x: Debug` and `(): ConstrainToU8` as nested goals, then proving `?x: Debug` is initially ambiguous, but after proving `(): ConstrainToU8` @@ -42,16 +43,19 @@ we constrain `?x` to `u8` and proving `u8: Debug` succeeds. ### Matching on `TyKind` We lazily normalize types in the solver, so we always have to assume that any types -and constants are potentially unnormalized. This means that matching on `TyKind` can easily -be incorrect. - -We handle normalization in two different ways. When proving `Trait` goals when normalizing -associated types, we separately assemble candidates depending on whether they structurally -match the self type. Candidates which match on the self type are handled in +and constants are potentially unnormalized. +This means that matching on `TyKind` can easily be incorrect. + +We handle normalization in two different ways. +When proving `Trait` goals when normalizing associated types, +we separately assemble candidates depending on whether they structurally +match the self type. +Candidates which match on the self type are handled in `EvalCtxt::assemble_candidates_via_self_ty` which recurses via -`EvalCtxt::assemble_candidates_after_normalizing_self_ty`, which normalizes the self type -by one level. In all other cases we have to match on a `TyKind` we first use -`EvalCtxt::try_normalize_ty` to normalize the type as much as possible. +`EvalCtxt::assemble_candidates_after_normalizing_self_ty`, +which normalizes the self type by one level. +In all other cases where we have to match on a `TyKind`, +we first use `EvalCtxt::try_normalize_ty` to normalize the type as much as possible. ### Higher ranked goals @@ -61,16 +65,19 @@ eagerly instantiates `'a` with a placeholder and then recursively proves ### Dealing with choice -Some goals can be proven in multiple ways. In these cases we try each option in -a separate "probe" and then attempt to merge the resulting responses by using -`EvalCtxt::try_merge_responses`. If merging the responses fails, we use -`EvalCtxt::flounder` instead, returning ambiguity. For some goals, we try to -incompletely prefer some choices over others in case `EvalCtxt::try_merge_responses` -fails. +Some goals can be proven in multiple ways. +In these cases, +we try each option in a separate "probe", +and then attempt to merge the resulting responses by using `EvalCtxt::try_merge_responses`. +If merging the responses fails, we use `EvalCtxt::flounder` instead, returning ambiguity. +For some goals, +we try to incompletely prefer some choices over others +in case `EvalCtxt::try_merge_responses` fails. ## Learning more -The solver should be fairly self-contained. I hope that the above information provides a -good foundation when looking at the code itself. Please reach out on Zulip if you get stuck +The solver should be fairly self-contained. +I hope that the above information provides a good foundation when looking at the code itself. +Please reach out on Zulip if you get stuck while doing so or there are some quirks and design decisions which were unclear and deserve better comments or should be mentioned here. diff --git a/src/doc/rustc-dev-guide/src/tests/perf.md b/src/doc/rustc-dev-guide/src/tests/perf.md index 567b2d7a97e48..50825a706cbe6 100644 --- a/src/doc/rustc-dev-guide/src/tests/perf.md +++ b/src/doc/rustc-dev-guide/src/tests/perf.md @@ -1,5 +1,26 @@ # Performance testing +## Performance considerations + +Compiler performance is important. +We have put a lot of effort over the last few years into [gradually improving it][perfdash]. + +[perfdash]: https://perf.rust-lang.org/dashboard.html + +If you suspect that your change may cause a performance regression (or +improvement), you can request a "perf run" (and your reviewer may also request one +before approving). +This is yet another bot that will compile a collection of +benchmarks on a compiler with your changes. +The numbers are reported +[here][perf], and you can see a comparison of your changes against the latest `main`. + +> For an introduction to the performance of Rust code in general +> which would also be useful in rustc development, see [The Rust Performance Book]. + +[perf]: https://perf.rust-lang.org +[The Rust Performance Book]: https://nnethercote.github.io/perf-book/ + ## rustc-perf A lot of work is put into improving the performance of the compiler and diff --git a/src/doc/rustc-dev-guide/src/the-parser.md b/src/doc/rustc-dev-guide/src/the-parser.md index 601a81e2e485b..b81728ab273e8 100644 --- a/src/doc/rustc-dev-guide/src/the-parser.md +++ b/src/doc/rustc-dev-guide/src/the-parser.md @@ -4,33 +4,33 @@ The very first thing the compiler does is take the program (in UTF-8 Unicode tex and turn it into a data format the compiler can work with more conveniently than strings. This happens in two stages: Lexing and Parsing. - 1. _Lexing_ takes strings and turns them into streams of [tokens]. For - example, `foo.bar + buz` would be turned into the tokens `foo`, `.`, `bar`, - `+`, and `buz`. This is implemented in [`rustc_lexer`][lexer]. + 1. _Lexing_ takes strings and turns them into streams of [tokens]. + For example, `foo.bar + buz` would be turned into the tokens `foo`, `.`, `bar`, + `+`, and `buz`. + This is implemented in [`rustc_lexer`][lexer]. [tokens]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/token/index.html [lexer]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lexer/index.html 2. _Parsing_ takes streams of tokens and turns them into a structured form which is easier for the compiler to work with, usually called an [*Abstract - Syntax Tree* (AST)][ast] . + Syntax Tree* (AST)][ast]. ## The AST The AST mirrors the structure of a Rust program in memory, using a `Span` to -link a particular AST node back to its source text. The AST is defined in -[`rustc_ast`][rustc_ast], along with some definitions for tokens and token +link a particular AST node back to its source text. +The AST is defined in [`rustc_ast`][rustc_ast], along with some definitions for tokens and token streams, data structures/traits for mutating ASTs, and shared definitions for -other AST-related parts of the compiler (like the lexer and -macro-expansion). +other AST-related parts of the compiler (like the lexer and macro-expansion). Every node in the AST has its own [`NodeId`], including top-level items -such as structs, but also individual statements and expressions. A [`NodeId`] -is an identifier number that uniquely identifies an AST node within a crate. +such as structs, but also individual statements and expressions. +A [`NodeId`] is an identifier number that uniquely identifies an AST node within a crate. However, because they are absolute within a crate, adding or removing a single -node in the AST causes all the subsequent [`NodeId`]s to change. This renders -[`NodeId`]s pretty much useless for incremental compilation, where you want as +node in the AST causes all the subsequent [`NodeId`]s to change. +This renders [`NodeId`]s pretty much useless for incremental compilation, where you want as few things as possible to change. [`NodeId`]s are used in all the `rustc` bits that operate directly on the AST, @@ -41,15 +41,14 @@ like macro expansion and name resolution (more on these over the next couple cha ## Parsing The parser is defined in [`rustc_parse`][rustc_parse], along with a -high-level interface to the lexer and some validation routines that run after -macro expansion. In particular, the [`rustc_parse::parser`][parser] contains -the parser implementation. +high-level interface to the lexer and some validation routines that run after macro expansion. +In particular, the [`rustc_parse::parser`][parser] contains the parser implementation. The main entrypoint to the parser is via the various `parse_*` functions and others in -[rustc_parse][rustc_parse]. They let you do things like turn a [`SourceFile`][sourcefile] +[rustc_parse][rustc_parse]. +They let you do things like turn a [`SourceFile`][sourcefile] (e.g. the source in a single file) into a token stream, create a parser from -the token stream, and then execute the parser to get a [`Crate`] (the root AST -node). +the token stream, and then execute the parser to get a [`Crate`] (the root AST node). To minimize the amount of copying that is done, both [`Lexer`] and [`Parser`] have lifetimes which bind them to the parent [`ParseSess`]. @@ -63,13 +62,13 @@ Expansion itself may require parsing the output of a macro, which may reveal mor Code for lexical analysis is split between two crates: -- [`rustc_lexer`] crate is responsible for breaking a `&str` into chunks - constituting tokens. Although it is popular to implement lexers as generated - finite state machines, the lexer in [`rustc_lexer`] is hand-written. +- [`rustc_lexer`] crate is responsible for breaking a `&str` into chunks constituting tokens. + Although it is popular to implement lexers as generated finite state machines, + the lexer in [`rustc_lexer`] is hand-written. -- [`Lexer`] integrates [`rustc_lexer`] with data structures specific to - `rustc`. Specifically, it adds `Span` information to tokens returned by - [`rustc_lexer`] and interns identifiers. +- [`Lexer`] integrates [`rustc_lexer`] with data structures specific to `rustc`. + Specifically, + it adds `Span` information to tokens returned by [`rustc_lexer`] and interns identifiers. [`Crate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.Crate.html [`Parser`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html 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 3b4072394e787..1a2e9b225c21f 100644 --- a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md @@ -10,7 +10,7 @@ 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 +Only ADTs and [CTAs](../appendix/glossary.md#cta) 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. diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthroughs/lang-feature.md similarity index 77% rename from src/doc/rustc-dev-guide/src/walkthrough.md rename to src/doc/rustc-dev-guide/src/walkthroughs/lang-feature.md index b7eb2b56617bc..f2bb3366bce50 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthroughs/lang-feature.md @@ -1,14 +1,7 @@ -# Walkthrough: a typical contribution +# Walkthrough: a new language feature, from design to stabilization -There are _a lot_ of ways to contribute to the Rust compiler, including fixing -bugs, improving performance, helping design features, providing feedback on existing features, etc. -This chapter does not claim to scratch the surface. -Instead, it walks through the design and implementation of a new feature. -Not all of the steps and processes described here are needed for every -contribution, and I will try to point those out as they arise. - -In general, if you are interested in making a contribution and aren't sure -where to start, please feel free to ask! +This chapter walks through the design and implementation of a new language feature. +Some of these steps are specific to language features, but many also extend to library features. ## Overview @@ -200,51 +193,7 @@ The feature gate is removed when the feature is stabilized. **Most bug fixes and improvements** don't require a feature gate. You can just make your changes/improvements. -When you open a PR on the [rust-lang/rust], a bot will assign your PR to a reviewer. -If there is a particular Rust team member you are working with, you can -request that reviewer by leaving a comment on the thread with `r? -@reviewer-github-id` (e.g. `r? @eddyb`). If you don't know who to request, -don't request anyone; -the bot will assign someone automatically based on which files you changed. - -The reviewer may request changes before they approve your PR, they may mark the PR with label -"S-waiting-on-author" after leaving comments, this means that the PR is blocked on you to make -some requested changes. -When you finished iterating on the changes, you can mark the PR as -`S-waiting-on-review` again by leaving a comment with `@rustbot ready`, this will remove the -`S-waiting-on-author` label and add the `S-waiting-on-review` label. - -Feel free to ask questions or discuss things you don't understand or disagree with. -However, recognize that the PR won't be merged unless someone on the Rust team approves it. -If a reviewer leave a comment like `r=me after fixing ...`, that means they approve the PR and -you can merge it with comment with `@bors r=reviewer-github-id`(e.g. `@bors r=eddyb`) to merge it -after fixing trivial issues. -Note that `r=someone` requires permission and bors could say -something like "🔑 Insufficient privileges..." when commenting `r=someone`. -In that case, you have to ask the reviewer to revisit your PR. - -When your reviewer approves the PR, it will go into a queue for yet another bot called `@bors`. -`@bors` manages the CI build/merge queue. -When your PR reaches the head of the `@bors` queue, `@bors` will test out the merge by running all -tests against your PR on GitHub Actions. -This takes a lot of time to finish. -If all tests pass, the PR is merged and becomes part of the next nightly compiler! - -There are a couple of things that may happen for some PRs during the review process - -- If the change is substantial enough, the reviewer may request an FCP on the PR. - This gives all members of the appropriate team a chance to review the changes. -- If the change may cause breakage, the reviewer may request a [crater] run. - This compiles the compiler with your changes and then attempts to compile all - crates on crates.io with your modified compiler. - This is a great smoke test - to check if you introduced a change to compiler behavior that affects a large - portion of the ecosystem. -- If the diff of your PR is large or the reviewer is busy, your PR may have - some merge conflicts with other PRs that happen to get merged first. - You should fix these merge conflicts using the normal git procedures. - -[crater]: ./tests/crater.md +See [PR Lifecycle](../pr-lifecycle.md) for information about how to open a PR and get it merged. If you are not doing a new feature or something like that (e.g. if you are fixing a bug), then that's it! @@ -293,6 +242,6 @@ A note is added to the [Release notes][relnotes] about the feature. [stab]: https://github.com/rust-lang/rust/pull/56245 -Steps to stabilize the feature can be found at [Stabilizing Features](./stabilization-guide.md). +Steps to stabilize the feature can be found at [Stabilizing Features](../stabilization-guide.md). [relnotes]: https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md diff --git a/src/doc/rustc-dev-guide/src/walkthroughs/test.md b/src/doc/rustc-dev-guide/src/walkthroughs/test.md new file mode 100644 index 0000000000000..70eff326a9f24 --- /dev/null +++ b/src/doc/rustc-dev-guide/src/walkthroughs/test.md @@ -0,0 +1,135 @@ +# Walkthrough: adding a new test + +This chapter gives an example of a small change that you could make as your first contribution to Rust, +using [rust#59333] and [rust#161442] as an example. + +[rust#59333]: https://github.com/rust-lang/rust/issues/59333 +[rust#161442]: https://github.com/rust-lang/rust/issues/161442 + +## Find an `E-needs-test` issue to work on + +See ["What should I work on?"](../getting-started.md#What-should-I-work-on) for a list of possible tasks you could try out. +Here, we've chosen an `E-needs-test` issue: +[rust#59333](https://github.com/rust-lang/rust/issues/59333). +This is an especially good fit because it has an example +[directly in the issue](https://github.com/rust-lang/rust/issues/59333#issuecomment-555973113), +without needing additional work from you to minimize the bug. +Of course, it's always very helpful for you to take `E-needs-test` that *doesn't* have a minimal example and create one. + +## Reproduce the issue + +The example here was posted in 2019, fully 7 years ago (at time of writing). +Quite a lot of things change in the compiler in that period of time. +To make sure the test is still accurate, *reproduce it with the most recent compiler*. +An easy way to do this is with [play.rust-lang.org](https://play.rust-lang.org/?version=nightly) on the `nightly` branch, +or [rust.godbolt.org](https://rust.godbolt.org/) with `rustc nightly`. +You can also use `rustc +nightly` locally if you need complicated setup that isn't possible on Playground. + +## Convert the issue to a test + +Check out and set up the `rust-lang/rust` repo, as documented in [Quickstart](../building/quickstart.md): + +```console +$ git clone https://github.com/rust-lang/rust +$ cd rust +$ ./x setup compiler +$ ./x build library +``` + +Here, we use `compiler` as the default profile, since the bug we're fixing is related to the compiler. +If you're adding a unit test to the standard library, you'd use `./x setup library`. + +This will also suggest setting up a [`.git/hooks/pre-push` check][pre-push]. +This is optional, but recommended. + +[pre-push]: ../building/suggested.md#installing-a-pre-push-hook + +We also started a build in the background with `./x build library`. +Rust unfortunately takes quite a while to build, +so starting a build early lets it run in the background while you're working on other things. + +See [UI tests](../tests/ui.md) for a guide on adding new tests. +In rare cases, you may need a [run-make](../tests/compiletest.md#run-make-tests) or even more specialized kind of test. +See [Compiletest](../tests/compiletest.md) for more information. + +In our case, our test is fairly simple: + +```rust +// Save this file to `tests/ui/lint/dead-code/type-alias-used-in-impl-59333.rs`. + +//@ check-pass +//! Regression test for . +//! A type alias used only as (part of) the self type of an impl was +//! incorrectly flagged as dead code. + +#![deny(dead_code)] + +struct Runner; + +type RuntimeImpl = Runner; + +trait Runtime { + fn run(&mut self); +} + +impl Runtime for &mut RuntimeImpl { + fn run(&mut self) {} +} + +struct Walker; + +type WalkerImpl = Walker; + +trait Walk { + fn walk(&self) {} +} + +impl Walk for WalkerImpl {} + +fn main() { + let mut runner = Runner; + (&mut runner).run(); + Walker.walk(); +} +``` + +Most of the details here don't matter too much, but note the `//@ check-pass` and `#![deny(dead_code)]` at the top. +Together, those ensure that the compiler doesn't emit a `dead_code` lint when compiling this file. + +Also note the "Regression test for ..." comment. +This is *very* helpful for your reviewer, since it helps them understand what the test is doing and whether there's a simpler way to test the behavior. +Please do your best to write a complete description for the test. + +Run your test. +[rust#161442] named its test `tests/ui/lint/dead-code/type-alias-used-in-impl-59333.rs`, +so you could run: + +``` +./x test tests/ui/lint/dead-code/type-alias-used-in-impl-59333.rs +``` + +If that passes, your test is ready. + +## Open a PR + +Follow the instructions in [PR lifecycle](../pr-lifecycle.md). + +First, run the pre-push check if you didn't set it up earlier: + +```sh +./x test tidy +``` + +Then, [open the PR](https://guides.github.com/activities/forking/#making-a-pull-request): + +``` +git switch --create issue-59333-test +git add tests/ui/lint/dead-code/type-alias-used-in-impl-59333.rs +git commit +git remote add personal https://github.com/YOUR_USERNAME_HERE/rust.git +git push --set-upstream personal issue-59333-test +``` + +## Review and feedback + +See [PR lifecycle](../pr-lifecycle.md) for information about review and merging.