Skip to content

Commit 9ccbd9a

Browse files
committed
fix(doc): respect public-dependency when documenting deps
1 parent 308c277 commit 9ccbd9a

2 files changed

Lines changed: 50 additions & 9 deletions

File tree

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ struct State<'a, 'gctx> {
6767
/// dependency from a to b was added purely because it was a dev-dependency.
6868
/// This is used during `connect_run_custom_build_deps`.
6969
dev_dependency_edges: HashSet<(Unit, Unit)>,
70+
71+
/// The set of packages explicitly selected by the user (e.g. via `-p`).
72+
/// Used to determine whether to apply the public-dependency doc filter:
73+
/// only root packages bypass the filter; their deps must be public to
74+
/// have their own docs generated.
75+
root_pkg_ids: HashSet<PackageId>,
7076
}
7177

7278
/// A boolean-like to indicate if a `Unit` is an artifact or not.
@@ -126,6 +132,7 @@ pub fn build_unit_dependencies<'a, 'gctx>(
126132
interner,
127133
scrape_units,
128134
dev_dependency_edges: HashSet::new(),
135+
root_pkg_ids: roots.iter().map(|u| u.pkg.package_id()).collect(),
129136
};
130137

131138
let std_unit_deps = calc_deps_of_std(&mut state, std_roots)?;
@@ -637,6 +644,21 @@ fn compute_deps_doc(
637644
// built. If we're documenting *all* libraries, then we also depend on
638645
// the documentation of the library being built.
639646
let mut ret = Vec::new();
647+
648+
// Check if public-dependency feature is enabled
649+
let public_deps_enabled = state.gctx.cli_unstable().public_dependency
650+
|| unit
651+
.pkg
652+
.manifest()
653+
.unstable_features()
654+
.is_enabled(Feature::public_dependency());
655+
656+
// Whether this package was explicitly selected by the user (e.g. via `-p`).
657+
// User-selected packages always have all their direct deps documented,
658+
// regardless of public/private status. For everything else, only public
659+
// deps get their own docs generated when public-dependency is enabled.
660+
let is_user_selected = state.root_pkg_ids.contains(&unit.pkg.package_id());
661+
640662
for (id, deps) in state.deps(unit, unit_for) {
641663
let Some(dep_lib) = calc_artifact_deps(unit, unit_for, id, &deps, state, &mut ret)? else {
642664
continue;
@@ -657,7 +679,20 @@ fn compute_deps_doc(
657679
IS_NO_ARTIFACT_DEP,
658680
)?;
659681
ret.push(lib_unit_dep);
660-
if dep_lib.documented() && state.intent.wants_deps_docs() {
682+
683+
// Decide whether to document this dependency.
684+
// When public-dependency is enabled, only document:
685+
// - Direct dependencies of user-selected packages
686+
// - Public dependencies (recursively)
687+
// This dramatically speeds up documentation builds by excluding indirect
688+
// private dependencies that cannot be used by readers of the docs.
689+
let should_doc_dep = if is_user_selected || !public_deps_enabled {
690+
true
691+
} else {
692+
state.resolve().is_public_dep(unit.pkg.package_id(), id)
693+
};
694+
695+
if dep_lib.documented() && state.intent.wants_deps_docs() && should_doc_dep {
661696
// Document this lib as well.
662697
let doc_unit_dep = new_unit_dep(
663698
state,

tests/testsuite/doc.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4218,7 +4218,6 @@ fn doc_with_private_dependency() {
42184218
[DOWNLOADING] crates ...
42194219
[DOWNLOADED] baz v0.0.1 (registry `dummy-registry`)
42204220
[DOWNLOADED] bar v0.0.1 (registry `dummy-registry`)
4221-
[DOCUMENTING] baz v0.0.1
42224221
[CHECKING] baz v0.0.1
42234222
[DOCUMENTING] bar v0.0.1
42244223
[CHECKING] bar v0.0.1
@@ -4233,7 +4232,7 @@ fn doc_with_private_dependency() {
42334232

42344233
assert!(p.root().join("target/doc/foo/index.html").is_file());
42354234
assert!(p.root().join("target/doc/bar/index.html").is_file());
4236-
assert!(p.root().join("target/doc/baz/index.html").is_file());
4235+
assert!(!p.root().join("target/doc/baz/index.html").is_file());
42374236
}
42384237

42394238
#[cargo_test(nightly, reason = "public-dependency feature is unstable")]
@@ -4290,17 +4289,21 @@ fn doc_mixed_public_private_deps() {
42904289
.join("target/doc/priv_dep_with_dep/index.html")
42914290
.is_file()
42924291
);
4293-
assert!(p.root().join("target/doc/transitive/index.html").is_file());
4292+
assert!(!p.root().join("target/doc/transitive/index.html").is_file());
42944293
}
42954294

42964295
#[cargo_test(nightly, reason = "public-dependency feature is unstable")]
42974296
fn doc_workspace_member_private_dep() {
42984297
// selected and skipped are both workspace members.
42994298
// selected has a private dep on skipped.
43004299
// skipped has a dep on transitive (a registry crate).
4301-
// Running `cargo doc -p selected` currently documents all of them,
4302-
// including transitive, because the public-dependency filter is not
4303-
// applied to workspace members' deps.
4300+
// Running `cargo doc -p selected`:
4301+
// - selected is documented (it is user-selected)
4302+
// - skipped is documented because it is a direct dep of selected (user-selected
4303+
// packages always have all their direct deps documented)
4304+
// - transitive is NOT documented: skipped is not user-selected, so the
4305+
// public-dependency filter applies to its deps, and transitive is not
4306+
// marked public by skipped
43044307

43054308
Package::new("transitive", "0.0.1")
43064309
.file("src/lib.rs", "pub fn transitive() {}")
@@ -4348,8 +4351,11 @@ fn doc_workspace_member_private_dep() {
43484351
.masquerade_as_nightly_cargo(&["public-dependency"])
43494352
.run();
43504353

4354+
// selected is documented (user-selected)
43514355
assert!(p.root().join("target/doc/selected/index.html").is_file());
4356+
// skipped is documented because it is a direct dep of the user-selected package
43524357
assert!(p.root().join("target/doc/skipped/index.html").is_file());
4353-
// transitive is documented under the current behavior (no filter applied)
4354-
assert!(p.root().join("target/doc/transitive/index.html").is_file());
4358+
// transitive is NOT documented: skipped is not user-selected, and it does
4359+
// not mark transitive as public
4360+
assert!(!p.root().join("target/doc/transitive/index.html").is_file());
43554361
}

0 commit comments

Comments
 (0)