bbb0389c51
Enclosing class for closure is a class whose instance is captured by
closure as an outer 'this', and stored in a field 'this$0'.
Usually enclosing class for closure is an immediate outer class,
including classes for nested closures. For example:
class C {
fun foo() {}
val example1 = L1@ { foo() }
// Enclosing class for lambda 'L1' is 'C'
val example2 = L2a@ { L2b@ { foo() } }
// Enclosing class for nested lambda 'L2b'
// is a closure class for outer lambda 'L2a'
}
However, if the closure is created in a super type constructor call for
the outer class, corresponding instance is considered "uninitialized",
and can't be used as a proper class instance, and can't be referenced:
corresponding code is rejected by front-end.
class Outer {
fun foo() {}
inner class Inner : Base(L3@ { foo() })
// Enclosing class for lambda 'L3' is 'Outer',
// because 'Inner' is uninitialized in super type constructor call.
}
In CodegenAnnotatingVisitor, we maintain a stack of currently
uninitialized classes, and chose enclosing class for closure
as an inner-most surrounding class with initialized instance.
When generating code for this or outer class instance, we skip
contexts corresponding to classes with uninitialized instances.
This fixes a number of bytecode verification errors caused by incorrect
enclosing class for closure.
#KT-4174 Fixed Target versions 1.2.20
#KT-13454 Fixed Target versions 1.2.20
#KT-14148 Fixed Target versions 1.2.20
20 lines
279 B
Kotlin
Vendored
20 lines
279 B
Kotlin
Vendored
open class C(val s: String) {
|
|
fun test(): String {
|
|
return s
|
|
}
|
|
}
|
|
|
|
class B {
|
|
fun foo(): String {
|
|
var s = "OK"
|
|
class Z : C(s) {}
|
|
return Z().test()
|
|
}
|
|
}
|
|
|
|
|
|
fun box() : String {
|
|
val b = B()
|
|
val result = b.foo()
|
|
return result
|
|
} |