[NI] Record substituted generic signature for SAM arguments

#KT-36297 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2020-02-03 18:43:31 +03:00
parent 8ef79f932c
commit cb07c9172f
6 changed files with 113 additions and 1 deletions
@@ -0,0 +1,92 @@
// !LANGUAGE: +NewInference +SamConversionPerArgument +SamConversionForKotlinFunctions +FunctionalInterfaceConversion
// WITH_REFLECT
// FULL_JDK
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Provider.java
public class Provider {
public <T> String samCall(java.util.concurrent.Callable<? extends T> value) {
return "fail";
}
}
// FILE: test.kt
import java.util.concurrent.Callable
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import kotlin.reflect.KClass
import kotlin.test.assertEquals
private fun getFirstArgumentType(types: Array<Type>, klass: KClass<*>): String {
return types
.filterIsInstance<ParameterizedType>()
.firstOrNull { it.rawType == klass.java }
?.let { it.actualTypeArguments[0] }
?.toString() ?: "fail, inferred type is null"
}
class KtProvider : Provider() {
override fun <T : Any> samCall(value: Callable<out T>): String =
getFirstArgumentType(value.javaClass.genericInterfaces, Callable::class)
}
fun interface KtCallable<T> {
fun invoke(): T
}
fun <T : Any> samCallViaFunInterface(value: KtCallable<out T>): String {
return getFirstArgumentType(value.javaClass.genericInterfaces, KtCallable::class)
}
fun testCallViaJava(p: Provider): String {
var result = "not changed"
wrapInline {
wrapNoInline {
result = p.samCall { "str" }
}
}
return result
}
fun testCallViaKotlin(p: KtProvider): String {
var result = "not changed"
wrapInline {
wrapNoInline {
result = p.samCall { "str" }
}
}
return result
}
fun testCallViaFunInterface(): String {
var result = "not changed"
wrapInline {
wrapNoInline {
result = samCallViaFunInterface { "str" }
}
}
return result
}
inline fun wrapInline(f: () -> Unit) {
f()
}
fun wrapNoInline(f: () -> Unit) {
f()
}
fun box(): String {
val inferredTypeInSamLambda1 = testCallViaJava(KtProvider())
val inferredTypeInSamLambda2 = testCallViaKotlin(KtProvider())
val inferredTypeInSamLambda3 = testCallViaFunInterface()
assertEquals(inferredTypeInSamLambda1, inferredTypeInSamLambda2)
assertEquals(inferredTypeInSamLambda2, inferredTypeInSamLambda3)
return if (inferredTypeInSamLambda1 == "class java.lang.String") "OK" else "fail: $inferredTypeInSamLambda1"
}