JVM_IR KT-47939 use FunInterfaceConstructorReference as base class
This commit is contained in:
committed by
TeamCityServer
parent
0ccd7a7e0c
commit
93713a9ad4
+12
@@ -3603,6 +3603,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorIsKFunction.kt")
|
||||
public void testFunInterfaceConstructorIsKFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorIsKFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void testFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorThrowsNpe.kt")
|
||||
public void testFunInterfaceConstructorThrowsNpe() throws Exception {
|
||||
|
||||
+34
-30
@@ -593,6 +593,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
samSuperType
|
||||
?: when {
|
||||
isLambda -> context.ir.symbols.lambdaClass
|
||||
isAdaptedFunInterfaceConstructorReference -> context.ir.symbols.funInterfaceConstructorReferenceClass
|
||||
useOptimizedSuperClass -> when {
|
||||
isAdaptedReference -> context.ir.symbols.adaptedFunctionReference
|
||||
else -> context.ir.symbols.functionReferenceImpl
|
||||
@@ -743,22 +744,29 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
}
|
||||
|
||||
// Super constructor:
|
||||
// - For fun interface constructor references, super class is kotlin.jvm.internal.FunInterfaceConstructorReference
|
||||
// with single constructor 'public FunInterfaceConstructorReference(Class funInterface)'
|
||||
// - For SAM references, the super class is Any
|
||||
// - For lambdas, accepts arity
|
||||
// - For optimized function references (1.4+), accepts:
|
||||
// arity, [receiver], owner, name, signature, flags
|
||||
// - For unoptimized function references, accepts:
|
||||
// arity, [receiver]
|
||||
val constructor = if (samSuperType != null) {
|
||||
context.irBuiltIns.anyClass.owner.constructors.single()
|
||||
} else {
|
||||
val expectedArity =
|
||||
if (isLambda && !isAdaptedReference) 1
|
||||
else 1 + (if (boundReceiver != null) 1 else 0) + (if (useOptimizedSuperClass) 4 else 0)
|
||||
superType.getClass()!!.constructors.single {
|
||||
it.valueParameters.size == expectedArity
|
||||
val constructor =
|
||||
when {
|
||||
isAdaptedFunInterfaceConstructorReference ->
|
||||
context.ir.symbols.funInterfaceConstructorReferenceClass.owner.constructors.single()
|
||||
samSuperType != null ->
|
||||
context.irBuiltIns.anyClass.owner.constructors.single()
|
||||
else -> {
|
||||
val expectedArity =
|
||||
if (isLambda && !isAdaptedReference) 1
|
||||
else 1 + (if (boundReceiver != null) 1 else 0) + (if (useOptimizedSuperClass) 4 else 0)
|
||||
superType.getClass()!!.constructors.single {
|
||||
it.valueParameters.size == expectedArity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body = context.createJvmIrBuilder(symbol).run {
|
||||
irBlockBody(startOffset, endOffset) {
|
||||
@@ -776,28 +784,24 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
call: IrFunctionAccessExpression,
|
||||
generateBoundReceiver: IrBuilder.() -> IrExpression
|
||||
) {
|
||||
var index = 0
|
||||
call.putValueArgument(index++, irInt(argumentTypes.size + if (irFunctionReference.isSuspend) 1 else 0))
|
||||
if (boundReceiver != null) {
|
||||
call.putValueArgument(index++, generateBoundReceiver())
|
||||
}
|
||||
if (isAdaptedFunInterfaceConstructorReference) {
|
||||
val owner = kClassReference(constructedFunInterfaceSymbol!!.owner.defaultType)
|
||||
// owner: <FUN_INTERFACE_TYPE>
|
||||
call.putValueArgument(index++, kClassToJavaClass(owner))
|
||||
// name: ""
|
||||
call.putValueArgument(index++, irString(""))
|
||||
// signature: ""
|
||||
call.putValueArgument(index++, irString(""))
|
||||
// flags: 8 = 3 << 1
|
||||
call.putValueArgument(index, irInt(8))
|
||||
} else if (!isLambda && useOptimizedSuperClass) {
|
||||
val callableReferenceTarget = adaptedReferenceOriginalTarget ?: callee
|
||||
val owner = calculateOwnerKClass(callableReferenceTarget.parent)
|
||||
call.putValueArgument(index++, kClassToJavaClass(owner))
|
||||
call.putValueArgument(index++, irString(callableReferenceTarget.originalName.asString()))
|
||||
call.putValueArgument(index++, generateSignature(callableReferenceTarget.symbol))
|
||||
call.putValueArgument(index, irInt(getFunctionReferenceFlags(callableReferenceTarget)))
|
||||
val funInterfaceKClassRef = kClassReference(constructedFunInterfaceSymbol!!.owner.defaultType)
|
||||
val funInterfaceJavaClassRef = kClassToJavaClass(funInterfaceKClassRef)
|
||||
call.putValueArgument(0, funInterfaceJavaClassRef)
|
||||
} else {
|
||||
var index = 0
|
||||
call.putValueArgument(index++, irInt(argumentTypes.size + if (irFunctionReference.isSuspend) 1 else 0))
|
||||
if (boundReceiver != null) {
|
||||
call.putValueArgument(index++, generateBoundReceiver())
|
||||
}
|
||||
if (!isLambda && useOptimizedSuperClass) {
|
||||
val callableReferenceTarget = adaptedReferenceOriginalTarget ?: callee
|
||||
val owner = calculateOwnerKClass(callableReferenceTarget.parent)
|
||||
call.putValueArgument(index++, kClassToJavaClass(owner))
|
||||
call.putValueArgument(index++, irString(callableReferenceTarget.originalName.asString()))
|
||||
call.putValueArgument(index++, generateSignature(callableReferenceTarget.symbol))
|
||||
call.putValueArgument(index, irInt(getFunctionReferenceFlags(callableReferenceTarget)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -377,6 +377,14 @@ class JvmSymbols(
|
||||
}
|
||||
}
|
||||
|
||||
val funInterfaceConstructorReferenceClass =
|
||||
createClass(FqName("kotlin.jvm.internal.FunInterfaceConstructorReference"), classModality = Modality.OPEN) { irClass ->
|
||||
irClass.superTypes = listOf(irBuiltIns.anyType)
|
||||
irClass.addConstructor().also { irConstructor ->
|
||||
irConstructor.addValueParameter("funInterface", javaLangClass.starProjectedType)
|
||||
}
|
||||
}
|
||||
|
||||
fun getFunction(parameterCount: Int): IrClassSymbol = irBuiltIns.functionN(parameterCount).symbol
|
||||
|
||||
private val jvmFunctionClasses = storageManager.createMemoizedFunction { n: Int ->
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// !LANGUAGE: +KotlinFunInterfaceConstructorReference
|
||||
|
||||
// DONT_TARGET_EXACT_BACKEND: JVM
|
||||
// ^ old JVM BE generates bogus code
|
||||
|
||||
// IGNORE_BACKEND: JS
|
||||
// ^ Failed: kr is class Function1
|
||||
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KFunction
|
||||
|
||||
fun interface KRunnable {
|
||||
fun run()
|
||||
}
|
||||
|
||||
val kr = ::KRunnable // : KFunction1<() -> Unit, KRunnable>
|
||||
|
||||
fun box(): String {
|
||||
return if (kr is KFunction<*>)
|
||||
"OK"
|
||||
else
|
||||
"Failed: kr is ${kr::class}"
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// !LANGUAGE: +KotlinFunInterfaceConstructorReference
|
||||
|
||||
// IGNORE_BACKEND: JVM
|
||||
// ^ unsupported in old JVM BE
|
||||
|
||||
fun interface KRunnable {
|
||||
fun run()
|
||||
}
|
||||
|
||||
val kr = ::KRunnable // : KFunction1<() -> Unit, KRunnable>
|
||||
|
||||
fun box(): String {
|
||||
var test = "Failed"
|
||||
kr { test = "OK" }.run()
|
||||
return test
|
||||
}
|
||||
+3
-3
@@ -3520,9 +3520,9 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorThrowsNpe.kt")
|
||||
public void testFunInterfaceConstructorThrowsNpe() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorThrowsNpe.kt");
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void testFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -3603,6 +3603,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorIsKFunction.kt")
|
||||
public void testFunInterfaceConstructorIsKFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorIsKFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void testFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorThrowsNpe.kt")
|
||||
public void testFunInterfaceConstructorThrowsNpe() throws Exception {
|
||||
|
||||
+3
-3
@@ -3078,9 +3078,9 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("funInterfaceConstructorThrowsNpe.kt")
|
||||
public void ignoreFunInterfaceConstructorThrowsNpe() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorThrowsNpe.kt");
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void ignoreFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
|
||||
+12
@@ -2462,6 +2462,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
public void testFunInterfaceConstructorEquality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorIsKFunction.kt")
|
||||
public void testFunInterfaceConstructorIsKFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorIsKFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void testFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+12
@@ -2504,6 +2504,18 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
public void testFunInterfaceConstructorEquality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorIsKFunction.kt")
|
||||
public void testFunInterfaceConstructorIsKFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorIsKFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void testFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
+10
@@ -2230,6 +2230,16 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
public void testFunInterfaceConstructorEquality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("funInterfaceConstructorIsKFunction.kt")
|
||||
public void testFunInterfaceConstructorIsKFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorIsKFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void testFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/callableReference/function")
|
||||
|
||||
@@ -31,12 +31,6 @@ public class FunctionReference extends CallableReference implements FunctionBase
|
||||
* fun useSuspend(f: suspend () -> Unit) {}
|
||||
* useSuspend(::target)
|
||||
* </pre></ul>
|
||||
* <ul>3 - whether it is a synthetic <code>fun interface</code> constructor, i.e., <pre>
|
||||
* fun interface KRunnable {
|
||||
* fun run()
|
||||
* }
|
||||
* val kr: (() -> Unit) -> KRunnable = ::KRunnable
|
||||
* </pre></ul>
|
||||
* </li>
|
||||
*/
|
||||
@SinceKotlin(version = "1.4")
|
||||
|
||||
+12
@@ -2534,6 +2534,18 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest {
|
||||
public void testFunInterfaceConstructorEquality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorEquality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorIsKFunction.kt")
|
||||
public void testFunInterfaceConstructorIsKFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorIsKFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("funInterfaceConstructorOfImplicitKFunctionType.kt")
|
||||
public void testFunInterfaceConstructorOfImplicitKFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/funInterfaceConstructor/funInterfaceConstructorOfImplicitKFunctionType.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
Reference in New Issue
Block a user