From c7e80be1779ad665435ed40cf910aa70a7f2fbdf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 17 Apr 2024 16:03:55 +0200 Subject: [PATCH] Improve handling of `--persist-doctests` with combined doctests and update associated test to check both combined and non-combined doctests --- src/librustdoc/doctest.rs | 29 ++++++++++++++----- .../run-make/doctests-keep-binaries/Makefile | 8 ++--- tests/run-make/doctests-keep-binaries/t.rs | 8 +++++ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a1d93e5a0ee6e..dd157cd8c59cd 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -318,6 +318,7 @@ enum TestFailure { UnexpectedRunPass, } +#[derive(Debug)] enum DirState { Temp(tempfile::TempDir), Perm(PathBuf), @@ -383,10 +384,26 @@ fn run_test( edition: Edition, report_unused_externs: impl Fn(UnusedExterns), no_run: bool, + // Used to prevent overwriting a binary in case `--persist-doctests` is used. + binary_extra: Option<&str>, ) -> Result<(), TestFailure> { // 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 = outdir.path().join(rust_out); + let rust_out = + add_exe_suffix(format!("rust_out{}", binary_extra.unwrap_or("")), &rustdoc_options.target); + let out_dir = outdir.path(); + let out_dir = if is_multiple_tests { + // If this a "multiple tests" case, we want to put it into the parent instead. + out_dir.parent().unwrap_or(out_dir) + } else { + out_dir + }; + if matches!(*outdir, DirState::Perm(..)) { + if let Err(err) = std::fs::create_dir_all(&out_dir) { + eprintln!("Couldn't create directory for doctest executables: {err}"); + panic::resume_unwind(Box::new(())); + } + } + let output_file = out_dir.join(rust_out); let rustc_binary = rustdoc_options .test_builder @@ -753,6 +770,7 @@ impl DocTest { edition, report_unused_externs, no_run, + None, ); if let Err(err) = res { @@ -897,11 +915,6 @@ pub(crate) fn make_test( let mut path = path.clone(); path.push(&test_id); - if let Err(err) = std::fs::create_dir_all(&path) { - eprintln!("Couldn't create directory for doctest executables: {err}"); - panic::resume_unwind(Box::new(())); - } - DirState::Perm(path) } else { DirState::Temp(get_doctest_dir().expect("rustdoc needs a tempdir")) @@ -1390,6 +1403,8 @@ test::test_main(&[{test_args}], vec![{ids}], None); self.edition, |_: UnusedExterns| {}, false, + // To prevent writing over an existing doctest + Some(&format!("_{}_{}", self.edition, *self.ran_edition_tests)), ); if let Err(TestFailure::CompileError) = ret { // We failed to compile all compatible tests as one so we push them into the diff --git a/tests/run-make/doctests-keep-binaries/Makefile b/tests/run-make/doctests-keep-binaries/Makefile index 2c647851ad0b7..e346ab7b79020 100644 --- a/tests/run-make/doctests-keep-binaries/Makefile +++ b/tests/run-make/doctests-keep-binaries/Makefile @@ -11,16 +11,16 @@ run: mkdir -p $(TMPDIR)/doctests $(RUSTC) --crate-type rlib t.rs $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs - $(TMPDIR)/doctests/t_rs_2_0/rust_out - $(TMPDIR)/doctests/t_rs_8_0/rust_out + $(TMPDIR)/doctests/t_rs_12_0/rust_out + $(TMPDIR)/doctests/rust_out_2015_0 rm -rf $(TMPDIR)/doctests no_run: mkdir -p $(TMPDIR)/doctests $(RUSTC) --crate-type rlib t.rs $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs --no-run - $(TMPDIR)/doctests/t_rs_2_0/rust_out - $(TMPDIR)/doctests/t_rs_8_0/rust_out + $(TMPDIR)/doctests/t_rs_12_0/rust_out + $(TMPDIR)/doctests/rust_out_2015_0 rm -rf $(TMPDIR)/doctests # Behavior with --test-run-directory with relative paths. diff --git a/tests/run-make/doctests-keep-binaries/t.rs b/tests/run-make/doctests-keep-binaries/t.rs index c38cf0a0b25d4..806f54764779d 100644 --- a/tests/run-make/doctests-keep-binaries/t.rs +++ b/tests/run-make/doctests-keep-binaries/t.rs @@ -8,4 +8,12 @@ pub fn foople() {} /// ``` /// t::florp(); /// ``` +/// +/// ``` +/// #![no_std] +/// +/// fn main() { +/// let x = 12; +/// } +/// ``` pub fn florp() {}