diff options
| author | The Miri Cronjob Bot <miri@cron.bot> | 2025-09-01 05:02:58 +0000 |
|---|---|---|
| committer | The Miri Cronjob Bot <miri@cron.bot> | 2025-09-01 05:02:58 +0000 |
| commit | 4cc7ccaf9812c1ba9606528345ce5a6a4060ca6c (patch) | |
| tree | 3e0ff00030a6ba4eb98ee0691ba8f61a51c05b95 /src | |
| parent | 988c077b068b9e6fb4e58650d7e921993a650983 (diff) | |
| parent | af627f557ad4806e1de1b4800fd1a7e5a42420a8 (diff) | |
| download | rust-4cc7ccaf9812c1ba9606528345ce5a6a4060ca6c.tar.gz rust-4cc7ccaf9812c1ba9606528345ce5a6a4060ca6c.zip | |
Merge ref '828e45ad11ce' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref: 828e45ad11ce4ab56dd64e93f1fb5dd8f0c0ae93 Filtered ref: 10ab51e1b1b8eadb430163bd78ef39c0721cfbf8 This merge was created using https://github.com/rust-lang/josh-sync.
Diffstat (limited to 'src')
30 files changed, 1254 insertions, 561 deletions
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index be29e77e572..1535d087033 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -95,9 +95,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.23" +version = "1.2.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +checksum = "4ad45f4f74e4e20eaa392913b7b33a7091c87e59628f4dd27888205ad888843c" dependencies = [ "shlex", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index cd5a60187e5..c7175584465 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -32,7 +32,7 @@ test = false # Most of the time updating these dependencies requires modifications to the # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565); # otherwise, some targets will fail. That's why these dependencies are explicitly pinned. -cc = "=1.2.23" +cc = "=1.2.28" cmake = "=0.1.54" build_helper = { path = "../build_helper" } diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index bebae893ee7..a604e7c0585 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -8,8 +8,8 @@ use crate::core::build_steps::compile::{ }; use crate::core::build_steps::tool; use crate::core::build_steps::tool::{ - COMPILETEST_ALLOW_FEATURES, SourceType, ToolTargetBuildMode, get_tool_target_compiler, - prepare_tool_cargo, + COMPILETEST_ALLOW_FEATURES, SourceType, TEST_FLOAT_PARSE_ALLOW_FEATURES, ToolTargetBuildMode, + get_tool_target_compiler, prepare_tool_cargo, }; use crate::core::builder::{ self, Alias, Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description, @@ -791,7 +791,7 @@ tool_check_step!(MiroptTestTools { tool_check_step!(TestFloatParse { path: "src/tools/test-float-parse", mode: |_builder| Mode::ToolStd, - allow_features: tool::TestFloatParse::ALLOW_FEATURES + allow_features: TEST_FLOAT_PARSE_ALLOW_FEATURES }); tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump", diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 9ef1fee1fec..0789eefa894 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -791,7 +791,11 @@ fn doc_std( } /// Prepare a compiler that will be able to document something for `target` at `stage`. -fn prepare_doc_compiler(builder: &Builder<'_>, target: TargetSelection, stage: u32) -> Compiler { +pub fn prepare_doc_compiler( + builder: &Builder<'_>, + target: TargetSelection, + stage: u32, +) -> Compiler { assert!(stage > 0, "Cannot document anything in stage 0"); let build_compiler = builder.compiler(stage - 1, builder.host_target); builder.std(build_compiler, target); @@ -1289,6 +1293,8 @@ impl Step for RustcBook { // functional sysroot. builder.std(self.build_compiler, self.target); let mut cmd = builder.tool_cmd(Tool::LintDocs); + cmd.arg("--build-rustc-stage"); + cmd.arg(self.build_compiler.stage.to_string()); cmd.arg("--src"); cmd.arg(builder.src.join("compiler")); cmd.arg("--out"); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 26b4aaa8b5b..ee2cbe9385e 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -12,14 +12,14 @@ use std::{env, fs, iter}; use build_helper::exit; use crate::core::build_steps::compile::{Std, run_cargo}; -use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler}; use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; use crate::core::build_steps::llvm::get_llvm_version; use crate::core::build_steps::run::get_completion_paths; use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; use crate::core::build_steps::tool::{ - self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType, Tool, ToolTargetBuildMode, - get_tool_target_compiler, + self, COMPILETEST_ALLOW_FEATURES, RustcPrivateCompilers, SourceType, + TEST_FLOAT_PARSE_ALLOW_FEATURES, Tool, ToolTargetBuildMode, get_tool_target_compiler, }; use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, dist, llvm}; @@ -98,6 +98,13 @@ impl Step for CrateBootstrap { let crate_name = path.rsplit_once('/').unwrap().1; run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test("crate-bootstrap", self.host) + .with_metadata(self.path.as_path().to_string_lossy().to_string()), + ) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -159,7 +166,7 @@ You can skip linkcheck with --skip src/tools/linkchecker" let linkchecker = builder.tool_cmd(Tool::Linkchecker); // Run the linkchecker. - let _guard = builder.msg(Kind::Test, "Linkcheck", None, compiler, bootstrap_host); + let _guard = builder.msg_test("Linkcheck", bootstrap_host, 1); let _time = helpers::timeit(builder); linkchecker.delay_failure().arg(builder.out.join(host).join("doc")).run(builder); } @@ -173,6 +180,10 @@ You can skip linkcheck with --skip src/tools/linkchecker" fn make_run(run: RunConfig<'_>) { run.builder.ensure(Linkcheck { host: run.target }); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::test("link-check", self.host)) + } } fn check_if_tidy_is_installed(builder: &Builder<'_>) -> bool { @@ -221,6 +232,10 @@ impl Step for HtmlCheck { .arg(builder.doc_out(self.target)) .run(builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::test("html-check", self.target)) + } } /// Builds cargo and then runs the `src/tools/cargotest` tool, which checks out @@ -399,6 +414,10 @@ impl Step for Cargo { let _time = helpers::timeit(builder); add_flags_and_try_run_tests(builder, &mut cargo); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::test("cargo", self.host).built_by(self.build_compiler)) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -457,6 +476,13 @@ impl Step for RustAnalyzer { cargo.add_rustc_lib_path(builder); run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test("rust-analyzer", self.compilers.target()) + .built_by(self.compilers.build_compiler()), + ) + } } /// Runs `cargo test` for rustfmt. @@ -508,6 +534,13 @@ impl Step for Rustfmt { run_cargo_test(cargo, &[], &[], "rustfmt", target, builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test("rustfmt", self.compilers.target()) + .built_by(self.compilers.build_compiler()), + ) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -638,8 +671,7 @@ impl Step for Miri { cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg()); { - let _guard = - builder.msg(Kind::Test, "miri", Mode::ToolRustc, miri.build_compiler, target); + let _guard = builder.msg_test("miri", target, target_compiler.stage); let _time = helpers::timeit(builder); cargo.run(builder); } @@ -655,13 +687,8 @@ impl Step for Miri { cargo.args(["tests/pass", "tests/panic"]); { - let _guard = builder.msg( - Kind::Test, - "miri (mir-opt-level 4)", - Mode::ToolRustc, - miri.build_compiler, - target, - ); + let _guard = + builder.msg_test("miri (mir-opt-level 4)", target, target_compiler.stage); let _time = helpers::timeit(builder); cargo.run(builder); } @@ -731,8 +758,7 @@ impl Step for CargoMiri { // Finally, run everything. let mut cargo = BootstrapCommand::from(cargo); { - let _guard = - builder.msg(Kind::Test, "cargo-miri", Mode::ToolRustc, (host, stage), target); + let _guard = builder.msg_test("cargo-miri", target, stage); let _time = helpers::timeit(builder); cargo.run(builder); } @@ -875,7 +901,7 @@ impl Step for Clippy { cargo.add_rustc_lib_path(builder); let cargo = prepare_cargo_test(cargo, &[], &[], target, builder); - let _guard = builder.msg(Kind::Test, "clippy", Mode::ToolRustc, build_compiler, target); + let _guard = builder.msg_test("clippy", target, target_compiler.stage); // Clippy reports errors if it blessed the outputs if cargo.allow_failure().run(builder) { @@ -887,6 +913,13 @@ impl Step for Clippy { crate::exit!(1); } } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test("clippy", self.compilers.target()) + .built_by(self.compilers.build_compiler()), + ) + } } fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { @@ -895,9 +928,11 @@ fn bin_path_for_cargo(builder: &Builder<'_>, compiler: Compiler) -> OsString { env::join_paths(iter::once(path).chain(env::split_paths(&old_path))).expect("") } +/// Run the rustdoc-themes tool to test a given compiler. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustdocTheme { - pub compiler: Compiler, + /// The compiler (more accurately, its rustdoc) that we test. + test_compiler: Compiler, } impl Step for RustdocTheme { @@ -910,9 +945,9 @@ impl Step for RustdocTheme { } fn make_run(run: RunConfig<'_>) { - let compiler = run.builder.compiler(run.builder.top_stage, run.target); + let test_compiler = run.builder.compiler(run.builder.top_stage, run.target); - run.builder.ensure(RustdocTheme { compiler }); + run.builder.ensure(RustdocTheme { test_compiler }); } fn run(self, builder: &Builder<'_>) { @@ -920,21 +955,34 @@ impl Step for RustdocTheme { let mut cmd = builder.tool_cmd(Tool::RustdocTheme); cmd.arg(rustdoc.to_str().unwrap()) .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap()) - .env("RUSTC_STAGE", self.compiler.stage.to_string()) - .env("RUSTC_SYSROOT", builder.sysroot(self.compiler)) - .env("RUSTDOC_LIBDIR", builder.sysroot_target_libdir(self.compiler, self.compiler.host)) + .env("RUSTC_STAGE", self.test_compiler.stage.to_string()) + .env("RUSTC_SYSROOT", builder.sysroot(self.test_compiler)) + .env( + "RUSTDOC_LIBDIR", + builder.sysroot_target_libdir(self.test_compiler, self.test_compiler.host), + ) .env("CFG_RELEASE_CHANNEL", &builder.config.channel) - .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.compiler)) + .env("RUSTDOC_REAL", builder.rustdoc_for_compiler(self.test_compiler)) .env("RUSTC_BOOTSTRAP", "1"); - cmd.args(linker_args(builder, self.compiler.host, LldThreads::No)); + cmd.args(linker_args(builder, self.test_compiler.host, LldThreads::No)); cmd.delay_failure().run(builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test("rustdoc-theme", self.test_compiler.host) + .stage(self.test_compiler.stage), + ) + } } +/// Test rustdoc JS for the standard library. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustdocJSStd { - pub target: TargetSelection, + /// Compiler that will build the standary library. + build_compiler: Compiler, + target: TargetSelection, } impl Step for RustdocJSStd { @@ -948,7 +996,10 @@ impl Step for RustdocJSStd { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustdocJSStd { target: run.target }); + run.builder.ensure(RustdocJSStd { + build_compiler: run.builder.compiler(run.builder.top_stage, run.builder.host_target), + target: run.target, + }); } fn run(self, builder: &Builder<'_>) { @@ -976,19 +1027,17 @@ impl Step for RustdocJSStd { } } builder.ensure(crate::core::build_steps::doc::Std::from_build_compiler( - builder.compiler(builder.top_stage, builder.host_target), + self.build_compiler, self.target, DocumentationFormat::Html, )); - let _guard = builder.msg( - Kind::Test, - "rustdoc-js-std", - None, - (builder.config.host_target, builder.top_stage), - self.target, - ); + let _guard = builder.msg_test("rustdoc-js-std", self.target, self.build_compiler.stage); command.run(builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::test("rustdoc-js-std", self.target).stage(self.build_compiler.stage)) + } } #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -1014,7 +1063,7 @@ impl Step for RustdocJSNotStd { fn run(self, builder: &Builder<'_>) { builder.ensure(Compiletest { - compiler: self.compiler, + test_compiler: self.compiler, target: self.target, mode: "rustdoc-js", suite: "rustdoc-js", @@ -1046,10 +1095,12 @@ fn get_browser_ui_test_version(builder: &Builder<'_>, npm: &Path) -> Option<Stri .or_else(|| get_browser_ui_test_version_inner(builder, npm, true)) } +/// Run GUI tests on a given rustdoc. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustdocGUI { - pub target: TargetSelection, - pub compiler: Compiler, + /// The compiler whose rustdoc we are testing. + test_compiler: Compiler, + target: TargetSelection, } impl Step for RustdocGUI { @@ -1073,12 +1124,12 @@ impl Step for RustdocGUI { } fn make_run(run: RunConfig<'_>) { - let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); - run.builder.ensure(RustdocGUI { target: run.target, compiler }); + let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); + run.builder.ensure(RustdocGUI { test_compiler, target: run.target }); } fn run(self, builder: &Builder<'_>) { - builder.std(self.compiler, self.target); + builder.std(self.test_compiler, self.target); let mut cmd = builder.tool_cmd(Tool::RustdocGUITest); @@ -1086,7 +1137,7 @@ impl Step for RustdocGUI { build_stamp::clear_if_dirty( builder, &out_dir, - &builder.rustdoc_for_compiler(self.compiler), + &builder.rustdoc_for_compiler(self.test_compiler), ); if let Some(src) = builder.config.src.to_str() { @@ -1103,10 +1154,10 @@ impl Step for RustdocGUI { cmd.arg("--jobs").arg(builder.jobs().to_string()); - cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.compiler)) - .env("RUSTC", builder.rustc(self.compiler)); + cmd.env("RUSTDOC", builder.rustdoc_for_compiler(self.test_compiler)) + .env("RUSTC", builder.rustc(self.test_compiler)); - add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No); + add_rustdoc_cargo_linker_args(&mut cmd, builder, self.test_compiler.host, LldThreads::No); for path in &builder.paths { if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) { @@ -1133,9 +1184,13 @@ impl Step for RustdocGUI { } let _time = helpers::timeit(builder); - let _guard = builder.msg(Kind::Test, "rustdoc-gui", None, self.compiler, self.target); + let _guard = builder.msg_test("rustdoc-gui", self.target, self.test_compiler.stage); try_run_tests(builder, &mut cmd, true); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::test("rustdoc-gui", self.target).stage(self.test_compiler.stage)) + } } /// Runs `src/tools/tidy` and `cargo fmt --check` to detect various style @@ -1253,76 +1308,6 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to } } -fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf { - builder.out.join(host).join("test") -} - -/// Declares a test step that invokes compiletest on a particular test suite. -macro_rules! test { - ( - $( #[$attr:meta] )* // allow docstrings and attributes - $name:ident { - path: $path:expr, - mode: $mode:expr, - suite: $suite:expr, - default: $default:expr - $( , IS_HOST: $IS_HOST:expr )? // default: false - $( , compare_mode: $compare_mode:expr )? // default: None - $( , )? // optional trailing comma - } - ) => { - $( #[$attr] )* - #[derive(Debug, Clone, PartialEq, Eq, Hash)] - pub struct $name { - pub compiler: Compiler, - pub target: TargetSelection, - } - - impl Step for $name { - type Output = (); - const DEFAULT: bool = $default; - const IS_HOST: bool = (const { - #[allow(unused_assignments, unused_mut)] - let mut value = false; - $( value = $IS_HOST; )? - value - }); - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.suite_path($path) - } - - fn make_run(run: RunConfig<'_>) { - let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); - - run.builder.ensure($name { compiler, target: run.target }); - } - - fn run(self, builder: &Builder<'_>) { - builder.ensure(Compiletest { - compiler: self.compiler, - target: self.target, - mode: $mode, - suite: $suite, - path: $path, - compare_mode: (const { - #[allow(unused_assignments, unused_mut)] - let mut value = None; - $( value = $compare_mode; )? - value - }), - }) - } - - fn metadata(&self) -> Option<StepMetadata> { - Some( - StepMetadata::test(stringify!($name), self.target) - ) - } - } - }; -} - /// Runs `cargo test` on the `src/tools/run-make-support` crate. /// That crate is used by run-make tests. #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -1399,6 +1384,70 @@ impl Step for CrateBuildHelper { } } +fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf { + builder.out.join(host).join("test") +} + +/// Declares a test step that invokes compiletest on a particular test suite. +macro_rules! test { + ( + $( #[$attr:meta] )* // allow docstrings and attributes + $name:ident { + path: $path:expr, + mode: $mode:expr, + suite: $suite:expr, + default: $default:expr + $( , IS_HOST: $IS_HOST:expr )? // default: false + $( , compare_mode: $compare_mode:expr )? // default: None + $( , )? // optional trailing comma + } + ) => { + $( #[$attr] )* + #[derive(Debug, Clone, PartialEq, Eq, Hash)] + pub struct $name { + test_compiler: Compiler, + target: TargetSelection, + } + + impl Step for $name { + type Output = (); + const DEFAULT: bool = $default; + const IS_HOST: bool = (const { + #[allow(unused_assignments, unused_mut)] + let mut value = false; + $( value = $IS_HOST; )? + value + }); + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.suite_path($path) + } + + fn make_run(run: RunConfig<'_>) { + let test_compiler = run.builder.compiler(run.builder.top_stage, run.build_triple()); + + run.builder.ensure($name { test_compiler, target: run.target }); + } + + fn run(self, builder: &Builder<'_>) { + builder.ensure(Compiletest { + test_compiler: self.test_compiler, + target: self.target, + mode: $mode, + suite: $suite, + path: $path, + compare_mode: (const { + #[allow(unused_assignments, unused_mut)] + let mut value = None; + $( value = $compare_mode; )? + value + }), + }) + } + } + }; +} + test!(Ui { path: "tests/ui", mode: "ui", suite: "ui", default: true }); test!(Crashes { path: "tests/crashes", mode: "crashes", suite: "crashes", default: true }); @@ -1563,7 +1612,7 @@ impl Step for Coverage { // Like other compiletest suite test steps, delegate to an internal // compiletest task to actually run the tests. builder.ensure(Compiletest { - compiler, + test_compiler: compiler, target, mode, suite: Self::SUITE, @@ -1604,7 +1653,7 @@ impl Step for MirOpt { fn run(self, builder: &Builder<'_>) { let run = |target| { builder.ensure(Compiletest { - compiler: self.compiler, + test_compiler: self.compiler, target, mode: "mir-opt", suite: "mir-opt", @@ -1639,9 +1688,15 @@ impl Step for MirOpt { } } +/// Executes the `compiletest` tool to run a suite of tests. +/// +/// Compiles all tests with `test_compiler` for `target` with the specified +/// compiletest `mode` and `suite` arguments. For example `mode` can be +/// "mir-opt" and `suite` can be something like "debuginfo". #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct Compiletest { - compiler: Compiler, + /// The compiler that we're testing. + test_compiler: Compiler, target: TargetSelection, mode: &'static str, suite: &'static str, @@ -1656,11 +1711,6 @@ impl Step for Compiletest { run.never() } - /// Executes the `compiletest` tool to run a suite of tests. - /// - /// Compiles all tests with `compiler` for `target` with the specified - /// compiletest `mode` and `suite` arguments. For example `mode` can be - /// "run-pass" or `suite` can be something like `debuginfo`. fn run(self, builder: &Builder<'_>) { if builder.doc_tests == DocTests::Only { return; @@ -1675,7 +1725,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the crate::exit!(1); } - let mut compiler = self.compiler; + let mut test_compiler = self.test_compiler; let target = self.target; let mode = self.mode; let suite = self.suite; @@ -1695,30 +1745,30 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // NOTE: Only stage 1 is special cased because we need the rustc_private artifacts to match the // running compiler in stage 2 when plugins run. let query_compiler; - let (stage, stage_id) = if suite == "ui-fulldeps" && compiler.stage == 1 { + let (stage, stage_id) = if suite == "ui-fulldeps" && test_compiler.stage == 1 { // Even when using the stage 0 compiler, we also need to provide the stage 1 compiler // so that compiletest can query it for target information. - query_compiler = Some(compiler); + query_compiler = Some(test_compiler); // At stage 0 (stage - 1) we are using the stage0 compiler. Using `self.target` can lead // finding an incorrect compiler path on cross-targets, as the stage 0 is always equal to // `build.build` in the configuration. let build = builder.build.host_target; - compiler = builder.compiler(compiler.stage - 1, build); - let test_stage = compiler.stage + 1; + test_compiler = builder.compiler(test_compiler.stage - 1, build); + let test_stage = test_compiler.stage + 1; (test_stage, format!("stage{test_stage}-{build}")) } else { query_compiler = None; - let stage = compiler.stage; + let stage = test_compiler.stage; (stage, format!("stage{stage}-{target}")) }; if suite.ends_with("fulldeps") { - builder.ensure(compile::Rustc::new(compiler, target)); + builder.ensure(compile::Rustc::new(test_compiler, target)); } if suite == "debuginfo" { builder.ensure(dist::DebuggerScripts { - sysroot: builder.sysroot(compiler).to_path_buf(), + sysroot: builder.sysroot(test_compiler).to_path_buf(), target, }); } @@ -1728,20 +1778,22 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // ensure that `libproc_macro` is available on the host. if suite == "mir-opt" { - builder.ensure(compile::Std::new(compiler, compiler.host).is_for_mir_opt_tests(true)); + builder.ensure( + compile::Std::new(test_compiler, test_compiler.host).is_for_mir_opt_tests(true), + ); } else { - builder.std(compiler, compiler.host); + builder.std(test_compiler, test_compiler.host); } let mut cmd = builder.tool_cmd(Tool::Compiletest); if suite == "mir-opt" { - builder.ensure(compile::Std::new(compiler, target).is_for_mir_opt_tests(true)); + builder.ensure(compile::Std::new(test_compiler, target).is_for_mir_opt_tests(true)); } else { - builder.std(compiler, target); + builder.std(test_compiler, target); } - builder.ensure(RemoteCopyLibs { compiler, target }); + builder.ensure(RemoteCopyLibs { build_compiler: test_compiler, target }); // compiletest currently has... a lot of arguments, so let's just pass all // of them! @@ -1749,9 +1801,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--stage").arg(stage.to_string()); cmd.arg("--stage-id").arg(stage_id); - cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(compiler)); - cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(compiler, target)); - cmd.arg("--rustc-path").arg(builder.rustc(compiler)); + cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler)); + cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target)); + cmd.arg("--rustc-path").arg(builder.rustc(test_compiler)); if let Some(query_compiler) = query_compiler { cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler)); } @@ -1764,18 +1816,23 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let is_rustdoc = suite == "rustdoc-ui" || suite == "rustdoc-js"; if mode == "run-make" { - let cargo_path = if builder.top_stage == 0 { + let cargo_path = if test_compiler.stage == 0 { // If we're using `--stage 0`, we should provide the bootstrap cargo. builder.initial_cargo.clone() } else { - builder.ensure(tool::Cargo::from_build_compiler(compiler, compiler.host)).tool_path + builder + .ensure(tool::Cargo::from_build_compiler( + builder.compiler(test_compiler.stage - 1, test_compiler.host), + test_compiler.host, + )) + .tool_path }; cmd.arg("--cargo-path").arg(cargo_path); // We need to pass the compiler that was used to compile run-make-support, // because we have to use the same compiler to compile rmake.rs recipes. - let stage0_rustc_path = builder.compiler(0, compiler.host); + let stage0_rustc_path = builder.compiler(0, test_compiler.host); cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path)); } @@ -1787,12 +1844,12 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the || mode == "rustdoc-json" || suite == "coverage-run-rustdoc" { - cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(compiler)); + cmd.arg("--rustdoc-path").arg(builder.rustdoc_for_compiler(test_compiler)); } if mode == "rustdoc-json" { // Use the stage0 compiler for jsondocck - let json_compiler = compiler.with_stage(0); + let json_compiler = builder.compiler(0, builder.host_target); cmd.arg("--jsondocck-path") .arg(builder.ensure(tool::JsonDocCk { compiler: json_compiler, target }).tool_path); cmd.arg("--jsondoclint-path").arg( @@ -1812,14 +1869,16 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the // directory immediately under the root build directory, and the test-suite-specific build // directory. cmd.arg("--build-root").arg(&builder.out); - cmd.arg("--build-test-suite-root").arg(testdir(builder, compiler.host).join(suite)); + cmd.arg("--build-test-suite-root").arg(testdir(builder, test_compiler.host).join(suite)); // When top stage is 0, that means that we're testing an externally provided compiler. // In that case we need to use its specific sysroot for tests to pass. + // Note: DO NOT check if test_compiler.stage is 0, because the test compiler can be stage 0 + // even if the top stage is 1 (when we run the ui-fulldeps suite). let sysroot = if builder.top_stage == 0 { builder.initial_sysroot.clone() } else { - builder.sysroot(compiler) + builder.sysroot(test_compiler) }; cmd.arg("--sysroot-base").arg(sysroot); @@ -1827,11 +1886,15 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--suite").arg(suite); cmd.arg("--mode").arg(mode); cmd.arg("--target").arg(target.rustc_target_arg()); - cmd.arg("--host").arg(&*compiler.host.triple); + cmd.arg("--host").arg(&*test_compiler.host.triple); cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target)); if let Some(codegen_backend) = builder.config.cmd.test_codegen_backend() { - if !builder.config.enabled_codegen_backends(compiler.host).contains(codegen_backend) { + if !builder + .config + .enabled_codegen_backends(test_compiler.host) + .contains(codegen_backend) + { eprintln!( "\ ERROR: No configured backend named `{name}` @@ -1850,7 +1913,7 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?} // Tells compiletest which codegen backend to use. // It is used to e.g. ignore tests that don't support that codegen backend. cmd.arg("--default-codegen-backend") - .arg(builder.config.default_codegen_backend(compiler.host).name()); + .arg(builder.config.default_codegen_backend(test_compiler.host).name()); } if builder.build.config.llvm_enzyme { @@ -1930,7 +1993,7 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?} if let Some(linker) = builder.linker(target) { cmd.arg("--target-linker").arg(linker); } - if let Some(linker) = builder.linker(compiler.host) { + if let Some(linker) = builder.linker(test_compiler.host) { cmd.arg("--host-linker").arg(linker); } } @@ -1941,16 +2004,18 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?} } let mut hostflags = flags.clone(); - hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No)); + hostflags.extend(linker_flags(builder, test_compiler.host, LldThreads::No)); let mut targetflags = flags; // Provide `rust_test_helpers` for both host and target. if suite == "ui" || suite == "incremental" { - builder.ensure(TestHelpers { target: compiler.host }); + builder.ensure(TestHelpers { target: test_compiler.host }); builder.ensure(TestHelpers { target }); - hostflags - .push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display())); + hostflags.push(format!( + "-Lnative={}", + builder.test_helpers_out(test_compiler.host).display() + )); targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display())); } @@ -2035,7 +2100,7 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?} let mut llvm_components_passed = false; let mut copts_passed = false; - if builder.config.llvm_enabled(compiler.host) { + if builder.config.llvm_enabled(test_compiler.host) { let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target: builder.config.host_target }); if !builder.config.dry_run() { @@ -2235,19 +2300,16 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?} mode: mode.into(), compare_mode: None, target: self.target.triple.to_string(), - host: self.compiler.host.triple.to_string(), - stage: self.compiler.stage, + host: self.test_compiler.host.triple.to_string(), + stage: self.test_compiler.stage, }, builder, ); - let _group = builder.msg( - Kind::Test, - format!("compiletest suite={suite} mode={mode}"), - // FIXME: compiletest sometimes behaves as ToolStd, we could expose that difference here - Mode::ToolBootstrap, - compiler, + let _group = builder.msg_test( + format!("with compiletest suite={suite} mode={mode}"), target, + test_compiler.stage, ); try_run_tests(builder, &mut cmd, false); @@ -2261,25 +2323,33 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?} mode: mode.into(), compare_mode: Some(compare_mode.into()), target: self.target.triple.to_string(), - host: self.compiler.host.triple.to_string(), - stage: self.compiler.stage, + host: self.test_compiler.host.triple.to_string(), + stage: self.test_compiler.stage, }, builder, ); builder.info(&format!( "Check compiletest suite={} mode={} compare_mode={} ({} -> {})", - suite, mode, compare_mode, &compiler.host, target + suite, mode, compare_mode, &test_compiler.host, target )); let _time = helpers::timeit(builder); try_run_tests(builder, &mut cmd, false); } } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test(&format!("compiletest-{}", self.suite), self.target) + .stage(self.test_compiler.stage), + ) + } } +/// Runs the documentation tests for a book in `src/doc` using the `rustdoc` of `test_compiler`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] struct BookTest { - compiler: Compiler, + test_compiler: Compiler, path: PathBuf, name: &'static str, is_ext_doc: bool, @@ -2294,9 +2364,6 @@ impl Step for BookTest { run.never() } - /// Runs the documentation tests for a book in `src/doc`. - /// - /// This uses the `rustdoc` that sits next to `compiler`. fn run(self, builder: &Builder<'_>) { // External docs are different from local because: // - Some books need pre-processing by mdbook before being tested. @@ -2319,13 +2386,13 @@ impl BookTest { /// This runs the equivalent of `mdbook test` (via the rustbook wrapper) /// which in turn runs `rustdoc --test` on each file in the book. fn run_ext_doc(self, builder: &Builder<'_>) { - let compiler = self.compiler; + let test_compiler = self.test_compiler; - builder.std(compiler, compiler.host); + builder.std(test_compiler, test_compiler.host); // mdbook just executes a binary named "rustdoc", so we need to update // PATH so that it points to our rustdoc. - let mut rustdoc_path = builder.rustdoc_for_compiler(compiler); + let mut rustdoc_path = builder.rustdoc_for_compiler(test_compiler); rustdoc_path.pop(); let old_path = env::var_os("PATH").unwrap_or_default(); let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path))) @@ -2348,7 +2415,7 @@ impl BookTest { let target = builder.config.host_target; let cargo = tool::prepare_tool_cargo( builder, - compiler, + test_compiler, mode, target, Kind::Build, @@ -2357,7 +2424,7 @@ impl BookTest { &[], ); - let stamp = BuildStamp::new(&builder.cargo_out(compiler, mode, target)) + let stamp = BuildStamp::new(&builder.cargo_out(test_compiler, mode, target)) .with_prefix(PathBuf::from(dep).file_name().and_then(|v| v.to_str()).unwrap()); let output_paths = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false); @@ -2386,12 +2453,10 @@ impl BookTest { } builder.add_rust_test_threads(&mut rustbook_cmd); - let _guard = builder.msg( - Kind::Test, + let _guard = builder.msg_test( format_args!("mdbook {}", self.path.display()), - None, - compiler, - compiler.host, + test_compiler.host, + test_compiler.stage, ); let _time = helpers::timeit(builder); let toolstate = if rustbook_cmd.delay_failure().run(builder) { @@ -2404,12 +2469,16 @@ impl BookTest { /// This runs `rustdoc --test` on all `.md` files in the path. fn run_local_doc(self, builder: &Builder<'_>) { - let compiler = self.compiler; - let host = self.compiler.host; + let test_compiler = self.test_compiler; + let host = self.test_compiler.host; - builder.std(compiler, host); + builder.std(test_compiler, host); - let _guard = builder.msg(Kind::Test, format!("book {}", self.name), None, compiler, host); + let _guard = builder.msg_test( + format!("book {}", self.name), + test_compiler.host, + test_compiler.stage, + ); // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` @@ -2432,7 +2501,7 @@ impl BookTest { files.sort(); for file in files { - markdown_test(builder, compiler, &file); + markdown_test(builder, test_compiler, &file); } } } @@ -2448,7 +2517,7 @@ macro_rules! test_book { $( #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name { - compiler: Compiler, + test_compiler: Compiler, } impl Step for $name { @@ -2462,7 +2531,7 @@ macro_rules! test_book { fn make_run(run: RunConfig<'_>) { run.builder.ensure($name { - compiler: run.builder.compiler(run.builder.top_stage, run.target), + test_compiler: run.builder.compiler(run.builder.top_stage, run.target), }); } @@ -2482,7 +2551,7 @@ macro_rules! test_book { )? builder.ensure(BookTest { - compiler: self.compiler, + test_compiler: self.test_compiler, path: PathBuf::from($path), name: $book_name, is_ext_doc: !$default, @@ -2551,13 +2620,7 @@ impl Step for ErrorIndex { let mut tool = tool::ErrorIndex::command(builder, self.compilers); tool.arg("markdown").arg(&output); - let guard = builder.msg( - Kind::Test, - "error-index", - None, - self.compilers.build_compiler(), - target_compiler.host, - ); + let guard = builder.msg_test("error-index", target_compiler.host, target_compiler.stage); let _time = helpers::timeit(builder); tool.run_capture(builder); drop(guard); @@ -2602,7 +2665,8 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) -> /// which have their own separate test steps.) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateLibrustc { - compiler: Compiler, + /// The compiler that will run unit tests and doctests on the in-tree rustc source. + build_compiler: Compiler, target: TargetSelection, crates: Vec<String>, } @@ -2619,18 +2683,18 @@ impl Step for CrateLibrustc { fn make_run(run: RunConfig<'_>) { let builder = run.builder; let host = run.build_triple(); - let compiler = builder.compiler_for(builder.top_stage, host, host); + let build_compiler = builder.compiler(builder.top_stage - 1, host); let crates = run.make_run_crates(Alias::Compiler); - builder.ensure(CrateLibrustc { compiler, target: run.target, crates }); + builder.ensure(CrateLibrustc { build_compiler, target: run.target, crates }); } fn run(self, builder: &Builder<'_>) { - builder.std(self.compiler, self.target); + builder.std(self.build_compiler, self.target); // To actually run the tests, delegate to a copy of the `Crate` step. builder.ensure(Crate { - compiler: self.compiler, + build_compiler: self.build_compiler, target: self.target, mode: Mode::Rustc, crates: self.crates, @@ -2638,7 +2702,7 @@ impl Step for CrateLibrustc { } fn metadata(&self) -> Option<StepMetadata> { - Some(StepMetadata::test("CrateLibrustc", self.target)) + Some(StepMetadata::test("CrateLibrustc", self.target).built_by(self.build_compiler)) } } @@ -2657,7 +2721,7 @@ fn run_cargo_test<'a>( let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder); let _time = helpers::timeit(builder); let _group = - description.into().and_then(|what| builder.msg(Kind::Test, what, None, compiler, target)); + description.into().and_then(|what| builder.msg_test(what, target, compiler.stage + 1)); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( @@ -2755,10 +2819,11 @@ fn prepare_cargo_test( /// library crates and compiler crates. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Crate { - pub compiler: Compiler, - pub target: TargetSelection, - pub mode: Mode, - pub crates: Vec<String>, + /// The compiler that will *build* libstd or rustc in test mode. + build_compiler: Compiler, + target: TargetSelection, + mode: Mode, + crates: Vec<String>, } impl Step for Crate { @@ -2772,14 +2837,14 @@ impl Step for Crate { fn make_run(run: RunConfig<'_>) { let builder = run.builder; let host = run.build_triple(); - let compiler = builder.compiler_for(builder.top_stage, host, host); + let build_compiler = builder.compiler(builder.top_stage, host); let crates = run .paths .iter() .map(|p| builder.crate_paths[&p.assert_single_path().path].clone()) .collect(); - builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates }); + builder.ensure(Crate { build_compiler, target: run.target, mode: Mode::Std, crates }); } /// Runs all unit tests plus documentation tests for a given crate defined @@ -2791,19 +2856,13 @@ impl Step for Crate { /// Currently this runs all tests for a DAG by passing a bunch of `-p foo` /// arguments, and those arguments are discovered from `cargo metadata`. fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; + let build_compiler = self.build_compiler; let target = self.target; let mode = self.mode; // Prepare sysroot // See [field@compile::Std::force_recompile]. - builder.ensure(Std::new(compiler, compiler.host).force_recompile(true)); - - // If we're not doing a full bootstrap but we're testing a stage2 - // version of libstd, then what we're actually testing is the libstd - // produced in stage1. Reflect that here by updating the compiler that - // we're working with automatically. - let compiler = builder.compiler_for(compiler.stage, compiler.host, target); + builder.ensure(Std::new(build_compiler, build_compiler.host).force_recompile(true)); let mut cargo = if builder.kind == Kind::Miri { if builder.top_stage == 0 { @@ -2815,7 +2874,7 @@ impl Step for Crate { // (Implicitly prepares target sysroot) let mut cargo = builder::Cargo::new( builder, - compiler, + build_compiler, mode, SourceType::InTree, target, @@ -2841,12 +2900,19 @@ impl Step for Crate { } else { // Also prepare a sysroot for the target. if !builder.config.is_host_target(target) { - builder.ensure(compile::Std::new(compiler, target).force_recompile(true)); - builder.ensure(RemoteCopyLibs { compiler, target }); + builder.ensure(compile::Std::new(build_compiler, target).force_recompile(true)); + builder.ensure(RemoteCopyLibs { build_compiler, target }); } // Build `cargo test` command - builder::Cargo::new(builder, compiler, mode, SourceType::InTree, target, builder.kind) + builder::Cargo::new( + builder, + build_compiler, + mode, + SourceType::InTree, + target, + builder.kind, + ) }; match mode { @@ -2865,7 +2931,7 @@ impl Step for Crate { } } Mode::Rustc => { - compile::rustc_cargo(builder, &mut cargo, target, &compiler, &self.crates); + compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates); } _ => panic!("can only test libraries"), }; @@ -2886,6 +2952,7 @@ impl Step for Crate { } } +/// Run cargo tests for the rustdoc crate. /// Rustdoc is special in various ways, which is why this step is different from `Crate`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateRustdoc { @@ -2981,7 +3048,8 @@ impl Step for CrateRustdoc { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CrateRustdocJsonTypes { - host: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, } impl Step for CrateRustdocJsonTypes { @@ -2996,23 +3064,22 @@ impl Step for CrateRustdocJsonTypes { fn make_run(run: RunConfig<'_>) { let builder = run.builder; - builder.ensure(CrateRustdocJsonTypes { host: run.target }); + builder.ensure(CrateRustdocJsonTypes { + build_compiler: get_tool_target_compiler( + builder, + ToolTargetBuildMode::Build(run.target), + ), + target: run.target, + }); } fn run(self, builder: &Builder<'_>) { - let target = self.host; - - // Use the previous stage compiler to reuse the artifacts that are - // created when running compiletest for tests/rustdoc. If this used - // `compiler`, then it would cause rustdoc to be built *again*, which - // isn't really necessary. - let compiler = builder.compiler_for(builder.top_stage, target, target); - builder.ensure(compile::Rustc::new(compiler, target)); + let target = self.target; let cargo = tool::prepare_tool_cargo( builder, - compiler, - Mode::ToolRustc, + self.build_compiler, + Mode::ToolTarget, target, builder.kind, "src/rustdoc-json-types", @@ -3021,7 +3088,7 @@ impl Step for CrateRustdocJsonTypes { ); // FIXME: this looks very wrong, libtest doesn't accept `-C` arguments and the quotes are fishy. - let libtest_args = if self.host.contains("musl") { + let libtest_args = if target.contains("musl") { ["'-Ctarget-feature=-crt-static'"].as_slice() } else { &[] @@ -3049,7 +3116,7 @@ impl Step for CrateRustdocJsonTypes { /// the build target (us) and the server is built for the target. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RemoteCopyLibs { - compiler: Compiler, + build_compiler: Compiler, target: TargetSelection, } @@ -3061,18 +3128,17 @@ impl Step for RemoteCopyLibs { } fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; + let build_compiler = self.build_compiler; let target = self.target; if !builder.remote_tested(target) { return; } - builder.std(compiler, target); + builder.std(build_compiler, target); builder.info(&format!("REMOTE copy libs to emulator ({target})")); - let remote_test_server = - builder.ensure(tool::RemoteTestServer { build_compiler: compiler, target }); + let remote_test_server = builder.ensure(tool::RemoteTestServer { build_compiler, target }); // Spawn the emulator and wait for it to come online let tool = builder.tool_exe(Tool::RemoteTestClient); @@ -3087,7 +3153,7 @@ impl Step for RemoteCopyLibs { cmd.run(builder); // Push all our dylibs to the emulator - for f in t!(builder.sysroot_target_libdir(compiler, target).read_dir()) { + for f in t!(builder.sysroot_target_libdir(build_compiler, target).read_dir()) { let f = t!(f); if helpers::is_dylib(&f.path()) { command(&tool).arg("push").arg(f.path()).run(builder); @@ -3192,8 +3258,6 @@ impl Step for Bootstrap { fn run(self, builder: &Builder<'_>) { let host = builder.config.host_target; let build_compiler = builder.compiler(0, host); - let _guard = - builder.msg(Kind::Test, "bootstrap", Mode::ToolBootstrap, build_compiler, host); // Some tests require cargo submodule to be present. builder.build.require_submodule("src/tools/cargo", None); @@ -3248,9 +3312,15 @@ impl Step for Bootstrap { } } +fn get_compiler_to_test(builder: &Builder<'_>, target: TargetSelection) -> Compiler { + builder.compiler(builder.top_stage, target) +} + +/// Tests the Platform Support page in the rustc book. +/// `test_compiler` is used to query the actual targets that are checked. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TierCheck { - pub compiler: Compiler, + test_compiler: Compiler, } impl Step for TierCheck { @@ -3263,48 +3333,46 @@ impl Step for TierCheck { } fn make_run(run: RunConfig<'_>) { - let compiler = run.builder.compiler_for( - run.builder.top_stage, - run.builder.build.host_target, - run.target, - ); - run.builder.ensure(TierCheck { compiler }); + run.builder + .ensure(TierCheck { test_compiler: get_compiler_to_test(run.builder, run.target) }); } - /// Tests the Platform Support page in the rustc book. fn run(self, builder: &Builder<'_>) { - builder.std(self.compiler, self.compiler.host); + let tool_build_compiler = builder.compiler(0, builder.host_target); + let mut cargo = tool::prepare_tool_cargo( builder, - self.compiler, - Mode::ToolStd, - self.compiler.host, + tool_build_compiler, + Mode::ToolBootstrap, + tool_build_compiler.host, Kind::Run, "src/tools/tier-check", SourceType::InTree, &[], ); cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md")); - cargo.arg(builder.rustc(self.compiler)); + cargo.arg(builder.rustc(self.test_compiler)); if builder.is_verbose() { cargo.arg("--verbose"); } - let _guard = builder.msg( - Kind::Test, + let _guard = builder.msg_test( "platform support check", - None, - self.compiler, - self.compiler.host, + self.test_compiler.host, + self.test_compiler.stage, ); BootstrapCommand::from(cargo).delay_failure().run(builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::test("tier-check", self.test_compiler.host)) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct LintDocs { - pub compiler: Compiler, - pub target: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, } impl Step for LintDocs { @@ -3313,12 +3381,23 @@ impl Step for LintDocs { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/lint-docs") + let stage = run.builder.top_stage; + // Lint docs tests might not work with stage 1, so do not run this test by default in + // `x test` below stage 2. + run.path("src/tools/lint-docs").default_condition(stage > 1) } fn make_run(run: RunConfig<'_>) { + if run.builder.top_stage < 2 { + eprintln!("WARNING: lint-docs tests might not work below stage 2"); + } + run.builder.ensure(LintDocs { - compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target), + build_compiler: prepare_doc_compiler( + run.builder, + run.builder.config.host_target, + run.builder.top_stage, + ), target: run.target, }); } @@ -3326,8 +3405,14 @@ impl Step for LintDocs { /// Tests that the lint examples in the rustc book generate the correct /// lints and have the expected format. fn run(self, builder: &Builder<'_>) { - builder - .ensure(crate::core::build_steps::doc::RustcBook::validate(self.compiler, self.target)); + builder.ensure(crate::core::build_steps::doc::RustcBook::validate( + self.build_compiler, + self.target, + )); + } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::test("lint-docs", self.target).built_by(self.build_compiler)) } } @@ -3354,8 +3439,7 @@ impl Step for RustInstaller { &[], ); - let _guard = - builder.msg(Kind::Test, "rust-installer", None, build_compiler, bootstrap_host); + let _guard = builder.msg_test("rust-installer", bootstrap_host, 1); run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder); // We currently don't support running the test.sh script outside linux(?) environments. @@ -3449,7 +3533,7 @@ impl Step for TestHelpers { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenCranelift { - compiler: Compiler, + compilers: RustcPrivateCompilers, target: TargetSelection, } @@ -3465,7 +3549,7 @@ impl Step for CodegenCranelift { fn make_run(run: RunConfig<'_>) { let builder = run.builder; let host = run.build_triple(); - let compiler = run.builder.compiler_for(run.builder.top_stage, host, host); + let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host); if builder.doc_tests == DocTests::Only { return; @@ -3495,71 +3579,54 @@ impl Step for CodegenCranelift { return; } - builder.ensure(CodegenCranelift { compiler, target: run.target }); + builder.ensure(CodegenCranelift { compilers, target: run.target }); } fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; - let target = self.target; + let compilers = self.compilers; + let build_compiler = compilers.build_compiler(); - builder.std(compiler, target); + // We need to run the cranelift tests with the compiler against cranelift links to, not with + // the build compiler. + let target_compiler = compilers.target_compiler(); + let target = self.target; - // If we're not doing a full bootstrap but we're testing a stage2 - // version of libstd, then what we're actually testing is the libstd - // produced in stage1. Reflect that here by updating the compiler that - // we're working with automatically. - let compiler = builder.compiler_for(compiler.stage, compiler.host, target); + builder.std(target_compiler, target); - let build_cargo = || { - let mut cargo = builder::Cargo::new( - builder, - compiler, - Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works - SourceType::InTree, - target, - Kind::Run, - ); + let mut cargo = builder::Cargo::new( + builder, + target_compiler, + Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works + SourceType::InTree, + target, + Kind::Run, + ); - cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift")); - cargo - .arg("--manifest-path") - .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml")); - compile::rustc_cargo_env(builder, &mut cargo, target); + cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift")); + cargo + .arg("--manifest-path") + .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml")); + compile::rustc_cargo_env(builder, &mut cargo, target); - // Avoid incremental cache issues when changing rustc - cargo.env("CARGO_BUILD_INCREMENTAL", "false"); + // Avoid incremental cache issues when changing rustc + cargo.env("CARGO_BUILD_INCREMENTAL", "false"); - cargo - }; - - builder.info(&format!( - "{} cranelift stage{} ({} -> {})", - Kind::Test.description(), - compiler.stage, - &compiler.host, - target - )); - let _time = helpers::timeit(builder); + let _guard = builder.msg_test( + "rustc_codegen_cranelift", + target_compiler.host, + target_compiler.stage, + ); // FIXME handle vendoring for source tarballs before removing the --skip-test below let download_dir = builder.out.join("cg_clif_download"); - // FIXME: Uncomment the `prepare` command below once vendoring is implemented. - /* - let mut prepare_cargo = build_cargo(); - prepare_cargo.arg("--").arg("prepare").arg("--download-dir").arg(&download_dir); - #[expect(deprecated)] - builder.config.try_run(&mut prepare_cargo.into()).unwrap(); - */ - - let mut cargo = build_cargo(); cargo .arg("--") .arg("test") .arg("--download-dir") .arg(&download_dir) .arg("--out-dir") - .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_clif")) + .arg(builder.stage_out(build_compiler, Mode::Codegen).join("cg_clif")) .arg("--no-unstable-features") .arg("--use-backend") .arg("cranelift") @@ -3573,11 +3640,18 @@ impl Step for CodegenCranelift { cargo.into_cmd().run(builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test("rustc_codegen_cranelift", self.target) + .built_by(self.compilers.build_compiler()), + ) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CodegenGCC { - compiler: Compiler, + compilers: RustcPrivateCompilers, target: TargetSelection, } @@ -3593,7 +3667,7 @@ impl Step for CodegenGCC { fn make_run(run: RunConfig<'_>) { let builder = run.builder; let host = run.build_triple(); - let compiler = run.builder.compiler_for(run.builder.top_stage, host, host); + let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, host); if builder.doc_tests == DocTests::Only { return; @@ -3622,68 +3696,45 @@ impl Step for CodegenGCC { return; } - builder.ensure(CodegenGCC { compiler, target: run.target }); + builder.ensure(CodegenGCC { compilers, target: run.target }); } fn run(self, builder: &Builder<'_>) { - let compiler = self.compiler; + let compilers = self.compilers; let target = self.target; let gcc = builder.ensure(Gcc { target }); builder.ensure( - compile::Std::new(compiler, target) + compile::Std::new(compilers.build_compiler(), target) .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]), ); - // If we're not doing a full bootstrap but we're testing a stage2 - // version of libstd, then what we're actually testing is the libstd - // produced in stage1. Reflect that here by updating the compiler that - // we're working with automatically. - let compiler = builder.compiler_for(compiler.stage, compiler.host, target); - - let build_cargo = || { - let mut cargo = builder::Cargo::new( - builder, - compiler, - Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works - SourceType::InTree, - target, - Kind::Run, - ); - - cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc")); - cargo - .arg("--manifest-path") - .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml")); - compile::rustc_cargo_env(builder, &mut cargo, target); - add_cg_gcc_cargo_flags(&mut cargo, &gcc); - - // Avoid incremental cache issues when changing rustc - cargo.env("CARGO_BUILD_INCREMENTAL", "false"); - cargo.rustflag("-Cpanic=abort"); - - cargo - }; + let _guard = builder.msg_test( + "rustc_codegen_gcc", + compilers.target(), + compilers.target_compiler().stage, + ); - builder.info(&format!( - "{} GCC stage{} ({} -> {})", - Kind::Test.description(), - compiler.stage, - &compiler.host, - target - )); - let _time = helpers::timeit(builder); + let mut cargo = builder::Cargo::new( + builder, + compilers.build_compiler(), + Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works + SourceType::InTree, + target, + Kind::Run, + ); - // FIXME: Uncomment the `prepare` command below once vendoring is implemented. - /* - let mut prepare_cargo = build_cargo(); - prepare_cargo.arg("--").arg("prepare"); - #[expect(deprecated)] - builder.config.try_run(&mut prepare_cargo.into()).unwrap(); - */ + cargo.current_dir(&builder.src.join("compiler/rustc_codegen_gcc")); + cargo + .arg("--manifest-path") + .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml")); + compile::rustc_cargo_env(builder, &mut cargo, target); + add_cg_gcc_cargo_flags(&mut cargo, &gcc); - let mut cargo = build_cargo(); + // Avoid incremental cache issues when changing rustc + cargo.env("CARGO_BUILD_INCREMENTAL", "false"); + cargo.rustflag("-Cpanic=abort"); cargo // cg_gcc's build system ignores RUSTFLAGS. pass some flags through CG_RUSTFLAGS instead. @@ -3695,7 +3746,7 @@ impl Step for CodegenGCC { .arg("--gcc-path") .arg(gcc.libgccjit.parent().unwrap()) .arg("--out-dir") - .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc")) + .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc")) .arg("--release") .arg("--mini-tests") .arg("--std-tests"); @@ -3703,6 +3754,13 @@ impl Step for CodegenGCC { cargo.into_cmd().run(builder); } + + fn metadata(&self) -> Option<StepMetadata> { + Some( + StepMetadata::test("rustc_codegen_gcc", self.target) + .built_by(self.compilers.build_compiler()), + ) + } } /// Test step that does two things: @@ -3711,8 +3769,17 @@ impl Step for CodegenGCC { /// float parsing routines. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TestFloatParse { - path: PathBuf, - host: TargetSelection, + /// The build compiler which will build and run unit tests of `test-float-parse`, and which will + /// build the `test-float-parse` tool itself. + /// + /// Note that the staging is a bit funny here, because this step essentially tests std, but it + /// also needs to build the tool. So if we test stage1 std, we build: + /// 1) stage1 rustc + /// 2) Use that to build stage1 libstd + /// 3) Use that to build and run *stage2* test-float-parse + build_compiler: Compiler, + /// Target for which we build std and test that std. + target: TargetSelection, } impl Step for TestFloatParse { @@ -3725,47 +3792,47 @@ impl Step for TestFloatParse { } fn make_run(run: RunConfig<'_>) { - for path in run.paths { - let path = path.assert_single_path().path.clone(); - run.builder.ensure(Self { path, host: run.target }); - } + run.builder.ensure(Self { + build_compiler: get_compiler_to_test(run.builder, run.target), + target: run.target, + }); } fn run(self, builder: &Builder<'_>) { - let bootstrap_host = builder.config.host_target; - let compiler = builder.compiler(builder.top_stage, bootstrap_host); - let path = self.path.to_str().unwrap(); - let crate_name = self.path.iter().next_back().unwrap().to_str().unwrap(); + let build_compiler = self.build_compiler; + let target = self.target; - builder.ensure(tool::TestFloatParse { host: self.host }); + // Build the standard library that will be tested, and a stdlib for host code + builder.std(build_compiler, target); + builder.std(build_compiler, builder.host_target); // Run any unit tests in the crate let mut cargo_test = tool::prepare_tool_cargo( builder, - compiler, + build_compiler, Mode::ToolStd, - bootstrap_host, + target, Kind::Test, - path, + "src/tools/test-float-parse", SourceType::InTree, &[], ); - cargo_test.allow_features(tool::TestFloatParse::ALLOW_FEATURES); + cargo_test.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES); - run_cargo_test(cargo_test, &[], &[], crate_name, bootstrap_host, builder); + run_cargo_test(cargo_test, &[], &[], "test-float-parse", target, builder); // Run the actual parse tests. let mut cargo_run = tool::prepare_tool_cargo( builder, - compiler, + build_compiler, Mode::ToolStd, - bootstrap_host, + target, Kind::Run, - path, + "src/tools/test-float-parse", SourceType::InTree, &[], ); - cargo_run.allow_features(tool::TestFloatParse::ALLOW_FEATURES); + cargo_run.allow_features(TEST_FLOAT_PARSE_ALLOW_FEATURES); if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) { cargo_run.args(["--", "--skip-huge"]); diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index b62c9a906b7..65c4c499086 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1539,42 +1539,7 @@ tool_rustc_extended!(Rustfmt { add_bins_to_sysroot: ["rustfmt"] }); -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TestFloatParse { - pub host: TargetSelection, -} - -impl TestFloatParse { - pub const ALLOW_FEATURES: &'static str = "f16,cfg_target_has_reliable_f16_f128"; -} - -impl Step for TestFloatParse { - type Output = ToolBuildResult; - const IS_HOST: bool = true; - const DEFAULT: bool = false; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/test-float-parse") - } - - fn run(self, builder: &Builder<'_>) -> ToolBuildResult { - let bootstrap_host = builder.config.host_target; - let compiler = builder.compiler(builder.top_stage, bootstrap_host); - - builder.ensure(ToolBuild { - build_compiler: compiler, - target: bootstrap_host, - tool: "test-float-parse", - mode: Mode::ToolStd, - path: "src/tools/test-float-parse", - source_type: SourceType::InTree, - extra_features: Vec::new(), - allow_features: Self::ALLOW_FEATURES, - cargo_args: Vec::new(), - artifact_kind: ToolArtifactKind::Binary, - }) - } -} +pub const TEST_FLOAT_PARSE_ALLOW_FEATURES: &str = "f16,cfg_target_has_reliable_f16_f128"; impl Builder<'_> { /// Gets a `BootstrapCommand` which is ready to run `tool` in `stage` built for diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index b224a7e7322..627085df812 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -295,7 +295,7 @@ pub fn crate_description(crates: &[impl AsRef<str>]) -> String { return "".into(); } - let mut descr = String::from(" {"); + let mut descr = String::from("{"); descr.push_str(crates[0].as_ref()); for krate in &crates[1..] { descr.push_str(", "); diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index b079117c5a7..ef01f14f5e9 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -2037,13 +2037,316 @@ mod snapshot { .render_steps(), @"[check] rustc 0 <host> -> RunMakeSupport 1 <host>"); } + fn prepare_test_config(ctx: &TestCtx) -> ConfigBuilder { + ctx.config("test") + // Bootstrap only runs by default on CI, so we have to emulate that also locally. + .args(&["--ci", "true"]) + // These rustdoc tests requires nodejs to be present. + // We can't easily opt out of it, so if it is present on the local PC, the test + // would have different result on CI, where nodejs might be missing. + .args(&["--skip", "rustdoc-js-std"]) + .args(&["--skip", "rustdoc-js"]) + .args(&["--skip", "rustdoc-gui"]) + } + + #[test] + fn test_all_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + prepare_test_config(&ctx) + .render_steps(), @r" + [build] rustc 0 <host> -> Tidy 1 <host> + [test] tidy <> + [build] rustdoc 0 <host> + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 0 <host> -> Compiletest 1 <host> + [test] compiletest-ui 1 <host> + [test] compiletest-crashes 1 <host> + [build] rustc 0 <host> -> CoverageDump 1 <host> + [test] compiletest-coverage 1 <host> + [test] compiletest-coverage 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [test] compiletest-mir-opt 1 <host> + [test] compiletest-codegen-llvm 1 <host> + [test] compiletest-codegen-units 1 <host> + [test] compiletest-assembly-llvm 1 <host> + [test] compiletest-incremental 1 <host> + [test] compiletest-debuginfo 1 <host> + [test] compiletest-ui-fulldeps 1 <host> + [build] rustdoc 1 <host> + [test] compiletest-rustdoc 1 <host> + [test] compiletest-coverage-run-rustdoc 1 <host> + [test] compiletest-pretty 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 0 <host> -> std 0 <host> + [test] rustc 0 <host> -> CrateLibrustc 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [test] crate-bootstrap <host> src/tools/coverage-dump + [test] crate-bootstrap <host> src/tools/jsondoclint + [test] crate-bootstrap <host> src/tools/replace-version-placeholder + [test] crate-bootstrap <host> tidyselftest + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> + [doc] unstable-book (book) <host> + [doc] book (book) <host> + [doc] book/first-edition (book) <host> + [doc] book/second-edition (book) <host> + [doc] book/2018-edition (book) <host> + [doc] rustc 0 <host> -> standalone 1 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 0 <host> -> error-index 1 <host> + [doc] rustc 0 <host> -> error-index 1 <host> + [doc] nomicon (book) <host> + [doc] rustc 1 <host> -> reference (book) 2 <host> + [doc] rustdoc (book) <host> + [doc] rust-by-example (book) <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [doc] rustc (book) <host> + [doc] cargo (book) <host> + [doc] clippy (book) <host> + [doc] embedded-book (book) <host> + [doc] edition-guide (book) <host> + [doc] style-guide (book) <host> + [doc] rustc 0 <host> -> releases 1 <host> + [build] rustc 0 <host> -> Linkchecker 1 <host> + [test] link-check <host> + [test] tier-check <host> + [test] rustc 0 <host> -> rust-analyzer 1 <host> + [build] rustc 0 <host> -> RustdocTheme 1 <host> + [test] rustdoc-theme 1 <host> + [test] compiletest-rustdoc-ui 1 <host> + [build] rustc 0 <host> -> JsonDocCk 1 <host> + [build] rustc 0 <host> -> JsonDocLint 1 <host> + [test] compiletest-rustdoc-json 1 <host> + [doc] rustc 0 <host> -> rustc 1 <host> + [build] rustc 0 <host> -> HtmlChecker 1 <host> + [test] html-check <host> + [build] rustc 0 <host> -> RunMakeSupport 1 <host> + [build] rustc 0 <host> -> cargo 1 <host> + [test] compiletest-run-make 1 <host> + "); + } + + #[test] + fn test_compiletest_suites_stage1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .args(&["ui", "ui-fulldeps", "run-make", "rustdoc", "rustdoc-gui", "incremental"]) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 0 <host> -> Compiletest 1 <host> + [test] compiletest-ui 1 <host> + [test] compiletest-ui-fulldeps 1 <host> + [build] rustc 0 <host> -> RunMakeSupport 1 <host> + [build] rustc 0 <host> -> cargo 1 <host> + [build] rustdoc 1 <host> + [test] compiletest-run-make 1 <host> + [test] compiletest-rustdoc 1 <host> + [build] rustc 0 <host> -> RustdocGUITest 1 <host> + [test] rustdoc-gui 1 <host> + [test] compiletest-incremental 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + "); + } + + #[test] + fn test_compiletest_suites_stage2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .args(&["ui", "ui-fulldeps", "run-make", "rustdoc", "rustdoc-gui", "incremental"]) + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [build] rustc 0 <host> -> Compiletest 1 <host> + [test] compiletest-ui 2 <host> + [build] rustc 2 <host> -> rustc 3 <host> + [test] compiletest-ui-fulldeps 2 <host> + [build] rustc 0 <host> -> RunMakeSupport 1 <host> + [build] rustc 1 <host> -> cargo 2 <host> + [build] rustdoc 2 <host> + [test] compiletest-run-make 2 <host> + [test] compiletest-rustdoc 2 <host> + [build] rustc 0 <host> -> RustdocGUITest 1 <host> + [test] rustdoc-gui 2 <host> + [test] compiletest-incremental 2 <host> + [build] rustdoc 1 <host> + "); + } + + #[test] + fn test_compiletest_suites_stage2_cross() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .hosts(&[TEST_TRIPLE_1]) + .targets(&[TEST_TRIPLE_1]) + .args(&["ui", "ui-fulldeps", "run-make", "rustdoc", "rustdoc-gui", "incremental"]) + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [build] rustc 0 <host> -> Compiletest 1 <host> + [build] rustc 1 <host> -> std 1 <target1> + [build] rustc 2 <host> -> std 2 <target1> + [test] compiletest-ui 2 <target1> + [build] llvm <target1> + [build] rustc 2 <host> -> rustc 3 <target1> + [test] compiletest-ui-fulldeps 2 <target1> + [build] rustc 0 <host> -> RunMakeSupport 1 <host> + [build] rustc 1 <host> -> cargo 2 <host> + [build] rustdoc 2 <host> + [test] compiletest-run-make 2 <target1> + [test] compiletest-rustdoc 2 <target1> + [build] rustc 0 <host> -> RustdocGUITest 1 <host> + [test] rustdoc-gui 2 <target1> + [test] compiletest-incremental 2 <target1> + [build] rustc 1 <host> -> rustc 2 <target1> + [build] rustdoc 1 <host> + [build] rustc 2 <target1> -> std 2 <target1> + [build] rustdoc 2 <target1> + "); + } + + #[test] + fn test_all_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + prepare_test_config(&ctx) + .stage(2) + .render_steps(), @r" + [build] rustc 0 <host> -> Tidy 1 <host> + [test] tidy <> + [build] rustdoc 0 <host> + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [build] rustc 0 <host> -> Compiletest 1 <host> + [test] compiletest-ui 2 <host> + [test] compiletest-crashes 2 <host> + [build] rustc 0 <host> -> CoverageDump 1 <host> + [test] compiletest-coverage 2 <host> + [test] compiletest-coverage 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [test] compiletest-mir-opt 2 <host> + [test] compiletest-codegen-llvm 2 <host> + [test] compiletest-codegen-units 2 <host> + [test] compiletest-assembly-llvm 2 <host> + [test] compiletest-incremental 2 <host> + [test] compiletest-debuginfo 2 <host> + [build] rustc 2 <host> -> rustc 3 <host> + [test] compiletest-ui-fulldeps 2 <host> + [build] rustdoc 2 <host> + [test] compiletest-rustdoc 2 <host> + [test] compiletest-coverage-run-rustdoc 2 <host> + [test] compiletest-pretty 2 <host> + [build] rustc 2 <host> -> std 2 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustdoc 1 <host> + [test] rustc 1 <host> -> CrateLibrustc 2 <host> + [test] crate-bootstrap <host> src/tools/coverage-dump + [test] crate-bootstrap <host> src/tools/jsondoclint + [test] crate-bootstrap <host> src/tools/replace-version-placeholder + [test] crate-bootstrap <host> tidyselftest + [build] rustc 0 <host> -> UnstableBookGen 1 <host> + [build] rustc 0 <host> -> Rustbook 1 <host> + [doc] unstable-book (book) <host> + [doc] book (book) <host> + [doc] book/first-edition (book) <host> + [doc] book/second-edition (book) <host> + [doc] book/2018-edition (book) <host> + [doc] rustc 1 <host> -> standalone 2 <host> + [doc] rustc 1 <host> -> std 1 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [build] rustc 1 <host> -> error-index 2 <host> + [doc] rustc 1 <host> -> error-index 2 <host> + [doc] nomicon (book) <host> + [doc] rustc 1 <host> -> reference (book) 2 <host> + [doc] rustdoc (book) <host> + [doc] rust-by-example (book) <host> + [build] rustc 0 <host> -> LintDocs 1 <host> + [doc] rustc (book) <host> + [doc] cargo (book) <host> + [doc] clippy (book) <host> + [doc] embedded-book (book) <host> + [doc] edition-guide (book) <host> + [doc] style-guide (book) <host> + [doc] rustc 1 <host> -> releases 2 <host> + [build] rustc 0 <host> -> Linkchecker 1 <host> + [test] link-check <host> + [test] tier-check <host> + [test] rustc 1 <host> -> rust-analyzer 2 <host> + [doc] rustc (book) <host> + [test] rustc 1 <host> -> lint-docs 2 <host> + [build] rustc 0 <host> -> RustdocTheme 1 <host> + [test] rustdoc-theme 2 <host> + [test] compiletest-rustdoc-ui 2 <host> + [build] rustc 0 <host> -> JsonDocCk 1 <host> + [build] rustc 0 <host> -> JsonDocLint 1 <host> + [test] compiletest-rustdoc-json 2 <host> + [doc] rustc 1 <host> -> rustc 2 <host> + [build] rustc 0 <host> -> HtmlChecker 1 <host> + [test] html-check <host> + [build] rustc 0 <host> -> RunMakeSupport 1 <host> + [build] rustc 1 <host> -> cargo 2 <host> + [test] compiletest-run-make 2 <host> + "); + } + + #[test] + fn test_compiler_stage_1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .path("compiler") + .stage(1) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 0 <host> -> std 0 <host> + [build] rustdoc 0 <host> + [test] rustc 0 <host> -> CrateLibrustc 1 <host> + "); + } + + #[test] + fn test_compiler_stage_2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .path("compiler") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustdoc 1 <host> + [test] rustc 1 <host> -> CrateLibrustc 2 <host> + "); + } + #[test] fn test_exclude() { let ctx = TestCtx::new(); let steps = ctx.config("test").args(&["--skip", "src/tools/tidy"]).get_steps(); let host = TargetSelection::from_user(&host_target()); - steps.assert_contains(StepMetadata::test("RustdocUi", host)); + steps.assert_contains(StepMetadata::test("compiletest-rustdoc-ui", host).stage(1)); steps.assert_not_contains(test::Tidy); } @@ -2054,13 +2357,15 @@ mod snapshot { let get_steps = |args: &[&str]| ctx.config("test").args(args).get_steps(); + let rustc_metadata = + || StepMetadata::test("CrateLibrustc", host).built_by(Compiler::new(0, host)); // Ensure our test is valid, and `test::Rustc` would be run without the exclude. - get_steps(&[]).assert_contains(StepMetadata::test("CrateLibrustc", host)); + get_steps(&[]).assert_contains(rustc_metadata()); let steps = get_steps(&["--skip", "compiler/rustc_data_structures"]); // Ensure tests for rustc are not skipped. - steps.assert_contains(StepMetadata::test("CrateLibrustc", host)); + steps.assert_contains(rustc_metadata()); steps.assert_contains_fuzzy(StepMetadata::build("rustc", host)); } @@ -2077,6 +2382,7 @@ mod snapshot { [build] rustc 1 <host> -> std 1 <host> [build] rustdoc 1 <host> [build] rustdoc 0 <host> + [test] rustc 0 <host> -> cargo 1 <host> "); } @@ -2096,6 +2402,7 @@ mod snapshot { [build] rustc 2 <host> -> std 2 <host> [build] rustdoc 2 <host> [build] rustdoc 1 <host> + [test] rustc 1 <host> -> cargo 2 <host> "); } @@ -2117,6 +2424,19 @@ mod snapshot { } #[test] + fn test_tier_check() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("test") + .path("tier-check") + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [test] tier-check <host> + "); + } + + #[test] fn doc_all() { let ctx = TestCtx::new(); insta::assert_snapshot!( diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a8eb563015f..d12cc962187 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1002,13 +1002,17 @@ impl Config { (0, Subcommand::Install) => { check_stage0("install"); } + (0, Subcommand::Test { .. }) if build_compiletest_allow_stage0 != Some(true) => { + eprintln!( + "ERROR: cannot test anything on stage 0. Use at least stage 1. If you want to run compiletest with an external stage0 toolchain, enable `build.compiletest-allow-stage0`." + ); + exit!(1); + } _ => {} } if flags_compile_time_deps && !matches!(flags_cmd, Subcommand::Check { .. }) { - eprintln!( - "WARNING: Can't use --compile-time-deps with any subcommand other than check." - ); + eprintln!("ERROR: Can't use --compile-time-deps with any subcommand other than check."); exit!(1); } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index b8ee83b20e4..59c0f9faaca 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -426,22 +426,22 @@ forward! { download_rustc() -> bool, } -/// A mostly temporary helper struct before we can migrate everything in bootstrap to use -/// the concept of a build compiler. -struct HostAndStage { - host: TargetSelection, +/// An alternative way of specifying what target and stage is involved in some bootstrap activity. +/// Ideally using a `Compiler` directly should be preferred. +struct TargetAndStage { + target: TargetSelection, stage: u32, } -impl From<(TargetSelection, u32)> for HostAndStage { - fn from((host, stage): (TargetSelection, u32)) -> Self { - Self { host, stage } +impl From<(TargetSelection, u32)> for TargetAndStage { + fn from((target, stage): (TargetSelection, u32)) -> Self { + Self { target, stage } } } -impl From<Compiler> for HostAndStage { +impl From<Compiler> for TargetAndStage { fn from(compiler: Compiler) -> Self { - Self { host: compiler.host, stage: compiler.stage } + Self { target: compiler.host, stage: compiler.stage } } } @@ -1109,11 +1109,12 @@ impl Build { /// Return a `Group` guard for a [`Step`] that: /// - Performs `action` + /// - If the action is `Kind::Test`, use [`Build::msg_test`] instead. /// - On `what` /// - Where `what` possibly corresponds to a `mode` - /// - `action` is performed using the given build compiler (`host_and_stage`). - /// - Since some steps do not use the concept of a build compiler yet, it is also possible - /// to pass the host and stage explicitly. + /// - `action` is performed with/on the given compiler (`target_and_stage`). + /// - Since for some steps it is not possible to pass a single compiler here, it is also + /// possible to pass the host and stage explicitly. /// - With a given `target`. /// /// [`Step`]: crate::core::builder::Step @@ -1124,13 +1125,19 @@ impl Build { action: impl Into<Kind>, what: impl Display, mode: impl Into<Option<Mode>>, - host_and_stage: impl Into<HostAndStage>, + target_and_stage: impl Into<TargetAndStage>, target: impl Into<Option<TargetSelection>>, ) -> Option<gha::Group> { - let host_and_stage = host_and_stage.into(); + let target_and_stage = target_and_stage.into(); + let action = action.into(); + assert!( + action != Kind::Test, + "Please use `Build::msg_test` instead of `Build::msg(Kind::Test)`" + ); + let actual_stage = match mode.into() { // Std has the same stage as the compiler that builds it - Some(Mode::Std) => host_and_stage.stage, + Some(Mode::Std) => target_and_stage.stage, // Other things have stage corresponding to their build compiler + 1 Some( Mode::Rustc @@ -1140,18 +1147,22 @@ impl Build { | Mode::ToolStd | Mode::ToolRustc, ) - | None => host_and_stage.stage + 1, + | None => target_and_stage.stage + 1, }; - let action = action.into().description(); - let msg = |fmt| format!("{action} stage{actual_stage} {what}{fmt}"); + let action = action.description(); + let what = what.to_string(); + let msg = |fmt| { + let space = if !what.is_empty() { " " } else { "" }; + format!("{action} stage{actual_stage} {what}{space}{fmt}") + }; let msg = if let Some(target) = target.into() { - let build_stage = host_and_stage.stage; - let host = host_and_stage.host; + let build_stage = target_and_stage.stage; + let host = target_and_stage.target; if host == target { - msg(format_args!(" (stage{build_stage} -> stage{actual_stage}, {target})")) + msg(format_args!("(stage{build_stage} -> stage{actual_stage}, {target})")) } else { - msg(format_args!(" (stage{build_stage}:{host} -> stage{actual_stage}:{target})")) + msg(format_args!("(stage{build_stage}:{host} -> stage{actual_stage}:{target})")) } } else { msg(format_args!("")) @@ -1159,6 +1170,24 @@ impl Build { self.group(&msg) } + /// Return a `Group` guard for a [`Step`] that tests `what` with the given `stage` and `target`. + /// Use this instead of [`Build::msg`] for test steps, because for them it is not always clear + /// what exactly is a build compiler. + /// + /// [`Step`]: crate::core::builder::Step + #[must_use = "Groups should not be dropped until the Step finishes running"] + #[track_caller] + fn msg_test( + &self, + what: impl Display, + target: TargetSelection, + stage: u32, + ) -> Option<gha::Group> { + let action = Kind::Test.description(); + let msg = format!("{action} stage{stage} {what} ({target})"); + self.group(&msg) + } + /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`. /// /// [`Step`]: crate::core::builder::Step @@ -2086,11 +2115,6 @@ impl Compiler { self.forced_compiler = forced_compiler; } - pub fn with_stage(mut self, stage: u32) -> Compiler { - self.stage = stage; - self - } - /// Returns `true` if this is a snapshot compiler for `build`'s configuration pub fn is_snapshot(&self, build: &Build) -> bool { self.stage == 0 && self.host == build.host_target diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 606d88d3db4..2cc2fb486fa 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -531,4 +531,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "It is now possible to `check/build/dist` the standard stage 0 library if you use a stage0 rustc built from in-tree sources. This is useful for quickly cross-compiling the standard library. You have to enable build.local-rebuild for this to work.", }, + ChangeInfo { + change_id: 145663, + severity: ChangeSeverity::Warning, + summary: "It is no longer possible to `x test` with stage 0, except for running compiletest and opting into `build.compiletest-allow-stage0`.", + }, ]; diff --git a/src/bootstrap/src/utils/tracing.rs b/src/bootstrap/src/utils/tracing.rs index 472781ffa73..b1226ed7de7 100644 --- a/src/bootstrap/src/utils/tracing.rs +++ b/src/bootstrap/src/utils/tracing.rs @@ -168,7 +168,11 @@ mod inner { impl TracingGuard { pub fn copy_to_dir(self, dir: &std::path::Path) { drop(self.guard); - std::fs::rename(&self.chrome_tracing_path, dir.join("chrome-trace.json")).unwrap(); + crate::utils::helpers::move_file( + &self.chrome_tracing_path, + dir.join("chrome-trace.json"), + ) + .unwrap(); } } diff --git a/src/ci/docker/host-x86_64/tidy/Dockerfile b/src/ci/docker/host-x86_64/tidy/Dockerfile index c8558689d3b..2dda51b155e 100644 --- a/src/ci/docker/host-x86_64/tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/tidy/Dockerfile @@ -44,5 +44,5 @@ RUN bash -c 'npm install -g eslint@$(cat /tmp/eslint.version)' # NOTE: intentionally uses python2 for x.py so we can test it still works. # validate-toolstate only runs in our CI, so it's ok for it to only support python3. -ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 \ +ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \ src/tools/tidy tidyselftest --extra-checks=py,cpp,js,spellcheck diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index 8acc5040a2f..70ff5d0d2c7 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,8 @@ set -euo pipefail -LINUX_VERSION=v6.16-rc1 +# https://github.com/rust-lang/rust/pull/144443 +LINUX_VERSION=7770d51bce622b13195b2d3c85407282fc9c27e5 # Build rustc, rustdoc, cargo, clippy-driver and rustfmt ../x.py build --stage 2 library rustdoc clippy rustfmt diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index e0d637a2a67..8e378e53e51 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -116,6 +116,7 @@ - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) - [\*-unknown-hermit](platform-support/hermit.md) - [\*-unknown-freebsd](platform-support/freebsd.md) + - [\*-unknown-managarm-mlibc](platform-support/managarm.md) - [\*-unknown-netbsd\*](platform-support/netbsd.md) - [\*-unknown-openbsd](platform-support/openbsd.md) - [\*-unknown-redox](platform-support/redox.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index edfc2db7d6f..dfe193e6e8a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -258,6 +258,7 @@ target | std | host | notes [`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit [`aarch64-unknown-illumos`](platform-support/illumos.md) | ✓ | ✓ | ARM64 illumos `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) +[`aarch64-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | ARM64 Managarm [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS | [`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | @@ -388,6 +389,7 @@ target | std | host | notes `riscv64gc-unknown-freebsd` | ? | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | ? | | RISC-V Fuchsia [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit +[`riscv64gc-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | RISC-V Managarm [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 @@ -428,6 +430,7 @@ target | std | host | notes [`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * | | 64-bit Linux with no libc +[`x86_64-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | x86_64 Managarm [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD [`x86_64-unknown-trusty`](platform-support/trusty.md) | ✓ | | `x86_64-uwp-windows-gnu` | ✓ | | diff --git a/src/doc/rustc/src/platform-support/managarm.md b/src/doc/rustc/src/platform-support/managarm.md new file mode 100644 index 00000000000..aa2d5a7ac23 --- /dev/null +++ b/src/doc/rustc/src/platform-support/managarm.md @@ -0,0 +1,53 @@ +# `*-unknown-managarm-mlibc` + +**Tier: 3** + +## Target Maintainers + +- [@no92](https://github.com/no92) +- [@64](https://github.com/64) +- [@Dennisbonke](https://github.com/Dennisbonke) + +## Requirements + +This target is cross-compiled. There is currently no support for `std` yet. It generates binaries in the ELF format. Currently, we support the `x86_64`, `aarch64` and `riscv64gc` architectures. The examples below `$ARCH` should be substituted for one of the supported architectures. + +## Building the target + +Managarm has upstream support in LLVM since the release of 21.1.0. + +Set up your `bootstrap.toml` like this: + +```toml +change-id = 142379 + +[llvm] +targets = "X86;AArch64;RISCV" +download-ci-llvm = false + +[build] +target = ["$ARCH-unknown-managarm-mlibc", "x86_64-unknown-linux-gnu"] + +[target.x86_64-unknown-linux-gnu] +llvm-config = "/path/to/your/llvm/bin/llvm-config" + +[target.$ARCH-unknown-managarm-mlibc] +llvm-config = "/path/to/your/llvm/bin/llvm-config" +``` + +## Building Rust programs + +Build a `$ARCH-managarm-gcc` using our [gcc fork](https://github.com/managarm/gcc). + +```toml +[build] +rustc = "/path/to/the/rust-prefix/bin/rustc" +target = "$ARCH-unknown-managarm-mlibc" + +[target.$ARCH-unknown-managarm-mlibc] +linker = "/path/to/the/managarm-gcc/bin/$ARCH-managarm-gcc" +``` + +## Testing + +This target does not support running the Rust testsuite yet. diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index dddc087d124..2984f3ab50e 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -289,8 +289,26 @@ impl SerializedSearchIndex { (Some(self_type_data), None) => Some(self_type_data), (None, Some(other_type_data)) => Some(TypeData { search_unbox: other_type_data.search_unbox, - inverted_function_signature_index: other_type_data - .inverted_function_signature_index + inverted_function_inputs_index: other_type_data + .inverted_function_inputs_index + .iter() + .cloned() + .map(|mut list: Vec<u32>| { + for fnid in &mut list { + assert!( + other.function_data + [usize::try_from(*fnid).unwrap()] + .is_some(), + ); + // this is valid because we call `self.push()` once, exactly, for every entry, + // even if we're just pushing a tombstone + *fnid += u32::try_from(other_entryid_offset).unwrap(); + } + list + }) + .collect(), + inverted_function_output_index: other_type_data + .inverted_function_output_index .iter() .cloned() .map(|mut list: Vec<u32>| { @@ -310,18 +328,42 @@ impl SerializedSearchIndex { }), (Some(mut self_type_data), Some(other_type_data)) => { for (size, other_list) in other_type_data - .inverted_function_signature_index + .inverted_function_inputs_index + .iter() + .enumerate() + { + while self_type_data.inverted_function_inputs_index.len() + <= size + { + self_type_data + .inverted_function_inputs_index + .push(Vec::new()); + } + self_type_data.inverted_function_inputs_index[size].extend( + other_list.iter().copied().map(|fnid| { + assert!( + other.function_data[usize::try_from(fnid).unwrap()] + .is_some(), + ); + // this is valid because we call `self.push()` once, exactly, for every entry, + // even if we're just pushing a tombstone + fnid + u32::try_from(other_entryid_offset).unwrap() + }), + ) + } + for (size, other_list) in other_type_data + .inverted_function_output_index .iter() .enumerate() { - while self_type_data.inverted_function_signature_index.len() + while self_type_data.inverted_function_output_index.len() <= size { self_type_data - .inverted_function_signature_index + .inverted_function_output_index .push(Vec::new()); } - self_type_data.inverted_function_signature_index[size].extend( + self_type_data.inverted_function_output_index[size].extend( other_list.iter().copied().map(|fnid| { assert!( other.function_data[usize::try_from(fnid).unwrap()] @@ -443,8 +485,25 @@ impl SerializedSearchIndex { param_names: function_data.param_names.clone(), }), other.type_data[other_entryid].as_ref().map(|type_data| TypeData { - inverted_function_signature_index: type_data - .inverted_function_signature_index + inverted_function_inputs_index: type_data + .inverted_function_inputs_index + .iter() + .cloned() + .map(|mut list| { + for fnid in &mut list { + assert!( + other.function_data[usize::try_from(*fnid).unwrap()] + .is_some(), + ); + // this is valid because we call `self.push()` once, exactly, for every entry, + // even if we're just pushing a tombstone + *fnid += u32::try_from(other_entryid_offset).unwrap(); + } + list + }) + .collect(), + inverted_function_output_index: type_data + .inverted_function_output_index .iter() .cloned() .map(|mut list| { @@ -599,9 +658,13 @@ impl SerializedSearchIndex { }, ), self.type_data[id].as_ref().map( - |TypeData { search_unbox, inverted_function_signature_index }| { - let inverted_function_signature_index: Vec<Vec<u32>> = - inverted_function_signature_index + |TypeData { + search_unbox, + inverted_function_inputs_index, + inverted_function_output_index, + }| { + let inverted_function_inputs_index: Vec<Vec<u32>> = + inverted_function_inputs_index .iter() .cloned() .map(|mut list| { @@ -615,7 +678,26 @@ impl SerializedSearchIndex { list }) .collect(); - TypeData { search_unbox: *search_unbox, inverted_function_signature_index } + let inverted_function_output_index: Vec<Vec<u32>> = + inverted_function_output_index + .iter() + .cloned() + .map(|mut list| { + for id in &mut list { + *id = u32::try_from( + *map.get(&usize::try_from(*id).unwrap()).unwrap(), + ) + .unwrap(); + } + list.sort(); + list + }) + .collect(); + TypeData { + search_unbox: *search_unbox, + inverted_function_inputs_index, + inverted_function_output_index, + } }, ), self.alias_pointers[id].and_then(|alias| map.get(&alias).copied()), @@ -934,18 +1016,20 @@ struct TypeData { /// | `Unboxable<Inner>` | yes | no | no | /// | `Inner<Unboxable>` | no | no | yes | search_unbox: bool, - /// List of functions that mention this type in their type signature. + /// List of functions that mention this type in their type signature, + /// on the left side of the `->` arrow. /// - /// - The outermost list has one entry per alpha-normalized generic. - /// - /// - The second layer is sorted by number of types that appear in the + /// - The outer layer is sorted by number of types that appear in the /// type signature. The search engine iterates over these in order from /// smallest to largest. Functions with less stuff in their type /// signature are more likely to be what the user wants, because we never /// show functions that are *missing* parts of the query, so removing.. /// - /// - The final layer is the list of functions. - inverted_function_signature_index: Vec<Vec<u32>>, + /// - The inner layer is the list of functions. + inverted_function_inputs_index: Vec<Vec<u32>>, + /// List of functions that mention this type in their type signature, + /// on the right side of the `->` arrow. + inverted_function_output_index: Vec<Vec<u32>>, } impl Serialize for TypeData { @@ -953,15 +1037,21 @@ impl Serialize for TypeData { where S: Serializer, { - if self.search_unbox || !self.inverted_function_signature_index.is_empty() { + if self.search_unbox + || !self.inverted_function_inputs_index.is_empty() + || !self.inverted_function_output_index.is_empty() + { let mut seq = serializer.serialize_seq(None)?; - if !self.inverted_function_signature_index.is_empty() { - let mut buf = Vec::new(); - encode::write_postings_to_string(&self.inverted_function_signature_index, &mut buf); - let mut serialized_result = Vec::new(); - stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result); - seq.serialize_element(&String::from_utf8(serialized_result).unwrap())?; - } + let mut buf = Vec::new(); + encode::write_postings_to_string(&self.inverted_function_inputs_index, &mut buf); + let mut serialized_result = Vec::new(); + stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result); + seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?; + buf.clear(); + serialized_result.clear(); + encode::write_postings_to_string(&self.inverted_function_output_index, &mut buf); + stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result); + seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?; if self.search_unbox { seq.serialize_element(&1)?; } @@ -984,21 +1074,39 @@ impl<'de> Deserialize<'de> for TypeData { write!(formatter, "type data") } fn visit_none<E>(self) -> Result<TypeData, E> { - Ok(TypeData { inverted_function_signature_index: vec![], search_unbox: false }) + Ok(TypeData { + inverted_function_inputs_index: vec![], + inverted_function_output_index: vec![], + search_unbox: false, + }) } fn visit_seq<A: de::SeqAccess<'de>>(self, mut v: A) -> Result<TypeData, A::Error> { - let inverted_function_signature_index: String = + let inverted_function_inputs_index: String = + v.next_element()?.unwrap_or(String::new()); + let inverted_function_output_index: String = v.next_element()?.unwrap_or(String::new()); let search_unbox: u32 = v.next_element()?.unwrap_or(0); let mut idx: Vec<u8> = Vec::new(); stringdex_internals::decode::read_base64_from_bytes( - inverted_function_signature_index.as_bytes(), + inverted_function_inputs_index.as_bytes(), &mut idx, ) .unwrap(); - let mut inverted_function_signature_index = Vec::new(); - encode::read_postings_from_string(&mut inverted_function_signature_index, &idx); - Ok(TypeData { inverted_function_signature_index, search_unbox: search_unbox == 1 }) + let mut inverted_function_inputs_index = Vec::new(); + encode::read_postings_from_string(&mut inverted_function_inputs_index, &idx); + idx.clear(); + stringdex_internals::decode::read_base64_from_bytes( + inverted_function_output_index.as_bytes(), + &mut idx, + ) + .unwrap(); + let mut inverted_function_output_index = Vec::new(); + encode::read_postings_from_string(&mut inverted_function_output_index, &idx); + Ok(TypeData { + inverted_function_inputs_index, + inverted_function_output_index, + search_unbox: search_unbox == 1, + }) } } deserializer.deserialize_any(TypeDataVisitor) @@ -1222,8 +1330,16 @@ pub(crate) fn build_index( let index = *index.get(); serialized_index.descs[index] = crate_doc; for type_data in serialized_index.type_data.iter_mut() { - if let Some(TypeData { inverted_function_signature_index, .. }) = type_data { - for list in &mut inverted_function_signature_index[..] { + if let Some(TypeData { + inverted_function_inputs_index, + inverted_function_output_index, + .. + }) = type_data + { + for list in inverted_function_inputs_index + .iter_mut() + .chain(inverted_function_output_index.iter_mut()) + { list.retain(|fnid| { serialized_index.entry_data[usize::try_from(*fnid).unwrap()] .as_ref() @@ -1449,7 +1565,8 @@ pub(crate) fn build_index( if serialized_index.type_data[id].as_mut().is_none() { serialized_index.type_data[id] = Some(TypeData { search_unbox, - inverted_function_signature_index: Vec::new(), + inverted_function_inputs_index: Vec::new(), + inverted_function_output_index: Vec::new(), }); } else if search_unbox { serialized_index.type_data[id].as_mut().unwrap().search_unbox = true; @@ -1473,7 +1590,11 @@ pub(crate) fn build_index( None }, }, - TypeData { search_unbox, inverted_function_signature_index: Vec::new() }, + TypeData { + inverted_function_inputs_index: Vec::new(), + inverted_function_output_index: Vec::new(), + search_unbox, + }, ); pathid } @@ -1695,13 +1816,14 @@ pub(crate) fn build_index( } } if let Some(search_type) = &mut item.search_type { - let mut used_in_function_signature = BTreeSet::new(); + let mut used_in_function_inputs = BTreeSet::new(); + let mut used_in_function_output = BTreeSet::new(); for item in &mut search_type.inputs { convert_render_type( item, cache, &mut serialized_index, - &mut used_in_function_signature, + &mut used_in_function_inputs, tcx, ); } @@ -1710,20 +1832,44 @@ pub(crate) fn build_index( item, cache, &mut serialized_index, - &mut used_in_function_signature, + &mut used_in_function_output, tcx, ); } + let mut used_in_constraints = Vec::new(); for constraint in &mut search_type.where_clause { + let mut used_in_constraint = BTreeSet::new(); for trait_ in &mut constraint[..] { convert_render_type( trait_, cache, &mut serialized_index, - &mut used_in_function_signature, + &mut used_in_constraint, tcx, ); } + used_in_constraints.push(used_in_constraint); + } + loop { + let mut inserted_any = false; + for (i, used_in_constraint) in used_in_constraints.iter().enumerate() { + let id = !(i as isize); + if used_in_function_inputs.contains(&id) + && !used_in_function_inputs.is_superset(&used_in_constraint) + { + used_in_function_inputs.extend(used_in_constraint.iter().copied()); + inserted_any = true; + } + if used_in_function_output.contains(&id) + && !used_in_function_output.is_superset(&used_in_constraint) + { + used_in_function_output.extend(used_in_constraint.iter().copied()); + inserted_any = true; + } + } + if !inserted_any { + break; + } } let search_type_size = search_type.size() + // Artificially give struct fields a size of 8 instead of their real @@ -1746,13 +1892,34 @@ pub(crate) fn build_index( .map(|sym| sym.map(|sym| sym.to_string()).unwrap_or(String::new())) .collect::<Vec<String>>(), }); - for index in used_in_function_signature { + for index in used_in_function_inputs { + let postings = if index >= 0 { + assert!(serialized_index.path_data[index as usize].is_some()); + &mut serialized_index.type_data[index as usize] + .as_mut() + .unwrap() + .inverted_function_inputs_index + } else { + let generic_id = usize::try_from(-index).unwrap() - 1; + for _ in serialized_index.generic_inverted_index.len()..=generic_id { + serialized_index.generic_inverted_index.push(Vec::new()); + } + &mut serialized_index.generic_inverted_index[generic_id] + }; + while postings.len() <= search_type_size { + postings.push(Vec::new()); + } + if postings[search_type_size].last() != Some(&(new_entry_id as u32)) { + postings[search_type_size].push(new_entry_id as u32); + } + } + for index in used_in_function_output { let postings = if index >= 0 { assert!(serialized_index.path_data[index as usize].is_some()); &mut serialized_index.type_data[index as usize] .as_mut() .unwrap() - .inverted_function_signature_index + .inverted_function_output_index } else { let generic_id = usize::try_from(-index).unwrap() - 1; for _ in serialized_index.generic_inverted_index.len()..=generic_id { @@ -1763,7 +1930,9 @@ pub(crate) fn build_index( while postings.len() <= search_type_size { postings.push(Vec::new()); } - postings[search_type_size].push(new_entry_id as u32); + if postings[search_type_size].last() != Some(&(new_entry_id as u32)) { + postings[search_type_size].push(new_entry_id as u32); + } } } } diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 3ac10742e41..74f646008eb 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -270,9 +270,12 @@ declare namespace rustdoc { */ interface TypeData { searchUnbox: boolean, - invertedFunctionSignatureIndex: RoaringBitmap[], + invertedFunctionInputsIndex: RoaringBitmap[], + invertedFunctionOutputIndex: RoaringBitmap[], } + type TypeInvertedIndexPolarity = "invertedFunctionInputsIndex" | "invertedFunctionOutputIndex"; + /** * A search entry of some sort. */ diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index b003bcc7bf9..fa812a2b67b 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1696,7 +1696,7 @@ class DocSearch { } /** * function_signature, param_names - * @type {[string, number] | [number] | [string] | [] | null} + * @type {[string, string, number] | [string, string] | [] | null} */ const raw = JSON.parse(encoded); @@ -1705,32 +1705,46 @@ class DocSearch { } let searchUnbox = false; - const invertedFunctionSignatureIndex = []; + const invertedFunctionInputsIndex = []; + const invertedFunctionOutputIndex = []; if (typeof raw[0] === "string") { - if (raw[1]) { + if (raw[2]) { searchUnbox = true; } // the inverted function signature index is a list of bitmaps, // by number of types that appear in the function let i = 0; - const pb = makeUint8ArrayFromBase64(raw[0]); - const l = pb.length; + let pb = makeUint8ArrayFromBase64(raw[0]); + let l = pb.length; while (i < l) { if (pb[i] === 0) { - invertedFunctionSignatureIndex.push(RoaringBitmap.empty()); + invertedFunctionInputsIndex.push(RoaringBitmap.empty()); i += 1; } else { const bitmap = new RoaringBitmap(pb, i); i += bitmap.consumed_len_bytes; - invertedFunctionSignatureIndex.push(bitmap); + invertedFunctionInputsIndex.push(bitmap); + } + } + i = 0; + pb = makeUint8ArrayFromBase64(raw[1]); + l = pb.length; + while (i < l) { + if (pb[i] === 0) { + invertedFunctionOutputIndex.push(RoaringBitmap.empty()); + i += 1; + } else { + const bitmap = new RoaringBitmap(pb, i); + i += bitmap.consumed_len_bytes; + invertedFunctionOutputIndex.push(bitmap); } } } else if (raw[0]) { searchUnbox = true; } - return { searchUnbox, invertedFunctionSignatureIndex }; + return { searchUnbox, invertedFunctionInputsIndex, invertedFunctionOutputIndex }; } /** @@ -4009,14 +4023,19 @@ class DocSearch { * or anything else. This function returns all possible permutations. * * @param {rustdoc.ParserQueryElement|null} elem + * @param {rustdoc.TypeInvertedIndexPolarity} polarity * @returns {Promise<PostingsList<rustdoc.QueryElement>[]>} */ - const unpackPostingsList = async elem => { + const unpackPostingsList = async(elem, polarity) => { if (!elem) { return empty_postings_list; } const typeFilter = itemTypeFromName(elem.typeFilter); - const searchResults = await index.search(elem.normalizedPathLast); + const [searchResults, upla, uplb] = await Promise.all([ + index.search(elem.normalizedPathLast), + unpackPostingsListAll(elem.generics, polarity), + unpackPostingsListBindings(elem.bindings, polarity), + ]); /** * @type {Promise<[ * number, @@ -4039,7 +4058,7 @@ class DocSearch { const types = (await Promise.all(typePromises)) .filter(([_id, name, ty, path]) => name !== null && name.toLowerCase() === elem.pathLast && - ty && !ty.invertedFunctionSignatureIndex.every(bitmap => { + ty && !ty[polarity].every(bitmap => { return bitmap.isEmpty(); }) && path && path.ty !== TY_ASSOCTYPE && @@ -4078,7 +4097,7 @@ class DocSearch { this.getPathData(id), ]); if (name !== null && ty !== null && path !== null && - !ty.invertedFunctionSignatureIndex.every(bitmap => { + !ty[polarity].every(bitmap => { return bitmap.isEmpty(); }) && path.ty !== TY_ASSOCTYPE @@ -4176,18 +4195,16 @@ class DocSearch { /** @type {PostingsList<rustdoc.QueryElement>[]} */ const results = []; for (const [id, _name, typeData] of types) { - if (!typeData || typeData.invertedFunctionSignatureIndex.every(bitmap => { + if (!typeData || typeData[polarity].every(bitmap => { return bitmap.isEmpty(); })) { continue; } - const upla = await unpackPostingsListAll(elem.generics); - const uplb = await unpackPostingsListBindings(elem.bindings); for (const {invertedIndex: genericsIdx, queryElem: generics} of upla) { for (const {invertedIndex: bindingsIdx, queryElem: bindings} of uplb) { results.push({ invertedIndex: intersectInvertedIndexes( - typeData.invertedFunctionSignatureIndex, + typeData[polarity], genericsIdx, bindingsIdx, ), @@ -4219,15 +4236,16 @@ class DocSearch { * take the intersection of this bitmap. * * @param {(rustdoc.ParserQueryElement|null)[]|null} elems + * @param {rustdoc.TypeInvertedIndexPolarity} polarity * @returns {Promise<PostingsList<rustdoc.QueryElement[]>[]>} */ - const unpackPostingsListAll = async elems => { + const unpackPostingsListAll = async(elems, polarity) => { if (!elems || elems.length === 0) { return nested_everything_postings_list; } const [firstPostingsList, remainingAll] = await Promise.all([ - unpackPostingsList(elems[0]), - unpackPostingsListAll(elems.slice(1)), + unpackPostingsList(elems[0], polarity), + unpackPostingsListAll(elems.slice(1), polarity), ]); /** @type {PostingsList<rustdoc.QueryElement[]>[]} */ const results = []; @@ -4261,11 +4279,12 @@ class DocSearch { * Before passing an actual parser item to it, make sure to clone the map. * * @param {Map<string, rustdoc.ParserQueryElement[]>} elems + * @param {rustdoc.TypeInvertedIndexPolarity} polarity * @returns {Promise<PostingsList< * Map<number, rustdoc.QueryElement[]>, * >[]>} */ - const unpackPostingsListBindings = async elems => { + const unpackPostingsListBindings = async(elems, polarity) => { if (!elems) { return [{ invertedIndex: everything_inverted_index, @@ -4286,19 +4305,23 @@ class DocSearch { queryElem: new Map(), }]; } - const firstKeyIds = await index.search(firstKey); + // HEADS UP! + // We must put this map back the way we found it before returning, + // otherwise things break. + elems.delete(firstKey); + const [firstKeyIds, firstPostingsList, remainingAll] = await Promise.all([ + index.search(firstKey), + unpackPostingsListAll(firstList, polarity), + unpackPostingsListBindings(elems, polarity), + ]); if (!firstKeyIds) { + elems.set(firstKey, firstList); // User specified a non-existent key. return [{ invertedIndex: empty_inverted_index, queryElem: new Map(), }]; } - elems.delete(firstKey); - const [firstPostingsList, remainingAll] = await Promise.all([ - unpackPostingsListAll(firstList), - unpackPostingsListBindings(elems), - ]); /** @type {PostingsList<Map<number, rustdoc.QueryElement[]>>[]} */ const results = []; for (const keyId of firstKeyIds.matches().entries()) { @@ -4335,8 +4358,8 @@ class DocSearch { // finally, we can do the actual unification loop const [allInputs, allOutput] = await Promise.all([ - unpackPostingsListAll(inputs), - unpackPostingsListAll(output), + unpackPostingsListAll(inputs, "invertedFunctionInputsIndex"), + unpackPostingsListAll(output, "invertedFunctionOutputIndex"), ]); let checkCounter = 0; /** diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8f88ab10bf7..2890d26d3f4 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -71,6 +71,7 @@ static TARGETS: &[&str] = &[ "aarch64-unknown-none-softfloat", "aarch64-unknown-redox", "aarch64-unknown-uefi", + "aarch64-unknown-managarm-mlibc", "amdgcn-amd-amdhsa", "arm64e-apple-darwin", "arm64e-apple-ios", @@ -155,6 +156,7 @@ static TARGETS: &[&str] = &[ "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", "riscv64gc-unknown-linux-musl", + "riscv64gc-unknown-managarm-mlibc", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", @@ -194,6 +196,7 @@ static TARGETS: &[&str] = &[ "x86_64-unknown-redox", "x86_64-unknown-hermit", "x86_64-unknown-uefi", + "x86_64-unknown-managarm-mlibc", ]; /// This allows the manifest to contain rust-docs for hosts that don't build diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index b72c0b7ed20..89b1b4f84b6 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -6,7 +6,6 @@ use std::sync::OnceLock; use build_helper::git::GitConfig; use camino::{Utf8Path, Utf8PathBuf}; use semver::Version; -use serde::de::{Deserialize, Deserializer, Error as _}; use crate::executor::ColorConfig; use crate::fatal; @@ -1072,7 +1071,7 @@ pub struct TargetCfg { pub(crate) abi: String, #[serde(rename = "target-family", default)] pub(crate) families: Vec<String>, - #[serde(rename = "target-pointer-width", deserialize_with = "serde_parse_u32")] + #[serde(rename = "target-pointer-width")] pub(crate) pointer_width: u32, #[serde(rename = "target-endian", default)] endian: Endian, @@ -1182,11 +1181,6 @@ fn query_rustc_output(config: &Config, args: &[&str], envs: HashMap<String, Stri String::from_utf8(output.stdout).unwrap() } -fn serde_parse_u32<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u32, D::Error> { - let string = String::deserialize(deserializer)?; - string.parse().map_err(D::Error::custom) -} - #[derive(Debug, Clone)] pub struct TestPaths { pub file: Utf8PathBuf, // e.g., compile-test/foo/bar/baz.rs diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index b33344ca5dd..bc38e931fe5 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -59,6 +59,8 @@ pub struct LintExtractor<'a> { pub rustc_target: &'a str, /// The target linker overriding `rustc`'s default pub rustc_linker: Option<&'a str>, + /// Stage of the compiler that builds the docs (the stage of `rustc_path`). + pub build_rustc_stage: u32, /// Verbose output. pub verbose: bool, /// Validate the style and the code example. @@ -216,14 +218,7 @@ impl<'a> LintExtractor<'a> { if let Some(text) = line.strip_prefix("/// ") { doc_lines.push(text.to_string()); } else if let Some(text) = line.strip_prefix("#[doc = \"") { - let escaped = text.strip_suffix("\"]").unwrap(); - let mut buf = String::new(); - unescape_str(escaped, |_, res| match res { - Ok(c) => buf.push(c), - Err(err) => { - assert!(!err.is_fatal(), "failed to unescape string literal") - } - }); + let buf = parse_doc_string(text); doc_lines.push(buf); } else if line == "///" { doc_lines.push("".to_string()); @@ -234,6 +229,20 @@ impl<'a> LintExtractor<'a> { // Ignore allow of lints (useful for // invalid_rust_codeblocks). continue; + } else if let Some(text) = + line.strip_prefix("#[cfg_attr(not(bootstrap), doc = \"") + { + if self.build_rustc_stage >= 1 { + let buf = parse_doc_string(text); + doc_lines.push(buf); + } + } else if let Some(text) = + line.strip_prefix("#[cfg_attr(bootstrap, doc = \"") + { + if self.build_rustc_stage == 0 { + let buf = parse_doc_string(text); + doc_lines.push(buf); + } } else { let name = lint_name(line).map_err(|e| { format!( @@ -580,6 +589,23 @@ impl<'a> LintExtractor<'a> { } } +/// Parses a doc string that follows `#[doc = "`. +fn parse_doc_string(text: &str) -> String { + let escaped = text.strip_suffix("]").unwrap_or(text); + let escaped = escaped.strip_suffix(")").unwrap_or(escaped).strip_suffix("\""); + let Some(escaped) = escaped else { + panic!("Cannot extract docstring content from {text}"); + }; + let mut buf = String::new(); + unescape_str(escaped, |_, res| match res { + Ok(c) => buf.push(c), + Err(err) => { + assert!(!err.is_fatal(), "failed to unescape string literal") + } + }); + buf +} + /// Adds `Lint`s that have been renamed. fn add_renamed_lints(lints: &mut Vec<Lint>) { for (level, names) in RENAMES { diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs index e377283b1a4..1933ce4d2f1 100644 --- a/src/tools/lint-docs/src/main.rs +++ b/src/tools/lint-docs/src/main.rs @@ -25,6 +25,7 @@ fn doit() -> Result<(), Box<dyn Error>> { let mut args = std::env::args().skip(1); let mut src_path = None; let mut out_path = None; + let mut build_rustc_stage = None; let mut rustc_path = None; let mut rustc_target = None; let mut rustc_linker = None; @@ -32,6 +33,14 @@ fn doit() -> Result<(), Box<dyn Error>> { let mut validate = false; while let Some(arg) = args.next() { match arg.as_str() { + "--build-rustc-stage" => { + build_rustc_stage = match args.next() { + Some(s) => { + Some(s.parse::<u32>().expect("build rustc stage has to be an integer")) + } + None => return Err("--build-rustc-stage requires a value".into()), + }; + } "--src" => { src_path = match args.next() { Some(s) => Some(PathBuf::from(s)), @@ -67,6 +76,9 @@ fn doit() -> Result<(), Box<dyn Error>> { s => return Err(format!("unexpected argument `{}`", s).into()), } } + if build_rustc_stage.is_none() { + return Err("--build-rustc-stage must be specified to the stage of the compiler that generates the docs".into()); + } if src_path.is_none() { return Err("--src must be specified to the directory with the compiler source".into()); } @@ -85,6 +97,7 @@ fn doit() -> Result<(), Box<dyn Error>> { rustc_path: &rustc_path.unwrap(), rustc_target: &rustc_target.unwrap(), rustc_linker: rustc_linker.as_deref(), + build_rustc_stage: build_rustc_stage.unwrap(), verbose, validate, }; diff --git a/src/tools/miri/tests/x86_64-unknown-kernel.json b/src/tools/miri/tests/x86_64-unknown-kernel.json index a5eaceb4f68..0f8032c39d5 100644 --- a/src/tools/miri/tests/x86_64-unknown-kernel.json +++ b/src/tools/miri/tests/x86_64-unknown-kernel.json @@ -1,7 +1,7 @@ { "llvm-target": "x86_64-unknown-none", "target-endian": "little", - "target-pointer-width": "64", + "target-pointer-width": 64, "target-c-int-width": 32, "data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", "arch": "x86_64", diff --git a/src/tools/opt-dist/src/bolt.rs b/src/tools/opt-dist/src/bolt.rs index a06e59fcc41..3ee9912b8c2 100644 --- a/src/tools/opt-dist/src/bolt.rs +++ b/src/tools/opt-dist/src/bolt.rs @@ -9,6 +9,7 @@ use crate::utils::io::copy_file; /// Instruments an artifact at the given `path` (in-place) with BOLT and then calls `func`. /// After this function finishes, the original file will be restored. pub fn with_bolt_instrumented<F: FnOnce(&Utf8Path) -> anyhow::Result<R>, R>( + env: &Environment, path: &Utf8Path, func: F, ) -> anyhow::Result<R> { @@ -26,7 +27,7 @@ pub fn with_bolt_instrumented<F: FnOnce(&Utf8Path) -> anyhow::Result<R>, R>( let profile_prefix = Utf8Path::from_path(&profile_prefix).unwrap(); // Instrument the original file with BOLT, saving the result into `instrumented_path` - cmd(&["llvm-bolt"]) + cmd(&[env.llvm_bolt().as_str()]) .arg("-instrument") .arg(path) .arg(&format!("--instrumentation-file={profile_prefix}")) @@ -61,7 +62,7 @@ pub fn bolt_optimize( let split_strategy = if env.host_tuple().starts_with("aarch64") { "profile2" } else { "cdsplit" }; - cmd(&["llvm-bolt"]) + cmd(&[env.llvm_bolt().as_str()]) .arg(temp_path.display()) .arg("-data") .arg(&profile.0) diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs index 2cae0785f33..7cc51901a83 100644 --- a/src/tools/opt-dist/src/environment.rs +++ b/src/tools/opt-dist/src/environment.rs @@ -116,6 +116,14 @@ impl Environment { pub fn stage0(&self) -> Utf8PathBuf { self.stage0_root.clone().unwrap_or_else(|| self.build_artifacts().join("stage0")) } + + pub fn llvm_bolt(&self) -> Utf8PathBuf { + self.host_llvm_dir().join(format!("bin/llvm-bolt{}", executable_extension())) + } + + pub fn merge_fdata(&self) -> Utf8PathBuf { + self.host_llvm_dir().join(format!("bin/merge-fdata{}", executable_extension())) + } } /// What is the extension of binary executables on this platform? diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 339c25552ad..48b25f235dd 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -329,7 +329,7 @@ fn execute_pipeline( // FIXME(kobzol): try gather profiles together, at once for LLVM and rustc // Instrument the libraries and gather profiles - let llvm_profile = with_bolt_instrumented(&llvm_lib, |llvm_profile_dir| { + let llvm_profile = with_bolt_instrumented(env, &llvm_lib, |llvm_profile_dir| { stage.section("Gather profiles", |_| { gather_bolt_profiles(env, "LLVM", llvm_benchmarks(env), llvm_profile_dir) }) @@ -354,7 +354,7 @@ fn execute_pipeline( log::info!("Optimizing {rustc_lib} with BOLT"); // Instrument it and gather profiles - let rustc_profile = with_bolt_instrumented(&rustc_lib, |rustc_profile_dir| { + let rustc_profile = with_bolt_instrumented(env, &rustc_lib, |rustc_profile_dir| { stage.section("Gather profiles", |_| { gather_bolt_profiles(env, "rustc", rustc_benchmarks(env), rustc_profile_dir) }) diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index ae062d5c60c..4f9352d11b1 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -195,7 +195,8 @@ pub fn gather_bolt_profiles( let profiles: Vec<_> = glob::glob(&format!("{profile_prefix}*"))?.collect::<Result<Vec<_>, _>>()?; - let mut merge_args = vec!["merge-fdata"]; + let fdata = env.merge_fdata(); + let mut merge_args = vec![fdata.as_str()]; merge_args.extend(profiles.iter().map(|p| p.to_str().unwrap())); with_log_group("Merging BOLT profiles", || { diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index 6cdb82a87bd..38e5e8bbdb9 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -92,7 +92,6 @@ static PROPERTIES: &[&str] = &[ "Case_Ignorable", "Grapheme_Extend", "White_Space", - "Cc", "N", ]; |
