From 81c2cd5a955c93edfad4444a7fd0dc168cbc9dba Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sun, 30 Jan 2022 00:06:27 +0800 Subject: [PATCH 1/2] Compute non custom build and non transitive deps for doc Signed-off-by: hi-rustin --- src/cargo/core/compiler/unit_dependencies.rs | 58 ++++++++++-------- tests/testsuite/doc.rs | 64 ++++++++++++++++++++ 2 files changed, 97 insertions(+), 25 deletions(-) diff --git a/src/cargo/core/compiler/unit_dependencies.rs b/src/cargo/core/compiler/unit_dependencies.rs index c2575fd77f1..4ea86f9c978 100644 --- a/src/cargo/core/compiler/unit_dependencies.rs +++ b/src/cargo/core/compiler/unit_dependencies.rs @@ -18,7 +18,6 @@ use crate::core::compiler::unit_graph::{UnitDep, UnitGraph}; use crate::core::compiler::UnitInterner; use crate::core::compiler::{CompileKind, CompileMode, RustcTargetData, Unit}; -use crate::core::dependency::DepKind; use crate::core::profiles::{Profile, Profiles, UnitFor}; use crate::core::resolver::features::{FeaturesFor, ResolvedFeatures}; use crate::core::resolver::Resolve; @@ -243,29 +242,7 @@ fn compute_deps( } let id = unit.pkg.package_id(); - let filtered_deps = state.deps(unit, unit_for, &|dep| { - // If this target is a build command, then we only want build - // dependencies, otherwise we want everything *other than* build - // dependencies. - if unit.target.is_custom_build() != dep.is_build() { - return false; - } - - // If this dependency is **not** a transitive dependency, then it - // only applies to test/example targets. - if !dep.is_transitive() - && !unit.target.is_test() - && !unit.target.is_example() - && !unit.mode.is_doc_scrape() - && !unit.mode.is_any_test() - { - return false; - } - - // If we've gotten past all that, then this dependency is - // actually used! - true - }); + let filtered_deps = non_custom_build_and_non_transitive_deps(unit, state, unit_for); let mut ret = Vec::new(); let mut dev_deps = Vec::new(); @@ -372,6 +349,37 @@ fn compute_deps( Ok(ret) } +/// Returns non-custom and non-transitive dependencies. +fn non_custom_build_and_non_transitive_deps<'a>( + unit: &Unit, + state: &'a State<'_, '_>, + unit_for: UnitFor, +) -> Vec<(PackageId, &'a HashSet)> { + state.deps(unit, unit_for, &|dep| { + // If this target is a build command, then we only want build + // dependencies, otherwise we want everything *other than* build + // dependencies. + if unit.target.is_custom_build() != dep.is_build() { + return false; + } + + // If this dependency is **not** a transitive dependency, then it + // only applies to test/example targets. + if !dep.is_transitive() + && !unit.target.is_test() + && !unit.target.is_example() + && !unit.mode.is_doc_scrape() + && !unit.mode.is_any_test() + { + return false; + } + + // If we've gotten past all that, then this dependency is + // actually used! + true + }) +} + /// Returns the dependencies needed to run a build script. /// /// The `unit` provided must represent an execution of a build script, and @@ -423,7 +431,7 @@ fn compute_deps_doc( state: &mut State<'_, '_>, unit_for: UnitFor, ) -> CargoResult> { - let deps = state.deps(unit, unit_for, &|dep| dep.kind() == DepKind::Normal); + let deps = non_custom_build_and_non_transitive_deps(unit, state, unit_for); // To document a library, we depend on dependencies actually being // built. If we're documenting *all* libraries, then we also depend on diff --git a/tests/testsuite/doc.rs b/tests/testsuite/doc.rs index da500d4a1d4..1e069c85f0b 100644 --- a/tests/testsuite/doc.rs +++ b/tests/testsuite/doc.rs @@ -1815,6 +1815,70 @@ fn doc_example() { .exists()); } +#[cargo_test] +fn doc_example_with_deps() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + edition = "2018" + + [[example]] + crate-type = ["lib"] + name = "ex" + doc = true + + [dev-dependencies] + a = {path = "a"} + b = {path = "b"} + "#, + ) + .file("src/lib.rs", "") + .file( + "examples/ex.rs", + r#" + use a::fun; + + /// Example + pub fn x() { fun(); } + "#, + ) + .file( + "a/Cargo.toml", + r#" + [package] + name = "a" + version = "0.0.1" + + [dependencies] + b = {path = "../b"} + "#, + ) + .file("a/src/fun.rs", "pub fn fun() {}") + .file("a/src/lib.rs", "pub mod fun;") + .file( + "b/Cargo.toml", + r#" + [package] + name = "b" + version = "0.0.1" + "#, + ) + .file("b/src/lib.rs", "") + .build(); + + p.cargo("doc --examples").run(); + assert!(p + .build_dir() + .join("doc") + .join("ex") + .join("fn.x.html") + .exists()); +} + #[cargo_test] fn bin_private_items() { let p = project() From bd45ac81ba062a7daa3b0178dfcb6fd5759a943c Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Thu, 3 Feb 2022 20:43:23 +0800 Subject: [PATCH 2/2] Inline non_custom_build_and_non_transitive_deps Signed-off-by: hi-rustin --- src/cargo/core/compiler/unit_dependencies.rs | 61 +++++++------------- 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/src/cargo/core/compiler/unit_dependencies.rs b/src/cargo/core/compiler/unit_dependencies.rs index 4ea86f9c978..78710952e84 100644 --- a/src/cargo/core/compiler/unit_dependencies.rs +++ b/src/cargo/core/compiler/unit_dependencies.rs @@ -242,7 +242,7 @@ fn compute_deps( } let id = unit.pkg.package_id(); - let filtered_deps = non_custom_build_and_non_transitive_deps(unit, state, unit_for); + let filtered_deps = state.deps(unit, unit_for); let mut ret = Vec::new(); let mut dev_deps = Vec::new(); @@ -349,37 +349,6 @@ fn compute_deps( Ok(ret) } -/// Returns non-custom and non-transitive dependencies. -fn non_custom_build_and_non_transitive_deps<'a>( - unit: &Unit, - state: &'a State<'_, '_>, - unit_for: UnitFor, -) -> Vec<(PackageId, &'a HashSet)> { - state.deps(unit, unit_for, &|dep| { - // If this target is a build command, then we only want build - // dependencies, otherwise we want everything *other than* build - // dependencies. - if unit.target.is_custom_build() != dep.is_build() { - return false; - } - - // If this dependency is **not** a transitive dependency, then it - // only applies to test/example targets. - if !dep.is_transitive() - && !unit.target.is_test() - && !unit.target.is_example() - && !unit.mode.is_doc_scrape() - && !unit.mode.is_any_test() - { - return false; - } - - // If we've gotten past all that, then this dependency is - // actually used! - true - }) -} - /// Returns the dependencies needed to run a build script. /// /// The `unit` provided must represent an execution of a build script, and @@ -431,7 +400,7 @@ fn compute_deps_doc( state: &mut State<'_, '_>, unit_for: UnitFor, ) -> CargoResult> { - let deps = non_custom_build_and_non_transitive_deps(unit, state, unit_for); + let deps = state.deps(unit, unit_for); // To document a library, we depend on dependencies actually being // built. If we're documenting *all* libraries, then we also depend on @@ -839,12 +808,7 @@ impl<'a, 'cfg> State<'a, 'cfg> { } /// Returns a filtered set of dependencies for the given unit. - fn deps( - &self, - unit: &Unit, - unit_for: UnitFor, - filter: &dyn Fn(&Dependency) -> bool, - ) -> Vec<(PackageId, &HashSet)> { + fn deps(&self, unit: &Unit, unit_for: UnitFor) -> Vec<(PackageId, &HashSet)> { let pkg_id = unit.pkg.package_id(); let kind = unit.kind; self.resolve() @@ -852,9 +816,24 @@ impl<'a, 'cfg> State<'a, 'cfg> { .filter(|&(_id, deps)| { assert!(!deps.is_empty()); deps.iter().any(|dep| { - if !filter(dep) { + // If this target is a build command, then we only want build + // dependencies, otherwise we want everything *other than* build + // dependencies. + if unit.target.is_custom_build() != dep.is_build() { + return false; + } + + // If this dependency is **not** a transitive dependency, then it + // only applies to test/example targets. + if !dep.is_transitive() + && !unit.target.is_test() + && !unit.target.is_example() + && !unit.mode.is_doc_scrape() + && !unit.mode.is_any_test() + { return false; } + // If this dependency is only available for certain platforms, // make sure we're only enabling it for that platform. if !self.target_data.dep_platform_activated(dep, kind) { @@ -870,6 +849,8 @@ impl<'a, 'cfg> State<'a, 'cfg> { } } + // If we've gotten past all that, then this dependency is + // actually used! true }) })