Skip to content

Commit 88e0192

Browse files
Prepend temp files with a string per invocation of rustc
1 parent 6f1e3c5 commit 88e0192

File tree

8 files changed

+90
-3
lines changed

8 files changed

+90
-3
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3896,6 +3896,7 @@ dependencies = [
38963896
name = "rustc_interface"
38973897
version = "0.0.0"
38983898
dependencies = [
3899+
"rand 0.9.0",
38993900
"rustc-rayon",
39003901
"rustc-rayon-core",
39013902
"rustc_abi",

compiler/rustc_driver_impl/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ fn print_crate_info(
670670
// no crate attributes, print out an error and exit
671671
return Compilation::Continue;
672672
};
673-
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
673+
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess, None);
674674
let crate_name = passes::get_crate_name(sess, attrs);
675675
let crate_types = collect_crate_types(sess, attrs);
676676
for &style in &crate_types {

compiler/rustc_interface/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
# tidy-alphabetical-start
8+
rand = "0.9.0"
89
rustc-rayon = { version = "0.5.0" }
910
rustc-rayon-core = { version = "0.5.0" }
1011
rustc_ast = { path = "../rustc_ast" }

compiler/rustc_interface/src/passes.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use std::path::{Path, PathBuf};
55
use std::sync::{Arc, LazyLock, OnceLock};
66
use std::{env, fs, iter};
77

8+
use rand::{RngCore, rng};
89
use rustc_ast as ast;
910
use rustc_codegen_ssa::traits::CodegenBackend;
11+
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
1012
use rustc_data_structures::parallel;
1113
use rustc_data_structures::steal::Steal;
1214
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, WorkerLocal};
@@ -800,7 +802,13 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
800802
sess.opts.cg.metadata.clone(),
801803
sess.cfg_version,
802804
);
803-
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
805+
806+
let invocation_temp = sess
807+
.opts
808+
.incremental
809+
.as_ref()
810+
.map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string());
811+
let outputs = util::build_output_filenames(&pre_configured_attrs, sess, invocation_temp);
804812

805813
let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() };
806814
let dep_graph = setup_dep_graph(sess, crate_name, &dep_type);

compiler/rustc_interface/src/util.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,11 @@ fn multiple_output_types_to_stdout(
486486
}
487487
}
488488

489-
pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> OutputFilenames {
489+
pub fn build_output_filenames(
490+
attrs: &[ast::Attribute],
491+
sess: &Session,
492+
invocation_temp: Option<String>,
493+
) -> OutputFilenames {
490494
if multiple_output_types_to_stdout(
491495
&sess.opts.output_types,
492496
sess.io.output_file == Some(OutFileName::Stdout),
@@ -515,6 +519,7 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
515519
crate_name.unwrap_or_else(|| stem.replace('-', "_")),
516520
stem,
517521
None,
522+
invocation_temp,
518523
sess.io.temps_dir.clone(),
519524
sess.opts.cg.extra_filename.clone(),
520525
sess.opts.output_types.clone(),
@@ -544,6 +549,7 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
544549
crate_name.unwrap_or_else(|| out_filestem.replace('-', "_")),
545550
out_filestem,
546551
ofile,
552+
invocation_temp,
547553
sess.io.temps_dir.clone(),
548554
sess.opts.cg.extra_filename.clone(),
549555
sess.opts.output_types.clone(),

compiler/rustc_session/src/config.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,13 @@ pub struct OutputFilenames {
10421042
crate_stem: String,
10431043
/// Typically based on `.rs` input file name. Any '-' is preserved.
10441044
filestem: String,
1045+
/// A random string generated per invocation of rustc.
1046+
///
1047+
/// This is prepended to all temporary files so that they do not collide
1048+
/// during concurrent invocations of rustc, or past invocations that were
1049+
/// preserved with a flag like `-C save-temps`, since these files may be
1050+
/// hard-linked.
1051+
invocation_temp: Option<String>,
10451052
pub single_output_file: Option<OutFileName>,
10461053
temps_directory: Option<PathBuf>,
10471054
pub outputs: OutputTypes,
@@ -1057,13 +1064,15 @@ impl OutputFilenames {
10571064
out_crate_name: String,
10581065
out_filestem: String,
10591066
single_output_file: Option<OutFileName>,
1067+
invocation_temp: Option<String>,
10601068
temps_directory: Option<PathBuf>,
10611069
extra: String,
10621070
outputs: OutputTypes,
10631071
) -> Self {
10641072
OutputFilenames {
10651073
out_directory,
10661074
single_output_file,
1075+
invocation_temp,
10671076
temps_directory,
10681077
outputs,
10691078
crate_stem: format!("{out_crate_name}{extra}"),
@@ -1109,6 +1118,12 @@ impl OutputFilenames {
11091118
pub fn temp_path_ext_for_cgu(&self, ext: &str, codegen_unit_name: &str) -> PathBuf {
11101119
let mut extension = codegen_unit_name.to_string();
11111120

1121+
// Append `.{invocation_temp}` to ensure temporary files are unique.
1122+
if let Some(rng) = &self.invocation_temp {
1123+
extension.push('.');
1124+
extension.push_str(rng);
1125+
}
1126+
11121127
// FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty.
11131128
// Append `.rcgu.{ext}`.
11141129
if !ext.is_empty() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//@ only-x86_64-unknown-linux-gnu
2+
3+
use run_make_support::{run, rustc};
4+
5+
fn main() {
6+
let mk_rustc = || {
7+
let mut rustc = rustc();
8+
rustc.input("test.rs").incremental("incr").arg("-Csave-temps").output("test");
9+
rustc
10+
};
11+
12+
// Revision 1
13+
mk_rustc().cfg("rpass1").run();
14+
15+
run("test");
16+
17+
// Revision 2
18+
mk_rustc().cfg("cfail2").run_fail();
19+
// Expected to fail.
20+
21+
// Revision 3
22+
mk_rustc().cfg("rpass3").run();
23+
24+
run("test");
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#[inline(never)]
2+
#[cfg(any(rpass1, rpass3))]
3+
fn a() -> i32 {
4+
0
5+
}
6+
7+
#[cfg(any(cfail2))]
8+
fn a() -> i32 {
9+
1
10+
}
11+
12+
fn main() {
13+
evil::evil();
14+
assert_eq!(a(), 0);
15+
}
16+
17+
mod evil {
18+
#[cfg(any(rpass1, rpass3))]
19+
pub fn evil() {
20+
unsafe {
21+
std::arch::asm!("/* */");
22+
}
23+
}
24+
25+
#[cfg(any(cfail2))]
26+
pub fn evil() {
27+
unsafe {
28+
std::arch::asm!("missing");
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)