about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-27 13:35:35 +0000
committerbors <bors@rust-lang.org>2023-03-27 13:35:35 +0000
commitdd19135b044cd21a9c3ae7ae87620bf41a208066 (patch)
treeffd0b773d4c0e583beae4dfd2f8eca3bc3e35e51
parent553ecbe8bae12bc43a34ac0b8a63e17026ce1e8a (diff)
parentc3a428fb1a2d229c7357fe76d66f4558945d68b7 (diff)
downloadrust-dd19135b044cd21a9c3ae7ae87620bf41a208066.tar.gz
rust-dd19135b044cd21a9c3ae7ae87620bf41a208066.zip
Auto merge of #109662 - matthiaskrgr:rollup-tk2g3jf, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #108625 (More config.toml.example cleanups)
 - #109418 (Rename 'src/bootstrap/native.rs' to llvm.rs)
 - #109580 (Remove some stale FIXMEs in new solver)
 - #109582 (Refactor: Separate `LocalRef` variant for not-evaluated-yet operands)
 - #109650 (Remove Nilstrieb from review rotation)
 - #109656 (Update cargo)
 - #109658 (Backport 1.68.1 and 1.68.2 release notes to `master`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--RELEASES.md23
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs6
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph/mod.rs2
-rw-r--r--config.example.toml171
-rw-r--r--src/bootstrap/builder.rs14
-rw-r--r--src/bootstrap/compile.rs18
-rw-r--r--src/bootstrap/config.rs6
-rw-r--r--src/bootstrap/config/tests.rs2
-rw-r--r--src/bootstrap/defaults/config.user.toml4
-rw-r--r--src/bootstrap/dist.rs12
-rw-r--r--src/bootstrap/download.rs2
-rw-r--r--src/bootstrap/lib.rs2
-rw-r--r--src/bootstrap/llvm.rs (renamed from src/bootstrap/native.rs)65
-rw-r--r--src/bootstrap/test.rs79
-rw-r--r--src/ci/stage-build.py2
m---------src/tools/cargo0
-rw-r--r--triagebot.toml1
24 files changed, 244 insertions, 209 deletions
diff --git a/RELEASES.md b/RELEASES.md
index a26dbbfa4f5..e453b8d6891 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,26 @@
+Version 1.68.2 (2023-03-28)
+===========================
+
+- [Update the GitHub RSA host key bundled within Cargo](https://github.com/rust-lang/cargo/pull/11883).
+  The key was [rotated by GitHub](https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/)
+  on 2023-03-24 after the old one leaked.
+- [Mark the old GitHub RSA host key as revoked](https://github.com/rust-lang/cargo/pull/11889).
+  This will prevent Cargo from accepting the leaked key even when trusted by
+  the system.
+- [Add support for `@revoked` and a better error message for `@cert-authority` in Cargo's SSH host key verification](https://github.com/rust-lang/cargo/pull/11635)
+
+Version 1.68.1 (2023-03-23)
+===========================
+
+- [Fix miscompilation in produced Windows MSVC artifacts](https://github.com/rust-lang/rust/pull/109094)
+  This was introduced by enabling ThinLTO for the distributed rustc which led
+  to miscompilations in the resulting binary. Currently this is believed to be
+  limited to the -Zdylib-lto flag used for rustc compilation, rather than a
+  general bug in ThinLTO, so only rustc artifacts should be affected.
+- [Fix --enable-local-rust builds](https://github.com/rust-lang/rust/pull/109111/)
+- [Treat `$prefix-clang` as `clang` in linker detection code](https://github.com/rust-lang/rust/pull/109156)
+- [Fix panic in compiler code](https://github.com/rust-lang/rust/pull/108162)
+
 Version 1.68.0 (2023-03-09)
 ==========================
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 5da0e826c56..2d647f5d7f2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -397,8 +397,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             PassMode::Cast(cast_ty, _) => {
                 let op = match self.locals[mir::RETURN_PLACE] {
-                    LocalRef::Operand(Some(op)) => op,
-                    LocalRef::Operand(None) => bug!("use of return before def"),
+                    LocalRef::Operand(op) => op,
+                    LocalRef::PendingOperand => bug!("use of return before def"),
                     LocalRef::Place(cg_place) => OperandRef {
                         val: Ref(cg_place.llval, None, cg_place.align),
                         layout: cg_place.layout,
@@ -1673,7 +1673,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             match self.locals[index] {
                 LocalRef::Place(dest) => dest,
                 LocalRef::UnsizedPlace(_) => bug!("return type must be sized"),
-                LocalRef::Operand(None) => {
+                LocalRef::PendingOperand => {
                     // Handle temporary places, specifically `Operand` ones, as
                     // they don't have `alloca`s.
                     return if fn_ret.is_indirect() {
@@ -1694,7 +1694,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         ReturnDest::DirectOperand(index)
                     };
                 }
-                LocalRef::Operand(Some(_)) => {
+                LocalRef::Operand(_) => {
                     bug!("place local already assigned to");
                 }
             }
@@ -1737,7 +1737,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             IndirectOperand(tmp, index) => {
                 let op = bx.load_operand(tmp);
                 tmp.storage_dead(bx);
-                self.locals[index] = LocalRef::Operand(Some(op));
+                self.locals[index] = LocalRef::Operand(op);
                 self.debug_introduce_local(bx, index);
             }
             DirectOperand(index) => {
@@ -1752,7 +1752,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 } else {
                     OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout)
                 };
-                self.locals[index] = LocalRef::Operand(Some(op));
+                self.locals[index] = LocalRef::Operand(op);
                 self.debug_introduce_local(bx, index);
             }
         }
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 6e32c28a42c..d15774696a5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -312,7 +312,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 LocalRef::Place(place) | LocalRef::UnsizedPlace(place) => {
                     bx.set_var_name(place.llval, name);
                 }
-                LocalRef::Operand(Some(operand)) => match operand.val {
+                LocalRef::Operand(operand) => match operand.val {
                     OperandValue::Ref(x, ..) | OperandValue::Immediate(x) => {
                         bx.set_var_name(x, name);
                     }
@@ -323,7 +323,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         bx.set_var_name(b, &(name.clone() + ".1"));
                     }
                 },
-                LocalRef::Operand(None) => {}
+                LocalRef::PendingOperand => {}
             }
         }
 
@@ -332,9 +332,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
 
         let base = match local_ref {
-            LocalRef::Operand(None) => return,
+            LocalRef::PendingOperand => return,
 
-            LocalRef::Operand(Some(operand)) => {
+            LocalRef::Operand(operand) => {
                 // Don't spill operands onto the stack in naked functions.
                 // See: https://github.com/rust-lang/rust/issues/42779
                 let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 5cffca5230a..189549953d9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -123,7 +123,10 @@ enum LocalRef<'tcx, V> {
     /// Every time it is initialized, we have to reallocate the place
     /// and update the fat pointer. That's the reason why it is indirect.
     UnsizedPlace(PlaceRef<'tcx, V>),
-    Operand(Option<OperandRef<'tcx, V>>),
+    /// The backend [`OperandValue`] has already been generated.
+    Operand(OperandRef<'tcx, V>),
+    /// Will be a `Self::Operand` once we get to its definition.
+    PendingOperand,
 }
 
 impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
@@ -135,9 +138,9 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
             // Zero-size temporaries aren't always initialized, which
             // doesn't matter because they don't contain data, but
             // we need something in the operand.
-            LocalRef::Operand(Some(OperandRef::new_zst(bx, layout)))
+            LocalRef::Operand(OperandRef::new_zst(bx, layout))
         } else {
-            LocalRef::Operand(None)
+            LocalRef::PendingOperand
         }
     }
 }
@@ -337,7 +340,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 // We don't have to cast or keep the argument in the alloca.
                 // FIXME(eddyb): We should figure out how to use llvm.dbg.value instead
                 // of putting everything in allocas just so we can use llvm.dbg.declare.
-                let local = |op| LocalRef::Operand(Some(op));
+                let local = |op| LocalRef::Operand(op);
                 match arg.mode {
                     PassMode::Ignore => {
                         return local(OperandRef::new_zst(bx, arg.layout));
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 25721f75583..b45e7c834e7 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -370,7 +370,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
 
         match self.locals[place_ref.local] {
-            LocalRef::Operand(Some(mut o)) => {
+            LocalRef::Operand(mut o) => {
                 // Moves out of scalar and scalar pair fields are trivial.
                 for elem in place_ref.projection.iter() {
                     match elem {
@@ -395,7 +395,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
                 Some(o)
             }
-            LocalRef::Operand(None) => {
+            LocalRef::PendingOperand => {
                 bug!("use of {:?} before def", place_ref);
             }
             LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index f6523a448e3..1633cfef19d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -558,6 +558,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     bug!("using operand local {:?} as place", place_ref);
                 }
             }
+            LocalRef::PendingOperand => {
+                bug!("using still-pending operand local {:?} as place", place_ref);
+            }
         };
         for elem in place_ref.projection[base..].iter() {
             cg_base = match *elem {
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 4bc4fdab59e..d867d6b0cd4 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -545,7 +545,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // ZST are passed as operands and require special handling
         // because codegen_place() panics if Local is operand.
         if let Some(index) = place.as_local() {
-            if let LocalRef::Operand(Some(op)) = self.locals[index] {
+            if let LocalRef::Operand(op) = self.locals[index] {
                 if let ty::Array(_, n) = op.layout.ty.kind() {
                     let n = n.eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
                     return bx.cx().const_usize(n);
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 41f585f7fcc..3fd7397ad38 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -18,12 +18,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         LocalRef::UnsizedPlace(cg_indirect_dest) => {
                             self.codegen_rvalue_unsized(bx, cg_indirect_dest, rvalue)
                         }
-                        LocalRef::Operand(None) => {
+                        LocalRef::PendingOperand => {
                             let operand = self.codegen_rvalue_operand(bx, rvalue);
-                            self.locals[index] = LocalRef::Operand(Some(operand));
+                            self.locals[index] = LocalRef::Operand(operand);
                             self.debug_introduce_local(bx, index);
                         }
-                        LocalRef::Operand(Some(op)) => {
+                        LocalRef::Operand(op) => {
                             if !op.layout.is_zst() {
                                 span_bug!(
                                     statement.source_info.span,
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 6a64dfdedd4..65e7bcb7f01 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -9,8 +9,6 @@
 //! FIXME(@lcnr): Write that section. If you read this before then ask me
 //! about it on zulip.
 
-// FIXME: uses of `infcx.at` need to enable deferred projection equality once that's implemented.
-
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_infer::traits::query::NoSolution;
@@ -105,8 +103,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         goal: Goal<'tcx, SubtypePredicate<'tcx>>,
     ) -> QueryResult<'tcx> {
         if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() {
-            // FIXME: Do we want to register a subtype relation between these vars?
-            // That won't actually reflect in the query response, so it seems moot.
             self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
         } else {
             self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?;
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
index 219890b9dc4..9773a3eacd6 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs
@@ -78,8 +78,6 @@ impl<'tcx> SearchGraph<'tcx> {
         tcx: TyCtxt<'tcx>,
         goal: CanonicalGoal<'tcx>,
     ) -> Result<(), QueryResult<'tcx>> {
-        // FIXME: start by checking the global cache
-
         // Look at the provisional cache to check for cycles.
         let cache = &mut self.provisional_cache;
         match cache.lookup_table.entry(goal) {
diff --git a/config.example.toml b/config.example.toml
index 32eab76b369..5ef83760aed 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -1,7 +1,7 @@
 # Sample TOML configuration file for building Rust.
 #
-# To configure rustbuild, copy this file to the directory from which you will be
-# running the build, and name it config.toml.
+# To configure rustbuild, run `./configure` or `./x.py setup`.
+# See https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#create-a-configtoml for more information.
 #
 # All options are commented out by default in this file, and they're commented
 # out with their default values. The build system by default looks for
@@ -9,12 +9,6 @@
 # a custom configuration file can also be specified with `--config` to the build
 # system.
 
-# Keeps track of the last version of `x.py` used.
-# If it does not match the version that is currently running,
-# `x.py` will prompt you to update it and read the changelog.
-# See `src/bootstrap/CHANGELOG.md` for more information.
-changelog-seen = 2
-
 # =============================================================================
 # Global Settings
 # =============================================================================
@@ -25,6 +19,12 @@ changelog-seen = 2
 # Note that this has no default value (x.py uses the defaults in `config.toml.example`).
 #profile = <none>
 
+# Keeps track of the last version of `x.py` used.
+# If `changelog-seen` does not match the version that is currently running,
+# `x.py` will prompt you to update it and to read the changelog.
+# See `src/bootstrap/CHANGELOG.md` for more information.
+changelog-seen = 2
+
 # =============================================================================
 # Tweaking how LLVM is compiled
 # =============================================================================
@@ -33,7 +33,7 @@ changelog-seen = 2
 # Whether to use Rust CI built LLVM instead of locally building it.
 #
 # Unless you're developing for a target where Rust CI doesn't build a compiler
-# toolchain or changing LLVM locally, you probably want to set this to true.
+# toolchain or changing LLVM locally, you probably want to leave this enabled.
 #
 # All tier 1 targets are currently supported; set this to `"if-available"` if
 # you are not sure whether you're on a tier 1 target.
@@ -42,9 +42,7 @@ changelog-seen = 2
 #
 # Note that many of the LLVM options are not currently supported for
 # downloading. Currently only the "assertions" option can be toggled.
-#
-# Defaults to "if-available" when `channel = "dev"` and "false" otherwise.
-#download-ci-llvm = "if-available"
+#download-ci-llvm = if rust.channel == "dev" { "if-available" } else { false }
 
 # Indicates whether the LLVM build is a Release or Debug build
 #optimize = true
@@ -59,6 +57,8 @@ changelog-seen = 2
 #release-debuginfo = false
 
 # Indicates whether the LLVM assertions are enabled or not
+# NOTE: When assertions are disabled, bugs in the integration between rustc and LLVM can lead to
+# unsoundness (segfaults, etc.) in the rustc process itself, not just in the generated code.
 #assertions = false
 
 # Indicates whether the LLVM testsuite is enabled in the build or not. Does
@@ -70,10 +70,9 @@ changelog-seen = 2
 # Indicates whether the LLVM plugin is enabled or not
 #plugins = false
 
-# Indicates whether ccache is used when building LLVM
+# Indicates whether ccache is used when building LLVM. Set to `true` to use the first `ccache` in
+# PATH, or set an absolute path to use a specific version.
 #ccache = false
-# or alternatively ...
-#ccache = "/path/to/ccache"
 
 # When true, link libstdc++ statically into the rustc_llvm.
 # This is useful if you don't want to use the dynamic version of that
@@ -87,11 +86,8 @@ changelog-seen = 2
 # Note: this is NOT related to Rust compilation targets. However, as Rust is
 # dependent on LLVM for code generation, turning targets off here WILL lead to
 # the resulting rustc being unable to compile for the disabled architectures.
-# Also worth pointing out is that, in case support for new targets are added to
-# LLVM, enabling them here doesn't mean Rust is automatically gaining said
-# support. You'll need to write a target specification at least, and most
-# likely, teach rustc about the C ABI of the target. Get in touch with the
-# Rust team and file an issue if you need assistance in porting!
+#
+# To add support for new targets, see https://rustc-dev-guide.rust-lang.org/building/new-target.html.
 #targets = "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
 
 # LLVM experimental targets to build support for. These targets are specified in
@@ -104,19 +100,18 @@ changelog-seen = 2
 # This can be useful when building LLVM with debug info, which significantly
 # increases the size of binaries and consequently the memory required by
 # each linker process.
-# If absent or 0, linker invocations are treated like any other job and
+# If set to 0, linker invocations are treated like any other job and
 # controlled by rustbuild's -j parameter.
 #link-jobs = 0
 
-# When invoking `llvm-config` this configures whether the `--shared` argument is
-# passed to prefer linking to shared libraries.
-# NOTE: `thin-lto = true` requires this to be `true` and will give an error otherwise.
-#link-shared = false
+# Whether to build LLVM as a dynamically linked library (as opposed to statically linked).
+# Under the hood, this passes `--shared` to llvm-config.
+# NOTE: To avoid performing LTO multiple times, we suggest setting this to `true` when `thin-lto` is enabled.
+#link-shared = llvm.thin-lto
 
 # When building llvm, this configures what is being appended to the version.
-# The default is "-rust-$version-$channel", except for dev channel where rustc
-# version number is omitted. To use LLVM version as is, provide an empty string.
-#version-suffix = "-rust-dev"
+# To use LLVM version as is, provide an empty string.
+#version-suffix = if rust.channel == "dev" { "-rust-dev" } else { "-rust-$version-$channel" }
 
 # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass
 # with clang-cl, so this is special in that it only compiles LLVM with clang-cl.
@@ -178,47 +173,58 @@ changelog-seen = 2
 # The default stage to use for the `bench` subcommand
 #bench-stage = 2
 
-# Build triple for the original snapshot compiler. This must be a compiler that
-# nightlies are already produced for. The current platform must be able to run
-# binaries of this build triple and the nightly will be used to bootstrap the
-# first compiler.
+# Build triple for the pre-compiled snapshot compiler. If `rustc` is set, this must match its host
+# triple (see `rustc --version --verbose`; cross-compiling the rust build system itself is NOT
+# supported). If `rustc` is unset, this must be a platform with pre-compiled host tools
+# (https://doc.rust-lang.org/nightly/rustc/platform-support.html). The current platform must be
+# able to run binaries of this build triple.
 #
-# Defaults to platform where `x.py` is run.
+# If `rustc` is present in path, this defaults to the host it was compiled for.
+# Otherwise, `x.py` will try to infer it from the output of `uname`.
+# If `uname` is not found in PATH, we assume this is `x86_64-pc-windows-msvc`.
+# This may be changed in the future.
 #build = "x86_64-unknown-linux-gnu" (as an example)
 
-# Which triples to produce a compiler toolchain for. Each of these triples will
-# be bootstrapped from the build triple themselves.
+# Which triples to produce a compiler toolchain for. Each of these triples will be bootstrapped from
+# the build triple themselves. In other words, this is the list of triples for which to build a
+# compiler that can RUN on that triple.
 #
-# Defaults to just the build triple.
-#host = ["x86_64-unknown-linux-gnu"] (as an example)
+# Defaults to just the `build` triple.
+#host = [build.build] (list of triples)
 
-# Which triples to build libraries (core/alloc/std/test/proc_macro) for. Each of
-# these triples will be bootstrapped from the build triple themselves.
+# Which triples to build libraries (core/alloc/std/test/proc_macro) for. Each of these triples will
+# be bootstrapped from the build triple themselves. In other words, this is the list of triples for
+# which to build a library that can CROSS-COMPILE to that triple.
 #
 # Defaults to `host`. If you set this explicitly, you likely want to add all
 # host triples to this list as well in order for those host toolchains to be
 # able to compile programs for their native target.
-#target = ["x86_64-unknown-linux-gnu"] (as an example)
+#target = build.host (list of triples)
 
-# Use this directory to store build artifacts.
-# You can use "$ROOT" to indicate the root of the git repository.
+# Use this directory to store build artifacts. Paths are relative to the current directory, not to
+# the root of the repository.
 #build-dir = "build"
 
 # Instead of downloading the src/stage0.json version of Cargo specified, use
 # this Cargo binary instead to build all Rust code
+# If you set this, you likely want to set `rustc` as well.
 #cargo = "/path/to/cargo"
 
 # Instead of downloading the src/stage0.json version of the compiler
 # specified, use this rustc binary instead as the stage0 snapshot compiler.
+# If you set this, you likely want to set `cargo` as well.
 #rustc = "/path/to/rustc"
 
-# Instead of download the src/stage0.json version of rustfmt specified,
+# Instead of downloading the src/stage0.json version of rustfmt specified,
 # use this rustfmt binary instead as the stage0 snapshot rustfmt.
 #rustfmt = "/path/to/rustfmt"
 
-# Flag to specify whether any documentation is built. If false, rustdoc and
+# Whether to build documentation by default. If false, rustdoc and
 # friends will still be compiled but they will not be used to generate any
 # documentation.
+#
+# You can still build documentation when this is disabled by explicitly passing paths,
+# e.g. `x doc library`.
 #docs = true
 
 # Flag to specify whether CSS, JavaScript, and HTML are minified when
@@ -229,8 +235,8 @@ changelog-seen = 2
 # Flag to specify whether private items should be included in the library docs.
 #library-docs-private-items = false
 
-# Indicate whether the compiler should be documented in addition to the standard
-# library and facade crates.
+# Indicate whether to build compiler documentation by default.
+# You can still build documentation when this is disabled by explicitly passing a path: `x doc compiler`.
 #compiler-docs = false
 
 # Indicate whether git submodules are managed and updated automatically.
@@ -247,14 +253,14 @@ changelog-seen = 2
 # Python interpreter to use for various tasks throughout the build, notably
 # rustdoc tests, the lldb python interpreter, and some dist bits and pieces.
 #
-# Defaults to the Python interpreter used to execute x.py
+# Defaults to the Python interpreter used to execute x.py.
 #python = "python"
 
 # The path to the REUSE executable to use. Note that REUSE is not required in
 # most cases, as our tooling relies on a cached (and shrinked) copy of the
 # REUSE output present in the git repository and in our source tarballs.
 #
-# REUSE is only needed if your changes caused the overral licensing of the
+# REUSE is only needed if your changes caused the overall licensing of the
 # repository to change, and the cached copy has to be regenerated.
 #
 # Defaults to the "reuse" command in the system path.
@@ -264,14 +270,19 @@ changelog-seen = 2
 # set that all the Cargo.toml files create, instead of updating it.
 #locked-deps = false
 
-# Indicate whether the vendored sources are used for Rust dependencies or not
+# Indicate whether the vendored sources are used for Rust dependencies or not.
+#
+# Vendoring requires additional setup. We recommend using the pre-generated source tarballs if you
+# want to use vendoring. See
+# https://forge.rust-lang.org/infra/other-installation-methods.html#source-code.
 #vendor = false
 
 # Typically the build system will build the Rust compiler twice. The second
 # compiler, however, will simply use its own libraries to link against. If you
 # would rather to perform a full bootstrap, compiling the compiler three times,
-# then you can set this option to true. You shouldn't ever need to set this
-# option to true.
+# then you can set this option to true.
+#
+# This is only useful for verifying that rustc generates reproducible builds.
 #full-bootstrap = false
 
 # Enable a build of the extended Rust tool set which is not only the compiler
@@ -300,7 +311,7 @@ changelog-seen = 2
 #    "rust-demangler",  # if profiler = true
 #]
 
-# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
+# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation
 #verbose = 0
 
 # Build the sanitizer runtimes
@@ -320,11 +331,12 @@ changelog-seen = 2
 
 # Arguments passed to the `./configure` script, used during distcheck. You
 # probably won't fill this in but rather it's filled in by the `./configure`
-# script.
+# script. Useful for debugging.
 #configure-args = []
 
 # Indicates that a local rebuild is occurring instead of a full bootstrap,
 # essentially skipping stage0 as the local compiler is recompiling itself again.
+# Useful for modifying only the stage2 compiler without having to pass `--keep-stage 0` each time.
 #local-rebuild = false
 
 # Print out how long each rustbuild step took (mostly intended for CI and
@@ -354,10 +366,10 @@ changelog-seen = 2
 # =============================================================================
 [install]
 
-# Instead of installing to /usr/local, install to this path instead.
+# Where to install the generated toolchain. Must be an absolute path.
 #prefix = "/usr/local"
 
-# Where to install system configuration files
+# Where to install system configuration files.
 # If this is a relative path, it will get installed in `prefix` above
 #sysconfdir = "/etc"
 
@@ -411,9 +423,10 @@ changelog-seen = 2
 #debug = false
 
 # Whether to download the stage 1 and 2 compilers from CI.
-# This is mostly useful for tools; if you have changes to `compiler/` they will be ignored.
+# This is mostly useful for tools; if you have changes to `compiler/` or `library/` they will be ignored.
 #
-# You can set this to "if-unchanged" to only download if `compiler/` has not been modified.
+# Set this to "if-unchanged" to only download if the compiler and standard library have not been modified.
+# Set this to `true` to download unconditionally (useful if e.g. you are only changing doc-comments).
 #download-rustc = false
 
 # Number of codegen units to use for each compiler invocation. A value of 0
@@ -429,10 +442,8 @@ changelog-seen = 2
 # See https://github.com/rust-lang/rust/issues/83600.
 #codegen-units-std = codegen-units
 
-# Whether or not debug assertions are enabled for the compiler and standard
-# library. Debug assertions control the maximum log level used by rustc. When
-# enabled calls to `trace!` and `debug!` macros are preserved in the compiled
-# binary, otherwise they are omitted.
+# Whether or not debug assertions are enabled for the compiler and standard library.
+# These can help find bugs at the cost of a small runtime slowdown.
 #
 # Defaults to rust.debug value
 #debug-assertions = rust.debug (boolean)
@@ -444,13 +455,11 @@ changelog-seen = 2
 #debug-assertions-std = rust.debug-assertions (boolean)
 
 # Whether or not to leave debug! and trace! calls in the rust binary.
-# Overrides the `debug-assertions` option, if defined.
 #
 # Defaults to rust.debug-assertions value
 #
-# If you see a message from `tracing` saying
-# `max_level_info` is enabled and means logging won't be shown,
-# set this value to `true`.
+# If you see a message from `tracing` saying "some trace filter directives would enable traces that
+# are disabled statically" because `max_level_info` is enabled, set this value to `true`.
 #debug-logging = rust.debug-assertions (boolean)
 
 # Whether or not overflow checks are enabled for the compiler and standard
@@ -477,18 +486,16 @@ changelog-seen = 2
 #
 # Note that debuginfo-level = 2 generates several gigabytes of debuginfo
 # and will slow down the linking process significantly.
-#
-# Defaults to 1 if debug is true
-#debuginfo-level = 0
+#debuginfo-level = if rust.debug { 1 } else { 0 }
 
 # Debuginfo level for the compiler.
-#debuginfo-level-rustc = debuginfo-level
+#debuginfo-level-rustc = rust.debuginfo-level
 
 # Debuginfo level for the standard library.
-#debuginfo-level-std = debuginfo-level
+#debuginfo-level-std = rust.debuginfo-level
 
 # Debuginfo level for the tools.
-#debuginfo-level-tools = debuginfo-level
+#debuginfo-level-tools = rust.debuginfo-level
 
 # Debuginfo level for the test suites run with compiletest.
 # FIXME(#61117): Some tests fail when this option is enabled.
@@ -520,6 +527,7 @@ changelog-seen = 2
 
 # Build a multi-threaded rustc
 # FIXME(#75760): Some UI tests fail when this option is enabled.
+# NOTE: This option is NOT SUPPORTED. See #48685.
 #parallel-compiler = false
 
 # The default linker that will be hard-coded into the generated
@@ -546,7 +554,7 @@ changelog-seen = 2
 # upstream Rust you need to set this to "". However, note that if you are not
 # actually compatible -- for example if you've backported patches that change
 # behavior -- this may lead to miscompilations or other bugs.
-#description = <none> (string)
+#description = ""
 
 # The root location of the musl installation directory. The library directory
 # will also need to contain libunwind.a for an unwinding implementation. Note
@@ -575,14 +583,16 @@ changelog-seen = 2
 
 # Flag indicating whether git info will be retrieved from .git automatically.
 # Having the git information can cause a lot of rebuilds during development.
-# Note: If this attribute is not explicitly set (e.g. if left commented out) it
-# will default to true if channel = "dev", but will default to false otherwise.
-#ignore-git = if channel == "dev" { true } else { false }
+#
+# FIXME(#76720): this can causes bugs if different compilers reuse the same metadata cache.
+#ignore-git = if rust.channel == "dev" { true } else { false }
 
-# When creating source tarballs whether or not to create a source tarball.
+# Whether to create a source tarball by default when running `x dist`.
+#
+# You can still build a source tarball when this is disabled by explicitly passing `x dist rustc-src`.
 #dist-src = true
 
-# After building or testing extended tools (e.g. clippy and rustfmt), append the
+# After building or testing an optional component (e.g. the nomicon or reference), append the
 # result (broken, compiling, testing) into this JSON file.
 #save-toolstates = <none> (path)
 
@@ -624,11 +634,12 @@ changelog-seen = 2
 # will make code compile faster at the expense of lower runtime performance.
 #thin-lto-import-instr-limit = if incremental { 10 } else { LLVM default (currently 100) }
 
-# Map debuginfo paths to `/rust/$sha/...`, generally only set for releases
+# Map debuginfo paths to `/rust/$sha/...`.
+# Useful for reproducible builds. Generally only set for releases
 #remap-debuginfo = false
 
-# Link the compiler against `jemalloc`, where on Linux and OSX it should
-# override the default allocator for rustc and LLVM.
+# Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
+# This option is only tested on Linux and OSX.
 #jemalloc = false
 
 # Run tests in various test suites with the "nll compare mode" in addition to
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 838e33aca04..4d528a767e4 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -16,7 +16,7 @@ use crate::config::{SplitDebuginfo, TargetSelection};
 use crate::doc;
 use crate::flags::{Color, Subcommand};
 use crate::install;
-use crate::native;
+use crate::llvm;
 use crate::run;
 use crate::setup;
 use crate::test;
@@ -636,13 +636,13 @@ impl<'a> Builder<'a> {
                 tool::Rustdoc,
                 tool::Clippy,
                 tool::CargoClippy,
-                native::Llvm,
-                native::Sanitizers,
+                llvm::Llvm,
+                llvm::Sanitizers,
                 tool::Rustfmt,
                 tool::Miri,
                 tool::CargoMiri,
-                native::Lld,
-                native::CrtBeginEnd
+                llvm::Lld,
+                llvm::CrtBeginEnd
             ),
             Kind::Check | Kind::Clippy | Kind::Fix => describe!(
                 check::Std,
@@ -1101,7 +1101,7 @@ impl<'a> Builder<'a> {
     /// check build or dry-run, where there's no need to build all of LLVM.
     fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
         if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run() {
-            let native::LlvmResult { llvm_config, .. } = self.ensure(native::Llvm { target });
+            let llvm::LlvmResult { llvm_config, .. } = self.ensure(llvm::Llvm { target });
             if llvm_config.is_file() {
                 return Some(llvm_config);
             }
@@ -1227,7 +1227,7 @@ impl<'a> Builder<'a> {
             // rustc_llvm. But if LLVM is stale, that'll be a tiny amount
             // of work comparatively, and we'd likely need to rebuild it anyway,
             // so that's okay.
-            if crate::native::prebuilt_llvm_config(self, target).is_err() {
+            if crate::llvm::prebuilt_llvm_config(self, target).is_err() {
                 cargo.env("RUST_CHECK", "1");
             }
         }
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 54971af644c..67bd573a855 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -24,7 +24,7 @@ use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
 use crate::config::{LlvmLibunwind, RustcLto, TargetSelection};
 use crate::dist;
-use crate::native;
+use crate::llvm;
 use crate::tool::SourceType;
 use crate::util::get_clang_cl_resource_dir;
 use crate::util::{exe, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date};
@@ -191,7 +191,7 @@ fn copy_and_stamp(
 }
 
 fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
-    let libunwind_path = builder.ensure(native::Libunwind { target });
+    let libunwind_path = builder.ensure(llvm::Libunwind { target });
     let libunwind_source = libunwind_path.join("libunwind.a");
     let libunwind_target = libdir.join("libunwind.a");
     builder.copy(&libunwind_source, &libunwind_target);
@@ -266,7 +266,7 @@ fn copy_self_contained_objects(
                 DependencyType::TargetSelfContained,
             );
         }
-        let crt_path = builder.ensure(native::CrtBeginEnd { target });
+        let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
         for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
             let src = crt_path.join(obj);
             let target = libdir_self_contained.join(obj);
@@ -474,7 +474,7 @@ fn copy_sanitizers(
     compiler: &Compiler,
     target: TargetSelection,
 ) -> Vec<PathBuf> {
-    let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
+    let runtimes: Vec<llvm::SanitizerRuntime> = builder.ensure(llvm::Sanitizers { target });
 
     if builder.config.dry_run() {
         return Vec::new();
@@ -876,12 +876,12 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
     // busting caches (e.g. like #71152).
     if builder.config.llvm_enabled()
         && (builder.kind != Kind::Check
-            || crate::native::prebuilt_llvm_config(builder, target).is_ok())
+            || crate::llvm::prebuilt_llvm_config(builder, target).is_ok())
     {
         if builder.is_rust_llvm(target) {
             cargo.env("LLVM_RUSTLLVM", "1");
         }
-        let native::LlvmResult { llvm_config, .. } = builder.ensure(native::Llvm { target });
+        let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
         cargo.env("LLVM_CONFIG", &llvm_config);
         if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
             cargo.env("CFG_LLVM_ROOT", s);
@@ -1359,7 +1359,7 @@ impl Step for Assemble {
         }
 
         let lld_install = if builder.config.lld_enabled {
-            Some(builder.ensure(native::Lld { target: target_compiler.host }))
+            Some(builder.ensure(llvm::Lld { target: target_compiler.host }))
         } else {
             None
         };
@@ -1423,8 +1423,8 @@ impl Step for Assemble {
         }
 
         if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
-            let native::LlvmResult { llvm_config, .. } =
-                builder.ensure(native::Llvm { target: target_compiler.host });
+            let llvm::LlvmResult { llvm_config, .. } =
+                builder.ensure(llvm::Llvm { target: target_compiler.host });
             if !builder.config.dry_run() {
                 let llvm_bin_dir = output(Command::new(llvm_config).arg("--bindir"));
                 let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 95625170478..0eba18c3a63 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -1207,11 +1207,11 @@ impl Config {
             config.llvm_from_ci = match llvm.download_ci_llvm {
                 Some(StringOrBool::String(s)) => {
                     assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s);
-                    crate::native::is_ci_llvm_available(&config, asserts)
+                    crate::llvm::is_ci_llvm_available(&config, asserts)
                 }
                 Some(StringOrBool::Bool(b)) => b,
                 None => {
-                    config.channel == "dev" && crate::native::is_ci_llvm_available(&config, asserts)
+                    config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, asserts)
                 }
             };
 
@@ -1254,7 +1254,7 @@ impl Config {
             }
         } else {
             config.llvm_from_ci =
-                config.channel == "dev" && crate::native::is_ci_llvm_available(&config, false);
+                config.channel == "dev" && crate::llvm::is_ci_llvm_available(&config, false);
         }
 
         if let Some(t) = toml.target {
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 16dc8c63abc..5cea143e0a7 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -11,7 +11,7 @@ fn parse(config: &str) -> Config {
 
 #[test]
 fn download_ci_llvm() {
-    if crate::native::is_ci_llvm_modified(&parse("")) {
+    if crate::llvm::is_ci_llvm_modified(&parse("")) {
         eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change");
         return;
     }
diff --git a/src/bootstrap/defaults/config.user.toml b/src/bootstrap/defaults/config.user.toml
index ee271c3fb51..25d9e649f23 100644
--- a/src/bootstrap/defaults/config.user.toml
+++ b/src/bootstrap/defaults/config.user.toml
@@ -8,9 +8,11 @@ doc-stage = 2
 # When compiling from source, you usually want all tools.
 extended = true
 
+# Most users installing from source want to build all parts of the project from source.
 [llvm]
-# Most users installing from source want to build all parts of the project from source, not just rustc itself.
 download-ci-llvm = false
+[rust]
+download-rustc = false
 
 [dist]
 # Use better compression when preparing tarballs.
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index dceb4bd1b89..2ce54d9a3b4 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -27,7 +27,7 @@ use crate::channel;
 use crate::compile;
 use crate::config::TargetSelection;
 use crate::doc::DocumentationFormat;
-use crate::native;
+use crate::llvm;
 use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
 use crate::tool::{self, Tool};
 use crate::util::{exe, is_dylib, output, t, timeit};
@@ -1965,8 +1965,8 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
             builder.install(&llvm_dylib_path, dst_libdir, 0o644);
         }
         !builder.config.dry_run()
-    } else if let Ok(native::LlvmResult { llvm_config, .. }) =
-        native::prebuilt_llvm_config(builder, target)
+    } else if let Ok(llvm::LlvmResult { llvm_config, .. }) =
+        llvm::prebuilt_llvm_config(builder, target)
     {
         let mut cmd = Command::new(llvm_config);
         cmd.arg("--libfiles");
@@ -2154,7 +2154,7 @@ impl Step for LlvmTools {
             }
         }
 
-        builder.ensure(crate::native::Llvm { target });
+        builder.ensure(crate::llvm::Llvm { target });
 
         let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
         tarball.set_overlay(OverlayKind::LLVM);
@@ -2213,10 +2213,10 @@ impl Step for RustDev {
         let mut tarball = Tarball::new(builder, "rust-dev", &target.triple);
         tarball.set_overlay(OverlayKind::LLVM);
 
-        builder.ensure(crate::native::Llvm { target });
+        builder.ensure(crate::llvm::Llvm { target });
 
         // We want to package `lld` to use it with `download-ci-llvm`.
-        builder.ensure(crate::native::Lld { target });
+        builder.ensure(crate::llvm::Lld { target });
 
         let src_bindir = builder.llvm_out(target).join("bin");
         // If updating this list, you likely want to change
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index d1e2149d3f9..8fbc034965a 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -12,7 +12,7 @@ use xz2::bufread::XzDecoder;
 
 use crate::{
     config::RustfmtMetadata,
-    native::detect_llvm_sha,
+    llvm::detect_llvm_sha,
     t,
     util::{check_run, exe, program_out_of_date, try_run},
     Config,
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 54aa5a585bb..20b92b294fe 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -53,8 +53,8 @@ mod download;
 mod flags;
 mod format;
 mod install;
+mod llvm;
 mod metadata;
-mod native;
 mod render_tests;
 mod run;
 mod sanity;
diff --git a/src/bootstrap/native.rs b/src/bootstrap/llvm.rs
index f27db5c91e2..de06f8ca8c0 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/llvm.rs
@@ -870,71 +870,6 @@ impl Step for Lld {
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct TestHelpers {
-    pub target: TargetSelection,
-}
-
-impl Step for TestHelpers {
-    type Output = ();
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("tests/auxiliary/rust_test_helpers.c")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(TestHelpers { target: run.target })
-    }
-
-    /// Compiles the `rust_test_helpers.c` library which we used in various
-    /// `run-pass` tests for ABI testing.
-    fn run(self, builder: &Builder<'_>) {
-        if builder.config.dry_run() {
-            return;
-        }
-        // The x86_64-fortanix-unknown-sgx target doesn't have a working C
-        // toolchain. However, some x86_64 ELF objects can be linked
-        // without issues. Use this hack to compile the test helpers.
-        let target = if self.target == "x86_64-fortanix-unknown-sgx" {
-            TargetSelection::from_user("x86_64-unknown-linux-gnu")
-        } else {
-            self.target
-        };
-        let dst = builder.test_helpers_out(target);
-        let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
-        if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
-            return;
-        }
-
-        builder.info("Building test helpers");
-        t!(fs::create_dir_all(&dst));
-        let mut cfg = cc::Build::new();
-        // FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013
-        if target.contains("emscripten") {
-            cfg.pic(false);
-        }
-
-        // We may have found various cross-compilers a little differently due to our
-        // extra configuration, so inform cc of these compilers. Note, though, that
-        // on MSVC we still need cc's detection of env vars (ugh).
-        if !target.contains("msvc") {
-            if let Some(ar) = builder.ar(target) {
-                cfg.archiver(ar);
-            }
-            cfg.compiler(builder.cc(target));
-        }
-        cfg.cargo_metadata(false)
-            .out_dir(&dst)
-            .target(&target.triple)
-            .host(&builder.config.build.triple)
-            .opt_level(0)
-            .warnings(false)
-            .debug(false)
-            .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
-            .compile("rust_test_helpers");
-    }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Sanitizers {
     pub target: TargetSelection,
 }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 29d37c09d88..92a7603a9df 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -19,11 +19,11 @@ use crate::config::TargetSelection;
 use crate::dist;
 use crate::doc::DocumentationFormat;
 use crate::flags::Subcommand;
-use crate::native;
+use crate::llvm;
 use crate::render_tests::add_flags_and_try_run_tests;
 use crate::tool::{self, SourceType, Tool};
 use crate::toolstate::ToolState;
-use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t};
+use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t, up_to_date};
 use crate::{envify, CLang, DocTests, GitRepo, Mode};
 
 const ADB_TEST_DIR: &str = "/data/local/tmp/work";
@@ -1434,11 +1434,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         builder.ensure(compile::Std::new(compiler, compiler.host));
 
         // Also provide `rust_test_helpers` for the host.
-        builder.ensure(native::TestHelpers { target: compiler.host });
+        builder.ensure(TestHelpers { target: compiler.host });
 
         // As well as the target, except for plain wasm32, which can't build it
         if !target.contains("wasm") || target.contains("emscripten") {
-            builder.ensure(native::TestHelpers { target });
+            builder.ensure(TestHelpers { target });
         }
 
         builder.ensure(RemoteCopyLibs { compiler, target });
@@ -1625,8 +1625,8 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         let mut llvm_components_passed = false;
         let mut copts_passed = false;
         if builder.config.llvm_enabled() {
-            let native::LlvmResult { llvm_config, .. } =
-                builder.ensure(native::Llvm { target: builder.config.build });
+            let llvm::LlvmResult { llvm_config, .. } =
+                builder.ensure(llvm::Llvm { target: builder.config.build });
             if !builder.config.dry_run() {
                 let llvm_version = output(Command::new(&llvm_config).arg("--version"));
                 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
@@ -1664,7 +1664,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 // If LLD is available, add it to the PATH
                 if builder.config.lld_enabled {
                     let lld_install_root =
-                        builder.ensure(native::Lld { target: builder.config.build });
+                        builder.ensure(llvm::Lld { target: builder.config.build });
 
                     let lld_bin_path = lld_install_root.join("bin");
 
@@ -2747,3 +2747,68 @@ impl Step for RustInstaller {
         run.builder.ensure(Self);
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct TestHelpers {
+    pub target: TargetSelection,
+}
+
+impl Step for TestHelpers {
+    type Output = ();
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("tests/auxiliary/rust_test_helpers.c")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(TestHelpers { target: run.target })
+    }
+
+    /// Compiles the `rust_test_helpers.c` library which we used in various
+    /// `run-pass` tests for ABI testing.
+    fn run(self, builder: &Builder<'_>) {
+        if builder.config.dry_run() {
+            return;
+        }
+        // The x86_64-fortanix-unknown-sgx target doesn't have a working C
+        // toolchain. However, some x86_64 ELF objects can be linked
+        // without issues. Use this hack to compile the test helpers.
+        let target = if self.target == "x86_64-fortanix-unknown-sgx" {
+            TargetSelection::from_user("x86_64-unknown-linux-gnu")
+        } else {
+            self.target
+        };
+        let dst = builder.test_helpers_out(target);
+        let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
+        if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
+            return;
+        }
+
+        builder.info("Building test helpers");
+        t!(fs::create_dir_all(&dst));
+        let mut cfg = cc::Build::new();
+        // FIXME: Workaround for https://github.com/emscripten-core/emscripten/issues/9013
+        if target.contains("emscripten") {
+            cfg.pic(false);
+        }
+
+        // We may have found various cross-compilers a little differently due to our
+        // extra configuration, so inform cc of these compilers. Note, though, that
+        // on MSVC we still need cc's detection of env vars (ugh).
+        if !target.contains("msvc") {
+            if let Some(ar) = builder.ar(target) {
+                cfg.archiver(ar);
+            }
+            cfg.compiler(builder.cc(target));
+        }
+        cfg.cargo_metadata(false)
+            .out_dir(&dst)
+            .target(&target.triple)
+            .host(&builder.config.build.triple)
+            .opt_level(0)
+            .warnings(false)
+            .debug(false)
+            .file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
+            .compile("rust_test_helpers");
+    }
+}
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index d4d80e8f77c..7cd5e88f6a2 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -727,7 +727,7 @@ def record_metrics(pipeline: Pipeline, timer: Timer):
     metrics = load_last_metrics(pipeline.metrics_path())
     if metrics is None:
         return
-    llvm_steps = tuple(metrics.find_all_by_type("bootstrap::native::Llvm"))
+    llvm_steps = tuple(metrics.find_all_by_type("bootstrap::llvm::Llvm"))
     assert len(llvm_steps) > 0
     llvm_duration = sum(step.duration for step in llvm_steps)
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 15d090969743630bff549a1b068bcaa8174e5ee
+Subproject 145219a9f089f8b57c09f40525374fbade1e34a
diff --git a/triagebot.toml b/triagebot.toml
index 9ffe2e72cab..c86c1613fa9 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -498,7 +498,6 @@ compiler-team-contributors = [
     "@eholk",
     "@jackh726",
     "@TaKO8Ki",
-    "@Nilstrieb",
     "@WaffleLapkin",
     "@b-naber",
 ]