Skip to content

Commit b9b39a6

Browse files
committed
Pass metadata flag to rustdoc, ensure that Doc and Check units have same metadata hash
1 parent 0b2e293 commit b9b39a6

File tree

4 files changed

+69
-12
lines changed

4 files changed

+69
-12
lines changed

src/cargo/core/compiler/context/compilation_files.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,17 @@ fn compute_metadata(
540540
// `panic=abort` and `panic=unwind` artifacts, additionally with various
541541
// settings like debuginfo and whatnot.
542542
unit.profile.hash(&mut hasher);
543-
unit.mode.hash(&mut hasher);
543+
544+
// For RFC #3123, we need the metadata of a Check and Doc unit of the same crate
545+
// to be the same. So we add a special case that ensures Doc and Check are hashed
546+
// to the same value.
547+
match unit.mode {
548+
CompileMode::Doc { .. } | CompileMode::Check { .. } => {
549+
(CompileMode::Check { test: false }).hash(&mut hasher)
550+
}
551+
mode => mode.hash(&mut hasher),
552+
};
553+
544554
cx.lto[unit].hash(&mut hasher);
545555

546556
// Artifacts compiled for the host should have a different metadata

src/cargo/core/compiler/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,10 @@ fn rustdoc(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Work> {
640640
rustdoc.arg("--cfg").arg(&format!("feature=\"{}\"", feat));
641641
}
642642

643+
// This is needed so StableCrateId can be computed correctly.
644+
let meta = cx.files().metadata(unit);
645+
rustdoc.arg("-C").arg(&format!("metadata={}", meta));
646+
643647
add_error_format_and_color(cx, &mut rustdoc, false);
644648
add_allow_features(cx, &mut rustdoc);
645649

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -419,10 +419,17 @@ fn compute_deps_doc(
419419
state: &mut State<'_, '_>,
420420
unit_for: UnitFor,
421421
) -> CargoResult<Vec<UnitDep>> {
422-
let deps = state.deps(unit, unit_for, &|dep| match dep.kind() {
423-
DepKind::Normal | DepKind::Development => true,
424-
DepKind::Build => false,
425-
});
422+
// FIXME(wcrichto): target.is_lib() is probably not the correct way to check
423+
// if the unit needs dev-dependencies
424+
let deps = state.deps(
425+
unit,
426+
unit_for,
427+
&|dep| match (unit.target.is_lib(), dep.kind()) {
428+
(_, DepKind::Normal) => true,
429+
(false, DepKind::Development) => true,
430+
_ => false,
431+
},
432+
);
426433

427434
// To document a library, we depend on dependencies actually being
428435
// built. If we're documenting *all* libraries, then we also depend on

src/cargo/ops/cargo_compile.rs

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ pub fn create_bcx<'a, 'cfg>(
540540
if build_config.mode == (CompileMode::Doc { deps: true }) {
541541
remove_duplicate_doc(build_config, &units, &mut unit_graph);
542542
}
543+
lift_doc_units_to_root(&mut units, &mut unit_graph);
543544

544545
if build_config
545546
.requested_kinds
@@ -624,14 +625,28 @@ pub fn create_bcx<'a, 'cfg>(
624625

625626
// Add --scrape-examples to each build unit's rustdoc args
626627
for (path, unit) in paths.iter().zip(bcx.roots.iter()) {
627-
bcx.extra_compiler_args
628+
let args = bcx
629+
.extra_compiler_args
628630
.entry(unit.clone())
629-
.or_insert_with(Vec::new)
630-
.extend_from_slice(&[
631-
"-Zunstable-options".into(),
632-
"--scrape-examples".into(),
633-
path.clone().into_os_string(),
634-
]);
631+
.or_insert_with(Vec::new);
632+
633+
args.extend_from_slice(&[
634+
"-Zunstable-options".into(),
635+
"--scrape-examples-output-path".into(),
636+
path.clone().into_os_string(),
637+
]);
638+
639+
let crate_names = units
640+
.iter()
641+
.map(|unit| {
642+
vec![
643+
"--scrape-examples-target-crate".into(),
644+
OsString::from(unit.pkg.name().as_str()),
645+
]
646+
.into_iter()
647+
})
648+
.flatten();
649+
args.extend(crate_names);
635650
}
636651

637652
// Invoke recursive Cargo
@@ -1680,6 +1695,27 @@ fn opt_patterns_and_names(
16801695
Ok((opt_patterns, opt_names))
16811696
}
16821697

1698+
/// Removes all CompileMode::Doc units from the unit graph and lifts them to the root set.
1699+
///
1700+
/// This is sound because rustdoc has no actual dependency on the generated files from one
1701+
/// invocation to the next.
1702+
///
1703+
/// This is necessary because for RFC #3123, we need Doc and Check units of the same crate
1704+
/// to have the same metadata hash. This pass ensures that they have the same dependency set.
1705+
/// Also it exposes more parallelism during document generation!
1706+
fn lift_doc_units_to_root(root_units: &mut Vec<Unit>, unit_graph: &mut UnitGraph) {
1707+
for deps in unit_graph.values_mut() {
1708+
deps.retain(|dep| {
1709+
if dep.unit.mode.is_doc() {
1710+
root_units.push(dep.unit.clone());
1711+
false
1712+
} else {
1713+
true
1714+
}
1715+
});
1716+
}
1717+
}
1718+
16831719
/// Removes duplicate CompileMode::Doc units that would cause problems with
16841720
/// filename collisions.
16851721
///

0 commit comments

Comments
 (0)