JVM_IR: use indy SAM conversions in jvmTarget 1.8+, fix bridges

KT-44278 KT-26060 KT-42621
This commit is contained in:
Dmitry Petrov
2021-02-05 15:23:04 +03:00
parent 6c6d43c29a
commit 3ebeca5852
50 changed files with 1293 additions and 287 deletions
@@ -1,5 +1,6 @@
// TARGET_BACKEND: JVM
// SAM_CONVERSIONS: CLASS
// ^ test checks reflection for synthetic classes
// WITH_RUNTIME
// FILE: Test.java
@@ -9,9 +10,10 @@ class Test {
}
}
// FILE: test.kt
// FILE: samLambda.kt
import java.lang.reflect.Method
import kotlin.test.assertEquals
@Target(AnnotationTarget.FUNCTION)
@@ -8,6 +8,6 @@ fun lambdaIsSerializable(fn: () -> Unit) = fn is java.io.Serializable
fun box(): String {
if (lambdaIsSerializable {})
return "Failed: indy lambdas are not serializable"
return "Failed: indy lambdas should not be serializable"
return "OK"
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface KRunnable {
fun run()
}
var test = "Failed"
fun box(): String {
KRunnable { test = "OK" }.run()
return test
}
@@ -0,0 +1,13 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface IFooAny {
fun foo(x: Any): Any
}
fun interface IFooStr : IFooAny {
override fun foo(x: Any): String
}
fun box() = IFooStr { x: Any -> x.toString() }.foo("OK")
@@ -0,0 +1,20 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface IFooNStr {
fun foo(x: Any): String?
}
fun interface IFooNN : IFooNStr {
override fun foo(x: Any): Nothing?
}
fun box(): String {
var r = "Failed"
IFooNN {
r = it.toString()
null
}.foo("OK")
return r
}
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
// IGNORE_DEXING
fun interface GenericToAny<T> {
fun invoke(x: T): Any
}
fun interface GenericCharToAny : GenericToAny<Char>
fun withK(fn: GenericCharToAny) = fn.invoke('K').toString()
fun box(): String =
withK { "O" + it }
@@ -0,0 +1,18 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface GenericToAny<T> {
fun invoke(x: T): Any
}
fun interface CharToAny {
fun invoke(x: Char): Any
}
fun interface GenericCharToAny : GenericToAny<Char>, CharToAny
fun withK(fn: GenericCharToAny) = fn.invoke('K').toString()
fun box(): String =
withK { "O" + it }
@@ -0,0 +1,16 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface GenericToAny<T> {
fun invoke(x: T): Any
}
fun interface GenericCharToAny : GenericToAny<Char> {
override fun invoke(x: Char): Any
}
fun withK(fn: GenericCharToAny) = fn.invoke('K').toString()
fun box(): String =
withK { "O" + it }
@@ -0,0 +1,17 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface GenericToAny<T> {
fun invoke(x: T): Any
}
fun interface GenericIntToAny : GenericToAny<Int>
fun with4(fn: GenericIntToAny) = fn.invoke(4).toString()
fun box(): String =
with4 {
if (it != 4) throw Exception()
"OK"
}
@@ -0,0 +1,14 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface GenericToAny<T> {
fun invoke(x: T): Any
}
fun interface GenericStringToAny : GenericToAny<String>
fun withK(fn: GenericStringToAny) = fn.invoke("K").toString()
fun box(): String =
withK { "O" + it }
@@ -0,0 +1,22 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface IFoo<T> {
fun foo(): T
}
fun interface IFooUnit : IFoo<Unit> {
override fun foo()
}
fun <T> fooT(iFoo: IFoo<T>) = iFoo.foo()
fun fooUnit(iFooUnit: IFooUnit) { iFooUnit.foo() }
var ok = "Failed"
fun box(): String {
fooT { ok = "O" }
fooUnit { ok += "K" }
return ok
}
@@ -0,0 +1,40 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
// WITH_RUNTIME
fun interface IFooT<T> {
fun foo(x: T): T
}
fun interface IFooIntArray {
fun foo(x: IntArray): IntArray
}
fun interface IFooMix0 : IFooT<IntArray>, IFooIntArray
fun interface IFooMix1 : IFooT<IntArray>, IFooIntArray {
override fun foo(x: IntArray): IntArray
}
fun box(): String {
var t0 = "Failed 0"
val f0 = IFooMix0 {
t0 = "O" + it[0].toChar()
it
}
f0.foo(intArrayOf('K'.toInt()))
if (t0 != "OK")
return "Failed: t0=$t0"
var t1 = "Failed 1"
val f1 = IFooMix1 {
t1 = it[0].toChar() + "K"
it
}
f1.foo(intArrayOf('O'.toInt()))
if (t1 != "OK")
return "Failed: t1=$t1"
return "OK"
}
@@ -0,0 +1,29 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface IFooT<T> {
fun foo(x: T): T
}
fun interface IFooStr {
fun foo(x: String): String
}
fun interface IFooMix0 : IFooT<String>, IFooStr
fun interface IFooMix1 : IFooT<String>, IFooStr {
override fun foo(x: String): String
}
fun box(): String {
val f0 = IFooMix0 { "O" + it }
if (f0.foo("K") != "OK")
return "Failed: f0.foo(\"K\")=${f0.foo("K")}"
val f1 = IFooMix1 { it + "K" }
if (f1.foo("O") != "OK")
return "Failed: f1.foo(\"O\")=${f1.foo("O")}"
return "OK"
}
@@ -0,0 +1,32 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
// WITH_RUNTIME
fun interface IFooT<T> {
fun foo(x: Array<T>): T
}
fun interface IFooStr {
fun foo(x: Array<String>): String
}
fun interface IFooMix0 : IFooT<String>, IFooStr
fun interface IFooMix1 : IFooT<String>, IFooStr {
override fun foo(x: Array<String>): String
}
fun box(): String {
val f0 = IFooMix0 { "O" + it[0] }
val t0 = f0.foo(arrayOf("K"))
if (t0 != "OK")
return "Failed: t0=$t0"
val f1 = IFooMix1 { it[0] + "K" }
val t1 = f1.foo(arrayOf("O"))
if (t1 != "OK")
return "Failed: t1=$t1"
return "OK"
}
@@ -0,0 +1,32 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM
// IGNORE_LIGHT_ANALYSIS
// JVM_TARGET: 1.8
// SAM_CONVERSIONS: INDY
fun interface IFooT<T> {
fun foo(x: T): T
}
fun interface IFooInt {
fun foo(x: Int): Int
}
fun interface IFooMixed0 : IFooInt, IFooT<Int>
fun interface IFooMixed1 : IFooInt, IFooT<Int> {
override fun foo(x: Int): Int
}
fun box(): String {
val f0 = IFooMixed0 { it * 2 }
if (f0.foo(21) != 42)
return "Failed: f0.foo(21)=${f0.foo(21)}"
val f1 = IFooMixed1 { it * 2 }
if (f1.foo(21) != 42)
return "Failed: f1.foo(21)=${f1.foo(21)}"
return "OK"
}
@@ -1,6 +1,6 @@
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// LAMBDAS: INDY
// SAM_CONVERSIONS: INDY
fun interface IFoo<T> {
fun foo(): T
@@ -1,4 +1,6 @@
// TARGET_BACKEND: JVM
// SAM_CONVERSIONS: CLASS
// ^ SAM-convertion classes created with LambdaMetafactory have 'enclosingMethod' and 'enclosingClass'
// WITH_REFLECT
package test
@@ -17,7 +19,7 @@ fun box(): String {
val javaClass = lambda.javaClass
val enclosingMethod = javaClass.getEnclosingMethod()
if (enclosingMethod?.getName() != "run") return "method: $enclosingMethod"
if (enclosingMethod?.getName() != "run") return "enclosing method: $enclosingMethod"
val enclosingClass = javaClass.getEnclosingClass()!!.getName()
if (enclosingClass != "test.A\$prop\$1") return "enclosing class: $enclosingClass"
@@ -1,4 +1,6 @@
// TARGET_BACKEND: JVM
// SAM_CONVERSIONS: CLASS
// ^ test checks reflection for synthetic classes
// MODULE: lib
// FILE: JavaClass.java
+2
View File
@@ -1,5 +1,7 @@
// TARGET_BACKEND: JVM
// SKIP_JDK6
// SAM_CONVERSIONS: CLASS
// ^ test checks reflection for synthetic classes
// MODULE: lib
// FILE: Custom.java
@@ -1,5 +1,7 @@
// TARGET_BACKEND: JVM
// SKIP_JDK6
// SAM_CONVERSIONS: CLASS
// ^ test checks reflection for synthetic classes
// MODULE: lib
// FILE: Custom.java
+2
View File
@@ -1,6 +1,8 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
// SAM_CONVERSIONS: CLASS
// ^ test checks reflection for synthetic classes
// MODULE: lib
// FILE: Promise.java
import org.jetbrains.annotations.NotNull;
@@ -2,6 +2,8 @@
// WITH_REFLECT
// FULL_JDK
// TARGET_BACKEND: JVM
// SAM_CONVERSIONS: CLASS
// ^ SAM-convertion classes created with LambdaMetafactory have no generic signatures
// FILE: Provider.java
@@ -2,6 +2,8 @@
// TARGET_BACKEND: JVM
// SKIP_JDK6
// WITH_RUNTIME
// SAM_CONVERSIONS: CLASS
// ^ test checks reflection for synthetic classes
// MODULE: lib
// FILE: JavaClass.java