]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #74872 - JohnTitor:ping-risc-v, r=Mark-Simulacrum
authorYuki Okushi <huyuumi.dev@gmail.com>
Wed, 29 Jul 2020 00:24:24 +0000 (09:24 +0900)
committerGitHub <noreply@github.com>
Wed, 29 Jul 2020 00:24:24 +0000 (09:24 +0900)
Enable to ping RISC-V group via triagebot

We have the RISC-V group (https://github.com/rust-lang/team/blob/master/teams/risc-v.toml) but don't enable to ping on this repository (https://github.com/rust-lang/rust/pull/74813#issuecomment-664841177).
We don't have the instructions on the rustc-dev-guide yet but I'll create it soonish.

48 files changed:
.github/workflows/ci.yml
config.toml.example
library/alloc/tests/lib.rs
library/alloc/tests/str.rs
library/core/src/str/mod.rs
library/std/src/lazy.rs
library/std/src/sys/wasm/condvar_atomics.rs
library/std/src/sys/wasm/mutex_atomics.rs
library/std/src/sys/wasm/thread.rs
library/stdarch
src/README.md
src/bootstrap/builder.rs
src/bootstrap/builder/tests.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/doc.rs
src/bootstrap/flags.rs
src/bootstrap/mk/Makefile.in
src/bootstrap/test.rs
src/ci/azure-pipelines/auto.yml
src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile
src/ci/docker/host-x86_64/arm-android/Dockerfile
src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
src/ci/docker/host-x86_64/disabled/asmjs/Dockerfile
src/ci/docker/host-x86_64/disabled/dist-armv7-android/Dockerfile
src/ci/docker/host-x86_64/disabled/dist-i686-android/Dockerfile
src/ci/docker/host-x86_64/disabled/riscv64gc-linux/Dockerfile
src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
src/ci/docker/host-x86_64/dist-various-1/Dockerfile
src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
src/ci/docker/host-x86_64/i686-gnu/Dockerfile
src/ci/docker/host-x86_64/mingw-check/Dockerfile
src/ci/docker/host-x86_64/test-various/Dockerfile
src/ci/docker/host-x86_64/wasm32/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-full-bootstrap/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-llvm-8/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-nopt/Dockerfile
src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
src/ci/github-actions/ci.yml
src/librustc_error_codes/error_codes/E0720.md
src/librustc_span/symbol.rs
src/librustc_typeck/check/op.rs
src/librustdoc/html/static/themes/ayu.css
src/test/ui/const-generics/coerce_unsized_array.rs [new file with mode: 0644]
src/tools/unstable-book-gen/src/main.rs

index d83971b70bedc45bfecb79c29608d884c0d5ef79..565c916db5b5d186b6c73c7006a7eed445ed450e 100644 (file)
@@ -406,7 +406,7 @@ jobs:
             os: windows-latest-xl
           - name: x86_64-msvc-cargo
             env:
-              SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
+              SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-lld"
               VCVARS_BAT: vcvars64.bat
               NO_DEBUG_ASSERTIONS: 1
@@ -598,7 +598,7 @@ jobs:
             os: macos-latest
           - name: x86_64-apple
             env:
-              SCRIPT: "./x.py test"
+              SCRIPT: "./x.py --stage 2 test"
               RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc"
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.8
index 01952b21ba4b1fe9a07f76b246b65e3a0151760c..8ecd8d88d4895a8ddd082c6342efd6e9ffaefc2b 100644 (file)
 # Debuginfo for tests run with compiletest is not controlled by this option
 # and needs to be enabled separately with `debuginfo-level-tests`.
 #
-# Defaults to 2 if debug is true
+# 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 for the compiler.
 # instead of LLVM's default of 100.
 #thin-lto-import-instr-limit = 100
 
-# Map all debuginfo paths for libstd and crates to `/rust/$sha/$crate/...`,
-# generally only set for releases
+# Map debuginfo paths to `/rust/$sha/...`, generally only set for releases
 #remap-debuginfo = false
 
 # Link the compiler against `jemalloc`, where on Linux and OSX it should
index e2dc816b0152647b89036796158a56c35ce3d024..fa20a46671591f4aef2c91dc1735ffc533d5a058 100644 (file)
@@ -6,6 +6,7 @@
 #![feature(map_first_last)]
 #![feature(new_uninit)]
 #![feature(pattern)]
+#![feature(str_split_once)]
 #![feature(trusted_len)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
index eee98d45340429f4f759f8bee607e8bd0ca2f5da..b20cf076aca3cac5dacea42cfc143ea5525b93fd 100644 (file)
@@ -1318,6 +1318,30 @@ fn test_rsplitn() {
     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
 }
 
+#[test]
+fn test_split_once() {
+    assert_eq!("".split_once("->"), None);
+    assert_eq!("-".split_once("->"), None);
+    assert_eq!("->".split_once("->"), Some(("", "")));
+    assert_eq!("a->".split_once("->"), Some(("a", "")));
+    assert_eq!("->b".split_once("->"), Some(("", "b")));
+    assert_eq!("a->b".split_once("->"), Some(("a", "b")));
+    assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c")));
+    assert_eq!("---".split_once("--"), Some(("", "-")));
+}
+
+#[test]
+fn test_rsplit_once() {
+    assert_eq!("".rsplit_once("->"), None);
+    assert_eq!("-".rsplit_once("->"), None);
+    assert_eq!("->".rsplit_once("->"), Some(("", "")));
+    assert_eq!("a->".rsplit_once("->"), Some(("a", "")));
+    assert_eq!("->b".rsplit_once("->"), Some(("", "b")));
+    assert_eq!("a->b".rsplit_once("->"), Some(("a", "b")));
+    assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c")));
+    assert_eq!("---".rsplit_once("--"), Some(("-", "")));
+}
+
 #[test]
 fn test_split_whitespace() {
     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
index 790ec4bd24f8dcab225c7a3c52ee4550f497e270..9d7e38d0e183100b6cd79dbd775dfd39f4dc5852 100644 (file)
@@ -3610,6 +3610,47 @@ pub fn rsplitn<'a, P>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
         RSplitN(self.splitn(n, pat).0)
     }
 
+    /// Splits the string on the first occurrence of the specified delimiter and
+    /// returns prefix before delimiter and suffix after delimiter.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_once)]
+    ///
+    /// assert_eq!("cfg".split_once('='), None);
+    /// assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo")));
+    /// assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar")));
+    /// ```
+    #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")]
+    #[inline]
+    pub fn split_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> {
+        let (start, end) = delimiter.into_searcher(self).next_match()?;
+        Some((&self[..start], &self[end..]))
+    }
+
+    /// Splits the string on the last occurrence of the specified delimiter and
+    /// returns prefix before delimiter and suffix after delimiter.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_split_once)]
+    ///
+    /// assert_eq!("cfg".rsplit_once('='), None);
+    /// assert_eq!("cfg=foo".rsplit_once('='), Some(("cfg", "foo")));
+    /// assert_eq!("cfg=foo=bar".rsplit_once('='), Some(("cfg=foo", "bar")));
+    /// ```
+    #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")]
+    #[inline]
+    pub fn rsplit_once<'a, P>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)>
+    where
+        P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
+    {
+        let (start, end) = delimiter.into_searcher(self).next_match_back()?;
+        Some((&self[..start], &self[end..]))
+    }
+
     /// An iterator over the disjoint matches of a pattern within the given string
     /// slice.
     ///
index 1705a4f77c5555b4ad5ac05d4e89e22000602bf3..60eba96bcc0156f8f0357ce1dbb25fc304d5e95d 100644 (file)
@@ -451,7 +451,9 @@ unsafe impl<T, F: Send> Sync for SyncLazy<T, F> where SyncOnceCell<T>: Sync {}
 // auto-derived `Send` impl is OK.
 
 #[unstable(feature = "once_cell", issue = "74465")]
-impl<T, F: RefUnwindSafe> RefUnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: RefUnwindSafe {}
+impl<T, F: UnwindSafe> RefUnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: RefUnwindSafe {}
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T, F: UnwindSafe> UnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: UnwindSafe {}
 
 impl<T, F> SyncLazy<T, F> {
     /// Creates a new lazy value with the given initializing
index 1859cdd5a0ed840f0db015383eaa2ddfa73adfc1..d86bb60507be2c0d9bd0f410bd3b8048a4d2f052 100644 (file)
@@ -42,13 +42,13 @@ pub unsafe fn init(&mut self) {
 
     pub unsafe fn notify_one(&self) {
         self.cnt.fetch_add(1, SeqCst);
-        wasm32::atomic_notify(self.ptr(), 1);
+        wasm32::memory_atomic_notify(self.ptr(), 1);
     }
 
     #[inline]
     pub unsafe fn notify_all(&self) {
         self.cnt.fetch_add(1, SeqCst);
-        wasm32::atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
+        wasm32::memory_atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
     }
 
     pub unsafe fn wait(&self, mutex: &Mutex) {
@@ -62,7 +62,7 @@ pub unsafe fn wait(&self, mutex: &Mutex) {
         // wake us up once we're asleep.
         let ticket = self.cnt.load(SeqCst) as i32;
         mutex.unlock();
-        let val = wasm32::i32_atomic_wait(self.ptr(), ticket, -1);
+        let val = wasm32::memory_atomic_wait32(self.ptr(), ticket, -1);
         // 0 == woken, 1 == not equal to `ticket`, 2 == timeout (shouldn't happen)
         debug_assert!(val == 0 || val == 1);
         mutex.lock();
@@ -76,7 +76,7 @@ pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
 
         // If the return value is 2 then a timeout happened, so we return
         // `false` as we weren't actually notified.
-        let ret = wasm32::i32_atomic_wait(self.ptr(), ticket, nanos as i64) != 2;
+        let ret = wasm32::memory_atomic_wait32(self.ptr(), ticket, nanos as i64) != 2;
         mutex.lock();
         return ret;
     }
index 268a53bb5641ca58ca79b89b75310b6d3d5c91d8..4b1a7c9b48141c04632f09560d64cacbeed77f4e 100644 (file)
@@ -26,7 +26,7 @@ pub unsafe fn init(&mut self) {
 
     pub unsafe fn lock(&self) {
         while !self.try_lock() {
-            let val = wasm32::i32_atomic_wait(
+            let val = wasm32::memory_atomic_wait32(
                 self.ptr(),
                 1,  // we expect our mutex is locked
                 -1, // wait infinitely
@@ -40,7 +40,7 @@ pub unsafe fn lock(&self) {
     pub unsafe fn unlock(&self) {
         let prev = self.locked.swap(0, SeqCst);
         debug_assert_eq!(prev, 1);
-        wasm32::atomic_notify(self.ptr(), 1); // wake up one waiter, if any
+        wasm32::memory_atomic_notify(self.ptr(), 1); // wake up one waiter, if any
     }
 
     #[inline]
@@ -91,7 +91,7 @@ pub unsafe fn init(&self) {
     pub unsafe fn lock(&self) {
         let me = thread::my_id();
         while let Err(owner) = self._try_lock(me) {
-            let val = wasm32::i32_atomic_wait(self.ptr(), owner as i32, -1);
+            let val = wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1);
             debug_assert!(val == 0 || val == 1);
         }
     }
@@ -130,7 +130,7 @@ pub unsafe fn unlock(&self) {
         match *self.recursions.get() {
             0 => {
                 self.owner.swap(0, SeqCst);
-                wasm32::atomic_notify(self.ptr() as *mut i32, 1); // wake up one waiter, if any
+                wasm32::memory_atomic_notify(self.ptr() as *mut i32, 1); // wake up one waiter, if any
             }
             ref mut n => *n -= 1,
         }
index 0a11896a0048f31cb28f9b6819319c11dfb41418..95a9230aa7888a4cc5ce474b977d54053f1bbb22 100644 (file)
@@ -40,7 +40,7 @@ pub fn sleep(dur: Duration) {
         while nanos > 0 {
             let amt = cmp::min(i64::MAX as u128, nanos);
             let mut x = 0;
-            let val = unsafe { wasm32::i32_atomic_wait(&mut x, 0, amt as i64) };
+            let val = unsafe { wasm32::memory_atomic_wait32(&mut x, 0, amt as i64) };
             debug_assert_eq!(val, 2);
             nanos -= amt;
         }
index 45340c0e2fdadf2f131ef43cb683b5cafab0ff15..311d56cd91609c1c1c0370cbd2ece8e3048653a5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 45340c0e2fdadf2f131ef43cb683b5cafab0ff15
+Subproject commit 311d56cd91609c1c1c0370cbd2ece8e3048653a5
index b69a92a723778b4b4224dfc37e1f85fb40c92cdb..2f8e9da179afaaedf4795bb106c084f222e879a3 100644 (file)
@@ -1,6 +1,6 @@
 This directory contains the source code of the rust project, including:
 - `rustc` and its tests
-- `libstd`
+- The bootstrapping build system
 - Various submodules for tools, like rustdoc, rls, etc.
 
 For more information on how various parts of the compiler work, see the [rustc dev guide].
index c1e56347ab1e0111ed0ff5d0bd71f1c88aead816..144e146685fb20658d051a1a92a9da41a4e5644a 100644 (file)
@@ -232,7 +232,7 @@ fn run(v: &[StepDescription], builder: &Builder<'_>, paths: &[PathBuf]) {
                 }
 
                 if !attempted_run {
-                    panic!("Error: no rules matched {}.", path.display());
+                    panic!("error: no rules matched {}", path.display());
                 }
             }
         }
@@ -501,16 +501,7 @@ pub fn get_help(build: &Build, subcommand: &str) -> Option<String> {
             _ => return None,
         };
 
-        let builder = Builder {
-            build,
-            top_stage: build.config.stage.unwrap_or(2),
-            kind,
-            cache: Cache::new(),
-            stack: RefCell::new(Vec::new()),
-            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
-            paths: vec![],
-        };
-
+        let builder = Self::new_internal(build, kind, vec![]);
         let builder = &builder;
         let mut should_run = ShouldRun::new(builder);
         for desc in Builder::get_step_descriptions(builder.kind) {
@@ -535,6 +526,32 @@ pub fn get_help(build: &Build, subcommand: &str) -> Option<String> {
         Some(help)
     }
 
+    fn new_internal(build: &Build, kind: Kind, paths: Vec<PathBuf>) -> Builder<'_> {
+        let top_stage = if let Some(explicit_stage) = build.config.stage {
+            explicit_stage
+        } else {
+            // See https://github.com/rust-lang/compiler-team/issues/326
+            match kind {
+                Kind::Doc => 0,
+                Kind::Build | Kind::Test => 1,
+                Kind::Bench | Kind::Dist | Kind::Install => 2,
+                // These are all bootstrap tools, which don't depend on the compiler.
+                // The stage we pass shouldn't matter, but use 0 just in case.
+                Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => 0,
+            }
+        };
+
+        Builder {
+            build,
+            top_stage,
+            kind,
+            cache: Cache::new(),
+            stack: RefCell::new(Vec::new()),
+            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
+            paths,
+        }
+    }
+
     pub fn new(build: &Build) -> Builder<'_> {
         let (kind, paths) = match build.config.cmd {
             Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
@@ -550,15 +567,20 @@ pub fn new(build: &Build) -> Builder<'_> {
             Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
         };
 
-        Builder {
-            build,
-            top_stage: build.config.stage.unwrap_or(2),
-            kind,
-            cache: Cache::new(),
-            stack: RefCell::new(Vec::new()),
-            time_spent_on_dependencies: Cell::new(Duration::new(0, 0)),
-            paths: paths.to_owned(),
+        let this = Self::new_internal(build, kind, paths.to_owned());
+
+        // CI should always run stage 2 builds, unless it specifically states otherwise
+        #[cfg(not(test))]
+        if build.config.stage.is_none() && build.ci_env != crate::CiEnv::None {
+            match kind {
+                Kind::Test | Kind::Doc | Kind::Build | Kind::Bench | Kind::Dist | Kind::Install => {
+                    assert_eq!(this.top_stage, 2)
+                }
+                Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => {}
+            }
         }
+
+        this
     }
 
     pub fn execute_cli(&self) {
index 6684ca82c2775ca7618b8d66209c4db20f5edd13..111971534ba5e903026bb9b1b60a973727cfde43 100644 (file)
@@ -2,8 +2,6 @@
 use crate::config::{Config, TargetSelection};
 use std::thread;
 
-use pretty_assertions::assert_eq;
-
 fn configure(host: &[&str], target: &[&str]) -> Config {
     let mut config = Config::default_opts();
     // don't save toolstates
@@ -35,463 +33,562 @@ fn first<A, B>(v: Vec<(A, B)>) -> Vec<A> {
     v.into_iter().map(|(a, _)| a).collect::<Vec<_>>()
 }
 
-#[test]
-fn dist_baseline() {
-    let build = Build::new(configure(&[], &[]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-
-    assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
-    assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-    // Make sure rustdoc is only built once.
-    assert_eq!(
-        first(builder.cache.all::<tool::Rustdoc>()),
-        &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
-    );
-}
-
-#[test]
-fn dist_with_targets() {
-    let build = Build::new(configure(&[], &["B"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-}
-
-#[test]
-fn dist_with_hosts() {
-    let build = Build::new(configure(&["B"], &[]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[
-            dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
-            dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-}
-
-#[test]
-fn dist_only_cross_host() {
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let mut build = Build::new(configure(&["B"], &[]));
-    build.config.docs = false;
-    build.config.extended = true;
-    build.hosts = vec![b];
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Rustc>()),
-        &[
-            compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-}
-
-#[test]
-fn dist_with_targets_and_hosts() {
-    let build = Build::new(configure(&["B"], &["C"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[
-            dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
-            dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-}
-
-#[test]
-fn dist_with_target_flag() {
-    let mut config = configure(&["B"], &["C"]);
-    config.skip_only_host_steps = true; // as-if --target=C was passed
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]);
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[]);
-}
-
-#[test]
-fn dist_with_same_targets_and_hosts() {
-    let build = Build::new(configure(&["B"], &["B"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-
-    assert_eq!(
-        first(builder.cache.all::<dist::Docs>()),
-        &[dist::Docs { host: a }, dist::Docs { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Mingw>()),
-        &[dist::Mingw { host: a }, dist::Mingw { host: b },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Rustc>()),
-        &[
-            dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
-            dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<dist::Std>()),
-        &[
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-    assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
-    assert_eq!(
-        first(builder.cache.all::<compile::Std>()),
-        &[
-            compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Assemble>()),
-        &[
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
-            compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-}
-
-#[test]
-fn build_default() {
-    let build = Build::new(configure(&["B"], &["C"]));
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<compile::Std>()),
-        &[
-            compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
-        ]
-    );
-    assert!(!builder.cache.all::<compile::Assemble>().is_empty());
-    assert_eq!(
-        first(builder.cache.all::<compile::Rustc>()),
-        &[
-            compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b },
-            compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: b },
-        ]
-    );
-}
-
-#[test]
-fn build_with_target_flag() {
-    let mut config = configure(&["B"], &["C"]);
-    config.skip_only_host_steps = true;
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
-
-    let a = TargetSelection::from_user("A");
-    let b = TargetSelection::from_user("B");
-    let c = TargetSelection::from_user("C");
-
-    assert_eq!(
-        first(builder.cache.all::<compile::Std>()),
-        &[
-            compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
-            compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
-            compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
-            compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Assemble>()),
-        &[
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
-            compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
-            compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
-        ]
-    );
-    assert_eq!(
-        first(builder.cache.all::<compile::Rustc>()),
-        &[
-            compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
-            compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
-        ]
-    );
-}
-
-#[test]
-fn test_with_no_doc_stage0() {
-    let mut config = configure(&[], &[]);
-    config.stage = Some(0);
-    config.cmd = Subcommand::Test {
-        paths: vec!["library/std".into()],
-        test_args: vec![],
-        rustc_args: vec![],
-        fail_fast: true,
-        doc_tests: DocTests::No,
-        bless: false,
-        compare_mode: None,
-        rustfix_coverage: false,
-        pass: None,
-    };
-
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-
-    let host = TargetSelection::from_user("A");
-
-    builder
-        .run_step_descriptions(&[StepDescription::from::<test::Crate>()], &["library/std".into()]);
-
-    // Ensure we don't build any compiler artifacts.
-    assert!(!builder.cache.contains::<compile::Rustc>());
-    assert_eq!(
-        first(builder.cache.all::<test::Crate>()),
-        &[test::Crate {
-            compiler: Compiler { host, stage: 0 },
-            target: host,
-            mode: Mode::Std,
-            test_kind: test::TestKind::Test,
-            krate: INTERNER.intern_str("std"),
-        },]
-    );
-}
-
-#[test]
-fn test_exclude() {
-    let mut config = configure(&[], &[]);
-    config.exclude = vec!["src/tools/tidy".into()];
-    config.cmd = Subcommand::Test {
-        paths: Vec::new(),
-        test_args: Vec::new(),
-        rustc_args: Vec::new(),
-        fail_fast: true,
-        doc_tests: DocTests::No,
-        bless: false,
-        compare_mode: None,
-        rustfix_coverage: false,
-        pass: None,
-    };
-
-    let build = Build::new(config);
-    let builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
-
-    // Ensure we have really excluded tidy
-    assert!(!builder.cache.contains::<test::Tidy>());
-
-    // Ensure other tests are not affected.
-    assert!(builder.cache.contains::<test::RustdocUi>());
-}
-
-#[test]
-fn doc_default() {
-    let mut config = configure(&[], &[]);
-    config.compiler_docs = true;
-    config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
-    let a = TargetSelection::from_user("A");
-
-    // error_index_generator uses stage 1 to share rustdoc artifacts with the
-    // rustdoc tool.
-    assert_eq!(
-        first(builder.cache.all::<doc::ErrorIndex>()),
-        &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<tool::ErrorIndex>()),
-        &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
-    );
-    // This is actually stage 1, but Rustdoc::run swaps out the compiler with
-    // stage minus 1 if --stage is not 0. Very confusing!
-    assert_eq!(
-        first(builder.cache.all::<tool::Rustdoc>()),
-        &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
-    );
+mod defaults {
+    use super::{configure, first};
+    use crate::builder::*;
+    use crate::Config;
+    use pretty_assertions::assert_eq;
+
+    #[test]
+    fn build_default() {
+        let build = Build::new(configure(&[], &[]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+
+        let a = TargetSelection::from_user("A");
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+            ]
+        );
+        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        // Make sure rustdoc is only built once.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            // Recall that rustdoc stages are off-by-one
+            // - this is the compiler it's _linked_ to, not built with.
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } }],
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },]
+        );
+    }
+
+    #[test]
+    fn build_stage_0() {
+        let config = Config { stage: Some(0), ..configure(&[], &[]) };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+
+        let a = TargetSelection::from_user("A");
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },]
+        );
+        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            // This is the beta rustdoc.
+            // Add an assert here to make sure this is the only rustdoc built.
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } }],
+        );
+        assert!(builder.cache.all::<compile::Rustc>().is_empty());
+    }
+
+    #[test]
+    fn doc_default() {
+        let mut config = configure(&[], &[]);
+        config.compiler_docs = true;
+        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
+        let a = TargetSelection::from_user("A");
+
+        // error_index_generator uses stage 0 to share rustdoc artifacts with the
+        // rustdoc tool.
+        assert_eq!(
+            first(builder.cache.all::<doc::ErrorIndex>()),
+            &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 0 }, target: a },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<tool::ErrorIndex>()),
+            &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 0 } }]
+        );
+        // docs should be built with the beta compiler, not with the stage0 artifacts.
+        // recall that rustdoc is off-by-one: `stage` is the compiler rustdoc is _linked_ to,
+        // not the one it was built by.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },]
+        );
+    }
 }
 
-//FIXME(mark-i-m): reinstate this test when things are fixed...
-//#[test]
-#[allow(dead_code)]
-fn test_docs() {
-    // Behavior of `x.py test` doing various documentation tests.
-    let mut config = configure(&[], &[]);
-    config.cmd = Subcommand::Test {
-        paths: vec![],
-        test_args: vec![],
-        rustc_args: vec![],
-        fail_fast: true,
-        doc_tests: DocTests::Yes,
-        bless: false,
-        compare_mode: None,
-        rustfix_coverage: false,
-        pass: None,
-    };
-    let build = Build::new(config);
-    let mut builder = Builder::new(&build);
-    builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
-    let a = TargetSelection::from_user("A");
-
-    // error_index_generator uses stage 1 to share rustdoc artifacts with the
-    // rustdoc tool.
-    assert_eq!(
-        first(builder.cache.all::<doc::ErrorIndex>()),
-        &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
-    );
-    assert_eq!(
-        first(builder.cache.all::<tool::ErrorIndex>()),
-        &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
-    );
-    // Unfortunately rustdoc is built twice. Once from stage1 for compiletest
-    // (and other things), and once from stage0 for std crates. Ideally it
-    // would only be built once. If someone wants to fix this, it might be
-    // worth investigating if it would be possible to test std from stage1.
-    // Note that the stages here are +1 than what they actually are because
-    // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
-    // not 0.
-    assert_eq!(
-        first(builder.cache.all::<tool::Rustdoc>()),
-        &[
-            tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
-            tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
-        ]
-    );
+mod dist {
+    use super::{first, Config};
+    use crate::builder::*;
+    use pretty_assertions::assert_eq;
+
+    fn configure(host: &[&str], target: &[&str]) -> Config {
+        Config { stage: Some(2), ..super::configure(host, target) }
+    }
+
+    #[test]
+    fn dist_baseline() {
+        let build = Build::new(configure(&[], &[]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+
+        assert_eq!(first(builder.cache.all::<dist::Docs>()), &[dist::Docs { host: a },]);
+        assert_eq!(first(builder.cache.all::<dist::Mingw>()), &[dist::Mingw { host: a },]);
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        // Make sure rustdoc is only built once.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+    }
+
+    #[test]
+    fn dist_with_targets() {
+        let build = Build::new(configure(&[], &["B"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[dist::Rustc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+    }
+
+    #[test]
+    fn dist_with_hosts() {
+        let build = Build::new(configure(&["B"], &[]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[
+                dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
+                dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+    }
+
+    #[test]
+    fn dist_only_cross_host() {
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let mut build = Build::new(configure(&["B"], &[]));
+        build.config.docs = false;
+        build.config.extended = true;
+        build.hosts = vec![b];
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[dist::Rustc { compiler: Compiler { host: b, stage: 2 } },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[
+                compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+    }
+
+    #[test]
+    fn dist_with_targets_and_hosts() {
+        let build = Build::new(configure(&["B"], &["C"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[
+                dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
+                dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+    }
+
+    #[test]
+    fn dist_with_target_flag() {
+        let mut config = configure(&["B"], &["C"]);
+        config.skip_only_host_steps = true; // as-if --target=C was passed
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b }, dist::Docs { host: c },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b }, dist::Mingw { host: c },]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Rustc>()), &[]);
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                dist::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[]);
+    }
+
+    #[test]
+    fn dist_with_same_targets_and_hosts() {
+        let build = Build::new(configure(&["B"], &["B"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+
+        assert_eq!(
+            first(builder.cache.all::<dist::Docs>()),
+            &[dist::Docs { host: a }, dist::Docs { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Mingw>()),
+            &[dist::Mingw { host: a }, dist::Mingw { host: b },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Rustc>()),
+            &[
+                dist::Rustc { compiler: Compiler { host: a, stage: 2 } },
+                dist::Rustc { compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<dist::Std>()),
+            &[
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                dist::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+        assert_eq!(first(builder.cache.all::<dist::Src>()), &[dist::Src]);
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Assemble>()),
+            &[
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
+                compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+    }
+
+    #[test]
+    fn build_all() {
+        let build = Build::new(configure(&["B"], &["C"]));
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(
+            &Builder::get_step_descriptions(Kind::Build),
+            &["src/rustc".into(), "library/std".into()],
+        );
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
+            ]
+        );
+        assert!(!builder.cache.all::<compile::Assemble>().is_empty());
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[
+                compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Rustc { compiler: Compiler { host: a, stage: 2 }, target: b },
+                compile::Rustc { compiler: Compiler { host: b, stage: 2 }, target: b },
+            ]
+        );
+    }
+
+    #[test]
+    fn build_with_target_flag() {
+        let mut config = configure(&["B"], &["C"]);
+        config.skip_only_host_steps = true;
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
+
+        let a = TargetSelection::from_user("A");
+        let b = TargetSelection::from_user("B");
+        let c = TargetSelection::from_user("C");
+
+        assert_eq!(
+            first(builder.cache.all::<compile::Std>()),
+            &[
+                compile::Std { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: a },
+                compile::Std { compiler: Compiler { host: a, stage: 1 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: b },
+                compile::Std { compiler: Compiler { host: a, stage: 2 }, target: c },
+                compile::Std { compiler: Compiler { host: b, stage: 2 }, target: c },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Assemble>()),
+            &[
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 0 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 1 } },
+                compile::Assemble { target_compiler: Compiler { host: a, stage: 2 } },
+                compile::Assemble { target_compiler: Compiler { host: b, stage: 2 } },
+            ]
+        );
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[
+                compile::Rustc { compiler: Compiler { host: a, stage: 0 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: a },
+                compile::Rustc { compiler: Compiler { host: a, stage: 1 }, target: b },
+            ]
+        );
+    }
+
+    #[test]
+    fn test_with_no_doc_stage0() {
+        let mut config = configure(&[], &[]);
+        config.stage = Some(0);
+        config.cmd = Subcommand::Test {
+            paths: vec!["library/std".into()],
+            test_args: vec![],
+            rustc_args: vec![],
+            fail_fast: true,
+            doc_tests: DocTests::No,
+            bless: false,
+            compare_mode: None,
+            rustfix_coverage: false,
+            pass: None,
+        };
+
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+
+        let host = TargetSelection::from_user("A");
+
+        builder.run_step_descriptions(
+            &[StepDescription::from::<test::Crate>()],
+            &["library/std".into()],
+        );
+
+        // Ensure we don't build any compiler artifacts.
+        assert!(!builder.cache.contains::<compile::Rustc>());
+        assert_eq!(
+            first(builder.cache.all::<test::Crate>()),
+            &[test::Crate {
+                compiler: Compiler { host, stage: 0 },
+                target: host,
+                mode: Mode::Std,
+                test_kind: test::TestKind::Test,
+                krate: INTERNER.intern_str("std"),
+            },]
+        );
+    }
+
+    #[test]
+    fn test_exclude() {
+        let mut config = configure(&[], &[]);
+        config.exclude = vec!["src/tools/tidy".into()];
+        config.cmd = Subcommand::Test {
+            paths: Vec::new(),
+            test_args: Vec::new(),
+            rustc_args: Vec::new(),
+            fail_fast: true,
+            doc_tests: DocTests::No,
+            bless: false,
+            compare_mode: None,
+            rustfix_coverage: false,
+            pass: None,
+        };
+
+        let build = Build::new(config);
+        let builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
+
+        // Ensure we have really excluded tidy
+        assert!(!builder.cache.contains::<test::Tidy>());
+
+        // Ensure other tests are not affected.
+        assert!(builder.cache.contains::<test::RustdocUi>());
+    }
+
+    #[test]
+    fn doc_ci() {
+        let mut config = configure(&[], &[]);
+        config.compiler_docs = true;
+        config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
+        let a = TargetSelection::from_user("A");
+
+        // error_index_generator uses stage 1 to share rustdoc artifacts with the
+        // rustdoc tool.
+        assert_eq!(
+            first(builder.cache.all::<doc::ErrorIndex>()),
+            &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<tool::ErrorIndex>()),
+            &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
+        );
+        // This is actually stage 1, but Rustdoc::run swaps out the compiler with
+        // stage minus 1 if --stage is not 0. Very confusing!
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },]
+        );
+    }
+
+    #[test]
+    fn test_docs() {
+        // Behavior of `x.py test` doing various documentation tests.
+        let mut config = configure(&[], &[]);
+        config.cmd = Subcommand::Test {
+            paths: vec![],
+            test_args: vec![],
+            rustc_args: vec![],
+            fail_fast: true,
+            doc_tests: DocTests::Yes,
+            bless: false,
+            compare_mode: None,
+            rustfix_coverage: false,
+            pass: None,
+        };
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+        builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]);
+        let a = TargetSelection::from_user("A");
+
+        // error_index_generator uses stage 1 to share rustdoc artifacts with the
+        // rustdoc tool.
+        assert_eq!(
+            first(builder.cache.all::<doc::ErrorIndex>()),
+            &[doc::ErrorIndex { compiler: Compiler { host: a, stage: 1 }, target: a },]
+        );
+        assert_eq!(
+            first(builder.cache.all::<tool::ErrorIndex>()),
+            &[tool::ErrorIndex { compiler: Compiler { host: a, stage: 1 } }]
+        );
+        // Unfortunately rustdoc is built twice. Once from stage1 for compiletest
+        // (and other things), and once from stage0 for std crates. Ideally it
+        // would only be built once. If someone wants to fix this, it might be
+        // worth investigating if it would be possible to test std from stage1.
+        // Note that the stages here are +1 than what they actually are because
+        // Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
+        // not 0.
+        assert_eq!(
+            first(builder.cache.all::<tool::Rustdoc>()),
+            &[
+                tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
+                tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
+            ]
+        );
+    }
 }
index e3d1e005373bbaee4fc80afdef48b466982c6107..373e240cb8e3e456018e8eec30688443d2425d40 100644 (file)
@@ -446,10 +446,10 @@ pub struct Rustc {
 impl Step for Rustc {
     type Output = ();
     const ONLY_HOSTS: bool = true;
-    const DEFAULT: bool = true;
+    const DEFAULT: bool = false;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.all_krates("rustc-main")
+        run.path("src/rustc")
     }
 
     fn make_run(run: RunConfig<'_>) {
index d71f31704209eb1b895956fe5acd46f37589509f..d64ca95d24392ab1221c90d6974eb122bf42d955 100644 (file)
@@ -734,7 +734,7 @@ pub fn parse(args: &[String]) -> Config {
 
         let with_defaults = |debuginfo_level_specific: Option<u32>| {
             debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) {
-                2
+                1
             } else {
                 0
             })
index b43108ccaf984eabbbfa5a4ffab29158d61e6df8..96cabf754490b4950273099aebc1ab3dcf81e914 100644 (file)
@@ -693,6 +693,7 @@ fn run(self, builder: &Builder<'_>) {
         builder.create_dir(&out);
         builder.remove_dir(&out);
         let mut cmd = builder.tool_cmd(Tool::UnstableBookGen);
+        cmd.arg(builder.src.join("library"));
         cmd.arg(builder.src.join("src"));
         cmd.arg(out);
 
index a298b299667d557d87c1abcadb2680ec6395ac19..56e4f0467cc50967978d2752e7cf99374e460977 100644 (file)
@@ -425,7 +425,7 @@ pub fn parse(args: &[String]) -> Flags {
     This subcommand accepts a number of paths to tools to build and run. For
     example:
 
-        ./x.py run src/tool/expand-yaml-anchors
+        ./x.py run src/tools/expand-yaml-anchors
 
     At least a tool needs to be called.",
                 );
index e5b9f27c258e053b4bd8dbe68a59f974f44191d8..1564cfb06199c7e77292e3b951c20441d4b20387 100644 (file)
@@ -9,8 +9,8 @@ endif
 BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
 
 all:
-       $(Q)$(BOOTSTRAP) build $(BOOTSTRAP_ARGS)
-       $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) build --stage 2 $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) doc --stage 2 $(BOOTSTRAP_ARGS)
 
 help:
        $(Q)echo 'Welcome to the rustbuild build system!'
@@ -31,17 +31,17 @@ rustc-stage2:
 
 docs: doc
 doc:
-       $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) doc --stage 2 $(BOOTSTRAP_ARGS)
 nomicon:
-       $(Q)$(BOOTSTRAP) doc src/doc/nomicon $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) doc --stage 2 src/doc/nomicon $(BOOTSTRAP_ARGS)
 book:
-       $(Q)$(BOOTSTRAP) doc src/doc/book $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) doc --stage 2 src/doc/book $(BOOTSTRAP_ARGS)
 standalone-docs:
-       $(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) doc --stage 2 src/doc $(BOOTSTRAP_ARGS)
 check:
-       $(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) test --stage 2 $(BOOTSTRAP_ARGS)
 check-aux:
-       $(Q)$(BOOTSTRAP) test \
+       $(Q)$(BOOTSTRAP) test --stage 2 \
                src/tools/cargo \
                src/tools/cargotest \
                $(BOOTSTRAP_ARGS)
@@ -51,18 +51,18 @@ dist:
        $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
 distcheck:
        $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
-       $(Q)$(BOOTSTRAP) test distcheck $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) test --stage 2 distcheck $(BOOTSTRAP_ARGS)
 install:
        $(Q)$(BOOTSTRAP) install $(BOOTSTRAP_ARGS)
 tidy:
-       $(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS)
+       $(Q)$(BOOTSTRAP) test --stage 2 src/tools/tidy $(BOOTSTRAP_ARGS)
 prepare:
-       $(Q)$(BOOTSTRAP) build nonexistent/path/to/trigger/cargo/metadata
+       $(Q)$(BOOTSTRAP) build --stage 2 nonexistent/path/to/trigger/cargo/metadata
 
 check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
-       $(Q)$(BOOTSTRAP) test --target arm-linux-androideabi
+       $(Q)$(BOOTSTRAP) test --stage 2 --target arm-linux-androideabi
 check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu:
-       $(Q)$(BOOTSTRAP) test --target x86_64-unknown-linux-musl
+       $(Q)$(BOOTSTRAP) test --stage 2 --target x86_64-unknown-linux-musl
 
 TESTS_IN_2 := \
        src/test/ui \
@@ -70,18 +70,18 @@ TESTS_IN_2 := \
        src/tools/linkchecker
 
 ci-subset-1:
-       $(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %)
+       $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_2:%=--exclude %)
 ci-subset-2:
-       $(Q)$(BOOTSTRAP) test $(TESTS_IN_2)
+       $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_2)
 
 TESTS_IN_MINGW_2 := \
        src/test/ui \
        src/test/compile-fail
 
 ci-mingw-subset-1:
-       $(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2:%=--exclude %)
+       $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2:%=--exclude %)
 ci-mingw-subset-2:
-       $(Q)$(BOOTSTRAP) test $(TESTS_IN_MINGW_2)
+       $(Q)$(BOOTSTRAP) test --stage 2 $(TESTS_IN_MINGW_2)
 
 
 .PHONY: dist
index addc51faa5e29fa2b8a511d314eaed19ad9855a4..05af7210b1c68569bd732d72c14dd571715eb9c7 100644 (file)
@@ -106,19 +106,18 @@ impl Step for Linkcheck {
     ///
     /// This tool in `src/tools` will verify the validity of all our links in the
     /// documentation to ensure we don't have a bunch of dead ones.
-    fn run(self, _builder: &Builder<'_>) {
-        // FIXME(mark-i-m): uncomment this after we fix the links...
-        // let host = self.host;
+    fn run(self, builder: &Builder<'_>) {
+        let host = self.host;
 
-        // builder.info(&format!("Linkcheck ({})", host));
+        builder.info(&format!("Linkcheck ({})", host));
 
-        // builder.default_doc(None);
+        builder.default_doc(None);
 
-        // let _time = util::timeit(&builder);
-        // try_run(
-        //     builder,
-        //     builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")),
-        // );
+        let _time = util::timeit(&builder);
+        try_run(
+            builder,
+            builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")),
+        );
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
index 06e284c763c1509f7c34b38d3edc5e0198ff158c..2185b0d30dbde350c3ae25708d9388970b408768 100644 (file)
@@ -36,7 +36,7 @@ jobs:
       # Note that the compiler is compiled to target 10.8 here because the Xcode
       # version that we're using, 8.2, cannot compile LLVM for OSX 10.7.
       x86_64-apple:
-        SCRIPT: ./x.py test
+        SCRIPT: ./x.py --stage 2 test
         INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
         RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
         MACOSX_DEPLOYMENT_TARGET: 10.8
index 114ac832cf504c38c65e7574fbb9719b8998c080..b6cf60a5e15a7b11aa31b4a60fb241ab4d4df2f9 100644 (file)
@@ -23,4 +23,4 @@ ENV RUST_CONFIGURE_ARGS \
  --enable-sanitizers \
  --enable-profiler \
  --enable-compiler-docs
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
index aa9335c473b5b34190ad9140f9892b5e7e57ac00..add2647fa1e65c503abe0514981dd062d02d12de 100644 (file)
@@ -31,7 +31,7 @@ ENV TARGETS=arm-linux-androideabi
 
 ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14
 
-ENV SCRIPT python3 ../x.py test --target $TARGETS
+ENV SCRIPT python3 ../x.py --stage 2 test --target $TARGETS
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
index 71071761f05cdea1e11063ab3b4a73397ab8ee51..1f3092c5513d956c21c9885a9d81c30dbbb30900 100644 (file)
@@ -78,6 +78,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --qemu-armhf-rootfs=/tmp/rootfs
-ENV SCRIPT python3 ../x.py test --target arm-unknown-linux-gnueabihf
+ENV SCRIPT python3 ../x.py --stage 2 test --target arm-unknown-linux-gnueabihf
 
 ENV NO_CHANGE_USER=1
index 3fa65511e94f783912f52b7f7d2619b9a7e41cce..a4d9f53ebabef1c3d32a4b07329f1de6e5abd9eb 100644 (file)
@@ -33,7 +33,7 @@ ENV EMCC_CFLAGS=-O1
 # Emscripten installation is user-specific
 ENV NO_CHANGE_USER=1
 
-ENV SCRIPT python3 ../x.py test --target $TARGETS
+ENV SCRIPT python3 ../x.py --stage 2 test --target $TARGETS
 
 # This is almost identical to the wasm32-unknown-emscripten target, so
 # running with assertions again is not useful
index 7227c41ccca9a7dda4f54bcac161c7163a50384a..f986c38ea02da913313c0760d701288aba98f81a 100644 (file)
@@ -33,7 +33,7 @@ ENV RUST_CONFIGURE_ARGS \
 # build to finish we use --warn-unresolved-symbols. Note that the missing
 # symbols does not affect std, only the compiler (llvm) and cargo (openssl).
 ENV SCRIPT \
-  python3 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
+  python3 ../x.py --stage 2 build src/llvm --host $HOSTS --target $HOSTS && \
   (export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
     rm /android/ndk/arm && \
     ln -s /android/ndk/arm-14 /android/ndk/arm && \
index b74dcefa3516c5566262896a62b18f781cf10b9a..4dfbc72560783f4d9a6229fd7f222b5cced9f934 100644 (file)
@@ -33,7 +33,7 @@ ENV RUST_CONFIGURE_ARGS \
 # build to finish we use --warn-unresolved-symbols. Note that the missing
 # symbols does not affect std, only the compiler (llvm) and cargo (openssl).
 ENV SCRIPT \
-  python3 ../x.py build src/llvm --host $HOSTS --target $HOSTS && \
+  python3 ../x.py --stage 2 build src/llvm --host $HOSTS --target $HOSTS && \
   (export RUSTFLAGS="\"-C link-arg=-Wl,--warn-unresolved-symbols\""; \
     rm /android/ndk/x86 && \
     ln -s /android/ndk/x86-14 /android/ndk/x86 && \
index a938899636a45878ad03f8d6a778e10e34c24240..e3c35000eb818086cc67c4cd0e77dc83bbc46c91 100644 (file)
@@ -97,6 +97,6 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs
-ENV SCRIPT python3 ../x.py test --target riscv64gc-unknown-linux-gnu
+ENV SCRIPT python3 ../x.py --stage 2 test --target riscv64gc-unknown-linux-gnu
 
 ENV NO_CHANGE_USER=1
index 996fffeb871cfc9f7f6fe23e08f7ac33cc7b11ae..162d7a1345ce1cb64f9b192b292da68f8d76abaf 100644 (file)
@@ -46,5 +46,5 @@ ENV CFLAGS_i586_unknown_linux_musl=-Wa,-mrelax-relocations=no
 ENV TARGETS=i586-unknown-linux-gnu,i686-unknown-linux-musl
 
 ENV SCRIPT \
-      python3 ../x.py test --target $TARGETS && \
+      python3 ../x.py --stage 2 test --target $TARGETS && \
       python3 ../x.py dist --target $TARGETS,i586-unknown-linux-musl
index ac228cfe01d800cb777297c58631957487e42d3d..fdd777e824ba89c5433e50ea6ff4d85837d6de59 100644 (file)
@@ -192,7 +192,7 @@ ENV RUST_CONFIGURE_ARGS \
       --disable-docs
 
 ENV SCRIPT \
-      python3 ../x.py test --target $RUN_MAKE_TARGETS src/test/run-make && \
+      python3 ../x.py --stage 2 test --target $RUN_MAKE_TARGETS src/test/run-make && \
       python3 ../x.py dist --target $TARGETS
 
 # sccache
index 436215839f7dd1d94177f4622321cf9f9d8efbd6..6a596b3465f20da7e0b22843b63871fb89c1daf9 100644 (file)
@@ -20,7 +20,7 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
 
 # FIXME(#59637) takes too long on CI right now
 ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
index 34a76f39668a727df3abf43ef3bb1e0691df42cb..9d319017d7967cbc0c9ccdc18846b561a333a74e 100644 (file)
@@ -22,7 +22,7 @@ RUN sh /scripts/sccache.sh
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
 # Exclude some tests that are unlikely to be platform specific, to speed up
 # this slow job.
-ENV SCRIPT python3 ../x.py test \
+ENV SCRIPT python3 ../x.py --stage 2 test \
   --exclude src/bootstrap \
   --exclude src/test/rustdoc-js \
   --exclude src/tools/error_index_generator \
index 0c59b95ea2143f16230d5302e1d5fa8853f44ed5..b902eda87bc6ec9bd3c2d7b6b23a129be73f3b31 100644 (file)
@@ -22,10 +22,10 @@ RUN sh /scripts/sccache.sh
 COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
 
 ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
-ENV SCRIPT python3 ../x.py test src/tools/expand-yaml-anchors && \
+ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
            python3 ../x.py build --stage 0 src/tools/build-manifest && \
            python3 ../x.py test --stage 0 src/tools/compiletest && \
-           python3 ../x.py test src/tools/tidy && \
+           python3 ../x.py test --stage 2 src/tools/tidy && \
            python3 ../x.py doc --stage 0 library/std && \
            /scripts/validate-toolstate.sh
index b7276f60867a7b8e01c5cfb019f648ec8afe346f..c55a284e137b34454e4c0914b6ea103167216254 100644 (file)
@@ -40,7 +40,7 @@ ENV RUST_CONFIGURE_ARGS \
 ENV NO_DEBUG_ASSERTIONS=1
 
 ENV WASM_TARGETS=wasm32-unknown-unknown
-ENV WASM_SCRIPT python3 /checkout/x.py test --target $WASM_TARGETS \
+ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --target $WASM_TARGETS \
   src/test/run-make \
   src/test/ui \
   src/test/compile-fail \
@@ -49,13 +49,13 @@ ENV WASM_SCRIPT python3 /checkout/x.py test --target $WASM_TARGETS \
   library/core
 
 ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
-ENV NVPTX_SCRIPT python3 /checkout/x.py test --target $NVPTX_TARGETS \
+ENV NVPTX_SCRIPT python3 /checkout/x.py --stage 2 test --target $NVPTX_TARGETS \
   src/test/run-make \
   src/test/assembly
 
 ENV MUSL_TARGETS=x86_64-unknown-linux-musl \
     CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc \
     CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
-ENV MUSL_SCRIPT python3 /checkout/x.py test --target $MUSL_TARGETS
+ENV MUSL_SCRIPT python3 /checkout/x.py --stage 2 test --target $MUSL_TARGETS
 
 ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT && $MUSL_SCRIPT
index a40ccb6bfd5ae3f82d06f35791b8a0fefbd81b00..e00177b4a67c9a979d104d956f98449f5bac7622 100644 (file)
@@ -52,7 +52,7 @@ ENV NO_CHANGE_USER=1
 
 # FIXME: Re-enable these tests once https://github.com/rust-lang/cargo/pull/7476
 # is picked up by CI
-ENV SCRIPT python3 ../x.py test --target $TARGETS \
+ENV SCRIPT python3 ../x.py test --stage 2 --target $TARGETS \
     --exclude library/core \
     --exclude library/alloc \
     --exclude library/proc_macro \
index c5e41b8a75afe506048fa18eba18a27da91ae2d0..c1cb20b631d319d20a4a35845860366ae577588a 100644 (file)
@@ -40,5 +40,5 @@ ENV RUST_CONFIGURE_ARGS \
       --set target.x86_64-unknown-linux-gnu.cxx=clang++
 
 ENV SCRIPT \
-  python3 ../x.py build && \
-  python3 ../x.py test src/test/run-make-fulldeps --test-args clang
+  python3 ../x.py --stage 2 build && \
+  python3 ../x.py --stage 2 test src/test/run-make-fulldeps --test-args clang
index cc07a591cc17bec1c7d1d853f8216f75165aa98f..68e89a7bade342b09d849945c053d00f44b95731 100644 (file)
@@ -19,10 +19,10 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.ignore-git=false
-ENV SCRIPT python3 ../x.py test distcheck
+ENV SCRIPT python3 ../x.py --stage 2 test distcheck
 ENV DIST_SRC 1
 
-# The purpose of this builder is to test that we can `./x.py test` successfully
+# The purpose of this builder is to test that we can `./x.py --stage 2 test` successfully
 # from a tarball, not to test LLVM/rustc's own set of assertions. These cause a
 # significant hit to CI compile time (over a half hour as observed in #61185),
 # so disable assertions for this builder.
index de7ee6950b51b26ca00c06b2c32af0bf8b2c51f0..8648e5ed7a4866e377d0fee584d6fdf189c80e01 100644 (file)
@@ -21,7 +21,7 @@ RUN sh /scripts/sccache.sh
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-full-bootstrap
-ENV SCRIPT python3 ../x.py build
+ENV SCRIPT python3 ../x.py --stage 2 build
 
 # In general this just slows down the build and we're just a smoke test that
 # a full bootstrap works in general, so there's not much need to take this
index 1d9cad149d9aeb627e34d0a007546ca0cc365831..5c971c73c97d3485ae5ce4811b603b26f5dfea87 100644 (file)
@@ -30,7 +30,7 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-llvm-link-shared \
       --set rust.thin-lto-import-instr-limit=10
 
-ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && \
+ENV SCRIPT python2.7 ../x.py --stage 2 test --exclude src/tools/tidy && \
            # Run the `mir-opt` tests again but this time for a 32-bit target.
            # This enforces that tests using `// EMIT_MIR_FOR_EACH_BIT_WIDTH` have
            # both 32-bit and 64-bit outputs updated by the PR author, before
@@ -43,7 +43,7 @@ ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && \
            # This also requires `--pass=build` because we can't execute the tests
            # on the `x86_64` host when they're built as `armv5te` binaries.
            # (we're only interested in the MIR output, so this doesn't matter)
-           python2.7 ../x.py test src/test/mir-opt --pass=build \
+           python2.7 ../x.py --stage 2 test src/test/mir-opt --pass=build \
                                   --target=armv5te-unknown-linux-gnueabi && \
            # Run the UI test suite again, but in `--pass=check` mode
            #
@@ -53,9 +53,9 @@ ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && \
            # FIXME: We ideally want to test this in 32-bit mode, but currently
            # (due to the LLVM problems mentioned above) that isn't readily
            # possible.
-           python2.7 ../x.py test src/test/ui --pass=check && \
+           python2.7 ../x.py --stage 2 test src/test/ui --pass=check && \
            # Run tidy at the very end, after all the other tests.
-           python2.7 ../x.py test src/tools/tidy
+           python2.7 ../x.py --stage 2 test src/tools/tidy
 
 # The purpose of this container isn't to test with debug assertions and
 # this is run on all PRs, so let's get speedier builds by disabling these extra
index 096f67e13d1e679c0414ca8445c63abece65cb49..fa769cac9c1da8ec7a8241049056dc1a193287fe 100644 (file)
@@ -21,4 +21,4 @@ RUN sh /scripts/sccache.sh
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
   --disable-optimize-tests \
   --set rust.test-compare-mode
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
index b4b23a245e0aa928b0d7689e9ba8b07ba953f25c..49a8e5e88a0390d412a115b731cb30dd9bd7d8f3 100755 (executable)
@@ -7,7 +7,7 @@ X_PY="$1"
 # Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
 
 set +e
-python3 "$X_PY" test --no-fail-fast \
+python3 "$X_PY" test --stage 2 --no-fail-fast \
     src/doc/book \
     src/doc/nomicon \
     src/doc/reference \
@@ -22,5 +22,5 @@ set -e
 
 # debugging: print out the saved toolstates
 cat /tmp/toolstate/toolstates.json
-python3 "$X_PY" test check-tools
-python3 "$X_PY" test src/tools/clippy
+python3 "$X_PY" test --stage 2 check-tools
+python3 "$X_PY" test --stage 2 src/tools/clippy
index af6e13180627688b881fc9cc49b7bd3715a5ca01..f8bacf79ac0dccea249b20a2aeaa55ed14e38f9e 100644 (file)
@@ -23,4 +23,4 @@ ENV RUST_CONFIGURE_ARGS \
  --enable-sanitizers \
  --enable-profiler \
  --enable-compiler-docs
-ENV SCRIPT python3 ../x.py test
+ENV SCRIPT python3 ../x.py --stage 2 test
index 0aeb6a04e5f773ec8d12ef17351ba9ef77f5d88f..a7c1987e8b1c9182ec1ae21a2661b73a2d832d5a 100644 (file)
@@ -471,7 +471,7 @@ jobs:
 
           - name: x86_64-msvc-cargo
             env:
-              SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
+              SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo
               RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
               VCVARS_BAT: vcvars64.bat
               # FIXME(#59637)
@@ -613,7 +613,7 @@ jobs:
 
           - name: x86_64-apple
             env:
-              SCRIPT: ./x.py test
+              SCRIPT: ./x.py --stage 2 test
               RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.8
index 410aa4f4609a82778f2db9e1656853e629df08eb..40dfa484d3f9443760894bb2680994fddcfa0645 100644 (file)
@@ -1,11 +1,13 @@
 An `impl Trait` type expands to a recursive type.
 
-An `impl Trait` type must be expandable to a concrete type that contains no
-`impl Trait` types. For example the following example tries to create an
-`impl Trait` type `T` that is equal to `[T, T]`:
+Erroneous code example:
 
 ```compile_fail,E0720
 fn make_recursive_type() -> impl Sized {
     [make_recursive_type(), make_recursive_type()]
 }
 ```
+
+An `impl Trait` type must be expandable to a concrete type that contains no
+`impl Trait` types. For example the previous example tries to create an
+`impl Trait` type `T` that is equal to `[T, T]`.
index dadf040304d4683b81d22cad0295ae3650dc12f6..98776a0478237495e80c53b76f93c7225ee39d8a 100644 (file)
         stop_after_dataflow,
         str,
         str_alloc,
+        string_type,
         stringify,
         struct_field_attributes,
         struct_inherit,
index 41aac3569d115f8e2e364eeb393e61db8f41add5..fd516c88ec61aac2896f340e66d4baee1236c065 100644 (file)
@@ -562,7 +562,11 @@ fn check_str_addition(
                    on the left and may require reallocation. This \
                    requires ownership of the string on the left";
 
-        let is_std_string = |ty| &format!("{:?}", ty) == "std::string::String";
+        let string_type = self.tcx.get_diagnostic_item(sym::string_type);
+        let is_std_string = |ty: Ty<'tcx>| match ty.ty_adt_def() {
+            Some(ty_def) => Some(ty_def.did) == string_type,
+            None => false,
+        };
 
         match (&lhs_ty.kind, &rhs_ty.kind) {
             (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str
index 01b7ae8778671957365f91c953dafb0615dafed2..f4710f6ae873aef882d6387c255e0553ca75f5e8 100644 (file)
@@ -197,9 +197,8 @@ pre {
        color: #a37acc;
 }
 
-pre.rust .comment, pre.rust .doccomment {
-       color: #788797;
-}
+pre.rust .comment { color: #788797; }
+pre.rust .doccomment { color: #a1ac88; }
 
 nav:not(.sidebar) {
        border-bottom-color: #424c57;
diff --git a/src/test/ui/const-generics/coerce_unsized_array.rs b/src/test/ui/const-generics/coerce_unsized_array.rs
new file mode 100644 (file)
index 0000000..b28768a
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+
+fn foo<const N: usize>(v: &[u8; N]) -> &[u8] {
+    v
+}
+
+fn main() {
+    assert_eq!(foo(&[1, 2]), &[1, 2]);
+}
index aa24881ac6bd75ea2b176f9180f65e26a5c9bd39..11617911446ecee0fed0f5ee4e3e830ec9bc5942 100644 (file)
@@ -94,13 +94,15 @@ fn copy_recursive(from: &Path, to: &Path) {
 }
 
 fn main() {
-    let src_path_str = env::args_os().skip(1).next().expect("source path required");
-    let dest_path_str = env::args_os().skip(2).next().expect("destination path required");
+    let library_path_str = env::args_os().skip(1).next().expect("library path required");
+    let src_path_str = env::args_os().skip(2).next().expect("source path required");
+    let dest_path_str = env::args_os().skip(3).next().expect("destination path required");
+    let library_path = Path::new(&library_path_str);
     let src_path = Path::new(&src_path_str);
     let dest_path = Path::new(&dest_path_str);
 
     let lang_features = collect_lang_features(src_path, &mut false);
-    let lib_features = collect_lib_features(src_path)
+    let lib_features = collect_lib_features(library_path)
         .into_iter()
         .filter(|&(ref name, _)| !lang_features.contains_key(name))
         .collect();