Describe the Bug
We ran a cleanup pass over a get_dead_code high-confidence, safe_to_delete-tier batch (5 unused_export findings) on a mixed Rust/JS/terraform monorepo. After manual verification, 5/5 were false positives, falling into four distinct classes. Filing them together since they share a theme: "no importers" is being computed from import-statement graph edges only, which misses same-crate references, string-based entry points, external-test consumers, and documentation references.
FP classes
1. Rust: intra-crate references produce no graph edges (same root cause as #628, not Go-specific)
pub structs flagged as unused_export at high confidence while being used extensively within their own crate — embedded in pub enum variants, held as struct fields, constructed and consumed across sibling modules. Rust intra-crate references need no use of the symbol (path-qualified or same-module access), so they produce no import edges, and the symbol appears to have zero importers. The pub visibility is required because the symbol appears inside other pub items.
// lib.rs
pub mod transport;
// transport/state.rs
pub struct RecvState { /* ... */ } // ← flagged: "no importers"
// transport/types.rs — same crate, no `use` needed via super::
pub enum Event {
Received { state: Option<super::RecvState> }, // pub position forces pub visibility
}
2. Rust: integration tests under tests/ not counted as consumers
A pub report struct returned by a pub fn, flagged as unused — but its fields are asserted one-by-one in the crate's tests/*.rs integration tests. Those compile as external crates, which is exactly why the symbol must stay pub. If the graph skips tests/ dirs (or treats them as non-importers), every symbol whose only external consumer is an integration test looks dead.
3. String-based entry points: AWS Lambda handler referenced from terraform
// lambda/broker.mjs
export const handler = async () => { /* ... */ }; // ← flagged: "no importers"
# main.tf
handler = "broker.handler" # AWS invokes the export by name at runtime
Similar in spirit to the framework-awareness you already ship (Flask/FastAPI/Rails routes): handler/lambda_handler exports in files referenced by IaC (aws_lambda_function handler attributes, SAM/serverless.yml) are runtime entry points. Even just special-casing the export name handler in .mjs/.js/.py under a confidence penalty would kill this class.
4. Documentation-referenced example files
A .ts example file whose exported helpers are flagged, but the file exists as a reference implementation pointed at by adjacent markdown docs ("See foo-example.ts in this directory for the complete implementation"). No importers is expected and correct — it's illustrative code, not application code. A markdown-mention check (filename appearing in sibling .md files) or a docs/examples path heuristic would down-rank these.
Expected Behavior
None of the above should land in the high-confidence / safe_to_delete tier. Classes 1–2 arguably shouldn't be flagged at all (real references exist in the graph's source language); classes 3–4 should at least drop to low confidence (dynamic/string reference risk).
Actual Behavior
All five findings surfaced as unused_export, high-confidence, safe-to-delete tier, reason "Public symbol 'X' has no importers". 5/5 manually verified as live.
Environment
- OS: Amazon Linux 2023
- Python version: 3.12
- Repowise version: 0.25.0
- Installation method: uv tool install
Describe the Bug
We ran a cleanup pass over a
get_dead_codehigh-confidence,safe_to_delete-tier batch (5unused_exportfindings) on a mixed Rust/JS/terraform monorepo. After manual verification, 5/5 were false positives, falling into four distinct classes. Filing them together since they share a theme: "no importers" is being computed from import-statement graph edges only, which misses same-crate references, string-based entry points, external-test consumers, and documentation references.FP classes
1. Rust: intra-crate references produce no graph edges (same root cause as #628, not Go-specific)
pubstructs flagged asunused_exportat high confidence while being used extensively within their own crate — embedded inpubenum variants, held as struct fields, constructed and consumed across sibling modules. Rust intra-crate references need nouseof the symbol (path-qualified or same-module access), so they produce no import edges, and the symbol appears to have zero importers. Thepubvisibility is required because the symbol appears inside otherpubitems.2. Rust: integration tests under
tests/not counted as consumersA
pubreport struct returned by apub fn, flagged as unused — but its fields are asserted one-by-one in the crate'stests/*.rsintegration tests. Those compile as external crates, which is exactly why the symbol must staypub. If the graph skipstests/dirs (or treats them as non-importers), every symbol whose only external consumer is an integration test looks dead.3. String-based entry points: AWS Lambda
handlerreferenced from terraformSimilar in spirit to the framework-awareness you already ship (Flask/FastAPI/Rails routes):
handler/lambda_handlerexports in files referenced by IaC (aws_lambda_functionhandlerattributes, SAM/serverless.yml) are runtime entry points. Even just special-casing the export namehandlerin.mjs/.js/.pyunder a confidence penalty would kill this class.4. Documentation-referenced example files
A
.tsexample file whose exported helpers are flagged, but the file exists as a reference implementation pointed at by adjacent markdown docs ("Seefoo-example.tsin this directory for the complete implementation"). No importers is expected and correct — it's illustrative code, not application code. A markdown-mention check (filename appearing in sibling.mdfiles) or a docs/examples path heuristic would down-rank these.Expected Behavior
None of the above should land in the high-confidence /
safe_to_deletetier. Classes 1–2 arguably shouldn't be flagged at all (real references exist in the graph's source language); classes 3–4 should at least drop to low confidence (dynamic/string reference risk).Actual Behavior
All five findings surfaced as
unused_export, high-confidence, safe-to-delete tier, reason "Public symbol 'X' has no importers". 5/5 manually verified as live.Environment