Provide configurable constructor call normalization

Three modes:

- 'disable' (default): normalize constructor calls in coroutines only
  (required because uninitialized objects can't be stored in fields),
  don't insert additional code for forced class initialization;

- 'enable': normalize constructor calls,
  don't insert additional code for forced class initialization;

- 'preserve-class-initialization': normalize constructor calls,
  insert additional code for forced class initialization.
This commit is contained in:
Dmitry Petrov
2017-10-05 16:29:14 +03:00
parent e71090ae4c
commit a89f978597
23 changed files with 323 additions and 33 deletions
+2
View File
@@ -5,6 +5,8 @@ where advanced options include:
or all modules on the module path if <module> is ALL-MODULE-PATH
-Xbuild-file=<path> Path to the .xml build file to compile
-Xcompile-java Reuse javac analysis and compile Java source files
-Xnormalize-constructor-calls={disable|enable|preserve-class-initialization}
Normalize constructor calls (disable: don't normalize; enable: normalize; preserve-class-initialization: normalize preserving class initialization order), default is disable
-Xdump-declarations-to=<path> Path to JSON file to dump Java to Kotlin declaration mappings
-Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade
-Xmodule-path=<path> Paths where to find Java 9+ modules
@@ -0,0 +1,41 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// KOTLIN_CONFIGURATION_FLAGS: CONSTRUCTOR_CALL_NORMALIZATION_MODE=disable
// FILE: test.kt
fun box(): String {
Foo(
logged("i", 1.let { it }),
logged("j",
Foo(
logged("k", 2.let { it }),
null
)
)
)
val result = log.toString()
if (result != "<clinit>ik<init>j<init>") return "Fail: '$result'"
return "OK"
}
// FILE: util.kt
val log = StringBuilder()
fun <T> logged(msg: String, value: T): T {
log.append(msg)
return value
}
// FILE: Foo.kt
class Foo(i: Int, j: Foo?) {
init {
log.append("<init>")
}
companion object {
init {
log.append("<clinit>")
}
}
}
@@ -0,0 +1,41 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// KOTLIN_CONFIGURATION_FLAGS: CONSTRUCTOR_CALL_NORMALIZATION_MODE=enable
// FILE: test.kt
fun box(): String {
Foo(
logged("i", 1.let { it }),
logged("j",
Foo(
logged("k", 2.let { it }),
null
)
)
)
val result = log.toString()
if (result != "ik<clinit><init>j<init>") return "Fail: '$result'"
return "OK"
}
// FILE: util.kt
val log = StringBuilder()
fun <T> logged(msg: String, value: T): T {
log.append(msg)
return value
}
// FILE: Foo.kt
class Foo(i: Int, j: Foo?) {
init {
log.append("<init>")
}
companion object {
init {
log.append("<clinit>")
}
}
}
@@ -0,0 +1,41 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// KOTLIN_CONFIGURATION_FLAGS: CONSTRUCTOR_CALL_NORMALIZATION_MODE=preserve-class-initialization
// FILE: test.kt
fun box(): String {
Foo(
logged("i", 1.let { it }),
logged("j",
Foo(
logged("k", 2.let { it }),
null
)
)
)
val result = log.toString()
if (result != "<clinit>ik<init>j<init>") return "Fail: '$result'"
return "OK"
}
// FILE: util.kt
val log = StringBuilder()
fun <T> logged(msg: String, value: T): T {
log.append(msg)
return value
}
// FILE: Foo.kt
class Foo(i: Int, j: Foo?) {
init {
log.append("<init>")
}
companion object {
init {
log.append("<clinit>")
}
}
}
@@ -49,7 +49,7 @@ fun box(): String {
}
}
if (logger.toString() != "A.<clinit>;args;A.<init>;") {
if (logger.toString() != "args;A.<clinit>;A.<init>;") {
return "Fail: '$logger'"
}