use std::collections::BTreeSet;
use std::path::Path;
use crate::build_script::freshness::BuildScriptFreshness;
use crate::compiler::observation::{CompilationObservationManifest, CompilationTargetKind, ObservationPath};
const SUPERSEDED_NATIVE_BYPASSES: [&str; 5] = [
"build_script_result_unavailable",
"build_script_action_key_unavailable",
"build_script_dependency_graph_incomplete",
"proc_macro_filesystem_observations_unavailable",
"native_link_sdk_inputs_unavailable",
];
pub(crate) struct CompilerInputProof<'a> {
observations: &'a [CompilationObservationManifest],
build_scripts: &'a [BuildScriptFreshness],
}
impl<'a> CompilerInputProof<'a> {
pub(crate) fn new(
observations: &'a [CompilationObservationManifest],
build_scripts: &'a [BuildScriptFreshness],
) -> Self {
Self {
observations,
build_scripts,
}
}
pub(crate) fn revalidation_reason(&self, source_root: &Path, workspace_root: &Path) -> Option<String> {
if self.observations.is_empty() {
return Some("compilation_observations_absent".to_string());
}
if let Some(reason) = self
.observations
.iter()
.filter(|manifest| manifest.unit.target_kind != CompilationTargetKind::BuildScript)
.flat_map(|manifest| manifest.bypasses.iter().map(String::as_str))
.find(|reason| !SUPERSEDED_NATIVE_BYPASSES.contains(reason))
{
return Some(reason.to_string());
}
let generated_root = ObservationPath::capture(
&crate::workspace::cargo_rail_state_root(workspace_root).join("compiler-artifacts-v1"),
source_root,
source_root,
);
let script_environment = self
.build_scripts
.iter()
.flat_map(BuildScriptFreshness::rustc_environment)
.collect::<BTreeSet<_>>();
if let Some(reason) = self.observations.iter().find_map(|manifest| {
manifest.input_revalidation_reason(source_root, Some(&generated_root), &script_environment)
}) {
return Some(reason.to_string());
}
self.build_scripts
.iter()
.find_map(|script| script.revalidation_reason(source_root))
.map(str::to_string)
}
}