Repository navigation
fix(resolution): library-method calls on untyped receivers need receiver evidence (Rust, Go, Python, Kotlin, Scala, C#, Java) - #1947
Conversation
f40e1d6 to
5213d7c
Compare
5213d7c to
b0a01fe
Compare
|
Rebased and reworked onto main's new structure. Rust, Kotlin and C# (and static
🤖 Generated with Claude Code |
0340bc7 to
21d5a2c
Compare
|
Rebased onto main. No maintainer PR has covered this one since the last rebase, so the Python, Scala and Java parts are unchanged. I removed the Go part (reading The remaining check uses 🤖 Generated with Claude Code |
92dbd97 to
ffd1b8a
Compare
1394bd9 to
dc53b19
Compare
dc53b19 to
92d44e7
Compare
…Rust Self:: and std impls, colbymchenry#2688 synthesis inputs, first foreign merges) Conflicts: name-matcher takes main's `isGoOutsideImport` family in place of colbymchenry#1954's `isGoExternalImport`; keeps colbymchenry#1942's Java same-language preference and colbymchenry#1947's `cls` beside main's `withinCppTranslationUnit`; colbymchenry#1949's Java static field block and main's Rust `Self::` block both stay; colbymchenry#1935's `findOwnMethod` gets main's Go standard-method-name condition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
04140fc to
e915072
Compare
…ame-named project methods A member call on a receiver of unknown type reached the lone same-named method for an untyped `recv.m` (instance-method 0.7). Standard-library names collected such calls: on Play ~2,500 Scala `map`/`get`/`foreach` calls and ~1,100 Java test-map `put` calls landed on unrelated project methods, and Python `d.setdefault()` on a same-file class's method. The standard-library method lists that already demand receiver evidence for Rust, Go, Kotlin, C# and VB.NET gain Python, Scala and Java sets: such a call now needs the receiver's own name to name the candidate's type. `cls` joins `self`/`this`/`base` as a receiver that is the calling type itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e915072 to
7a29580
Compare
…es stay unlinked Root cause: when nothing types a call's receiver, matchMethodCall's last strategy links `recv.m()` to the one project method named `m` (0.7), or to the best receiver-word match among several. A standard-library call on a plain value - `options.setdefault(...)` on a dict, `m.getOrElse(...)` on an Option, `data.put(...)` on a map in a `var` - then linked to an unrelated project method of that name. Go, Rust, Kotlin, C#, VB.NET and Dart already keep such a guess only when the receiver names the method's owner (stdMethodNames); Python, Scala and Java had no list. Fix (contributor): Python, Scala and Java standard-library method lists in stdMethodNames. Ours: the PR also exempted a receiver named `cls` from the rule; both extractors already strip `cls.` from Python calls, so it never applied there, while in C#, Dart, Rust and VB.NET it let `var cls = Make(); cls.ToString()` link to an unrelated Money.ToString. Removed, with a C# test case. CHANGELOG bullet rewritten and moved next to the Python built-in method bullets. Validation: library-method-calls.test.ts: 3 of its 5 cases fail on main (Python build, Scala go, Java untyped), all 5 pass; the C# case fails when `cls` is put back. Kernel A/B against main 0174f80, 11 repos: 0 added, 0 retargeted, 540 removed. Python: flask 12, netbox 2, django 140, fastapi 0, all wrong (list/dict/file/re-match calls landing on ListMixin, QueryDict, HttpRequest, AnonymousUser, _AppCtxGlobals). Java: Minestom 20, spring-ai 86, all wrong (Map put/computeIfAbsent, reactor Context put, stream(), enum valueOf). Scala: playframework 98 (4 of them Java), scalachess 31, http4s 151; 267 wrong, 13 right links lost where a project type has collection-like methods and the receiver is not named after it (scalachess Board.put/replace through for-comprehension binds, ByColor through `type Pockets`; http4s Headers.put; Play Form.fold, Router.orElse). gin and serilog byte-identical. CPU on playframework, median of 3 interleaved: 71.7 s main, 71.1 s branch. Also settles the Holder.LOOKUP.get and Mode.ON.equals cases of PR 1949. Original PR #1947 by @danusha2345. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks @danusha2345, this landed as #2942 with you as the commit author. The Python, Scala and Java lists hold up well on real code: across django, flask, netbox, fastapi, spring-ai, Minestom, playframework, scalachess and http4s the change only removed links, and 527 of the 540 it removed were wrong; the 13 right ones lost are Scala types with collection-like methods. We dropped the |
…mchenry#2972; 10 landed PRs yield to main; EXTRACTION_VERSION 56) Main landed ten more of our PRs as our own commits with the maintainer's additions (colbymchenry#2923 ← colbymchenry#1936, colbymchenry#2924 ← colbymchenry#1951, colbymchenry#2925 ← colbymchenry#1939, colbymchenry#2930 ← colbymchenry#2921, colbymchenry#2940 ← colbymchenry#1736, colbymchenry#2942 ← colbymchenry#1947, colbymchenry#2950 ← colbymchenry#1952, colbymchenry#2961 ← colbymchenry#1954, colbymchenry#2965 ← colbymchenry#1942, colbymchenry#2972 ← colbymchenry#1933) and the module-path half of colbymchenry#2308 (colbymchenry#2955). Where the integration carried our version, main's wins: the enclosing-scope member pick and its tests, the Go and Java receiver typers, the delegating-call self-loop rule, the duplicated-module copy confidence, the C #if collapse, the module-path resolution of Rust paths, the trail/path hardening in utils.ts. Kept beside main: colbymchenry#1875's Verilog hooks and status fields, colbymchenry#2839's implementations command, colbymchenry#1923, colbymchenry#2922, colbymchenry#2258, colbymchenry#1761, colbymchenry#1583, the bare-call half of colbymchenry#2308 (rust-use-bindings.ts). CHANGELOG is main's plus the open PRs' bullets. EXTRACTION_VERSION 56: the C #if group handling (colbymchenry#2940) and the kernel change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tests, colbymchenry#1947's cls exemption, locale-tiebreak test) Our copies of the C #if tests colbymchenry#2940 superseded are dropped (one of them was main's own test twice); the library-method rule no longer exempts a receiver named `cls`, as colbymchenry#2942 landed it; ts-this-field-call.test.ts is main's (colbymchenry#2927 landed the same code-unit tiebreak the integration carried from the earlier PR). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Rebased onto the 2026-09-27 main. #1944 landed as #2032, so this PR now stands on main alone: 5213d7c on top of fa6dd01. It also absorbs #1953, the Java list: that PR only added to the same
library-methods.tsand the same check, so the two would have conflicted as separate PRs. #2028 covers JS/TS built-in names; this PR covers the other languages, so the two don't overlap.Problem
For many member calls, no receiver type reaches the resolver, and the call then binds to the only project method with the same name. There are two paths.
x.f().m(),a.b.m(),x?.m(); Kotlin/Scala chains with a lowercase root; Go chains deeper than two hops; Pythona.b.m(). Exact-match then binds them at 0.9, 0.7 or 0.4.x.m(). These reachmatchMethodCall's name-only strategy 3.Where the method name belongs to the language's standard library, the call is almost always that library method, and the one project method with that name collects every such call:
name.len()/v.iter().all()→ a RustAppLog::len/SpeedProfile::all: about 500 edges in one Rust GUI.conn.Close()→ a GorotatingLogWriter::Close.d.setdefault(k, [])→ a projectsetdefault.Task.Run(...)→ a C#Run.opt.map/get/foreach→ Scala project methods.Precision on
main, from 40 randomly sampled edges per language covering both paths:Fix
The fix is in the resolver only: no extractor or kernel change and no re-index.
library-methods.tsholds per-language lists of standard-library method names for Rust, Go, Python, Kotlin, Scala and C#.self.state.log.clear()→logkeepsAppLog::clear.GpsMode.ON.next().self/this/super/base/clsreceivers and implicit-this calls. Typed receivers resolve before any of these strategies and never reach the check.Measured
Base is #1944. Nothing was gained, node counts are unchanged, and every lost group was checked by hand:
flask.g.setdefault/pop: a one-letter receiver gives no word evidence)Task.Run×16,e.ToString×12)After the fix, 39 of 40 sampled remaining Rust edges are correct. Scala's remaining noise comes from ambiguous project method names (
header,value,apply), which this change doesn't touch.Tests
__tests__/library-method-calls.test.tscovers Rust, Kotlin, Python, Go and C#. Five of its six cases fail on the base. The controls cover:self.setdefault;The full suite passes: 276 files, 4734 tests.
Java (was #1953)
Problem
The list above of standard-library method names. A call with one of those names on an untyped receiver no longer binds to a lone same-named project method unless the receiver's name shares a word with that method's class. Java wasn't on the list, and its name-only matches have the same problem.
data.put(k, v)on a testMap→ a projectRejectingMap::put. That's 1,115 call sites in playframework.s.charAt(i),list.size(),CONSTANT.equals(x)andmView.getResources()bind to whichever project class declares that name.Collections.emptyMap()andString.valueOf(x)underimport java.util.*. The check for imported library classes only knows named andjava.langimports, so wildcard imports slip through.Integer.TYPE.equals(...)andX.KEY.equals(...)get no receiver type, so they bind by name too.On our integration build, which already has the Java receiver typing from #1942, name-only edges with a JDK/Android method name are about 30% correct on playframework's Java and about 40% on decompiled Android SystemUI. These were checked by hand.
Fix
A
javalist inlibrary-methods.ts, 64 names:Object:equals,hashCode,toString,getClass,compareTo;Stringmethods;Optional/Streammethods;getResources,getSystemService,findViewById,postDelayed,removeCallbacks,setVisibility,startActivity.Names that projects commonly declare themselves were left out:
post,of,apply,run,call,start,stop,getId,getContextand similar. Playframework alone declaresapply60 times.JAVA_STD_CLASSES. A call on one of these classes counts as a library call whatever the method name, also when written asjava.lang.X:Objects,Arrays,Collections,Optional,List,Map,Set,UUID,String, the boxed number types,Math,System,Thread. A project class with the same name keeps its edge through the existing receiver-word check.Constant receivers. A Java receiver ending in an ALL_CAPS constant gives no type evidence.
INSTANCEis exempt.Typed resolution at 0.9 is untouched.
Measured
Node counts are unchanged in every pair, and no edges were gained.
ByteString.EMPTY.equals, removed by the constant rule)Five other corpora are unchanged: two Kotlin apps, a Kotlin/C app, a small Java/Kotlin app and a Rust app.
Tests
New Java cases in
__tests__/library-method-calls.test.ts:list.get(0),s.toString(),Objects.hash(a),Collections.emptyMap()underimport java.util.*,Registry.KEY.equals(a).registry.get→Registry::get), a baresize()andthis.get()inside the owning class, and a receiver named after its type (userRegistry.size()).The full suite passes: 276 files, 4734 tests.
🤖 Generated with Claude Code