get_dependencies (direction=in): crate-scope reverse-dep matching to cut generic-name false positives #9
Labels
No labels
code-review
correctness
dos
performance
security
severity/high
severity/low
severity/medium
tech-debt
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
h-dv/code-index#9
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
get_dependencieswithdirection=in(reverse dependencies / "who imports this file") over-reports when the target file's module-name keys are generic and collide with same-named modules in other crates of the workspace. This is the known recall-over-precision tradeoff in segment matching; this issue tracks tightening it toward precision without losing recall.Where
crates/daemon/src/local_index.rs—module_matches_keys()andimporters_of_file()[: . / \]and returns the file if any segment equals any of the target file's keys (file stem + declared module-symbol names).Observed (dogfooded live on v0.5.8)
inresultcrates/plugins/src/lib.rslib.rsdeclarespub mod common; pub mod pos; …. Matching then pulls in the daemon'scrates/daemon/tests/common/importers (a differentcommon) and the ruby fixture'slib/greeter(matches stemlib). Most are false positives.crates/mcp-server/src/gitdiff.rsuse crate::gitdiff::…sites inserver.rs.crates/indexer/src/test_paths.rscrate::test_paths::…, nouse).Conclusion: noise scales with name genericness, not a regression. Distinctive names resolve precisely; generic ones (
common,pos,lib,mod,utils) attract cross-crate collisions.Why it's hard
The import string alone (
common::{build_daemon}) doesn't encode which crate itscommonresolves to. Precise matching needs crate/scope context:crate::commonin the plugins crate must NOT match an importer whosecommonlives in the daemon crate.Proposed directions (pick one, smallest that works)
Cargo.toml/ crate root) and require the target and importer to share a crate forcrate::/super::/relative imports. Highest precision; most work.crate::gitdiff), prefer matches on the longer qualified segment chain over single generic segments. Cheaper; helps thelib.rscase partially.confidence(e.g. lower for single generic-segment matches) so callers/UI can rank or filter. Least invasive; preserves recall.Leaning toward (3) as an immediate mitigation + (1) as the correct long-term fix.
Acceptance
get_dependencies inoncrates/plugins/src/lib.rsreturns only true importers of that crate's modules (plugin-internalcrate::common/crate::posusers), excluding the daemon-testcommonand the ruby fixture.gitdiff.rs→ 2,test_paths.rs→ 0) unchanged.Context
Surfaced during the v0.5.8 deep dogfood pass. Not a defect — the current behavior is documented in the
importers_of_filedoc comment as an intentional recall bias. This issue is the tracked enhancement to move it toward precision.Implemented on
fix/ultradeep-review-findings(commit12f942a) — a combination of directions (1) crate-scoping and (2) prefer-distinctive, without needing manifest parsing.importers_of_filenow scopes ambiguous matches to the target's own package. A key is ambiguous if it names a module defined in a different package (queried from the symbol table) or is a generic module-root stem (lib/mod/main/index/__init__/app). A match resting solely on ambiguous keys is kept only when the importer shares the target's package root (package_root, a lexical crate/pkg-root heuristic forcrate/<name>/src,<pkg>/lib, and single-rootsrclayouts). A match on a distinctive key (unique to the target's package, e.g.gitdiff) still resolves cross-package, preserving real cross-crate reverse-deps.Acceptance:
commoncross-crate leak is closed: a two-crate fixture where both crates declarecommonasserts the daemon-package importer is dropped while the plugins-package sibling is kept.gitdiffresolves cross-package (test), and the existinggitdiff.rs → 2/test_paths.rs → 0lang_e2e coverage stays green.lib-stem leak (ruby fixture) is closed by the generic-stem rule.Honest scope note: this is precision-over-recall by design — an ambiguous-named module imported cross-crate via its (unqualifiable-from-the-string) crate name is conservatively dropped. That's the genuinely-ambiguous case the issue's "Why it's hard" section describes; full manifest-based crate resolution would be the only way to recover it, and is a larger follow-up. This removes the documented false positives. Closing.