Kotlin nested lambdas are stripped
Java class file shrinker, optimizer, obfuscator, and preverifier
Brought to you by:
guardsquare
Referencing https://discuss.kotlinlang.org/t/proguard-cant-process-this-simple-code/7054
Proguard fails to optizime the following code in Kotlin.
This seems to be a pattern that pops up in Kotlin based Android apps, or at least did for me the other day. I worked around this fairly easily with a helper method, but definitely unfortunate.
main.kt
fun main(args: Array<String>) {
Error().run()
}
error.kt
class Error {
fun run() {
with(TestEnum.CASE) {
runLambda {
runLambda {
println("Hello, World!")
}
}
}
}
private fun runLambda(lambda: () -> Unit) = lambda()
}
enum class TestEnum {
CASE
}
// Alternatively even more simply
/*
class Error {
fun run() {
with(Unit) {
runLambda {
runLambda {
println("Hello, World!")
}
}
}
}
private fun runLambda(lambda: () -> Unit) = lambda()
}
*/
myconfig.pro
-injars proguard-bug.jar
-outjars proguard-bug_out.jar
-libraryjars <java.home>/lib/rt.jar
-keep public class MainKt {
public static void main(java.lang.String[]);
}
-keep class org.jetbrains.annotations.** {
public protected *;
}
-keep class kotlin.** {
public protected *;
}
-dontnote kotlin.internal.PlatformImplementationsKt
-keepattributes Signature
-dontnote kotlin.reflect.jvm.internal.**
Compile instructions + Expected result
kotlinc . -include-runtime -d proguard-bug.jar
java -jar proguard-bug.jar
# Hello world!
./proguard6.0.3/bin/proguard.sh @myconfig.pro
# ...
# Warning: Error$run$1$1$1: can't find referenced class Error$run$1$1
# Warning: Error$run$1$1$1: can't find referenced class Error$run$1$1
# ...
Kotlin version 1.2.51
Java version 1.8.0_172
ProGuard version 6.0.3
Thanks for your report. The class
Error$run$1$1$1in the compiled Kotlin code references a classError$run$1$1which is not present. The reference is from a constant that is not actually used in the code, so technically the compiled code is valid. However, ProGuard tries to resolve all references before finding out that the constant is not used (and removing it). Hopefully the Kotlin compiler will clean up its generated code somewhat in the future. For the time being, you can work around it by letting ProGuard accept the missing reference:You can use wildcards if you have many such cases.
It's not necessary to explicitly preserve the Jetbrains annotations or Kotlin runtime in your configuration.