diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bootstrap/src/core/build_steps/test.rs | 30 | ||||
| -rw-r--r-- | src/bootstrap/src/core/config/config.rs | 13 | ||||
| -rw-r--r-- | src/bootstrap/src/core/config/toml/build.rs | 1 | ||||
| -rw-r--r-- | src/bootstrap/src/utils/change_tracker.rs | 5 | ||||
| -rw-r--r-- | src/ci/docker/host-x86_64/pr-check-1/Dockerfile | 1 | ||||
| -rw-r--r-- | src/ci/docker/host-x86_64/pr-check-2/Dockerfile | 3 | ||||
| -rw-r--r-- | src/doc/rustdoc/src/unstable-features.md | 6 | ||||
| -rw-r--r-- | src/librustdoc/doctest.rs | 84 | ||||
| -rw-r--r-- | src/librustdoc/doctest/runner.rs | 11 | ||||
| -rw-r--r-- | src/librustdoc/formats/cache.rs | 30 | ||||
| -rw-r--r-- | src/tools/opt-dist/src/tests.rs | 2 |
11 files changed, 151 insertions, 35 deletions
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 0f9268097d7..951ca73fcc4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -8,6 +8,9 @@ use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; use std::{env, fs, iter}; +#[cfg(feature = "tracing")] +use tracing::instrument; + use crate::core::build_steps::compile::{Std, run_cargo}; use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; @@ -30,7 +33,7 @@ use crate::utils::helpers::{ linker_flags, t, target_supports_cranelift_backend, up_to_date, }; use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests}; -use crate::{CLang, DocTests, GitRepo, Mode, PathSet, envify}; +use crate::{CLang, DocTests, GitRepo, Mode, PathSet, debug, envify}; const ADB_TEST_DIR: &str = "/data/local/tmp/work"; @@ -713,9 +716,23 @@ impl Step for CompiletestTest { } /// Runs `cargo test` for compiletest. + #[cfg_attr( + feature = "tracing", + instrument(level = "debug", name = "CompiletestTest::run", skip_all) + )] fn run(self, builder: &Builder<'_>) { let host = self.host; + + if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 { + eprintln!("\ +ERROR: `--stage 0` runs compiletest self-tests against the stage0 (precompiled) compiler, not the in-tree compiler, and will almost always cause tests to fail +NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`." + ); + crate::exit!(1); + } + let compiler = builder.compiler(builder.top_stage, host); + debug!(?compiler); // We need `ToolStd` for the locally-built sysroot because // compiletest uses unstable features of the `test` crate. @@ -723,8 +740,8 @@ impl Step for CompiletestTest { let mut cargo = tool::prepare_tool_cargo( builder, compiler, - // compiletest uses libtest internals; make it use the in-tree std to make sure it never breaks - // when std sources change. + // compiletest uses libtest internals; make it use the in-tree std to make sure it never + // breaks when std sources change. Mode::ToolStd, host, Kind::Test, @@ -1612,12 +1629,11 @@ impl Step for Compiletest { return; } - if builder.top_stage == 0 && env::var("COMPILETEST_FORCE_STAGE0").is_err() { + if builder.top_stage == 0 && !builder.config.compiletest_allow_stage0 { eprintln!("\ ERROR: `--stage 0` runs compiletest on the stage0 (precompiled) compiler, not your local changes, and will almost always cause tests to fail -HELP: to test the compiler, use `--stage 1` instead -HELP: to test the standard library, use `--stage 0 library/std` instead -NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `COMPILETEST_FORCE_STAGE0=1`." +HELP: to test the compiler or standard library, omit the stage or explicitly use `--stage 1` instead +NOTE: if you're sure you want to do this, please open an issue as to why. In the meantime, you can override this with `--set build.compiletest-allow-stage0=true`." ); crate::exit!(1); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 9644ade00b3..78abdd7f9b8 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -298,8 +298,16 @@ pub struct Config { /// Command for visual diff display, e.g. `diff-tool --color=always`. pub compiletest_diff_tool: Option<String>, + /// Whether to allow running both `compiletest` self-tests and `compiletest`-managed test suites + /// against the stage 0 (rustc, std). + /// + /// This is only intended to be used when the stage 0 compiler is actually built from in-tree + /// sources. + pub compiletest_allow_stage0: bool, + /// Whether to use the precompiled stage0 libtest with compiletest. pub compiletest_use_stage0_libtest: bool, + /// Default value for `--extra-checks` pub tidy_extra_checks: Option<String>, pub is_running_on_ci: bool, @@ -749,6 +757,7 @@ impl Config { optimized_compiler_builtins, jobs, compiletest_diff_tool, + compiletest_allow_stage0, compiletest_use_stage0_libtest, tidy_extra_checks, ccache, @@ -1020,8 +1029,12 @@ impl Config { config.optimized_compiler_builtins = optimized_compiler_builtins.unwrap_or(config.channel != "dev"); + config.compiletest_diff_tool = compiletest_diff_tool; + + config.compiletest_allow_stage0 = compiletest_allow_stage0.unwrap_or(false); config.compiletest_use_stage0_libtest = compiletest_use_stage0_libtest.unwrap_or(true); + config.tidy_extra_checks = tidy_extra_checks; let download_rustc = config.download_rustc_commit.is_some(); diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs index 4d29691f38b..728367b3972 100644 --- a/src/bootstrap/src/core/config/toml/build.rs +++ b/src/bootstrap/src/core/config/toml/build.rs @@ -68,6 +68,7 @@ define_config! { optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins", jobs: Option<u32> = "jobs", compiletest_diff_tool: Option<String> = "compiletest-diff-tool", + compiletest_allow_stage0: Option<bool> = "compiletest-allow-stage0", compiletest_use_stage0_libtest: Option<bool> = "compiletest-use-stage0-libtest", tidy_extra_checks: Option<String> = "tidy-extra-checks", ccache: Option<StringOrBool> = "ccache", diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 4b0c4821364..d3331b81587 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -486,4 +486,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "Removed `rust.description` and `llvm.ccache` as it was deprecated in #137723 and #136941 long time ago.", }, + ChangeInfo { + change_id: 144675, + severity: ChangeSeverity::Warning, + summary: "Added `build.compiletest-allow-stage0` flag instead of `COMPILETEST_FORCE_STAGE0` env var, and reject running `compiletest` self tests against stage 0 rustc unless explicitly allowed.", + }, ]; diff --git a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile index f7d51fba861..04ac0f33daf 100644 --- a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile @@ -43,7 +43,6 @@ ENV SCRIPT \ python3 ../x.py check bootstrap && \ /scripts/check-default-config-profiles.sh && \ python3 ../x.py build src/tools/build-manifest && \ - python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py check compiletest --set build.compiletest-use-stage0-libtest=true && \ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python3 ../x.py check --set build.optimized-compiler-builtins=false core alloc std --target=aarch64-unknown-linux-gnu,i686-pc-windows-msvc,i686-unknown-linux-gnu,x86_64-apple-darwin,x86_64-pc-windows-gnu,x86_64-pc-windows-msvc && \ diff --git a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile index ce18a181d31..f82e19bcbb4 100644 --- a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile @@ -30,6 +30,7 @@ ENV SCRIPT \ python3 ../x.py check && \ python3 ../x.py clippy ci && \ python3 ../x.py test --stage 1 core alloc std test proc_macro && \ + python3 ../x.py test --stage 1 src/tools/compiletest && \ python3 ../x.py doc --stage 0 bootstrap && \ # Build both public and internal documentation. RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \ @@ -37,6 +38,6 @@ ENV SCRIPT \ mkdir -p /checkout/obj/staging/doc && \ cp -r build/x86_64-unknown-linux-gnu/doc /checkout/obj/staging && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 1 library/test && \ - # The BOOTSTRAP_TRACING flag is added to verify whether the + # The BOOTSTRAP_TRACING flag is added to verify whether the # bootstrap process compiles successfully with this flag enabled. BOOTSTRAP_TRACING=1 python3 ../x.py --help diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 27910ad0ab7..7bd2970eee7 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -395,6 +395,12 @@ flags to control that behavior. When the `--extern-html-root-url` flag is given one of your dependencies, rustdoc use that URL for those docs. Keep in mind that if those docs exist in the output directory, those local docs will still override this flag. +The names in this flag are first matched against the names given in the `--extern name=` flags, +which allows selecting between multiple crates with the same name (e.g. multiple versions of +the same crate). For transitive dependencies that haven't been loaded via an `--extern` flag, matching +falls backs to using crate names only, without ability to distinguish between multiple crates with +the same name. + ## `-Z force-unstable-if-unmarked` Using this flag looks like this: diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a32c2f7fb18..0bef091468f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -11,7 +11,8 @@ use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; -use std::{panic, str}; +use std::time::{Duration, Instant}; +use std::{fmt, panic, str}; pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder}; pub(crate) use markdown::test as test_markdown; @@ -36,6 +37,50 @@ use crate::config::{Options as RustdocOptions, OutputFormat}; use crate::html::markdown::{ErrorCodes, Ignore, LangString, MdRelLine}; use crate::lint::init_lints; +/// Type used to display times (compilation and total) information for merged doctests. +struct MergedDoctestTimes { + total_time: Instant, + /// Total time spent compiling all merged doctests. + compilation_time: Duration, + /// This field is used to keep track of how many merged doctests we (tried to) compile. + added_compilation_times: usize, +} + +impl MergedDoctestTimes { + fn new() -> Self { + Self { + total_time: Instant::now(), + compilation_time: Duration::default(), + added_compilation_times: 0, + } + } + + fn add_compilation_time(&mut self, duration: Duration) { + self.compilation_time += duration; + self.added_compilation_times += 1; + } + + fn display_times(&self) { + // If no merged doctest was compiled, then there is nothing to display since the numbers + // displayed by `libtest` for standalone tests are already accurate (they include both + // compilation and runtime). + if self.added_compilation_times > 0 { + println!("{self}"); + } + } +} + +impl fmt::Display for MergedDoctestTimes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "all doctests ran in {:.2}s; merged doctests compilation took {:.2}s", + self.total_time.elapsed().as_secs_f64(), + self.compilation_time.as_secs_f64(), + ) + } +} + /// Options that apply to all doctests in a crate or Markdown file (for `rustdoc foo.md`). #[derive(Clone)] pub(crate) struct GlobalTestOptions { @@ -295,6 +340,7 @@ pub(crate) fn run_tests( let mut nb_errors = 0; let mut ran_edition_tests = 0; + let mut times = MergedDoctestTimes::new(); let target_str = rustdoc_options.target.to_string(); for (MergeableTestKey { edition, global_crate_attrs_hash }, mut doctests) in mergeable_tests { @@ -314,13 +360,15 @@ pub(crate) fn run_tests( for (doctest, scraped_test) in &doctests { tests_runner.add_test(doctest, scraped_test, &target_str); } - if let Ok(success) = tests_runner.run_merged_tests( + let (duration, ret) = tests_runner.run_merged_tests( rustdoc_test_options, edition, &opts, &test_args, rustdoc_options, - ) { + ); + times.add_compilation_time(duration); + if let Ok(success) = ret { ran_edition_tests += 1; if !success { nb_errors += 1; @@ -354,11 +402,13 @@ pub(crate) fn run_tests( test::test_main_with_exit_callback(&test_args, standalone_tests, None, || { // We ensure temp dir destructor is called. std::mem::drop(temp_dir.take()); + times.display_times(); }); } if nb_errors != 0 { // We ensure temp dir destructor is called. std::mem::drop(temp_dir); + times.display_times(); // libtest::ERROR_EXIT_CODE is not public but it's the same value. std::process::exit(101); } @@ -496,16 +546,19 @@ impl RunnableDocTest { /// /// This is the function that calculates the compiler command line, invokes the compiler, then /// invokes the test or tests in a separate executable (if applicable). +/// +/// Returns a tuple containing the `Duration` of the compilation and the `Result` of the test. fn run_test( doctest: RunnableDocTest, rustdoc_options: &RustdocOptions, supports_color: bool, report_unused_externs: impl Fn(UnusedExterns), -) -> Result<(), TestFailure> { +) -> (Duration, Result<(), TestFailure>) { let langstr = &doctest.langstr; // Make sure we emit well-formed executable names for our target. let rust_out = add_exe_suffix("rust_out".to_owned(), &rustdoc_options.target); let output_file = doctest.test_opts.outdir.path().join(rust_out); + let instant = Instant::now(); // Common arguments used for compiling the doctest runner. // On merged doctests, the compiler is invoked twice: once for the test code itself, @@ -589,7 +642,7 @@ fn run_test( if std::fs::write(&input_file, &doctest.full_test_code).is_err() { // If we cannot write this file for any reason, we leave. All combined tests will be // tested as standalone tests. - return Err(TestFailure::CompileError); + return (Duration::default(), Err(TestFailure::CompileError)); } if !rustdoc_options.nocapture { // If `nocapture` is disabled, then we don't display rustc's output when compiling @@ -660,7 +713,7 @@ fn run_test( if std::fs::write(&runner_input_file, merged_test_code).is_err() { // If we cannot write this file for any reason, we leave. All combined tests will be // tested as standalone tests. - return Err(TestFailure::CompileError); + return (instant.elapsed(), Err(TestFailure::CompileError)); } if !rustdoc_options.nocapture { // If `nocapture` is disabled, then we don't display rustc's output when compiling @@ -713,7 +766,7 @@ fn run_test( let _bomb = Bomb(&out); match (output.status.success(), langstr.compile_fail) { (true, true) => { - return Err(TestFailure::UnexpectedCompilePass); + return (instant.elapsed(), Err(TestFailure::UnexpectedCompilePass)); } (true, false) => {} (false, true) => { @@ -729,17 +782,18 @@ fn run_test( .collect(); if !missing_codes.is_empty() { - return Err(TestFailure::MissingErrorCodes(missing_codes)); + return (instant.elapsed(), Err(TestFailure::MissingErrorCodes(missing_codes))); } } } (false, false) => { - return Err(TestFailure::CompileError); + return (instant.elapsed(), Err(TestFailure::CompileError)); } } + let duration = instant.elapsed(); if doctest.no_run { - return Ok(()); + return (duration, Ok(())); } // Run the code! @@ -771,17 +825,17 @@ fn run_test( cmd.output() }; match result { - Err(e) => return Err(TestFailure::ExecutionError(e)), + Err(e) => return (duration, Err(TestFailure::ExecutionError(e))), Ok(out) => { if langstr.should_panic && out.status.success() { - return Err(TestFailure::UnexpectedRunPass); + return (duration, Err(TestFailure::UnexpectedRunPass)); } else if !langstr.should_panic && !out.status.success() { - return Err(TestFailure::ExecutionFailure(out)); + return (duration, Err(TestFailure::ExecutionFailure(out))); } } } - Ok(()) + (duration, Ok(())) } /// Converts a path intended to use as a command to absolute if it is @@ -1071,7 +1125,7 @@ fn doctest_run_fn( no_run: scraped_test.no_run(&rustdoc_options), merged_test_code: None, }; - let res = + let (_, res) = run_test(runnable_test, &rustdoc_options, doctest.supports_color, report_unused_externs); if let Err(err) = res { diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index f0914474c79..fcfa424968e 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -1,4 +1,5 @@ use std::fmt::Write; +use std::time::Duration; use rustc_data_structures::fx::FxIndexSet; use rustc_span::edition::Edition; @@ -67,6 +68,10 @@ impl DocTestRunner { self.nb_tests += 1; } + /// Returns a tuple containing the `Duration` of the compilation and the `Result` of the test. + /// + /// If compilation failed, it will return `Err`, otherwise it will return `Ok` containing if + /// the test ran successfully. pub(crate) fn run_merged_tests( &mut self, test_options: IndividualTestOptions, @@ -74,7 +79,7 @@ impl DocTestRunner { opts: &GlobalTestOptions, test_args: &[String], rustdoc_options: &RustdocOptions, - ) -> Result<bool, ()> { + ) -> (Duration, Result<bool, ()>) { let mut code = "\ #![allow(unused_extern_crates)] #![allow(internal_features)] @@ -204,9 +209,9 @@ std::process::Termination::report(test::test_main(test_args, tests, None)) no_run: false, merged_test_code: Some(code), }; - let ret = + let (duration, ret) = run_test(runnable_test, rustdoc_options, self.supports_color, |_: UnusedExterns| {}); - if let Err(TestFailure::CompileError) = ret { Err(()) } else { Ok(ret.is_ok()) } + (duration, if let Err(TestFailure::CompileError) = ret { Err(()) } else { Ok(ret.is_ok()) }) } } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 5191120ebdb..e28cc3a542e 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -4,6 +4,7 @@ use rustc_ast::join_path_syms; use rustc_attr_data_structures::StabilityLevel; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet}; +use rustc_metadata::creader::CStore; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; use tracing::debug; @@ -158,18 +159,33 @@ impl Cache { assert!(cx.external_traits.is_empty()); cx.cache.traits = mem::take(&mut krate.external_traits); + let render_options = &cx.render_options; + let extern_url_takes_precedence = render_options.extern_html_root_takes_precedence; + let dst = &render_options.output; + + // Make `--extern-html-root-url` support the same names as `--extern` whenever possible + let cstore = CStore::from_tcx(tcx); + for (name, extern_url) in &render_options.extern_html_root_urls { + if let Some(crate_num) = cstore.resolved_extern_crate(Symbol::intern(name)) { + let e = ExternalCrate { crate_num }; + let location = e.location(Some(extern_url), extern_url_takes_precedence, dst, tcx); + cx.cache.extern_locations.insert(e.crate_num, location); + } + } + // Cache where all our extern crates are located - // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code + // This is also used in the JSON output. for &crate_num in tcx.crates(()) { let e = ExternalCrate { crate_num }; let name = e.name(tcx); - let render_options = &cx.render_options; - let extern_url = render_options.extern_html_root_urls.get(name.as_str()).map(|u| &**u); - let extern_url_takes_precedence = render_options.extern_html_root_takes_precedence; - let dst = &render_options.output; - let location = e.location(extern_url, extern_url_takes_precedence, dst, tcx); - cx.cache.extern_locations.insert(e.crate_num, location); + cx.cache.extern_locations.entry(e.crate_num).or_insert_with(|| { + // falls back to matching by crates' own names, because + // transitive dependencies and injected crates may be loaded without `--extern` + let extern_url = + render_options.extern_html_root_urls.get(name.as_str()).map(|u| &**u); + e.location(extern_url, extern_url_takes_precedence, dst, tcx) + }); cx.cache.external_paths.insert(e.def_id(), (vec![name], ItemType::Module)); } diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index c9a21fc6fb2..d5121b8c786 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -79,6 +79,7 @@ lld = false rustc = "{rustc}" cargo = "{cargo}" local-rebuild = true +compiletest-allow-stage0=true [target.{host_triple}] llvm-config = "{llvm_config}" @@ -117,7 +118,6 @@ llvm-config = "{llvm_config}" args.extend(["--skip", test_path]); } cmd(&args) - .env("COMPILETEST_FORCE_STAGE0", "1") // Also run dist-only tests .env("COMPILETEST_ENABLE_DIST_TESTS", "1") .run() |
