The local-variable receiver-type inference from #1108/#1110 covered typed
parameters for every language except TypeScript/JavaScript (+ TSX/JSX). The
TS/JS `:`-annotation pattern required a leading `const|let|var`, so it only
matched a local's own annotation (`const lg: Logger`) and never a bare
parameter (`function use(lg: Logger)` / `(lg: Logger) =>`). With a second
class sharing the method name — the case where a same-name fallback can't
paper over it — `lg.log()` resolved to no edge, dropping it from callers and
impact/blast-radius. TS/JS is the most common language pair in the userbase,
so this was a real precision gap.
Replace the keyword-anchored pattern with the keyword-free
`\b${r}\b\s*:\s*([A-Z][\w.$]*)`, mirroring Kotlin/Swift/Scala. It's a strict
superset (still matches `const lg: Logger`) plus the typed-parameter case,
and the capture stops at `<` so a generic-typed param
(`repo: Repository<User>`) still yields `Repository`. resolveMethodOnType
already validates the inferred type declares the method, so the looser match
produces no edge on a mis-inference — the same safety net the other
languages rely on; Swift already ships this identical bare-colon pattern with
the same theoretical ternary/dict-literal exposure.
Adds a regression test using two ambiguous classes + typed params, asserting
each call routes to its OWN class's method (verified to fail without the fix
and pass with it — a single-class version would pass either way via the
same-name fallback, which is why the collision is load-bearing).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7c7514f43f
commit
385001398b
@@ -1065,7 +1065,14 @@ function localReceiverTypePatterns(language: Language, r: string): RegExp[] {
|
||||
case 'jsx':
|
||||
return [
|
||||
new RegExp(`\\b${r}\\b\\s*=\\s*new\\s+([A-Za-z_$][\\w.$]*)`), // = new Logger()
|
||||
new RegExp(`\\b(?:const|let|var)\\s+${r}\\s*:\\s*([A-Z][\\w.$]*)`), // lg: Logger
|
||||
// No keyword requirement, so this matches BOTH a local annotation
|
||||
// (`const lg: Logger`) and a typed parameter (`function use(lg: Logger)`
|
||||
// / `(lg: Logger) =>`) — the parameter case the old `const|let|var`
|
||||
// prefix excluded (#1125). Mirrors Kotlin/Swift/Scala; the capture stops
|
||||
// at `<` so a generic-typed param (`repo: Repository<User>`) still yields
|
||||
// `Repository`. resolveMethodOnType validates the type actually declares
|
||||
// the method, so the looser match produces no edge on a mis-inference.
|
||||
new RegExp(`\\b${r}\\b\\s*:\\s*([A-Z][\\w.$]*)`), // lg: Logger (annotation or typed param)
|
||||
];
|
||||
case 'python':
|
||||
return [
|
||||
|
||||
Reference in New Issue
Block a user