Auto merge of #10549 - willcrichton:fix-issue-10535, r=ehuss

Ensure host units don't depend on Docscrape units, fixes #10545

### What does this PR try to resolve?

This PR fixes issue #10545. The root cause was:
* Cargo workspace contains a host-type crate (e.g. a proc macro).
* `unit_dependencies` attempts to add `Docscrape` units as dependencies of the host-type crate.
* `activated_features` attempts to lookup `(dep, Host)` in the feature map, but only `(dep, NotHost)` exists.

The fix is to ensure that host-type crates do not have Docscrape units added as dependencies.

### How should we test and review this PR?

The added test `scrape_examples_issue_10545` provides a minimal example that fails before this fix, and succeeds after.
This commit is contained in:
bors 2022-04-09 18:30:09 +00:00
commit 5f400f098b
4 changed files with 65 additions and 3 deletions

View file

@ -682,7 +682,7 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
rustdoc.arg("--scrape-examples-target-crate").arg(name);
}
}
} else if cx.bcx.scrape_units.len() > 0 && cx.bcx.ws.is_member(&unit.pkg) {
} else if cx.bcx.scrape_units.len() > 0 && cx.bcx.ws.unit_needs_doc_scrape(unit) {
// We only pass scraped examples to packages in the workspace
// since examples are only coming from reverse-dependencies of workspace packages

View file

@ -708,8 +708,8 @@ fn compute_deps_doc(
}
}
// Add all units being scraped for examples as a dependency of Doc units.
if state.ws.is_member(&unit.pkg) {
// Add all units being scraped for examples as a dependency of top-level Doc units.
if state.ws.unit_needs_doc_scrape(unit) {
for scrape_unit in state.scrape_units.iter() {
deps_of(scrape_unit, state, unit_for)?;
ret.push(new_unit_dep(

View file

@ -11,6 +11,7 @@ use log::debug;
use toml_edit::easy as toml;
use url::Url;
use crate::core::compiler::Unit;
use crate::core::features::Features;
use crate::core::registry::PackageRegistry;
use crate::core::resolver::features::CliFeatures;
@ -1500,6 +1501,15 @@ impl<'cfg> Workspace<'cfg> {
ms
}
/// Returns true if `unit` should depend on the output of Docscrape units.
pub fn unit_needs_doc_scrape(&self, unit: &Unit) -> bool {
// We do not add scraped units for Host units, as they're either build scripts
// (not documented) or proc macros (have no scrape-able exports). Additionally,
// naively passing a proc macro's unit_for to new_unit_dep will currently cause
// Cargo to panic, see issue #10545.
self.is_member(&unit.pkg) && !unit.target.for_host()
}
}
impl<'cfg> Packages<'cfg> {

View file

@ -2593,6 +2593,58 @@ fn scrape_examples_configure_profile() {
assert!(doc_html.contains("More examples"));
}
#[cargo_test]
fn scrape_examples_issue_10545() {
if !is_nightly() {
// -Z rustdoc-scrape-examples is unstable
return;
}
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
resolver = "2"
members = ["a", "b"]
"#,
)
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "0.0.1"
authors = []
edition = "2021"
[features]
default = ["foo"]
foo = []
"#,
)
.file("a/src/lib.rs", "")
.file(
"b/Cargo.toml",
r#"
[package]
name = "b"
version = "0.0.1"
authors = []
edition = "2021"
[lib]
proc-macro = true
"#,
)
.file("b/src/lib.rs", "")
.build();
p.cargo("doc -Zunstable-options -Z rustdoc-scrape-examples=all")
.masquerade_as_nightly_cargo()
.run();
}
#[cargo_test]
fn lib_before_bin() {
// Checks that the library is documented before the binary.