Skip to content

Commit 9b81660

Browse files
committed
Auto merge of #9834 - ehuss:fix-build-std-proc-macro-only, r=alexcrichton
Fix panic with build-std of a proc-macro. If you try to run `cargo build -Zbuild-std` in a proc-macro project, cargo would panic in [`check_collisions`](https://github.com/rust-lang/cargo/blob/835d5576e1f0b917a42ba18a9556242204377cd1/src/cargo/core/compiler/context/mod.rs#L427). This is because it iterates over every Unit in the build graph checking the `outputs` for filenames. However, [`outputs`](https://github.com/rust-lang/cargo/blob/835d5576e1f0b917a42ba18a9556242204377cd1/src/cargo/core/compiler/context/compilation_files.rs#L109-L110) was missing the outputs for standard library units. That is because `outputs` is computed by walking the graph starting from the roots. The bug here is that `attach_std_deps` was adding the standard library units to graph, even though they aren't reachable from the roots, thus creating orphans. The solution is to avoid adding the standard library units if they are not needed (as is the case when building just a proc-macro). Fixes #9828
2 parents f066c50 + 00e925f commit 9b81660

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ fn attach_std_deps(
142142
std_unit_deps: UnitGraph,
143143
) {
144144
// Attach the standard library as a dependency of every target unit.
145+
let mut found = false;
145146
for (unit, deps) in state.unit_dependencies.iter_mut() {
146147
if !unit.kind.is_host() && !unit.mode.is_run_custom_build() {
147148
deps.extend(std_roots[&unit.kind].iter().map(|unit| UnitDep {
@@ -152,12 +153,16 @@ fn attach_std_deps(
152153
public: true,
153154
noprelude: true,
154155
}));
156+
found = true;
155157
}
156158
}
157-
// And also include the dependencies of the standard library itself.
158-
for (unit, deps) in std_unit_deps.into_iter() {
159-
if let Some(other_unit) = state.unit_dependencies.insert(unit, deps) {
160-
panic!("std unit collision with existing unit: {:?}", other_unit);
159+
// And also include the dependencies of the standard library itself. Don't
160+
// include these if no units actually needed the standard library.
161+
if found {
162+
for (unit, deps) in std_unit_deps.into_iter() {
163+
if let Some(other_unit) = state.unit_dependencies.insert(unit, deps) {
164+
panic!("std unit collision with existing unit: {:?}", other_unit);
165+
}
161166
}
162167
}
163168
}

tests/testsuite/standard_lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,3 +662,31 @@ fn no_roots() {
662662
.with_stderr_contains("[FINISHED] [..]")
663663
.run();
664664
}
665+
666+
#[cargo_test]
667+
fn proc_macro_only() {
668+
// Checks for a bug where it would panic if building a proc-macro only
669+
let setup = match setup() {
670+
Some(s) => s,
671+
None => return,
672+
};
673+
let p = project()
674+
.file(
675+
"Cargo.toml",
676+
r#"
677+
[package]
678+
name = "pm"
679+
version = "0.1.0"
680+
681+
[lib]
682+
proc-macro = true
683+
"#,
684+
)
685+
.file("src/lib.rs", "")
686+
.build();
687+
p.cargo("build")
688+
.build_std(&setup)
689+
.target_host()
690+
.with_stderr_contains("[FINISHED] [..]")
691+
.run();
692+
}

0 commit comments

Comments
 (0)