Lookup for local variables taking into account uninitialized this
Consider a context with uninitialized this, e.g.:
fun foo() {
val x = "..."
class Local(y: String) : Base(L@{ x + y })
}
Lambda 'L' is an argument of a super class constructor call.
Here 'this@Local' is not initialized yet. Thus local variables captured
in 'Local' can't be used. Instead, they should be captured by lambda 'L'
itself.
Note that lambda 'L' sees both 'x' and 'y' as local variables that
should be captured.
When in context with uninitialized this (generating arguments for super
type constructor or delegating constructor call), and a variable in
question is not found in the current context, use enclosing local lookup
to determine whether a local variable should be captured by a closure.
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
open class Base(val fn: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
val o = "O"
|
||||
|
||||
class Local {
|
||||
inner class Inner(k: String) : Base({ o + k })
|
||||
}
|
||||
|
||||
return Local().Inner("K").fn()
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
open class Base(val fn: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
class Local {
|
||||
inner class Inner(ok: String) : Base({ ok })
|
||||
}
|
||||
|
||||
return Local().Inner("OK").fn()
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
open class Base(val fn: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
class Local(val ok: String) {
|
||||
inner class Inner : Base({ ok })
|
||||
}
|
||||
|
||||
return Local("OK").Inner().fn()
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
interface Callback {
|
||||
fun invoke(): String
|
||||
}
|
||||
|
||||
open class Base(val fn: Callback)
|
||||
|
||||
fun box(): String {
|
||||
val ok = "OK"
|
||||
|
||||
class Local : Base(
|
||||
object : Callback {
|
||||
override fun invoke() = ok
|
||||
})
|
||||
|
||||
return Local().fn.invoke()
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
interface Callback {
|
||||
fun invoke(): String
|
||||
}
|
||||
|
||||
open class Base(val fn: Callback): Callback {
|
||||
override fun invoke() = fn.invoke()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val ok = "OK"
|
||||
|
||||
class Local : Base(
|
||||
object : Base(
|
||||
object : Callback {
|
||||
override fun invoke() = ok
|
||||
}
|
||||
) {}
|
||||
)
|
||||
|
||||
return Local().fn.invoke()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
open class Base(val fn: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
val ok = "OK"
|
||||
|
||||
class Local {
|
||||
inner class Inner : Base({ ok })
|
||||
}
|
||||
|
||||
return Local().Inner().fn()
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
open class Base(val fn: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
val o = "O"
|
||||
|
||||
class Local(k: String) : Base({ o + k })
|
||||
|
||||
return Local("K").fn()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
open class Base(val fn: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
val x = "O"
|
||||
|
||||
fun localFn() = x
|
||||
|
||||
class Local(y: String) : Base({ localFn() + y })
|
||||
|
||||
return Local("K").fn()
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
abstract class Base(val fn: () -> String)
|
||||
|
||||
open class Outer {
|
||||
val outerO = "O"
|
||||
|
||||
fun test(): Base {
|
||||
val localK = "K"
|
||||
class Local : Base({ outerO + localK })
|
||||
|
||||
return Local()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = Outer().test().fn()
|
||||
compiler/testData/codegen/box/closures/captureInSuperConstructorCall/outerCapturedInInlineLambda2.kt
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
open class Base(val callback: () -> String)
|
||||
|
||||
class Outer {
|
||||
val ok = "OK"
|
||||
|
||||
inner class Inner : Base(run { { ok } })
|
||||
}
|
||||
|
||||
fun box(): String =
|
||||
Outer().Inner().callback()
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
open class Foo(val x: () -> String)
|
||||
open class Foo2(val foo: Foo)
|
||||
|
||||
class Outer {
|
||||
val s = "OK"
|
||||
|
||||
inner class Inner : Foo2(Foo({ s }))
|
||||
}
|
||||
|
||||
fun box() = Outer().Inner().foo.x()
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
open class Outer(val fn: (() -> String)?) {
|
||||
companion object {
|
||||
val ok = "Fail: Companion.ok"
|
||||
}
|
||||
|
||||
val ok = "Fail: Outer.ok"
|
||||
|
||||
fun test(): Outer {
|
||||
val ok = "OK"
|
||||
class Local : Outer({ ok })
|
||||
|
||||
return Local()
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = Outer(null).test().fn?.invoke()!!
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
open class Outer(val fn: (() -> String)?) {
|
||||
companion object {
|
||||
val ok = "OK"
|
||||
}
|
||||
|
||||
val ok = "Fail: Outer.ok"
|
||||
|
||||
inner class Inner : Outer({ ok })
|
||||
}
|
||||
|
||||
fun box() = Outer(null).Inner().fn?.invoke()!!
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
open class Base(val fn1: () -> String, val fn2: () -> String)
|
||||
|
||||
fun box(): String {
|
||||
val x = "x"
|
||||
|
||||
class Local(y: String) : Base({ x + y }, { y + x })
|
||||
|
||||
val local = Local("y")
|
||||
val z1 = local.fn1()
|
||||
val z2 = local.fn2()
|
||||
|
||||
if (z1 != "xy") return "Fail: z1=$z1"
|
||||
if (z2 != "yx") return "Fail: z2=$z2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user