Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement 'multidep' (RFC-3176) #10061

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/cargo/core/compiler/context/compilation_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ struct MetaInfo {
///
/// If this is `true`, the `meta_hash` is used for the filename.
use_extra_filename: bool,

/// This flag is set by collision detection and forces the use of a more unique hash
/// instead of the stable one.
output_conflicts_without_meta_hash: bool,
}

/// Collection of information about the files emitted by the compiler, and the
Expand Down Expand Up @@ -220,7 +224,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
fn pkg_dir(&self, unit: &Unit) -> String {
let name = unit.pkg.package_id().name();
let meta = &self.metas[unit];
if meta.use_extra_filename {
if meta.use_extra_filename || meta.output_conflicts_without_meta_hash {
format!("{}-{}", name, meta.meta_hash)
} else {
format!("{}-{}", name, self.target_short_hash(unit))
Expand Down Expand Up @@ -370,6 +374,12 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
.map(Arc::clone)
}

pub(super) fn set_non_colliding_outputs(&mut self, unit: &Unit, outputs: Arc<Vec<OutputFile>>) {
let cell = LazyCell::new();
cell.fill(outputs).unwrap();
self.outputs.insert(unit.clone(), cell);
}

/// Returns the path where the output for the given unit and FileType
/// should be uplifted to.
///
Expand Down Expand Up @@ -421,7 +431,7 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
Some(uplift_path)
}

fn calc_outputs(
pub(super) fn calc_outputs(
&self,
unit: &Unit,
bcx: &BuildContext<'a, 'cfg>,
Expand Down Expand Up @@ -625,6 +635,7 @@ fn compute_metadata(
MetaInfo {
meta_hash: Metadata(hasher.finish()),
use_extra_filename: should_use_metadata(bcx, unit),
output_conflicts_without_meta_hash: false,
}
}

Expand Down
34 changes: 31 additions & 3 deletions src/cargo/core/compiler/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
self.prepare_units()?;
self.prepare()?;
custom_build::build_map(&mut self)?;
self.check_collisions()?;
self.check_collisions_and_avoid_some()?;
self.compute_metadata_for_doc_units();

// We need to make sure that if there were any previous docs
Expand Down Expand Up @@ -421,7 +421,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
}
}

fn check_collisions(&self) -> CargoResult<()> {
fn check_collisions_and_avoid_some(&mut self) -> CargoResult<()> {
let mut output_collisions = HashMap::new();
let describe_collision = |unit: &Unit, other_unit: &Unit, path: &PathBuf| -> String {
format!(
Expand Down Expand Up @@ -528,17 +528,36 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
doc_collision_error(unit, prev)?;
}
}
let mut alt_outputs = None;
let mut collisions_prevented = 0;
for output in self.outputs(unit)?.iter() {
if let Some(other_unit) = output_collisions.insert(output.path.clone(), unit) {
if unit.mode.is_doc() {
// See https://github.com/rust-lang/rust/issues/56169
// and https://github.com/rust-lang/rust/issues/61378
report_collision(unit, other_unit, &output.path, rustdoc_suggestion)?;
} else {
report_collision(unit, other_unit, &output.path, suggestion)?;
let files = self.files.as_mut().unwrap();
if !files.use_extra_filename(unit)
&& !alt_outputs
.get_or_insert_with(|| {
files
.calc_outputs(unit, &self.bcx)
.expect("infallible by now")
})
.iter()
.any(|out| out.path == output.path)
{
collisions_prevented += 1;
continue;
} else {
report_collision(unit, other_unit, &output.path, suggestion)?;
}
}
}
if let Some(hardlink) = output.hardlink.as_ref() {
// We don't check for collision prevention on unix as typically these only happen on MSVC platforms
// which doesn't use hardlinks. If this changes, one would do another collision here.
if let Some(other_unit) = output_collisions.insert(hardlink.clone(), unit) {
report_collision(unit, other_unit, hardlink, suggestion)?;
}
Expand All @@ -556,6 +575,15 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
}
}
}

if collisions_prevented != 0 {
if let Some(alt_outputs) = alt_outputs {
self.files
.as_mut()
.unwrap()
.set_non_colliding_outputs(unit, alt_outputs);
}
}
}
Ok(())
}
Expand Down
Loading