Skip to content

follow-up: receiver-type-aware invoked-property matching to reduce dead-code false negatives #2088

Description

@carlos-alm

Deferred from PR #2034 review.

Original reviewer comment: inline comment — #2034 (comment)

Context:

collectInvokedPropertyNames (src/domain/graph/builder/call-resolver.ts, mirrored as collect_invoked_property_names in crates/codegraph-core/src/domain/graph/builder/stages/build_edges.rs) adds a property name to its evidence set whenever ANY call in the processed files has a non-empty receiver and that name — with no check that the receiver is plausibly the same dispatch-table object referenced by the object-literal being evaluated. A completely unrelated logger.resolve() or promise.resolve() call anywhere in the codebase will add resolve to the set and prevent { resolve: neverCalled } from being flagged dead, even if the actual dispatch table is never read.

This is the conservative error direction (false negative for dead-code — it can never misclassify genuinely live code as dead), so it was accepted as-is for #2034: that PR's stated scope was "require any invocation evidence" as a deliberately coarse "one hop further" heuristic (see the doc comment on collectInvokedPropertyNames), not precise receiver-type correlation. Tightening it now would require:

  • Extending the existing points-to/type-map machinery to track each receiver call site's inferred type/binding.
  • Correlating that inferred type back to the specific object-literal (or dispatch-table variable) that defines the property being checked.
  • Implementing this identically in both the WASM/TS and native Rust engines, per this repo's dual-engine parity requirement.

That's a nontrivial dataflow precision improvement, not a small tweak, so it's being tracked separately rather than folded into #2034's narrower "any evidence at all" fix.

What the fix entails: teach collectInvokedPropertyNames/resolveFallbackTargets (and their Rust mirrors) to only count a x.name(...) call as evidence for a given object-literal's { name: fn } property when x's resolved type/binding plausibly refers to that same object (e.g. via the existing typeMap/points-to infrastructure), rather than matching on bare property name alone.

Metadata

Metadata

Assignees

No one assigned

    Labels

    follow-upDeferred work from PR reviews that needs tracking

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions