From da1360d981f272cc1c3aa81b1fa013fff5b2676d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 3 Feb 2023 18:53:27 +0000 Subject: [PATCH 1/4] Provide structured suggestion for binding needing type on E0594 Partially address #45405. --- .../src/diagnostics/mutability_errors.rs | 60 +++++++++++++++++-- ...orrow-mut-base-ptr-in-aliasable-loc.stderr | 8 ++- tests/ui/borrowck/issue-85765.rs | 6 +- tests/ui/borrowck/issue-85765.stderr | 24 +++++--- tests/ui/borrowck/issue-91206.rs | 2 +- tests/ui/borrowck/issue-91206.stderr | 8 ++- tests/ui/borrowck/issue-92015.stderr | 7 ++- tests/ui/issues/issue-51515.rs | 1 + tests/ui/issues/issue-51515.stderr | 9 ++- 9 files changed, 95 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 40f518b33cf..cf3240226fb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -606,12 +606,60 @@ pub(crate) fn report_mutability_error( } } Some((false, err_label_span, message)) => { - err.span_label( - err_label_span, - &format!( - "consider changing this binding's type to be: `{message}`" - ), - ); + struct V { + span: Span, + hir_id: Option, + } + + impl<'tcx> Visitor<'tcx> for V { + fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { + if let hir::StmtKind::Local(local) = s.kind { + if local.pat.span == self.span { + self.hir_id = Some(local.hir_id); + } + } + hir::intravisit::walk_stmt(self, s); + } + } + let hir_map = self.infcx.tcx.hir(); + let pat = loop { + // Poor man's try block + let def_id = self.body.source.def_id(); + let hir_id = + hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap()); + let node = hir_map.find(hir_id); + let Some(hir::Node::Item(item)) = node else { break None; }; + let hir::ItemKind::Fn(.., body_id) = item.kind else { break None; }; + let body = self.infcx.tcx.hir().body(body_id); + let mut v = V { span: err_label_span, hir_id: None }; + v.visit_body(body); + break v.hir_id; + }; + if let Some(hir_id) = pat + && let Some(hir::Node::Local(local)) = hir_map.find(hir_id) + { + let (changing, span, sugg) = match local.ty { + Some(ty) => ("changing", ty.span, message), + None => ( + "specifying", + local.pat.span.shrink_to_hi(), + format!(": {message}"), + ), + }; + err.span_suggestion_verbose( + span, + &format!("consider {changing} this binding's type"), + sugg, + Applicability::HasPlaceholders, + ); + } else { + err.span_label( + err_label_span, + &format!( + "consider changing this binding's type to be: `{message}`" + ), + ); + } } None => {} } diff --git a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr index ce9f7aa050a..dd0817ff233 100644 --- a/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr +++ b/tests/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.stderr @@ -1,11 +1,13 @@ error[E0594]: cannot assign to `**t1`, which is behind a `&` reference --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5 | -LL | let t1 = t0; - | -- consider changing this binding's type to be: `&mut &mut isize` -LL | let p: &isize = &**t0; LL | **t1 = 22; | ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written + | +help: consider specifying this binding's type + | +LL | let t1: &mut &mut isize = t0; + | +++++++++++++++++ error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21 diff --git a/tests/ui/borrowck/issue-85765.rs b/tests/ui/borrowck/issue-85765.rs index 1598cd5d3c8..76e0b517354 100644 --- a/tests/ui/borrowck/issue-85765.rs +++ b/tests/ui/borrowck/issue-85765.rs @@ -1,7 +1,7 @@ fn main() { let mut test = Vec::new(); let rofl: &Vec> = &mut test; - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type rofl.push(Vec::new()); //~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference //~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable @@ -15,14 +15,14 @@ fn main() { #[rustfmt::skip] let x: &usize = &mut{0}; - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type *x = 1; //~^ ERROR cannot assign to `*x`, which is behind a `&` reference //~| NOTE `x` is a `&` reference, so the data it refers to cannot be written #[rustfmt::skip] let y: &usize = &mut(0); - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider changing this binding's type *y = 1; //~^ ERROR cannot assign to `*y`, which is behind a `&` reference //~| NOTE `y` is a `&` reference, so the data it refers to cannot be written diff --git a/tests/ui/borrowck/issue-85765.stderr b/tests/ui/borrowck/issue-85765.stderr index 7da7dba68ab..b4bb128cbb4 100644 --- a/tests/ui/borrowck/issue-85765.stderr +++ b/tests/ui/borrowck/issue-85765.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference --> $DIR/issue-85765.rs:5:5 | -LL | let rofl: &Vec> = &mut test; - | ---- consider changing this binding's type to be: `&mut Vec>` -LL | LL | rofl.push(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider changing this binding's type + | +LL | let rofl: &mut Vec> = &mut test; + | ~~~~~~~~~~~~~~~~~~ error[E0594]: cannot assign to `*r`, which is behind a `&` reference --> $DIR/issue-85765.rs:12:5 @@ -21,20 +23,24 @@ LL | let r = &mut mutvar; error[E0594]: cannot assign to `*x`, which is behind a `&` reference --> $DIR/issue-85765.rs:19:5 | -LL | let x: &usize = &mut{0}; - | - consider changing this binding's type to be: `&mut usize` -LL | LL | *x = 1; | ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this binding's type + | +LL | let x: &mut usize = &mut{0}; + | ~~~~~~~~~~ error[E0594]: cannot assign to `*y`, which is behind a `&` reference --> $DIR/issue-85765.rs:26:5 | -LL | let y: &usize = &mut(0); - | - consider changing this binding's type to be: `&mut usize` -LL | LL | *y = 1; | ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this binding's type + | +LL | let y: &mut usize = &mut(0); + | ~~~~~~~~~~ error: aborting due to 4 previous errors diff --git a/tests/ui/borrowck/issue-91206.rs b/tests/ui/borrowck/issue-91206.rs index 67407c1eae3..e062a253767 100644 --- a/tests/ui/borrowck/issue-91206.rs +++ b/tests/ui/borrowck/issue-91206.rs @@ -9,7 +9,7 @@ fn get_inner_ref(&self) -> &Vec { fn main() { let client = TestClient; let inner = client.get_inner_ref(); - //~^ NOTE consider changing this binding's type to be + //~^ HELP consider specifying this binding's type inner.clear(); //~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596] //~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable diff --git a/tests/ui/borrowck/issue-91206.stderr b/tests/ui/borrowck/issue-91206.stderr index 12d8d27c5f0..6653d497873 100644 --- a/tests/ui/borrowck/issue-91206.stderr +++ b/tests/ui/borrowck/issue-91206.stderr @@ -1,11 +1,13 @@ error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference --> $DIR/issue-91206.rs:13:5 | -LL | let inner = client.get_inner_ref(); - | ----- consider changing this binding's type to be: `&mut Vec` -LL | LL | inner.clear(); | ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | +help: consider specifying this binding's type + | +LL | let inner: &mut Vec = client.get_inner_ref(); + | +++++++++++++++++ error: aborting due to previous error diff --git a/tests/ui/borrowck/issue-92015.stderr b/tests/ui/borrowck/issue-92015.stderr index 62b1183e71b..ea4f9abb87d 100644 --- a/tests/ui/borrowck/issue-92015.stderr +++ b/tests/ui/borrowck/issue-92015.stderr @@ -1,10 +1,13 @@ error[E0594]: cannot assign to `*foo`, which is behind a `&` reference --> $DIR/issue-92015.rs:6:5 | -LL | let foo = Some(&0).unwrap(); - | --- consider changing this binding's type to be: `&mut i32` LL | *foo = 1; | ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written + | +help: consider specifying this binding's type + | +LL | let foo: &mut i32 = Some(&0).unwrap(); + | ++++++++++ error: aborting due to previous error diff --git a/tests/ui/issues/issue-51515.rs b/tests/ui/issues/issue-51515.rs index 797c1085d51..84e09afac0a 100644 --- a/tests/ui/issues/issue-51515.rs +++ b/tests/ui/issues/issue-51515.rs @@ -5,6 +5,7 @@ fn main() { *foo = 32; //~^ ERROR cannot assign to `*foo`, which is behind a `&` reference let bar = foo; + //~^ HELP consider specifying this binding's type *bar = 64; //~^ ERROR cannot assign to `*bar`, which is behind a `&` reference } diff --git a/tests/ui/issues/issue-51515.stderr b/tests/ui/issues/issue-51515.stderr index c4e61e71953..94e5c9f1b83 100644 --- a/tests/ui/issues/issue-51515.stderr +++ b/tests/ui/issues/issue-51515.stderr @@ -10,12 +10,15 @@ LL | let foo = &mut 16; | ~~~~~~~ error[E0594]: cannot assign to `*bar`, which is behind a `&` reference - --> $DIR/issue-51515.rs:8:5 + --> $DIR/issue-51515.rs:9:5 | -LL | let bar = foo; - | --- consider changing this binding's type to be: `&mut i32` LL | *bar = 64; | ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written + | +help: consider specifying this binding's type + | +LL | let bar: &mut i32 = foo; + | ++++++++++ error: aborting due to 2 previous errors From e6c56cda09633c0388ef4c6c9e97d064db829cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 3 Feb 2023 23:41:39 +0000 Subject: [PATCH 2/4] review comments --- .../src/diagnostics/mutability_errors.rs | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index cf3240226fb..9f37b915b77 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -606,12 +606,12 @@ pub(crate) fn report_mutability_error( } } Some((false, err_label_span, message)) => { - struct V { + struct BindingFinder { span: Span, hir_id: Option, } - impl<'tcx> Visitor<'tcx> for V { + impl<'tcx> Visitor<'tcx> for BindingFinder { fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { if let hir::StmtKind::Local(local) = s.kind { if local.pat.span == self.span { @@ -622,20 +622,23 @@ fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { } } let hir_map = self.infcx.tcx.hir(); - let pat = loop { - // Poor man's try block - let def_id = self.body.source.def_id(); - let hir_id = - hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap()); - let node = hir_map.find(hir_id); - let Some(hir::Node::Item(item)) = node else { break None; }; - let hir::ItemKind::Fn(.., body_id) = item.kind else { break None; }; - let body = self.infcx.tcx.hir().body(body_id); - let mut v = V { span: err_label_span, hir_id: None }; + let def_id = self.body.source.def_id(); + let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local()); + let node = hir_map.find(hir_id); + let hir_id = if let Some(hir::Node::Item(item)) = node + && let hir::ItemKind::Fn(.., body_id) = item.kind + { + let body = hir_map.body(body_id); + let mut v = BindingFinder { + span: err_label_span, + hir_id: None, + }; v.visit_body(body); - break v.hir_id; + v.hir_id + } else { + None }; - if let Some(hir_id) = pat + if let Some(hir_id) = hir_id && let Some(hir::Node::Local(local)) = hir_map.find(hir_id) { let (changing, span, sugg) = match local.ty { From d78fb1a0157f64e937b2cd1d9a575488e1e36b94 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Sat, 4 Feb 2023 11:48:50 +0000 Subject: [PATCH 3/4] Remove Esteban from review queues for a while --- triagebot.toml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index d54d80c5adb..62a99b70438 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -441,15 +441,15 @@ cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakar [mentions."compiler/rustc_error_messages"] message = "`rustc_error_messages` was changed" -cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] [mentions."compiler/rustc_errors/src/translation.rs"] message = "`rustc_errors::translation` was changed" -cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] [mentions."compiler/rustc_macros/src/diagnostics"] message = "`rustc_macros::diagnostics` was changed" -cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"] +cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] [mentions."compiler/rustc_target/src/spec"] message = """ @@ -475,7 +475,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/contributing.html" [assign.adhoc_groups] compiler-team = [ "@cjgillot", - "@estebank", "@petrochenkov", "@davidtwco", "@oli-obk", @@ -532,13 +531,11 @@ incremental = [ diagnostics = [ "@compiler-errors", "@davidtwco", - "@estebank", "@oli-obk", "@TaKO8Ki", ] parser = [ "@davidtwco", - "@estebank", "@nnethercote", "@petrochenkov", ] From 6558326e7b5f8f5591b0a1289bc48099ae473a01 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Fri, 20 Jan 2023 11:04:44 +0300 Subject: [PATCH 4/4] consolidate bootstrap docs Signed-off-by: ozkanonur --- src/bootstrap/README.md | 199 ++++++++-------------------------------- src/bootstrap/lib.rs | 87 ------------------ 2 files changed, 38 insertions(+), 248 deletions(-) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 8dce9e79e16..71eee8968e2 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -4,105 +4,31 @@ This is an in-progress README which is targeted at helping to explain how Rust is bootstrapped and in general, some of the technical details of the build system. -## Using rustbuild +Note that this README only covers internal information, not how to use the tool. +Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information. -The rustbuild build system has a primary entry point, a top level `x.py` script: +[bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html -```sh -$ python ./x.py build -``` +## Introduction -Note that if you're on Unix, you should be able to execute the script directly: +The build system defers most of the complicated logic managing invocations +of rustc and rustdoc to Cargo itself. However, moving through various stages +and copying artifacts is still necessary for it to do. Each time rustbuild +is invoked, it will iterate through the list of predefined steps and execute +each serially in turn if it matches the paths passed or is a default rule. +For each step rustbuild relies on the step internally being incremental and +parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded +to appropriate test harnesses and such. -```sh -$ ./x.py build -``` - -The script accepts commands, flags, and arguments to determine what to do: - -* `build` - a general purpose command for compiling code. Alone, `build` will - bootstrap the entire compiler, and otherwise, arguments passed indicate what to - build. For example: - - ``` - # build the whole compiler - ./x.py build --stage 2 - - # build the stage1 compiler - ./x.py build - - # build stage0 libstd - ./x.py build --stage 0 library/std - - # build a particular crate in stage0 - ./x.py build --stage 0 library/test - ``` - - If files that would normally be rebuilt from stage 0 are dirty, the rebuild can be - overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps - that belong to stage n or earlier: - - ``` - # build stage 1, keeping old build products for stage 0 - ./x.py build --keep-stage 0 - ``` - -* `test` - a command for executing unit tests. Like the `build` command, this - will execute the entire test suite by default, and otherwise, it can be used to - select which test suite is run: - - ``` - # run all unit tests - ./x.py test - - # execute tool tests - ./x.py test tidy - - # execute the UI test suite - ./x.py test tests/ui - - # execute only some tests in the UI test suite - ./x.py test tests/ui --test-args substring-of-test-name - - # execute tests in the standard library in stage0 - ./x.py test --stage 0 library/std - - # execute tests in the core and standard library in stage0, - # without running doc tests (thus avoid depending on building the compiler) - ./x.py test --stage 0 --no-doc library/core library/std - - # execute all doc tests - ./x.py test src/doc - ``` - -* `doc` - a command for building documentation. Like above, can take arguments - for what to document. - -## Configuring rustbuild - -rustbuild offers a TOML-based configuration system with a `config.toml` -file. An example of this configuration can be found at `config.toml.example`, -and the configuration file can also be passed as `--config path/to/config.toml` -if the build system is being invoked manually (via the python script). - -You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it. - -Finally, rustbuild makes use of the [cc-rs crate] which has [its own -method][env-vars] of configuring C compilers and C flags via environment -variables. - -[cc-rs crate]: https://github.com/alexcrichton/cc-rs -[env-vars]: https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables - -## Build stages +## Build phases The rustbuild build system goes through a few phases to actually build the compiler. What actually happens when you invoke rustbuild is: -1. The entry point script, `x.py` is run. This script is - responsible for downloading the stage0 compiler/Cargo binaries, and it then - compiles the build system itself (this folder). Finally, it then invokes the - actual `bootstrap` binary build system. +1. The entry point script(`x` for unix like systems, `x.ps1` for windows systems, + `x.py` cross-platform) is run. This script is responsible for downloading the stage0 + compiler/Cargo binaries, and it then compiles the build system itself (this folder). + Finally, it then invokes the actual `bootstrap` binary build system. 2. In Rust, `bootstrap` will slurp up all configuration, perform a number of sanity checks (whether compilers exist, for example), and then start building the stage0 artifacts. @@ -115,24 +41,6 @@ compiler. What actually happens when you invoke rustbuild is: The goal of each stage is to (a) leverage Cargo as much as possible and failing that (b) leverage Rust as much as possible! -## Incremental builds - -You can configure rustbuild to use incremental compilation with the -`--incremental` flag: - -```sh -$ ./x.py build --incremental -``` - -The `--incremental` flag will store incremental compilation artifacts -in `build//stage0-incremental`. Note that we only use incremental -compilation for the stage0 -> stage1 compilation -- this is because -the stage1 compiler is changing, and we don't try to cache and reuse -incremental artifacts across different versions of the compiler. - -You can always drop the `--incremental` to build as normal (but you -will still be using the local nightly as your bootstrap). - ## Directory Layout This build system houses all output under the `build` directory, which looks @@ -236,63 +144,31 @@ build/ # system will link (using hard links) output from stageN-{std,rustc} into # each of these directories. # - # In theory, there is no extra build output in these directories. + # In theory these are working rustc sysroot directories, meaning there is + # no extra build output in these directories. stage1/ stage2/ stage3/ ``` -## Cargo projects - -The current build is unfortunately not quite as simple as `cargo build` in a -directory, but rather the compiler is split into three different Cargo projects: - -* `library/std` - the standard library -* `library/test` - testing support, depends on libstd -* `compiler/rustc` - the actual compiler itself - -Each "project" has a corresponding Cargo.lock file with all dependencies, and -this means that building the compiler involves running Cargo three times. The -structure here serves two goals: - -1. Facilitating dependencies coming from crates.io. These dependencies don't - depend on `std`, so libstd is a separate project compiled ahead of time - before the actual compiler builds. -2. Splitting "host artifacts" from "target artifacts". That is, when building - code for an arbitrary target, you don't need the entire compiler, but you'll - end up needing libraries like libtest that depend on std but also want to use - crates.io dependencies. Hence, libtest is split out as its own project that - is sequenced after `std` but before `rustc`. This project is built for all - targets. - -There is some loss in build parallelism here because libtest can be compiled in -parallel with a number of rustc artifacts, but in theory, the loss isn't too bad! - -## Build tools - -We've actually got quite a few tools that we use in the compiler's build system -and for testing. To organize these, each tool is a project in `src/tools` with a -corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having -independent `Cargo.lock` files) and do not currently explicitly depend on the -compiler or standard library. Compiling each tool is sequenced after the -appropriate libstd/libtest/librustc compile above. - ## Extending rustbuild -So, you'd like to add a feature to the rustbuild build system or just fix a bug. -Great! One of the major motivational factors for moving away from `make` is that -Rust is in theory much easier to read, modify, and write. If you find anything -excessively confusing, please open an issue on this, and we'll try to get it -documented or simplified, pronto. +When you use the bootstrap system, you'll call it through the entry point script +(`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`. +`bootstrap` has a difficult problem: it is written in Rust, but yet it is run +before the Rust compiler is built! To work around this, there are two components +of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py` +is what gets run by entry point script. It takes care of downloading the `stage0` +compiler, which will then build the bootstrap binary written in Rust. -First up, you'll probably want to read over the documentation above, as that'll -give you a high level overview of what rustbuild is doing. You also probably -want to play around a bit yourself by just getting it up and running before you -dive too much into the actual build system itself. +Because there are two separate codebases behind `x.py`, they need to +be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary +parse `config.toml` and read the same command line arguments. `bootstrap.py` +keeps these in sync by setting various environment variables, and the +programs sometimes have to add arguments that are explicitly ignored, to be +read by the other. -After that, each module in rustbuild should have enough documentation to keep -you up and running. Some general areas that you may be interested in modifying -are: +Some general areas that you may be interested in modifying are: * Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of other tools. @@ -320,8 +196,9 @@ A 'major change' includes Changes that do not affect contributors to the compiler or users building rustc from source don't need an update to `VERSION`. -If you have any questions, feel free to reach out on the `#t-infra` channel in -the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When -you encounter bugs, please file issues on the rust-lang/rust issue tracker. +If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel +at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs, +please file issues on the [Rust issue tracker][rust-issue-tracker]. -[rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra +[rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap +[rust-issue-tracker]: https://github.com/rust-lang/rust/issues diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index d44b96cfb99..698edb52d8f 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -11,93 +11,6 @@ //! crates.io and Cargo. //! * A standard interface to build across all platforms, including MSVC //! -//! ## Architecture -//! -//! The build system defers most of the complicated logic managing invocations -//! of rustc and rustdoc to Cargo itself. However, moving through various stages -//! and copying artifacts is still necessary for it to do. Each time rustbuild -//! is invoked, it will iterate through the list of predefined steps and execute -//! each serially in turn if it matches the paths passed or is a default rule. -//! For each step rustbuild relies on the step internally being incremental and -//! parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded -//! to appropriate test harnesses and such. -//! -//! Most of the "meaty" steps that matter are backed by Cargo, which does indeed -//! have its own parallelism and incremental management. Later steps, like -//! tests, aren't incremental and simply run the entire suite currently. -//! However, compiletest itself tries to avoid running tests when the artifacts -//! that are involved (mainly the compiler) haven't changed. -//! -//! When you execute `x.py build`, the steps executed are: -//! -//! * First, the python script is run. This will automatically download the -//! stage0 rustc and cargo according to `src/stage0.json`, or use the cached -//! versions if they're available. These are then used to compile rustbuild -//! itself (using Cargo). Finally, control is then transferred to rustbuild. -//! -//! * Rustbuild takes over, performs sanity checks, probes the environment, -//! reads configuration, and starts executing steps as it reads the command -//! line arguments (paths) or going through the default rules. -//! -//! The build output will be something like the following: -//! -//! Building stage0 std artifacts -//! Copying stage0 std -//! Building stage0 test artifacts -//! Copying stage0 test -//! Building stage0 compiler artifacts -//! Copying stage0 rustc -//! Assembling stage1 compiler -//! Building stage1 std artifacts -//! Copying stage1 std -//! Building stage1 test artifacts -//! Copying stage1 test -//! Building stage1 compiler artifacts -//! Copying stage1 rustc -//! Assembling stage2 compiler -//! Uplifting stage1 std -//! Uplifting stage1 test -//! Uplifting stage1 rustc -//! -//! Let's disect that a little: -//! -//! ## Building stage0 {std,test,compiler} artifacts -//! -//! These steps use the provided (downloaded, usually) compiler to compile the -//! local Rust source into libraries we can use. -//! -//! ## Copying stage0 {std,test,rustc} -//! -//! This copies the build output from Cargo into -//! `build/$HOST/stage0-sysroot/lib/rustlib/$ARCH/lib`. FIXME: this step's -//! documentation should be expanded -- the information already here may be -//! incorrect. -//! -//! ## Assembling stage1 compiler -//! -//! This copies the libraries we built in "building stage0 ... artifacts" into -//! the stage1 compiler's lib directory. These are the host libraries that the -//! compiler itself uses to run. These aren't actually used by artifacts the new -//! compiler generates. This step also copies the rustc and rustdoc binaries we -//! generated into build/$HOST/stage/bin. -//! -//! The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have -//! any libraries to link built binaries or libraries to. The next 3 steps will -//! provide those libraries for it; they are mostly equivalent to constructing -//! the stage1/bin compiler so we don't go through them individually. -//! -//! ## Uplifting stage1 {std,test,rustc} -//! -//! This step copies the libraries from the stage1 compiler sysroot into the -//! stage2 compiler. This is done to avoid rebuilding the compiler; libraries -//! we'd build in this step should be identical (in function, if not necessarily -//! identical on disk) so there's no need to recompile the compiler again. Note -//! that if you want to, you can enable the full-bootstrap option to change this -//! behavior. -//! -//! Each step is driven by a separate Cargo project and rustbuild orchestrates -//! copying files between steps and otherwise preparing for Cargo to run. -//! //! ## Further information //! //! More documentation can be found in each respective module below, and you can