diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-03-10 15:57:15 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-10 15:57:15 +0100 |
| commit | d1a875cd37ea27346e43d3091dabd84258113150 (patch) | |
| tree | 4e246d1ce367dafb04df5a074fc63cceddea927a | |
| parent | 0d6311931b3aa04460aa2c73aaf012242e5715e6 (diff) | |
| parent | 295c70ef03d442c608d0dda0c14c06598c034411 (diff) | |
| download | rust-d1a875cd37ea27346e43d3091dabd84258113150.tar.gz rust-d1a875cd37ea27346e43d3091dabd84258113150.zip | |
Rollup merge of #138281 - saethlin:mergeable-doctests-stacksize, r=GuillaumeGomez
Fix O(tests) stack usage in edition 2024 mergeable doctests Fixes https://github.com/rust-lang/rust/issues/138248 The important change here is that we are not passing a potentially-large array by value. Between the fact that `TestFn` cannot be `Clone` and `test_main` takes a `Vec<TestDescAndFn>`, the only way to call `test::test_main` without O(tests) stack use is to call `Vec::push` many times. The normal test harness does not have this problem because it calls `test_main_static` or `test_main_static_abort`, which take `&[TestDescAndFn]`. Changing `test::test_main` to take a slice is not a simple change, so I'm avoiding doing it here.
| -rw-r--r-- | src/librustdoc/doctest/runner.rs | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/src/librustdoc/doctest/runner.rs b/src/librustdoc/doctest/runner.rs index 58efa35711a..f891505d2a6 100644 --- a/src/librustdoc/doctest/runner.rs +++ b/src/librustdoc/doctest/runner.rs @@ -47,11 +47,8 @@ impl DocTestRunner { self.crate_attrs.insert(line.to_string()); } } - if !self.ids.is_empty() { - self.ids.push(','); - } self.ids.push_str(&format!( - "{}::TEST", + "tests.push({}::TEST);\n", generate_mergeable_doctest( doctest, scraped_test, @@ -142,7 +139,11 @@ mod __doctest_mod {{ #[rustc_main] fn main() -> std::process::ExitCode {{ -const TESTS: [test::TestDescAndFn; {nb_tests}] = [{ids}]; +let tests = {{ + let mut tests = Vec::with_capacity({nb_tests}); + {ids} + tests +}}; let test_marker = std::ffi::OsStr::new(__doctest_mod::RUN_OPTION); let test_args = &[{test_args}]; const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\"; @@ -150,11 +151,11 @@ const ENV_BIN: &'static str = \"RUSTDOC_DOCTEST_BIN_PATH\"; if let Ok(binary) = std::env::var(ENV_BIN) {{ let _ = crate::__doctest_mod::BINARY_PATH.set(binary.into()); unsafe {{ std::env::remove_var(ENV_BIN); }} - return std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)); + return std::process::Termination::report(test::test_main(test_args, tests, None)); }} else if let Ok(nb_test) = std::env::var(__doctest_mod::RUN_OPTION) {{ if let Ok(nb_test) = nb_test.parse::<usize>() {{ - if let Some(test) = TESTS.get(nb_test) {{ - if let test::StaticTestFn(f) = test.testfn {{ + if let Some(test) = tests.get(nb_test) {{ + if let test::StaticTestFn(f) = &test.testfn {{ return std::process::Termination::report(f()); }} }} @@ -164,7 +165,7 @@ if let Ok(binary) = std::env::var(ENV_BIN) {{ eprintln!(\"WARNING: No rustdoc doctest environment variable provided so doctests will be run in \ the same process\"); -std::process::Termination::report(test::test_main(test_args, Vec::from(TESTS), None)) +std::process::Termination::report(test::test_main(test_args, tests, None)) }}", nb_tests = self.nb_tests, output = self.output_merged_tests, |
