FIR: Support lambda inference from platform types

This commit is contained in:
Denis Zharkov
2019-09-09 18:27:09 +03:00
parent d787df3880
commit 6e51bed30c
5 changed files with 61 additions and 3 deletions
@@ -106,7 +106,7 @@ private fun extraLambdaInfo(
val isSuspend = expectedType?.isSuspendFunctionType ?: false
val isFunctionSupertype =
expectedType != null && expectedType.isBuiltinFunctionalType//isNotNullOrNullableFunctionSupertype(expectedType)
expectedType != null && expectedType.lowerBoundIfFlexible().isBuiltinFunctionalType//isNotNullOrNullableFunctionSupertype(expectedType)
val argumentAsFunctionExpression = argument//.safeAs<FunctionExpression>()
val typeVariable = TypeVariableForLambdaReturnType(argument, "_L")
@@ -133,7 +133,9 @@ internal fun extractLambdaInfoFromFunctionalType(
expectedTypeRef: FirTypeRef,
argument: FirAnonymousFunction
): ResolvedLambdaAtom? {
if (expectedType == null || !expectedType.isBuiltinFunctionalType) return null
if (expectedType == null) return null
if (expectedType is ConeFlexibleType) return extractLambdaInfoFromFunctionalType(expectedType.lowerBound, expectedTypeRef, argument)
if (!expectedType.isBuiltinFunctionalType) return null
val parameters = extractLambdaParameters(expectedType, argument)
val argumentAsFunctionExpression = argument//.safeAs<FunctionExpression>()
@@ -193,4 +195,4 @@ class ResolvedLambdaAtom(
override val inputTypes: Collection<ConeKotlinType> get() = receiver?.let { parameters + it } ?: parameters
override val outputType: ConeKotlinType get() = returnType
}
}
@@ -0,0 +1,22 @@
// WITH_RUNTIME
// FILE: JavaClass.java
public class JavaClass {
public static void foo1(kotlin.jvm.functions.Function0<Integer> x) {}
public static void foo2(kotlin.jvm.functions.Function1<Integer, String> x) {}
public static <T> void foo3(kotlin.jvm.functions.Function1<T, String> x, T y) {}
}
// FILE: main.kt
fun main() {
JavaClass.foo1 { 123 }
JavaClass.foo2 { (it + 2).toString() }
JavaClass.foo2({ (it + 3).toString() })
val y = { x: Int -> x.toString() }
JavaClass.foo2(y)
JavaClass.foo3({ (it + 4).toString() }, 5)
}
@@ -0,0 +1,24 @@
FILE: main.kt
public final fun main(): R|kotlin/Unit| {
Q|JavaClass|.R|/JavaClass.foo1|(<L> = foo1@fun <anonymous>(): R|ft<kotlin/Int, kotlin/Int?>!| <kind=EXACTLY_ONCE> {
Int(123)
}
)
Q|JavaClass|.R|/JavaClass.foo2|(<L> = foo2@fun <anonymous>(it: R|ft<kotlin/Int, kotlin/Int?>!|): R|ft<kotlin/String, kotlin/String?>!| <kind=EXACTLY_ONCE> {
R|<local>/it|.R|kotlin/Int.plus|(Int(2)).R|kotlin/Any.toString|()
}
)
Q|JavaClass|.R|/JavaClass.foo2|(foo2@fun <anonymous>(it: R|ft<kotlin/Int, kotlin/Int?>!|): R|ft<kotlin/String, kotlin/String?>!| <kind=EXACTLY_ONCE> {
R|<local>/it|.R|kotlin/Int.plus|(Int(3)).R|kotlin/Any.toString|()
}
)
lval y: R|kotlin/Function1<kotlin/Int, kotlin/String>| = fun <anonymous>(x: R|kotlin/Int|): R|kotlin/String| {
R|<local>/x|.R|kotlin/Any.toString|()
}
Q|JavaClass|.R|/JavaClass.foo2|(R|<local>/y|)
Q|JavaClass|.R|/JavaClass.foo3|<R|ft<kotlin/Int, kotlin/Int>|>(foo3@fun <anonymous>(it: R|ft<kotlin/Int, kotlin/Int>|): R|ft<kotlin/String, kotlin/String?>!| <kind=EXACTLY_ONCE> {
R|<local>/it|.R|kotlin/Int.plus|(Int(4)).R|kotlin/Any.toString|()
}
, Int(5))
}
@@ -6,11 +6,16 @@
package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class AbstractFirDiagnosticsTest : AbstractFirDiagnosticsSmokeTest() {
override fun getConfigurationKind(): ConfigurationKind {
return ConfigurationKind.ALL
}
override fun checkResultingFirFiles(
firFiles: MutableList<FirFile>,
testDataFile: File
@@ -46,6 +46,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/diagnostics/j+k/complexFlexibleInference.kt");
}
@TestMetadata("FunctionTypeInJava.kt")
public void testFunctionTypeInJava() throws Exception {
runTest("compiler/fir/resolve/testData/diagnostics/j+k/FunctionTypeInJava.kt");
}
@TestMetadata("KJKComplexHierarchy.kt")
public void testKJKComplexHierarchy() throws Exception {
runTest("compiler/fir/resolve/testData/diagnostics/j+k/KJKComplexHierarchy.kt");