You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Kotlin: call on the result of an unqualified helper (repository().m()) resolves to a same-named decoy in another package #2805
Related: #750 / #752 fixed Foo.factory().bar() for Kotlin. This is the neighbouring shape where the factory is an unqualified call (a same-class private helper, implicit this), plus its local-variable form. The helper declares its return type explicitly, so the information #752 relies on is there.
Repro
// src/main/kotlin/demo/domain/Repo.ktpackagedemo.domaininterfaceRepo {
funpending(id:Long): Int
}
The wrong edge needs the decoy in a different package. With all three classes in one package, both helper calls land on the interface method instead (imprecise, but not wrong).
Same results with the calls inside a lambda (runTest { … }), for / if blocks, a block-bodied helper, and suspend functions.
Impact
callers RealRepo::pending misses the helper-based call sites, and callers FakeRepo::pending gains a call it never receives. So impact / affected on a repository implementation under-reports its tests and points at the fake. This is the common Android test setup: a private repository() builder in the test class, and a shared fake in a testutil package.
In a larger private Kotlin codebase (~1.1k Kotlin files) the local-variable form went further: val repo = repository(); for (…) { repo.m(…) } inside runTest { } produced nocalls edge to m at all (the test's callees listed repository but not m). I couldn't reduce that variant: the toy project above resolves it to the interface. Treat it as an extra data point.
Expected
Infer the receiver type from the helper's declared return type for unqualified calls and for val x = helper() locals, the same way it already works for Foo.factory() (#752) and constructor-initialised locals. Per #750's invariant, when the type can't be validated, emit no edge rather than one to a same-named method on an unrelated class.
Happy to turn the repro into a fixture PR if that helps.
Thanks for the clear report and the four-file example, @mindcipherrr.
#2822 is merged to main and fixes both forms. With private fun repository(): RealRepo, both repository().pending(1) and val repo = repository(); repo.pending(1) now link to RealRepo.pending. That holds whether the helper is declared in the class, inherited from a base class or declared at the top level. When the declared type has no such method, the call now links to nothing instead of a same-named method elsewhere, and types from outside your project are still matched by name as before.
It ships in the next release; re-index your Kotlin project to pick it up. If the val repo = repository() local inside runTest { for (…) { … } } in your larger codebase still shows no edge after that, a small snippet with that shape would help us track it down.
Activity
fix(kotlin): repository().pending() links the method of the type repo…
colbymchenry commentedon Oct 23, 2026
Thanks for the clear report and the four-file example, @mindcipherrr.
#2822 is merged to
mainand fixes both forms. Withprivate fun repository(): RealRepo, bothrepository().pending(1)andval repo = repository(); repo.pending(1)now link toRealRepo.pending. That holds whether the helper is declared in the class, inherited from a base class or declared at the top level. When the declared type has no such method, the call now links to nothing instead of a same-named method elsewhere, and types from outside your project are still matched by name as before.It ships in the next release; re-index your Kotlin project to pick it up. If the
val repo = repository()local insiderunTest { for (…) { … } }in your larger codebase still shows no edge after that, a small snippet with that shape would help us track it down.fix(kotlin): repository().pending() links the method of the type repo…
fix(rust): kotlin repository().pending() links the method of the type…