Skip to content

Commit 30c967d

Browse files
authored
Rollup merge of rust-lang#145408 - Kobzol:deduplicate-search-paths, r=petrochenkov
Deduplicate -L search paths For each -L passed to the compiler, we eagerly scan the whole directory. If it has a lot of files, that results in a lot of allocations. So it's needless to do this if some -L paths are actually duplicated (which can happen e.g. in the situation in the linked issue). This PR both deduplicates the args, and also teaches rustdoc not to pass duplicated args to merged doctests. Fixes: rust-lang#145375
2 parents 0734cbd + fd5b737 commit 30c967d

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

compiler/rustc_session/src/config.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2847,16 +2847,27 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
28472847
// This is the location used by the `rustc-dev` `rustup` component.
28482848
real_source_base_dir("lib/rustlib/rustc-src/rust", "compiler/rustc/src/main.rs");
28492849

2850-
let mut search_paths = vec![];
2851-
for s in &matches.opt_strs("L") {
2852-
search_paths.push(SearchPath::from_cli_opt(
2853-
sysroot.path(),
2854-
&target_triple,
2855-
early_dcx,
2856-
s,
2857-
unstable_opts.unstable_options,
2858-
));
2859-
}
2850+
// We eagerly scan all files in each passed -L path. If the same directory is passed multiple
2851+
// times, and the directory contains a lot of files, this can take a lot of time.
2852+
// So we remove -L paths that were passed multiple times, and keep only the first occurrence.
2853+
// We still have to keep the original order of the -L arguments.
2854+
let search_paths: Vec<SearchPath> = {
2855+
let mut seen_search_paths = FxHashSet::default();
2856+
let search_path_matches: Vec<String> = matches.opt_strs("L");
2857+
search_path_matches
2858+
.iter()
2859+
.filter(|p| seen_search_paths.insert(*p))
2860+
.map(|path| {
2861+
SearchPath::from_cli_opt(
2862+
sysroot.path(),
2863+
&target_triple,
2864+
early_dcx,
2865+
&path,
2866+
unstable_opts.unstable_options,
2867+
)
2868+
})
2869+
.collect()
2870+
};
28602871

28612872
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
28622873
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));

src/librustdoc/doctest.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{fmt, panic, str};
1616

1717
pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder};
1818
pub(crate) use markdown::test as test_markdown;
19-
use rustc_data_structures::fx::{FxHashMap, FxHasher, FxIndexMap, FxIndexSet};
19+
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxHasher, FxIndexMap, FxIndexSet};
2020
use rustc_errors::emitter::HumanReadableErrorType;
2121
use rustc_errors::{ColorConfig, DiagCtxtHandle};
2222
use rustc_hir as hir;
@@ -689,6 +689,10 @@ fn run_test(
689689
"--extern=doctest_bundle_{edition}=",
690690
edition = doctest.edition
691691
));
692+
693+
// Deduplicate passed -L directory paths, since usually all dependencies will be in the
694+
// same directory (e.g. target/debug/deps from Cargo).
695+
let mut seen_search_dirs = FxHashSet::default();
692696
for extern_str in &rustdoc_options.extern_strs {
693697
if let Some((_cratename, path)) = extern_str.split_once('=') {
694698
// Direct dependencies of the tests themselves are
@@ -698,7 +702,9 @@ fn run_test(
698702
.parent()
699703
.filter(|x| x.components().count() > 0)
700704
.unwrap_or(Path::new("."));
701-
runner_compiler.arg("-L").arg(dir);
705+
if seen_search_dirs.insert(dir) {
706+
runner_compiler.arg("-L").arg(dir);
707+
}
702708
}
703709
}
704710
let output_bundle_file = doctest

0 commit comments

Comments
 (0)