Skip to content

fix(resolution): resolve same-named methods to the call site's own file (#1079)#1107

Merged
colbymchenry merged 1 commit into
mainfrom
fix/samename-method-resolution-1079
Jul 1, 2026
Merged

fix(resolution): resolve same-named methods to the call site's own file (#1079)#1107
colbymchenry merged 1 commit into
mainfrom
fix/samename-method-resolution-1079

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Closes #1079.

Problem

When two files each declared a same-named class with a same-named method — class Logger { void log(); } in both a/svc and b/svc — a call resolved to whichever definition happened to be indexed first. So a call in b/ wrongly pointed at a/'s method, mixing up that method's callers and blast radius.

@inth3shadows reported this for C++ instance calls and diagnosed it precisely: resolveMethodOnType only disambiguated multiple matches when a Java/Kotlin import FQN was present (#314), and every other language fell through to matches[0].

Scope — it's a cross-language pattern, not one site

Validating "are other languages affected?" with two-file repros surfaced the same "pick the first-indexed, ignore the call site's file" pattern in three distinct resolution paths, each firing for a different call shape:

Call shape Firing path Affected (confirmed)
obj.log() — instance resolveMethodOnType C++
Logger.log() — class receiver matchMethodCall Strategy 1/2/3 Python, TypeScript, Java, C#
Logger::log() — qualified matchByQualifiedName C++, Rust

(The plain instance case only resolves to a method in C++ today — other languages don't infer a local variable's type, so they produced no edge rather than a wrong one. Constructor / instantiates resolution and the general name-match path were already file-aware via path proximity, which is why only these method paths were affected.)

Fix

One shared helper — preferCallSiteFile(nodes, callSiteFile) — prefers a candidate declared in the call site's own file when a name is ambiguous, and is a no-op when there are fewer than two candidates or none share the file. Applied at all five sites (resolveMethodOnType, both branches of matchByQualifiedName, and matchMethodCall Strategies 1/2/3).

In resolveMethodOnType it runs after the preferredFqn block, so Java/Kotlin import disambiguation (#314) — whose target is intentionally in another file — is unaffected.

Tests

8 tests under Same-name method disambiguation (#1079): the preferCallSiteFile contract, resolveMethodOnType precedence (including a guard that an import FQN still beats the same-file preference, #314), matchByQualifiedName disambiguation, and end-to-end index tests for the C++ instance, TypeScript static, and C++ qualified call shapes. Full suite green (1905 passed).

🤖 Generated with Claude Code

…le (#1079)

When two files each declared a same-named class with a same-named method
(e.g. `class Logger { void log(); }`), a call resolved to whichever
definition was indexed first — so a call in `b/svc` wrongly targeted
`a/svc`, mixing up that method's callers and blast radius.

The reported case was C++ instance calls, but the underlying pattern —
"multiple same-named candidates, pick the first-indexed, ignore the call
site's file" — lived in three resolution paths, each firing for a
different call shape and affecting different languages:

  - `obj.log()`     instance        -> resolveMethodOnType (C++)
  - `Logger.log()`  class receiver  -> matchMethodCall Strategy 1/2/3
                                       (Python, TypeScript, Java, C#)
  - `Logger::log()` qualified       -> matchByQualifiedName (C++, Rust)

All five sites now share one helper, `preferCallSiteFile`, that prefers
a candidate declared in the call site's own file when a name is
ambiguous. It runs after the `preferredFqn` block in resolveMethodOnType,
so Java/Kotlin import disambiguation (#314) — whose target is
intentionally in another file — is unaffected. The helper is a no-op
when there are fewer than two candidates or none share the call site's
file, so the common single-definition case is unchanged.

Adds 8 tests under `Same-name method disambiguation (#1079)`: the
`preferCallSiteFile` contract, resolveMethodOnType precedence (including
a guard that an import FQN still beats the same-file preference),
`matchByQualifiedName` disambiguation, and end-to-end index tests for the
C++ instance, TypeScript static, and C++ qualified call shapes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

C++ method calls to same-named classes in different files all resolve to the first definition

1 participant