Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ pub(crate) struct RunnableDocTest<'a> {
/// In a standalone test this is just the regular test code.
full_test_code: String,
full_test_line_offset: usize,
test_opts: &'a IndividualTestOptions,
test_opts: IndividualTestOptions,
global_opts: &'a GlobalTestOptions,
langstr: LangString,
line: usize,
Expand Down Expand Up @@ -1143,8 +1143,6 @@ fn generate_test_desc_and_fn(
unused_externs: Arc<Mutex<Vec<UnusedExterns>>>,
) -> test::TestDescAndFn {
let target_str = rustdoc_options.target.to_string();
let rustdoc_test_options =
IndividualTestOptions::new(&rustdoc_options, &test.test_id, scraped_test.local_path());

debug!("creating test {}: {}", scraped_test.name, scraped_test.text);
test::TestDescAndFn {
Expand All @@ -1168,8 +1166,13 @@ fn generate_test_desc_and_fn(
test_type: test::TestType::DocTest,
},
testfn: test::DynTestFn(Arc::new(move || {
let rustdoc_test_options = IndividualTestOptions::new(
&rustdoc_options,
&test.test_id,
scraped_test.local_path(),
);
doctest_run_fn(
&rustdoc_test_options,
rustdoc_test_options,
&opts,
&test,
&scraped_test,
Expand All @@ -1181,7 +1184,7 @@ fn generate_test_desc_and_fn(
}

fn doctest_run_fn(
test_opts: &IndividualTestOptions,
test_opts: IndividualTestOptions,
global_opts: &GlobalTestOptions,
doctest: &DocTestBuilder,
scraped_test: &ScrapedDocTest,
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/doctest/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ test::test_main(test_args, tests)
let runnable_test = RunnableDocTest {
full_test_code: format!("{code_prefix}{code}", code = self.output),
full_test_line_offset: 0,
test_opts: &test_options,
test_opts: test_options,
global_opts: opts,
langstr: LangString::default(),
line: 0,
Expand Down
18 changes: 18 additions & 0 deletions tests/run-make/rustdoc-doctest-tempdir-cleanup/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// ```
/// assert!(true);
/// ```
pub fn a() {}

/// ```
/// let count = std::fs::read_dir(std::env::temp_dir())
/// .unwrap()
/// .filter(|entry| {
/// entry.as_ref().unwrap().file_name().to_str().unwrap().starts_with("rustdoctest")
/// })
/// .count();
/// // It's 2 and not one because rustdoc creates a temp dir where it puts the `rustdoc-cfgs`
/// // file which contains the list of flags to be passed down to the doctests. It lives
/// // until all doctests have been run.
/// assert_eq!(count, 2);

@RalfJung RalfJung Oct 12, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is 2 the right number here? Shouldn't it be 1 if the previous test got cleaned up?

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We create a first temp dir where we write the rustdoc-cfgs file which contains the list of all args to be passed to the doctests. But I'll write a code comment to explain it.

/// ```
pub fn b() {}
23 changes: 23 additions & 0 deletions tests/run-make/rustdoc-doctest-tempdir-cleanup/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// This test ensures that a temporary doctest directory is removed as soon as the doctest
// was run to prevent "No space left on device". To ensure it works, we use a file with two
// doctests, run without the "merged doctests" feature (hence the "2021" edition) with
// one thread to prevent potential concurrent cleanups.
// Regression test for <https://github.com/rust-lang/rust/issues/164145>.

//@ ignore-cross-compile
//@ only-linux

use run_make_support::{is_windows, path, rfs, rustdoc};

fn main() {
let tmp = path("tmp");
rfs::create_dir(&tmp);

let mut cmd = rustdoc()
.env("TMPDIR", &tmp)
.input("lib.rs")
.edition("2021")
.arg("--test")
.arg("--test-args=--test-threads=1")
.run();
}
2 changes: 2 additions & 0 deletions tests/rustdoc-ui/issues/issue-98690.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//@ compile-flags: --test --persist-doctests /../../ -Z unstable-options
//@ failure-status: 101
//@ only-linux
//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME"
//@ normalize-stdout: ".rs:\d+:\d+" -> ".rs:$$LINE:$$COL"

#![crate_name = "foo"]

Expand Down
1 change: 0 additions & 1 deletion tests/rustdoc-ui/issues/issue-98690.stderr

This file was deleted.

15 changes: 15 additions & 0 deletions tests/rustdoc-ui/issues/issue-98690.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

running 1 test

@GuillaumeGomez GuillaumeGomez Oct 12, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is because we used to try to make the temporary directly ahead of the DynTestFn closure when using --persist-doctest, so before the doctest was even running. But it actually doesn't make much sense to have a different behaviour so it's now moved inside the DynTestFn closure and has the same output as when --persist-doctest isn't used.

View changes since the review

test $DIR/issue-98690.rs - (line 9) ... FAILED

failures:

---- $DIR/issue-98690.rs - (line 9) stdout ----
Couldn't create directory for doctest executables: Permission denied (os error 13)


failures:
$DIR/issue-98690.rs - (line 9)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

Loading