Skip to content

Commit 5ebb605

Browse files
committed
Fix panic with doc collision orphan.
1 parent 34170fc commit 5ebb605

File tree

2 files changed

+69
-11
lines changed

2 files changed

+69
-11
lines changed

src/cargo/ops/cargo_compile.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ pub fn create_bcx<'a, 'cfg>(
507507
// TODO: In theory, Cargo should also dedupe the roots, but I'm uncertain
508508
// what heuristics to use in that case.
509509
if build_config.mode == (CompileMode::Doc { deps: true }) {
510-
remove_duplicate_doc(build_config, &mut unit_graph);
510+
remove_duplicate_doc(build_config, &units, &mut unit_graph);
511511
}
512512

513513
if build_config
@@ -1508,14 +1508,11 @@ fn opt_patterns_and_names(
15081508
/// - Different sources. See `collision_doc_sources` test.
15091509
///
15101510
/// Ideally this would not be necessary.
1511-
fn remove_duplicate_doc(build_config: &BuildConfig, unit_graph: &mut UnitGraph) {
1512-
// NOTE: There is some risk that this can introduce problems because it
1513-
// may create orphans in the unit graph (parts of the tree get detached
1514-
// from the roots). I currently can't think of any ways this will cause a
1515-
// problem because all other parts of Cargo traverse the graph starting
1516-
// from the roots. Perhaps this should scan for detached units and remove
1517-
// them too?
1518-
//
1511+
fn remove_duplicate_doc(
1512+
build_config: &BuildConfig,
1513+
root_units: &[Unit],
1514+
unit_graph: &mut UnitGraph,
1515+
) {
15191516
// First, create a mapping of crate_name -> Unit so we can see where the
15201517
// duplicates are.
15211518
let mut all_docs: HashMap<String, Vec<Unit>> = HashMap::new();
@@ -1601,4 +1598,18 @@ fn remove_duplicate_doc(build_config: &BuildConfig, unit_graph: &mut UnitGraph)
16011598
for unit_deps in unit_graph.values_mut() {
16021599
unit_deps.retain(|unit_dep| !removed_units.contains(&unit_dep.unit));
16031600
}
1601+
// Remove any orphan units that were detached from the graph.
1602+
let mut visited = HashSet::new();
1603+
fn visit(unit: &Unit, graph: &UnitGraph, visited: &mut HashSet<Unit>) {
1604+
if !visited.insert(unit.clone()) {
1605+
return;
1606+
}
1607+
for dep in &graph[unit] {
1608+
visit(&dep.unit, graph, visited);
1609+
}
1610+
}
1611+
for unit in root_units {
1612+
visit(unit, unit_graph, &mut visited);
1613+
}
1614+
unit_graph.retain(|unit, _| visited.contains(unit));
16041615
}

tests/testsuite/collisions.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
//! Ideally these should never happen, but I don't think we'll ever be able to
44
//! prevent all collisions.
55
6-
use cargo_test_support::basic_manifest;
7-
use cargo_test_support::project;
86
use cargo_test_support::registry::Package;
7+
use cargo_test_support::{basic_manifest, cross_compile, project};
98
use std::env;
109

1110
#[cargo_test]
@@ -431,3 +430,51 @@ the same path; see <https://github.com/rust-lang/cargo/issues/6313>.
431430
)
432431
.run();
433432
}
433+
434+
#[cargo_test]
435+
fn collision_doc_target() {
436+
// collision in doc with --target, doesn't fail due to orphans
437+
if cross_compile::disabled() {
438+
return;
439+
}
440+
441+
Package::new("orphaned", "1.0.0").publish();
442+
Package::new("bar", "1.0.0")
443+
.dep("orphaned", "1.0")
444+
.publish();
445+
Package::new("bar", "2.0.0").publish();
446+
let p = project()
447+
.file(
448+
"Cargo.toml",
449+
r#"
450+
[package]
451+
name = "foo"
452+
version = "0.1.0"
453+
454+
[dependencies]
455+
bar2 = { version = "2.0", package="bar" }
456+
bar = "1.0"
457+
"#,
458+
)
459+
.file("src/lib.rs", "")
460+
.build();
461+
462+
p.cargo("doc --target")
463+
.arg(cross_compile::alternate())
464+
.with_stderr_unordered(
465+
"\
466+
[UPDATING] [..]
467+
[DOWNLOADING] crates ...
468+
[DOWNLOADED] orphaned v1.0.0 [..]
469+
[DOWNLOADED] bar v2.0.0 [..]
470+
[DOWNLOADED] bar v1.0.0 [..]
471+
[CHECKING] orphaned v1.0.0
472+
[DOCUMENTING] bar v2.0.0
473+
[CHECKING] bar v2.0.0
474+
[CHECKING] bar v1.0.0
475+
[DOCUMENTING] foo v0.1.0 [..]
476+
[FINISHED] [..]
477+
",
478+
)
479+
.run();
480+
}

0 commit comments

Comments
 (0)