Repository navigation
fix(scala): an Outer.Inner(...) call reaches the Scala case class or object it builds - #2924
Merged
Merged
Conversation
…object it builds Scala qualified names carry no package (Outer::Inner), so a call written Outer.Inner(args), a case-class or companion apply, found no type by its written name. It fell through to the name strategies, and under a return type annotation (def f(): WebSocket = WebSocket.Accepted(flow)) the local-declaration reader took WebSocket for the receiver's type and handed over an unrelated Java constructor, Other::Accepted::Accepted. Before the receiver-word strategy, a Scala call whose member is capitalized now resolves to the Scala type Outer::Inner when that is unambiguous: every match in one file (a class and its companion), or one in the call's own file; a class or trait wins over a same-named object. It is recorded as instantiates for a class, as a call for an object. The typed-receiver path no longer hands a Scala call another language's constructor. Real Java static methods are still reached from Scala. Validation: - resolution.test.ts: 5 cases, 4 red on main; the fifth (a Scala call to a real Java static) passes on both and guards the Java side. - A/B against main 81559dc (with #1950 and #1936): scalachess +77/-0, http4s +371/-1 (the one a retarget from a wrong defaults::Host to the Origin.Host case class), playframework +291/-1 (the one a retarget: Writeable's HttpEntity.Strict(...) from the Java play.http constructor to the Scala case class), play-samples +2 (two case-class applies #1950 unlinked from Java constructors); CMAK, click and gin identical. Every addition is a Scala case-class or object apply; sampled all right (Uci.Move, Header.Raw, H2Frame.Data, RemoteNode.Ip, ApplicationLoader.Context, Request.Connection over headers.Connection). - Cost (http4s, median of 3 interleaved fresh indexes, on main 69af19a): wall 8.6 s on main vs 7.8 s, process CPU 27.5 s vs 26.2 s, within noise. The A/B gave the same edges on both bases. Original PR #1951 by @danusha2345. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A Scala call like
RemoteNode.Obfuscated("x"),Uci.Move(from, to)orHeader.Raw(name, value), a case-class or companionapplyon a nested type, now links to the Scala case class or object it builds, and a Scala call no longer takes an unrelated Java constructor through a return-type annotation.Root cause
Scala qualified names carry no package (
Outer::Inner), so a call writtenOuter.Inner(...)found no type by its written name and fell through to the name strategies. Underdef f(): WebSocket = WebSocket.Accepted(flow), the local-declaration reader tookWebSocketfor the receiver's type and handed over an unrelated Java constructor (Other::Accepted::Accepted).From the contributor, and what we changed
From @danusha2345 (#1951), unchanged: the Scala
Outer.Innertype lookup before the receiver-word strategy (one file, or the call's own file; a class or trait before an object), the guard that keeps the typed-receiver path from handing a Scala call another language's constructor, and the fiveresolution.test.tscases.Our changes: the CHANGELOG bullet rewritten in the house format (without the "never guessed" claim: only the typed path is guarded, though the receiver-word strategy never produced such an edge in our fixtures or repos) and moved next to the JVM overload bullet. Rebased onto main
81559dcc, which has #2875 (#1950), #2874 and #2923 (#1936).Validation
Tests. 5 cases in
resolution.test.ts: 4 red on main, all green here; the fifth, a Scala call to a real Java static method, passes on both and guards that link.A/B against main
81559dcc(with #1950 and #1936), fresh indexes, edges compared by site (file, kind, position, ref name) and target identity (name, file, line):Triage:
Uci.Move(17),Uci.Drop(13),Position.AndFullMoveNumber(11),Clock.Config(7),Eval.Mate(an object); http4sHeader.Raw(66),H2Frame.Data(36),Uri.Ipv6Address(20),WebSocketFrame.Text(16),Uri.RegName(16),Request.Connectionover the same-namedheaders.Connection. playframework: all 291 are Scala applies of nested case classes, recorded as instantiations at 0.85:RemoteNode.Ip(54),RemoteNode.Obfuscated(53),RemoteNode.Unknown(33),NodePort.Numeric(31),HttpEntity.Strict(20),HttpEntity.Streamed(19),WebSocket.Accepted(15),ApplicationLoader.Contextunderimport play.api._beside the renamed JavaJApplicationLoader; these include theHttpEntityandWebSocketapplies that fix(play): look up Class.method among the class's own members, not the whole file #1950 unlinked from Java constructors.Origin.Host(...)moves from a 0.7 guess ondefaults::Hostto theOrigin.Hostcase class. playframework:Writeable.scala'sHttpEntity.Strict(...), in packageplay.api.http, moves from the Javaplay.http.HttpEntity.Strictconstructor to the Scala case class.UserActor.WatchStocks(...)andUserParentActor.Create(...)to Java constructors of another sample; this PR links both to their Scala case classes. On scalachess and http4s the two are independent: fix(play): look up Class.method among the class's own members, not the whole file #1950 gave +6 on scalachess and nothing on http4s, and this PR gives the same +77 and +371/-1 with or without it. The two merged cleanly in either order.Cost (http4s, median of 3 interleaved fresh indexes, measured on main
69af19ac, where the A/B gave the same edges as on81559dcc): wall 8.6 s on main vs 7.8 s with this PR, process CPU 27.5 s vs 26.2 s: within noise.Suite:
CODEGRAPH_KERNEL_EXPECT=1 npx vitest run --maxWorkers=4 --minWorkers=1onc3937888(Windows 11, kernel built): 760 files passed, 6 skipped; 9,037 tests passed, 83 skipped, 0 failed.Lands #1951 by @danusha2345.
🤖 Generated with Claude Code