Skip to content

[ENH][auto] rust/rust-intra-crate-module-cycle-unreported: build a dependency graph for Rust modules #221

Open

Description

@DaisukeYoda

Track: feature-gap

Summary

polyscan builds no dependency graph for Rust. Dependency analysis covers Go and JavaScript/TypeScript, so a Rust crate gets no module graph, no cycle detection and no instability or distance metrics.

Rationale

The modules of one Rust crate may depend on each other in a cycle, which Go forbids between packages. A cycle does not break the build, but it ties the modules together: none of them can be moved into a separate crate, because the crate graph must stay acyclic, and that limits incremental and parallel builds. A dependency graph would show where a crate's layering has collapsed, which is the question the dependency dimension answers for Go and JavaScript.

Evidence

In EmbarkStudios/quilkin, the root crate (src/, about 105 module files) has 15 top-level modules, and 11 of them (alloc, cli, codec, components, config, filters, metrics, net, service, signal, tls) form one strongly connected component through crate:: paths. None of the edges below is test code.

From To
src/cli.rs:132 pub service: crate::service::Service, src/service.rs:380 termination_timeout: Option<crate::cli::Duration>
src/config.rs:77 crate::metrics::leader_election(is_leader) src/metrics.rs:581 icao: crate::config::IcaoCode
src/config/filter.rs:1 use crate::filters::{CreationError, FilterChain, FilterInstance}; src/filters.rs:81 use crate::config::filter::Filter as FilterConfig;
src/net/packet.rs:54 use crate::service::ALLOW_EMPTY_PACKETS_FLAG; src/service.rs:1246 crate::net::packet::spawn_receivers(

polyscan reports no Rust module. Its only dependency module on this repository is one JavaScript file in docs/:

{"total_modules": 1, "nodes": ["docs/mermaid-init.js"], "total_cycles": 0}

Repro

// src/lib.rs
pub mod config;
pub mod service;

// src/config.rs
pub struct Config {
    pub port: u16,
}

pub fn build(s: &crate::service::Service) -> Config {
    Config { port: s.port() }
}

// src/service.rs
pub struct Service {
    port: u16,
}

impl Service {
    pub fn port(&self) -> u16 {
        self.port
    }

    pub fn reload(&self) -> crate::config::Config {
        crate::config::build(self)
    }
}

With a Cargo.toml beside it, polyscan analyze --format json . prints "deps_enabled": false and no deps section, although config and service depend on each other.

Proposed change

For Rust, polyscan builds a module dependency graph from the mod tree of each crate and the use and qualified paths that name another module of the same workspace. It reports cycles, the longest chains, and instability and distance per module, as it does for Go packages, and test modules stay out of it. A child module that reaches its parent through super:: is idiomatic Rust, so the graph does not report a parent and its own child as a cycle; scoring the graph at the level of a crate's top-level modules is one way to achieve that.

Impact: med. Effort: medium. Confidence: high.

polyscan version 0.6.1.

Verification: survived refutation. No issue tracks Rust dependency analysis, all cited lines match, and a separate scan re-derived the same 11-module component. Impact was lowered from high because a module cycle inside a crate has no runtime cost; its cost is architectural.

Found via the polyscan-enhancement-audit skill in repo EmbarkStudios/quilkin@58f4f0b1b390a7c527cb0228c9267055f716d48f.


Want to work on this? Run polyscan on a project of your own first, and say in a comment which project you ran it on. See CONTRIBUTING.md, "Pull Requests".

Activity

  1. added
    enhancementNew feature or request
    auto-filedFiled automatically by the polyscan-fp-audit skill (review before acting)
    on Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    auto-filedFiled automatically by the polyscan-fp-audit skill (review before acting)enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions