Implement script instance capturing in script lowering

for regular classes only. Reimplementing the main behavior of the
old BE and implementing few cases on top of it.
#KT-19423 fixed
This commit is contained in:
Ilya Chernikov
2021-11-24 15:51:02 +01:00
committed by TeamCityServer
parent 87952d63a3
commit cb5e451e05
22 changed files with 659 additions and 94 deletions
@@ -0,0 +1,17 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// expected: rv: 42
fun foo() = B.bar()
val life = 42
interface A {
fun bar(): Int
}
val B = object : A {
override fun bar() = life
}
val rv = foo()
@@ -0,0 +1,20 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// expected: rv: kotlin.Unit
fun foo() {
B()
}
val b = B()
class A
fun A.ext() = Unit
class B {
fun bar() {
A().ext()
}
}
val rv = foo()
@@ -0,0 +1,21 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// expected: rv: kotlin.Unit
class C {
fun foo() {
B()
}
}
class A
fun A.ext() = Unit
class B {
fun bar() {
A().ext()
}
}
val rv = C().foo()
@@ -0,0 +1,14 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// expected: rv: 42
val x = 6
val y = 7
fun foo() = x
class A {
fun bar() = foo() * y
}
val rv = A().bar()
@@ -0,0 +1,11 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// expected: rv: abc
// KT-19423
val used = "abc"
class User {
val property = used // error: Expression is inaccessible from a nested class
}
val rv = User().property
@@ -0,0 +1,18 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// expected: rv: 42
fun foo() = B().bar()
val life = 42
class A {
val x = "$life"
}
class B {
fun bar() = A().x
}
val rv = foo()
@@ -0,0 +1,18 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// expected: rv: 42
fun foo() = B().bar()
val life = 42
class A {
val x = life
}
class B {
fun bar() = A().x
}
val rv = foo()
@@ -0,0 +1,20 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM
// expected: rv: 42
class C {
fun foo() = B().bar()
}
val life = 42
class A {
val x = life
}
class B {
fun bar() = A().x
}
val rv = C().foo()
@@ -0,0 +1,15 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM, JVM_IR
// expected: rv: <nofield>
// KT-30616
val foo = "hello"
class Bar(val s: String) {
companion object {
fun t() {
Bar(foo)
}
}
}
@@ -0,0 +1,12 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM, JVM_IR
// expected: rv: <nofield>
// KT-30616
val foo = "hello"
enum class Bar(val s: String = foo) {
Eleven("0")
}
@@ -0,0 +1,11 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM, JVM_IR
// expected: rv: <nofield>
// KT-30616
val foo = "hello"
enum class Bar(val s: String) {
Eleven(s = foo)
}
@@ -0,0 +1,18 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM, JVM_IR
// expected: rv: 42
fun foo() = B().bar()
val life = 42
interface A {
val x get() = life
}
class B : A {
fun bar() = x
}
val rv = foo()
@@ -0,0 +1,14 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM, JVM_IR
// expected: rv: 42
fun foo() = B.bar()
val life = 42
object B {
fun bar() = life
}
val rv = foo()
@@ -0,0 +1,18 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM, JVM_IR
// expected: rv: 42
fun foo() = B.bar()
val life = 42
class A {
val x = life
}
object B {
fun bar() = A().x
}
val rv = foo()
@@ -0,0 +1,34 @@
// IGNORE_BACKEND: JS, JS_IR, JS_IR_ES6, NATIVE, WASM
// IGNORE_BACKEND: JVM_IR
// expected: rv: <nofield>
// This example shows a bug in the old BE
// original issue - KT-49443, this is the reduced example of it.
// Here the old BE manages to compile the script, because it assumes incorrect constructor of the DefaultEachEntryConfiguration class
// on generating code for buildZip.
// The original example from the issue works supposedly because the constructor is not called on the runtime.
// In this example, uncommenting call to buildZip leads to the runtime exception, while uncommenting the call to copy or
// moving DefaultEachEntryConfiguration class definition before ZipHelper breaks codegeneration (somewhat expectedly).
// The JVM IR BE now generates correct error about invalid script instance capturing.
interface I {
fun rename()
}
object ZipHelper {
fun buildZip() {
DefaultEachEntryConfiguration(0).rename()
// 0.copy()
}
}
class DefaultEachEntryConfiguration(val entry: Int) : I {
override fun rename() {
entry.copy()
}
}
fun Int.copy() = Unit
//ZipHelper.buildZip()