Johann Beleites
07/20/2022, 1:38 PMabstract class Base {
open fun foo() = "Base"
}
class A: Base()
class B: Base() {
override fun foo() = "B"
}
fun main(vararg args: String) {
val foo: Base = B()
if (foo is B) println(foo.foo())
}
The call to foo.foo()
in the main method results in B
to be printed, as expected. However, when I try to resolve foo.foo()
using the compiler, it resolves it to the implementation in Base
. This can be observed as well when pasting the code into IntelliJ and Ctrl + clicking
on foo.foo()
call.
If I change the line to println((foo as B).foo())
the static resolution works as expected and resolves to the implementation in B
. I don't know how exactly smart casts work internally, however, shouldn't the compiler resolve to B#foo
in both cases?mcpiroman
07/21/2022, 7:19 AMdmitriy.novozhilov
07/21/2022, 7:44 AMx.foo()
receiver has smartcast, compiler will look for function foo
firstly in scope of original type and then in scope of smartcasted type. If function foo
was found in both scopes and function from B
is not more specific than from A
(by signature), then compiler will chose function from original type
Lack of such mechanism may lead to issues like that: https://youtrack.jetbrains.com/issue/KT-51460