BE-640: Fix cargo unused_dependencies warnings and surface them in CI#8963
Conversation
PR SummaryLow Risk Overview Across the workspace, Feature-gated false positives are handled with cfg Reviewed by Cursor Bugbot for commit d59064b. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
This PR addresses persistent Rust cargo::unused_dependencies manifest warnings across the workspace and ensures they’re surfaced as CI failures, preventing them from silently accumulating in green builds.
Changes:
- Updates many Rust crates to use an unconditional
#![doc = simple_mermaid::mermaid!(…)]attribute sosimple-mermaidis considered “used” in non-doc builds. - Removes or rewires unused/misconfigured dependencies and features (e.g.,
reqwest/stream, optionalclap_builder, removal of unused crates). - Adds a CI gate in
lint.ymlto detect manifest-lint warnings from clippy output logs and fail the job.
Reviewed changes
Copilot reviewed 47 out of 48 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/graph/test-data/rust/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/error-stack/src/fmt/hook.rs | Anchor spin in std + hooks builds to satisfy unused-dep lint. |
| libs/@local/temporal-client/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/telemetry/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/telemetry/Cargo.toml | Make clap_builder optional and tie it to the clap feature. |
| libs/@local/status/rust/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/repo-chores/rust/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/syntax-jexpr/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/mir/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/hir/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/eval/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/diagnostics/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/diagnostics/Cargo.toml | Remove unused derive_more dependency. |
| libs/@local/hashql/core/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/core/Cargo.toml | Remove unused rpds dependency. |
| libs/@local/hashql/compiletest/src/main.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/compiletest/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/hashql/ast/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/wire-protocol/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/types/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/tower/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/system/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/server/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/net/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/codec/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/harpc/client/rust/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/validation/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/types/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/type-fetcher/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/type-fetcher/Cargo.toml | Explicitly enable reqwest’s stream feature. |
| libs/@local/graph/type-defs/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/temporal-versioning/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/store/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/postgres-store/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/migrations/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/migrations-macros/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/authorization/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/authorization/Cargo.toml | Remove unused reqwest, futures, and futures-core dependencies. |
| libs/@local/graph/api/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/graph/api/Cargo.toml | Remove unused opentelemetry_sdk dependency. |
| libs/@local/effect-dns/hickory/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/codegen/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@local/codec/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@blockprotocol/type-system/rust/src/lib.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| libs/@blockprotocol/type-system/rust/Cargo.toml | Remove unused futures dependency. |
| Cargo.lock | Update lockfile to reflect dependency removals/feature changes. |
| apps/hash-graph/src/main.rs | Make mermaid doc attribute unconditional to avoid unused-dep manifest lint. |
| .github/workflows/lint.yml | Tee clippy output for grep-based manifest-lint gating in CI. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…gounused_dependencies-warnings-across-the
Benchmark results
|
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 2002 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 1002 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 3314 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 1527 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 2078 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 1033 | Flame Graph |
policy_resolution_medium
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 102 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 52 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 269 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 108 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 133 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 63 | Flame Graph |
policy_resolution_none
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 2 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 2 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 8 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 3 | Flame Graph |
policy_resolution_small
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| resolve_policies_for_actor | user: empty, selectivity: high, policies: 52 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: empty, selectivity: medium, policies: 26 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: high, policies: 94 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: seeded, selectivity: medium, policies: 27 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: high, policies: 66 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: low, policies: 1 | Flame Graph | |
| resolve_policies_for_actor | user: system, selectivity: medium, policies: 29 | Flame Graph |
read_scaling_complete
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id;one_depth | 1 entities | Flame Graph | |
| entity_by_id;one_depth | 10 entities | Flame Graph | |
| entity_by_id;one_depth | 25 entities | Flame Graph | |
| entity_by_id;one_depth | 5 entities | Flame Graph | |
| entity_by_id;one_depth | 50 entities | Flame Graph | |
| entity_by_id;two_depth | 1 entities | Flame Graph | |
| entity_by_id;two_depth | 10 entities | Flame Graph | |
| entity_by_id;two_depth | 25 entities | Flame Graph | |
| entity_by_id;two_depth | 5 entities | Flame Graph | |
| entity_by_id;two_depth | 50 entities | Flame Graph | |
| entity_by_id;zero_depth | 1 entities | Flame Graph | |
| entity_by_id;zero_depth | 10 entities | Flame Graph | |
| entity_by_id;zero_depth | 25 entities | Flame Graph | |
| entity_by_id;zero_depth | 5 entities | Flame Graph | |
| entity_by_id;zero_depth | 50 entities | Flame Graph |
read_scaling_linkless
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id | 1 entities | Flame Graph | |
| entity_by_id | 10 entities | Flame Graph | |
| entity_by_id | 100 entities | Flame Graph | |
| entity_by_id | 1000 entities | Flame Graph | |
| entity_by_id | 10000 entities | Flame Graph |
representative_read_entity
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1
|
Flame Graph | |
| entity_by_id | entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1
|
Flame Graph |
representative_read_entity_type
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| get_entity_type_by_id | Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba
|
Flame Graph |
representative_read_multiple_entities
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| entity_by_property | traversal_paths=0 | 0 | |
| entity_by_property | traversal_paths=255 | 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true | |
| entity_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=0 | 0 | |
| link_by_source_by_property | traversal_paths=255 | 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true | |
| link_by_source_by_property | traversal_paths=2 | 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true |
scenarios
| Function | Value | Mean | Flame graphs |
|---|---|---|---|
| full_test | query-limited | Flame Graph | |
| full_test | query-unlimited | Flame Graph | |
| linked_queries | query-limited | Flame Graph | |
| linked_queries | query-unlimited | Flame Graph |
🌟 What is the purpose of this PR?
Cargo's
unused_dependencieslint (active through the repo'scargo-lintsopt-in since at leastnightly-2026-06-08) has been reporting unused dependencies for weeks, but nobody saw it: the warnings are cargo manifest diagnostics emitted as plain text, not compiler JSON messages, so they bypass the SARIF gate in CI and only ever existed in unread logs of green jobs. Locally they are equally easy to miss because cargo only reports them for primary packages of an invocation.This PR fixes every current finding across the workspace and adds a CI gate so new ones fail the lint job.
🔗 Related links
cargo cleanbuild)🚫 Blocked by
Nothing.
🔍 What does this change?
#![cfg_attr(doc, doc = simple_mermaid::mermaid!(…))]with an unconditional#![doc = …]. The dependency is compiled in every build anyway and doc attributes are inert outside rustdoc, but thecfg_attrvariant made every non-doc build considersimple-mermaidunused.reqwest,futures,futures-core(hash-graph-authorization),rpds(hashql-core),derive_more(hashql-diagnostics),opentelemetry_sdk(hash-graph-api),futures(type-system).reqwest/streamfeature itself. It usesResponse::bytes_streambut previously only compiled because hash-graph-authorization's (unused) reqwest dependency enabled the feature via unification.spinwith ause spin as _;gated onall(feature = "std", feature = "hooks")— it is genuinely used, but only on no-std paths, sostd+hooksbuilds flagged it. A per-crate[lints.cargo]override is not possible next tolints.workspace = true.clap_builderoptional and wire it into theclapfeature; it is only referenced by theclap::Argsderives behind that feature.postgres-types,utoipa, andbytesare only consumed by theRealintegration in thenumericmodule — i.e. at the intersection ofnumericand the respective feature. Cargo activates dependencies on the feature union, so the merge-queue feature powerset flags them as unused in the single-sided permutations. Madebytesoptional (it was compiled unconditionally) and anchored the intersection deps with cfg-gateduse … as _;for the exact combinations where the consuming code isn't compiled. Keepspostgres/utoipa/numericindependent and general (no feature coupling, no combined features) and leaves the powerset check fully active.lint.yml):teethe clippy stream intoclippy-output.logand fail the step when it containswarning: unused dependencylines, with zero additional build time. A workspace-widedenylevel was deliberately rejected because it would make local builds fail mid-refactor.Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
--all-features, which by construction cannot detect dependencies that are unused only in some feature combinations (theclap_builderclass). Those are still caught by thecargo hack --feature-powersetrun outside of pull requests.clippy-sarifhas no JSON events to convert.cargo::unused_workspace_dependencieslint reports false positives in the package jobs becauseprune-repositoryremoves most workspace members, making their[workspace.dependencies]entries look unused (this is what failed the first CI run of this PR).🐾 Next steps
--message-format=json(the lint system is still unstable), the grep gate can be folded into the SARIF pipeline.🛡 What tests cover this?
cargo check --workspace --all-featuresis warning-free (run to fixpoint locally).cargo check -p error-stack --all-featuresand--no-default-features --features hooksboth clean.❓ How to test this?
cargo clean && cargo check --workspace --all-features— nounused dependencywarnings appear.Cargo.tomland push — the "Run clippy" step for that package fails with the offending lines in the log.📹 Demo