From 8c2155f3497d58113c540412578e3ef8fad531a0 Mon Sep 17 00:00:00 2001 From: Justus Adam Date: Mon, 31 Jul 2023 14:02:08 -0700 Subject: [PATCH 1/3] Pass a hash of the modification date for cache control --- crates/rustc_plugin/src/cli.rs | 25 ++++++++++++++++++++++++- crates/rustc_plugin/src/driver.rs | 10 ++++++++++ crates/rustc_plugin/src/lib.rs | 2 ++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/crates/rustc_plugin/src/cli.rs b/crates/rustc_plugin/src/cli.rs index 62758ee8d..b0633e6ea 100644 --- a/crates/rustc_plugin/src/cli.rs +++ b/crates/rustc_plugin/src/cli.rs @@ -37,12 +37,35 @@ pub fn cli_main(plugin: T) { .expect("current executable path invalid") .with_file_name(plugin.driver_name().as_ref()); + let exec_hash = { + use std::hash::{Hash, Hasher}; + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + path + .metadata() + .unwrap() + .modified() + .unwrap() + .hash(&mut hasher); + std::env::current_exe() + .unwrap() + .metadata() + .unwrap() + .modified() + .unwrap() + .hash(&mut hasher); + hasher.finish() + }; + if cfg!(windows) { path.set_extension("exe"); } cmd - .env("RUSTC_WORKSPACE_WRAPPER", path) + .env("RUSTC_WRAPPER", path) + .env( + "CARGO_ENCODED_RUSTFLAGS", + format!("{}\x1f{exec_hash:x}", crate::EXEC_HASH_ARG), + ) .args(["check", "-vv", "--target-dir"]) .arg(&target_dir); diff --git a/crates/rustc_plugin/src/driver.rs b/crates/rustc_plugin/src/driver.rs index 929704004..1d03d0567 100644 --- a/crates/rustc_plugin/src/driver.rs +++ b/crates/rustc_plugin/src/driver.rs @@ -104,6 +104,16 @@ pub fn driver_main(plugin: T) { exit(rustc_driver::catch_with_exit_code(move || { let mut orig_args: Vec = env::args().collect(); + let hash_check_arg = orig_args + .iter() + .enumerate() + .find(|elem| elem.1 == crate::EXEC_HASH_ARG) + .map(|t| t.0) + .unwrap(); + + orig_args.remove(hash_check_arg); + orig_args.remove(hash_check_arg); + let (have_sys_root_arg, sys_root) = get_sysroot(&orig_args); if orig_args.iter().any(|a| a == "--version" || a == "-V") { diff --git a/crates/rustc_plugin/src/lib.rs b/crates/rustc_plugin/src/lib.rs index 8870cfc7c..fa97cb04e 100644 --- a/crates/rustc_plugin/src/lib.rs +++ b/crates/rustc_plugin/src/lib.rs @@ -8,6 +8,8 @@ extern crate rustc_driver; extern crate rustc_interface; +const EXEC_HASH_ARG: &str = "--exec-hash"; + #[doc(hidden)] pub use cargo_metadata::camino::Utf8Path; pub use cli::cli_main; From 9bbb36abd592a18bca4e80bcb4fbdb602489fea1 Mon Sep 17 00:00:00 2001 From: Justus Adam Date: Wed, 13 Sep 2023 10:52:58 -0700 Subject: [PATCH 2/3] Make sure rustflags set prior are propagated --- crates/rustc_plugin/src/cli.rs | 68 ++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/crates/rustc_plugin/src/cli.rs b/crates/rustc_plugin/src/cli.rs index b0633e6ea..d9ac5c471 100644 --- a/crates/rustc_plugin/src/cli.rs +++ b/crates/rustc_plugin/src/cli.rs @@ -12,6 +12,26 @@ use crate::CrateFilter; pub const RUN_ON_ALL_CRATES: &str = "RUSTC_PLUGIN_ALL_TARGETS"; pub const SPECIFIC_CRATE: &str = "SPECIFIC_CRATE"; pub const SPECIFIC_TARGET: &str = "SPECIFIC_TARGET"; +pub const CARGO_ENCODED_RUSTFLAGS: &str = "CARGO_ENCODED_RUSTFLAGS"; + +fn prior_rustflags() -> Result, std::env::VarError> { + use std::env::{var, VarError}; + var(CARGO_ENCODED_RUSTFLAGS) + .map(|flags| flags.split('\x1f').map(str::to_string).collect()) + .or_else(|err| { + if matches!(err, VarError::NotPresent) { + var("RUSTFLAGS") + .map(|flags| flags.split_whitespace().map(str::to_string).collect()) + } else { + Err(err) + } + }) + .or_else(|err| { + matches!(err, VarError::NotPresent) + .then(Vec::new) + .ok_or(err) + }) +} /// The top-level function that should be called in your user-facing binary. pub fn cli_main(plugin: T) { @@ -60,12 +80,13 @@ pub fn cli_main(plugin: T) { path.set_extension("exe"); } + let mut prior_rustflags = prior_rustflags().unwrap(); + + prior_rustflags.push(format!("{}\x1f{exec_hash:x}", crate::EXEC_HASH_ARG)); + cmd .env("RUSTC_WRAPPER", path) - .env( - "CARGO_ENCODED_RUSTFLAGS", - format!("{}\x1f{exec_hash:x}", crate::EXEC_HASH_ARG), - ) + .env(CARGO_ENCODED_RUSTFLAGS, prior_rustflags.join("\x1f")) .args(["check", "-vv", "--target-dir"]) .arg(&target_dir); @@ -214,3 +235,42 @@ fn only_run_on_file( target.name ); } + +#[cfg(test)] +mod tests { + use std::ffi::OsStr; + + use crate::cli::{prior_rustflags, CARGO_ENCODED_RUSTFLAGS}; + + fn with_var, V: AsRef, R>( + k: K, + v: V, + f: impl FnOnce() -> R, + ) -> R { + let k_ref = k.as_ref(); + std::env::set_var(k_ref, v); + let result = f(); + // XXX does not restore any old values (because I'm lazy) + std::env::remove_var(k_ref); + result + } + + #[test] + fn rustflags_test() { + with_var("RUSTFLAGS", "space double_space tab end", || { + assert_eq!( + prior_rustflags(), + Ok(vec![ + "space".to_string(), + "double_space".to_string(), + "tab".to_string(), + "end".to_string() + ]), + "whitespace works" + ); + with_var(CARGO_ENCODED_RUSTFLAGS, "override", || { + assert_eq!(prior_rustflags(), Ok(vec!["override".to_string()])) + }) + }); + } +} From a6983425b9be1dbcc8fb9a501483710c614ceb1e Mon Sep 17 00:00:00 2001 From: Justus Adam Date: Wed, 4 Oct 2023 08:25:05 -0700 Subject: [PATCH 3/3] WIP test case --- crates/rustc_plugin/tests/test_example.rs | 41 ++++++++++++++++--- crates/rustc_utils/src/mir/places_conflict.rs | 2 +- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/crates/rustc_plugin/tests/test_example.rs b/crates/rustc_plugin/tests/test_example.rs index 861fae8ca..83aea8b86 100644 --- a/crates/rustc_plugin/tests/test_example.rs +++ b/crates/rustc_plugin/tests/test_example.rs @@ -1,10 +1,30 @@ -use std::{env, fs, path::Path, process::Command, sync::Once}; +use std::{ + env, fs, + path::Path, + process::{Command, Output}, + sync::Once, +}; use anyhow::{ensure, Context, Result}; static SETUP: Once = Once::new(); fn run(dir: &str, f: impl FnOnce(&mut Command)) -> Result<()> { + let output = run_configures(dir, true, f)?; + + ensure!( + output.status.success(), + "Process exited with non-zero exit code" + ); + + Ok(()) +} + +fn run_configures( + dir: &str, + remove_target: bool, + f: impl FnOnce(&mut Command), +) -> Result { let root = env::temp_dir().join("rustc_plugin"); let heredir = Path::new(".").canonicalize()?; @@ -42,12 +62,11 @@ fn run(dir: &str, f: impl FnOnce(&mut Command)) -> Result<()> { f(&mut cmd); - let _ = fs::remove_dir_all(ws.join("target")); - - let status = cmd.status().context("Process failed")?; - ensure!(status.success(), "Process exited with non-zero exit code"); + if remove_target { + let _ = fs::remove_dir_all(ws.join("target")); + } - Ok(()) + cmd.output().context("Process failed") } #[test] @@ -66,3 +85,13 @@ fn basic_with_arg() -> Result<()> { fn multi() -> Result<()> { run("workspaces/multi", |_cmd| {}) } + +#[test] +fn caching() -> Result<()> { + let workspace = "workspaces/basic"; + let first_run = run_configures(workspace, false, |_| {})?; + + let second_run = run_configures(workspace, true, |_| {})?; + ensure!(first_run == second_run); + Ok(()) +} diff --git a/crates/rustc_utils/src/mir/places_conflict.rs b/crates/rustc_utils/src/mir/places_conflict.rs index 3d79a9fac..898b66207 100644 --- a/crates/rustc_utils/src/mir/places_conflict.rs +++ b/crates/rustc_utils/src/mir/places_conflict.rs @@ -152,7 +152,7 @@ fn place_components_conflict<'tcx>( // are disjoint // // Our invariant is, that at each step of the iteration: - // - If we didn't run out of access to match, our borrow and access are comparable + // - If we didn't run out of access to match, our borrow and access are comparalegal_flow // and either equal or disjoint. // - If we did run out of access, the borrow can access a part of it.