Skip to content

Commit 6eb0f92

Browse files
authored
Rollup merge of rust-lang#148199 - Zalathar:paths, r=jieyouxu
compiletest: Don't modify `testpaths` when creating aux contexts Modifying `TestCx::testpaths` makes it vastly harder to reason about how compiletest is using test paths, and can be avoided without much trouble by simply passing explicit source-file paths into a small number of auxiliary-aware methods. --- This PR was originally based on a much larger change that split `TestPaths` into multiple structs and multiple `TestCx` fields (as seen in early revisions of rust-lang#148160), but after further cleanups it turned out that very few tweaks were actually needed to avoid changes to `testpaths`. r? jieyouxu
2 parents 94f71d0 + 720bfff commit 6eb0f92

File tree

9 files changed

+75
-68
lines changed

9 files changed

+75
-68
lines changed

src/tools/compiletest/src/runtest.rs

Lines changed: 49 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use crate::common::{
1818
CompareMode, Config, Debugger, FailMode, PassMode, RunFailMode, RunResult, TestMode, TestPaths,
1919
TestSuite, UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG,
2020
UI_WINDOWS_SVG, expected_output_path, incremental_dir, output_base_dir, output_base_name,
21-
output_testname_unique,
2221
};
2322
use crate::directives::TestProps;
2423
use crate::errors::{Error, ErrorKind, load_errors};
@@ -563,7 +562,7 @@ impl<'test> TestCx<'test> {
563562
self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags);
564563
rustc.args(&self.props.compile_flags);
565564

566-
self.compose_and_run_compiler(rustc, Some(src), self.testpaths)
565+
self.compose_and_run_compiler(rustc, Some(src))
567566
}
568567

569568
fn maybe_add_external_args(&self, cmd: &mut Command, args: &Vec<String>) {
@@ -994,37 +993,41 @@ impl<'test> TestCx<'test> {
994993
passes,
995994
);
996995

997-
self.compose_and_run_compiler(rustc, None, self.testpaths)
996+
self.compose_and_run_compiler(rustc, None)
998997
}
999998

1000999
/// `root_out_dir` and `root_testpaths` refer to the parameters of the actual test being run.
10011000
/// Auxiliaries, no matter how deep, have the same root_out_dir and root_testpaths.
1002-
fn document(
1001+
fn document(&self, root_out_dir: &Utf8Path, kind: DocKind) -> ProcRes {
1002+
self.document_inner(&self.testpaths.file, root_out_dir, kind)
1003+
}
1004+
1005+
/// Like `document`, but takes an explicit `file_to_doc` argument so that
1006+
/// it can also be used for documenting auxiliaries, in addition to
1007+
/// documenting the main test file.
1008+
fn document_inner(
10031009
&self,
1010+
file_to_doc: &Utf8Path,
10041011
root_out_dir: &Utf8Path,
1005-
root_testpaths: &TestPaths,
10061012
kind: DocKind,
10071013
) -> ProcRes {
10081014
if self.props.build_aux_docs {
10091015
assert_eq!(kind, DocKind::Html, "build-aux-docs only make sense for html output");
10101016

10111017
for rel_ab in &self.props.aux.builds {
1012-
let aux_testpaths = self.compute_aux_test_paths(root_testpaths, rel_ab);
1013-
let props_for_aux =
1014-
self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
1018+
let aux_path = self.resolve_aux_path(rel_ab);
1019+
let props_for_aux = self.props.from_aux_file(&aux_path, self.revision, self.config);
10151020
let aux_cx = TestCx {
10161021
config: self.config,
10171022
stdout: self.stdout,
10181023
stderr: self.stderr,
10191024
props: &props_for_aux,
1020-
testpaths: &aux_testpaths,
1025+
testpaths: self.testpaths,
10211026
revision: self.revision,
10221027
};
10231028
// Create the directory for the stdout/stderr files.
10241029
create_dir_all(aux_cx.output_base_dir()).unwrap();
1025-
// use root_testpaths here, because aux-builds should have the
1026-
// same --out-dir and auxiliary directory.
1027-
let auxres = aux_cx.document(&root_out_dir, root_testpaths, kind);
1030+
let auxres = aux_cx.document_inner(&aux_path, &root_out_dir, kind);
10281031
if !auxres.status.success() {
10291032
return auxres;
10301033
}
@@ -1038,7 +1041,7 @@ impl<'test> TestCx<'test> {
10381041
// actual --out-dir given to the auxiliary or test, as opposed to the root out dir for the entire
10391042
// test
10401043
let out_dir: Cow<'_, Utf8Path> = if self.props.unique_doc_out_dir {
1041-
let file_name = self.testpaths.file.file_stem().expect("file name should not be empty");
1044+
let file_name = file_to_doc.file_stem().expect("file name should not be empty");
10421045
let out_dir = Utf8PathBuf::from_iter([
10431046
root_out_dir,
10441047
Utf8Path::new("docs"),
@@ -1052,7 +1055,7 @@ impl<'test> TestCx<'test> {
10521055
};
10531056

10541057
let mut rustdoc = Command::new(rustdoc_path);
1055-
let current_dir = output_base_dir(self.config, root_testpaths, self.safe_revision());
1058+
let current_dir = self.output_base_dir();
10561059
rustdoc.current_dir(current_dir);
10571060
rustdoc
10581061
.arg("-L")
@@ -1063,7 +1066,7 @@ impl<'test> TestCx<'test> {
10631066
.arg(out_dir.as_ref())
10641067
.arg("--deny")
10651068
.arg("warnings")
1066-
.arg(&self.testpaths.file)
1069+
.arg(file_to_doc)
10671070
.arg("-A")
10681071
.arg("internal_features")
10691072
.args(&self.props.compile_flags)
@@ -1080,7 +1083,7 @@ impl<'test> TestCx<'test> {
10801083
rustdoc.arg(format!("-Clinker={}", linker));
10811084
}
10821085

1083-
self.compose_and_run_compiler(rustdoc, None, root_testpaths)
1086+
self.compose_and_run_compiler(rustdoc, None)
10841087
}
10851088

10861089
fn exec_compiled_test(&self) -> ProcRes {
@@ -1195,24 +1198,21 @@ impl<'test> TestCx<'test> {
11951198

11961199
/// For each `aux-build: foo/bar` annotation, we check to find the file in an `auxiliary`
11971200
/// directory relative to the test itself (not any intermediate auxiliaries).
1198-
fn compute_aux_test_paths(&self, of: &TestPaths, rel_ab: &str) -> TestPaths {
1199-
let test_ab =
1200-
of.file.parent().expect("test file path has no parent").join("auxiliary").join(rel_ab);
1201-
if !test_ab.exists() {
1202-
self.fatal(&format!("aux-build `{}` source not found", test_ab))
1201+
fn resolve_aux_path(&self, relative_aux_path: &str) -> Utf8PathBuf {
1202+
let aux_path = self
1203+
.testpaths
1204+
.file
1205+
.parent()
1206+
.expect("test file path has no parent")
1207+
.join("auxiliary")
1208+
.join(relative_aux_path);
1209+
if !aux_path.exists() {
1210+
self.fatal(&format!(
1211+
"auxiliary source file `{relative_aux_path}` not found at `{aux_path}`"
1212+
));
12031213
}
12041214

1205-
TestPaths {
1206-
file: test_ab,
1207-
relative_dir: of
1208-
.relative_dir
1209-
.join(self.output_testname_unique())
1210-
.join("auxiliary")
1211-
.join(rel_ab)
1212-
.parent()
1213-
.expect("aux-build path has no parent")
1214-
.to_path_buf(),
1215-
}
1215+
aux_path
12161216
}
12171217

12181218
fn is_vxworks_pure_static(&self) -> bool {
@@ -1258,13 +1258,13 @@ impl<'test> TestCx<'test> {
12581258
aux_dir
12591259
}
12601260

1261-
fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Utf8Path, rustc: &mut Command) {
1261+
fn build_all_auxiliary(&self, aux_dir: &Utf8Path, rustc: &mut Command) {
12621262
for rel_ab in &self.props.aux.builds {
1263-
self.build_auxiliary(of, rel_ab, &aux_dir, None);
1263+
self.build_auxiliary(rel_ab, &aux_dir, None);
12641264
}
12651265

12661266
for rel_ab in &self.props.aux.bins {
1267-
self.build_auxiliary(of, rel_ab, &aux_dir, Some(AuxType::Bin));
1267+
self.build_auxiliary(rel_ab, &aux_dir, Some(AuxType::Bin));
12681268
}
12691269

12701270
let path_to_crate_name = |path: &str| -> String {
@@ -1283,20 +1283,20 @@ impl<'test> TestCx<'test> {
12831283
};
12841284

12851285
for (aux_name, aux_path) in &self.props.aux.crates {
1286-
let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, None);
1286+
let aux_type = self.build_auxiliary(&aux_path, &aux_dir, None);
12871287
add_extern(rustc, aux_name, aux_path, aux_type);
12881288
}
12891289

12901290
for proc_macro in &self.props.aux.proc_macros {
1291-
self.build_auxiliary(of, proc_macro, &aux_dir, Some(AuxType::ProcMacro));
1291+
self.build_auxiliary(proc_macro, &aux_dir, Some(AuxType::ProcMacro));
12921292
let crate_name = path_to_crate_name(proc_macro);
12931293
add_extern(rustc, &crate_name, proc_macro, AuxType::ProcMacro);
12941294
}
12951295

12961296
// Build any `//@ aux-codegen-backend`, and pass the resulting library
12971297
// to `-Zcodegen-backend` when compiling the test file.
12981298
if let Some(aux_file) = &self.props.aux.codegen_backend {
1299-
let aux_type = self.build_auxiliary(of, aux_file, aux_dir, None);
1299+
let aux_type = self.build_auxiliary(aux_file, aux_dir, None);
13001300
if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) {
13011301
let lib_path = aux_dir.join(&lib_name);
13021302
rustc.arg(format!("-Zcodegen-backend={}", lib_path));
@@ -1306,20 +1306,15 @@ impl<'test> TestCx<'test> {
13061306

13071307
/// `root_testpaths` refers to the path of the original test. the auxiliary and the test with an
13081308
/// aux-build have the same `root_testpaths`.
1309-
fn compose_and_run_compiler(
1310-
&self,
1311-
mut rustc: Command,
1312-
input: Option<String>,
1313-
root_testpaths: &TestPaths,
1314-
) -> ProcRes {
1309+
fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
13151310
if self.props.add_core_stubs {
13161311
let minicore_path = self.build_minicore();
13171312
rustc.arg("--extern");
13181313
rustc.arg(&format!("minicore={}", minicore_path));
13191314
}
13201315

13211316
let aux_dir = self.aux_output_dir();
1322-
self.build_all_auxiliary(root_testpaths, &aux_dir, &mut rustc);
1317+
self.build_all_auxiliary(&aux_dir, &mut rustc);
13231318

13241319
rustc.envs(self.props.rustc_env.clone());
13251320
self.props.unset_rustc_env.iter().fold(&mut rustc, Command::env_remove);
@@ -1364,14 +1359,12 @@ impl<'test> TestCx<'test> {
13641359
/// If `aux_type` is `None`, then this will determine the aux-type automatically.
13651360
fn build_auxiliary(
13661361
&self,
1367-
of: &TestPaths,
13681362
source_path: &str,
13691363
aux_dir: &Utf8Path,
13701364
aux_type: Option<AuxType>,
13711365
) -> AuxType {
1372-
let aux_testpaths = self.compute_aux_test_paths(of, source_path);
1373-
let mut aux_props =
1374-
self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config);
1366+
let aux_path = self.resolve_aux_path(source_path);
1367+
let mut aux_props = self.props.from_aux_file(&aux_path, self.revision, self.config);
13751368
if aux_type == Some(AuxType::ProcMacro) {
13761369
aux_props.force_host = true;
13771370
}
@@ -1388,21 +1381,20 @@ impl<'test> TestCx<'test> {
13881381
stdout: self.stdout,
13891382
stderr: self.stderr,
13901383
props: &aux_props,
1391-
testpaths: &aux_testpaths,
1384+
testpaths: self.testpaths,
13921385
revision: self.revision,
13931386
};
13941387
// Create the directory for the stdout/stderr files.
13951388
create_dir_all(aux_cx.output_base_dir()).unwrap();
1396-
let input_file = &aux_testpaths.file;
13971389
let mut aux_rustc = aux_cx.make_compile_args(
1398-
input_file,
1390+
&aux_path,
13991391
aux_output,
14001392
Emit::None,
14011393
AllowUnused::No,
14021394
LinkToAux::No,
14031395
Vec::new(),
14041396
);
1405-
aux_cx.build_all_auxiliary(of, &aux_dir, &mut aux_rustc);
1397+
aux_cx.build_all_auxiliary(&aux_dir, &mut aux_rustc);
14061398

14071399
aux_rustc.envs(aux_props.rustc_env.clone());
14081400
for key in &aux_props.unset_rustc_env {
@@ -1471,7 +1463,7 @@ impl<'test> TestCx<'test> {
14711463
);
14721464
if !auxres.status.success() {
14731465
self.fatal_proc_rec(
1474-
&format!("auxiliary build of {} failed to compile: ", aux_testpaths.file),
1466+
&format!("auxiliary build of {aux_path} failed to compile: "),
14751467
&auxres,
14761468
);
14771469
}
@@ -2033,11 +2025,6 @@ impl<'test> TestCx<'test> {
20332025
self.aux_output_dir_name().join("bin")
20342026
}
20352027

2036-
/// Generates a unique name for the test, such as `testname.revision.mode`.
2037-
fn output_testname_unique(&self) -> Utf8PathBuf {
2038-
output_testname_unique(self.config, self.testpaths, self.safe_revision())
2039-
}
2040-
20412028
/// The revision, ignored for incremental compilation since it wants all revisions in
20422029
/// the same directory.
20432030
fn safe_revision(&self) -> Option<&str> {
@@ -2132,7 +2119,7 @@ impl<'test> TestCx<'test> {
21322119
Vec::new(),
21332120
);
21342121

2135-
let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
2122+
let proc_res = self.compose_and_run_compiler(rustc, None);
21362123
(proc_res, output_path)
21372124
}
21382125

@@ -2210,9 +2197,9 @@ impl<'test> TestCx<'test> {
22102197
Vec::new(),
22112198
);
22122199
let aux_dir = new_rustdoc.aux_output_dir();
2213-
new_rustdoc.build_all_auxiliary(&new_rustdoc.testpaths, &aux_dir, &mut rustc);
2200+
new_rustdoc.build_all_auxiliary(&aux_dir, &mut rustc);
22142201

2215-
let proc_res = new_rustdoc.document(&compare_dir, &new_rustdoc.testpaths, DocKind::Html);
2202+
let proc_res = new_rustdoc.document(&compare_dir, DocKind::Html);
22162203
if !proc_res.status.success() {
22172204
writeln!(self.stderr, "failed to run nightly rustdoc");
22182205
return;

src/tools/compiletest/src/runtest/assembly.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl TestCx<'_> {
4343
Vec::new(),
4444
);
4545

46-
let proc_res = self.compose_and_run_compiler(rustc, None, self.testpaths);
46+
let proc_res = self.compose_and_run_compiler(rustc, None);
4747
(proc_res, output_path)
4848
}
4949
}

src/tools/compiletest/src/runtest/coverage.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl<'test> TestCx<'test> {
197197

198198
rustdoc_cmd.arg(&self.testpaths.file);
199199

200-
let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None, self.testpaths);
200+
let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None);
201201
if !proc_res.status.success() {
202202
self.fatal_proc_rec("rustdoc --test failed!", &proc_res)
203203
}

src/tools/compiletest/src/runtest/js_doc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ impl TestCx<'_> {
77
if let Some(nodejs) = &self.config.nodejs {
88
let out_dir = self.output_base_dir();
99

10-
self.document(&out_dir, &self.testpaths, DocKind::Html);
10+
self.document(&out_dir, DocKind::Html);
1111

1212
let file_stem = self.testpaths.file.file_stem().expect("no file stem");
1313
let res = self.run_command_to_procres(

src/tools/compiletest/src/runtest/rustdoc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ impl TestCx<'_> {
1111
panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
1212
});
1313

14-
let proc_res = self.document(&out_dir, &self.testpaths, DocKind::Html);
14+
let proc_res = self.document(&out_dir, DocKind::Html);
1515
if !proc_res.status.success() {
1616
self.fatal_proc_rec("rustdoc failed!", &proc_res);
1717
}

src/tools/compiletest/src/runtest/rustdoc_json.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ impl TestCx<'_> {
1313
panic!("failed to remove and recreate output directory `{out_dir}`: {e}")
1414
});
1515

16-
let proc_res = self.document(&out_dir, &self.testpaths, DocKind::Json);
16+
let proc_res = self.document(&out_dir, DocKind::Json);
1717
if !proc_res.status.success() {
1818
self.fatal_proc_rec("rustdoc failed!", &proc_res);
1919
}

src/tools/compiletest/src/runtest/ui.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ impl TestCx<'_> {
253253
rustc.arg(crate_name);
254254
}
255255

256-
let res = self.compose_and_run_compiler(rustc, None, self.testpaths);
256+
let res = self.compose_and_run_compiler(rustc, None);
257257
if !res.status.success() {
258258
self.fatal_proc_rec("failed to compile fixed code", &res);
259259
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ edition: 2024
2+
//@ aux-build: aux_with_props.rs
3+
//@ compile-flags: --check-cfg=cfg(this_is_aux)
4+
//@ run-pass
5+
6+
// Test that auxiliaries are built using the directives in the auxiliary file,
7+
// and don't just accidentally use the directives of the main test file.
8+
9+
extern crate aux_with_props;
10+
11+
fn main() {
12+
assert!(!cfg!(this_is_aux));
13+
assert!(aux_with_props::aux_directives_are_respected());
14+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@ edition: 2024
2+
//@ compile-flags: --cfg=this_is_aux
3+
4+
pub fn aux_directives_are_respected() -> bool {
5+
cfg!(this_is_aux)
6+
}

0 commit comments

Comments
 (0)