feat(resolution): conformance-aware chained-method resolution (#750)#754
Merged
Conversation
A chained static-factory/fluent call whose method lives on a SUPERTYPE the receiver conforms to — a protocol-extension method (Swift), an interface default method, or an inherited superclass method — now resolves. resolveMethodOnType falls back to walking the return type's implements/extends edges (via the new context.getSupertypes) when the method isn't a direct member. Because those edges don't exist during the single-pass resolution, a second pass (resolveChainedCallsViaConformance) re-resolves the deferred chained refs after edges are built. Still validated, so a wrong inference yields no edge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
colbymchenry
added a commit
that referenced
this pull request
Jun 9, 2026
…nsion naming (#750) (#755) Completes Swift in the #750 chained-call series (after Java #751, Kotlin #752, C# #753, conformance #754). Two parts: 1. Swift chained-call resolution (the #645/#608 mechanism): capture Swift return types (positional, member types -> last segment), encode capitalized-receiver chains `Foo.make().draw()` / `Foo(args).draw()`, resolve+validate via the shared matchDottedCallChain (+ constructor branch). Fixes the decoy wrong-edge bug where a chained method dropped to a bare name and attached to a same-named method on an unrelated class. 2. Nested-type extension naming fix: `extension KF.Builder: KFOptionSetter` parsed as a class_declaration named `KF.Builder` (dot) — inconsistent with the type's own declaration `KF::Builder` (name `Builder`) — so the extension's conformances and members were invisible to a chained call on the type. A Swift resolveName now names a nested-type extension by its last segment (`Builder`), so its `implements`/`extends` edges and methods are found by the supertype walk (conformance #754) and the simple-name method match. Validated: synthetic decoy + args + constructor + absent-method tests; full suite green; nested-extension repro (`KF.url().onSuccess()` resolves via conformance to the protocol method). Real-repo A/B vs main (conformance) — Alamofire and Kingfisher both **0 added / 0 removed, node count unchanged**: NEUTRAL and SAFE. The prior -168 Kingfisher regression (from the naming inconsistency) is eliminated; Swift's unique-named fluent methods already resolved by bare name, so the chain path lands the same edges — the value here is decoy-collision correctness, the nested-extension naming fix, and consistency with the other four languages. EXTRACTION_VERSION 9 -> 10. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 9, 2026
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.
Part of #750. A general resolver upgrade that makes chained-call resolution conformance-aware — it benefits the already-shipped Java/Kotlin/C# chained-call fixes and is a prerequisite for Swift.
Problem
The chained-call mechanism (#751/#752/#753) validates the chained method against the exact return type. But a chained method is often inherited from a superclass or declared on an interface/protocol the receiver conforms to — e.g.
Either.Right(x).combine(...), whereRightis a sealed subclass andcombinelives on the parentEither. Those chains found no edge even though the type was known.Fix
resolveMethodOnTypenow falls back to walking the receiver type's supertypes (a newcontext.getSupertypes, backed by the resolvedimplements/extendsedges) — transitively, depth-capped — when the method isn't a direct member. Still validated: the edge is created only when a supertype genuinely declares the method, so a wrong inference still yields no edge.resolveChainedCallsViaConformance, wired intoindexAll+syncafter edges are built). The batched resolver deletes unresolved refs from the DB, so they're carried in-memory rather than re-read.Validation
#662daemon test — passes in isolation).Either.Right(x).combine(),Option/Evalchains). Notably these include edges the Kotlin fix(kotlin): resolve chained companion-factory callsFoo.getInstance().bar()(#750) #752 A/B had dropped (exampleEither22 → Either::isRight), so this partially heals fix(kotlin): resolve chained companion-factory callsFoo.getInstance().bar()(#750) #752.EXTRACTION_VERSION8 → 9.🤖 Generated with Claude Code