Fix protected call to super method from lambda
Previously JVM back-end had an assumption that if we're calling a method declared in the super class from a lambda via a synthetic accessor, that should be a super call and it must be done with 'invokespecial'. Which is wrong because a method declared in the super class may be open and overridden in the subclass, so 'invokevirtual' should be used. Surprisingly, Java SE verifier allowed both instructions, but on Android only the latter is possible #KT-8899 Fixed #KT-9052 Fixed
This commit is contained in:
+49
@@ -0,0 +1,49 @@
|
||||
import test.A
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
open class B : A() {
|
||||
fun box(): String {
|
||||
val overriddenMethod: () -> String = {
|
||||
method()
|
||||
}
|
||||
assertEquals("C.method", overriddenMethod())
|
||||
|
||||
val superMethod: () -> String = {
|
||||
super.method()
|
||||
}
|
||||
assertEquals("A.method", superMethod())
|
||||
|
||||
val overriddenPropertyGetter: () -> String = {
|
||||
property
|
||||
}
|
||||
assertEquals("C.property", overriddenPropertyGetter())
|
||||
|
||||
val superPropertyGetter: () -> String = {
|
||||
super.property
|
||||
}
|
||||
assertEquals("A.property", superPropertyGetter())
|
||||
|
||||
val overriddenPropertySetter: () -> Unit = {
|
||||
property = ""
|
||||
}
|
||||
overriddenPropertySetter()
|
||||
|
||||
val superPropertySetter: () -> Unit = {
|
||||
super.property = ""
|
||||
}
|
||||
superPropertySetter()
|
||||
|
||||
assertEquals("C.property;A.property;", state)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
class C : B() {
|
||||
override fun method() = "C.method"
|
||||
override var property: String
|
||||
get() = "C.property"
|
||||
set(value) { state += "C.property;" }
|
||||
}
|
||||
|
||||
fun box() = C().box()
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package test
|
||||
|
||||
abstract class A {
|
||||
public var state = ""
|
||||
|
||||
// These implementations should not be called, because they are overridden in C
|
||||
|
||||
protected open fun method(): String = "A.method"
|
||||
|
||||
protected open var property: String
|
||||
get() = "A.property"
|
||||
set(value) { state += "A.property;" }
|
||||
}
|
||||
Reference in New Issue
Block a user