This commit is contained in:
Igor Chevdar
2021-02-10 18:06:16 +05:00
committed by Vasily Levchenko
parent f6f050ff68
commit ab36e919bc
3 changed files with 66 additions and 57 deletions
@@ -263,65 +263,51 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
private val kSuspendFunctionImplConstructorSymbol = kSuspendFunctionImplSymbol.constructors.single() private val kSuspendFunctionImplConstructorSymbol = kSuspendFunctionImplSymbol.constructors.single()
fun build(): BuiltFunctionReference { fun build(): BuiltFunctionReference {
val numberOfParameters = unboundFunctionParameters.size val superClass = when {
val functionParameterTypes = unboundFunctionParameters.map { it.type } isKSuspendFunction -> kSuspendFunctionImplSymbol.typeWith(referencedFunction.returnType)
val superTypes = mutableListOf<IrType>() isLambda -> irBuiltIns.anyType
val functionClass: IrClass else -> kFunctionImplSymbol.typeWith(referencedFunction.returnType)
val suspendFunctionClass: IrClass?
if (isKSuspendFunction) {
superTypes += kSuspendFunctionImplSymbol.typeWith(referencedFunction.returnType)
functionClass = symbols.functionN(numberOfParameters + 1).owner
val continuationType = continuationClassSymbol.typeWith(referencedFunction.returnType)
superTypes += functionClass.typeWith(functionParameterTypes + continuationType + irBuiltIns.anyNType)
suspendFunctionClass = symbols.kSuspendFunctionN(numberOfParameters).owner
superTypes += suspendFunctionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
}
else {
superTypes += if (isLambda)
irBuiltIns.anyType
else
kFunctionImplSymbol.typeWith(referencedFunction.returnType)
functionClass = (if (isKFunction) symbols.kFunctionN(numberOfParameters) else symbols.functionN(numberOfParameters)).owner
superTypes += functionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
if (lastParameterType?.classifierOrNull != continuationClassSymbol)
suspendFunctionClass = null
else {
lastParameterType as IrSimpleType
// If the last parameter is Continuation<> inherit from SuspendFunction.
suspendFunctionClass = symbols.suspendFunctionN(numberOfParameters - 1).owner
val suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
(lastParameterType.arguments.single().typeOrNull ?: irBuiltIns.anyNType)
superTypes += suspendFunctionClass.symbol.typeWith(suspendFunctionClassTypeParameters)
}
} }
val superTypes = mutableListOf(superClass)
if (samSuperType != null) {
superTypes += samSuperType
val constructor = buildConstructor() val sam = samSuperClass!!.functions.single { it.owner.modality == Modality.ABSTRACT }
val functionInvoke = if (isKSuspendFunction) buildInvokeMethod(sam.owner)
null } else {
else val numberOfParameters = unboundFunctionParameters.size
buildInvokeMethod(functionClass.getInvokeFunction()) val functionParameterTypes = unboundFunctionParameters.map { it.type }
val suspendFunctionInvoke = if (suspendFunctionClass == null) val functionClass: IrClass
null val suspendFunctionClass: IrClass?
else { if (isKSuspendFunction) {
buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also { functionClass = symbols.functionN(numberOfParameters + 1).owner
if (isKSuspendFunction) val continuationType = continuationClassSymbol.typeWith(referencedFunction.returnType)
it.overriddenSymbols += functionClass.getInvokeFunction().symbol superTypes += functionClass.typeWith(functionParameterTypes + continuationType + irBuiltIns.anyNType)
suspendFunctionClass = symbols.kSuspendFunctionN(numberOfParameters).owner
superTypes += suspendFunctionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
} else {
functionClass = (if (isKFunction) symbols.kFunctionN(numberOfParameters) else symbols.functionN(numberOfParameters)).owner
superTypes += functionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
if (lastParameterType?.classifierOrNull != continuationClassSymbol)
suspendFunctionClass = null
else {
lastParameterType as IrSimpleType
// If the last parameter is Continuation<> inherit from SuspendFunction.
suspendFunctionClass = symbols.suspendFunctionN(numberOfParameters - 1).owner
val suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
(lastParameterType.arguments.single().typeOrNull ?: irBuiltIns.anyNType)
superTypes += suspendFunctionClass.symbol.typeWith(suspendFunctionClassTypeParameters)
}
} }
}
samSuperType?.let { superTypes += it } if (!isKSuspendFunction)
val sam = samSuperClass?.functions?.single { it.owner.modality == Modality.ABSTRACT } buildInvokeMethod(functionClass.getInvokeFunction())
if (sam != null) { if (suspendFunctionClass != null) {
if (sam.owner.extensionReceiverParameter != null) buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also {
buildInvokeMethod(sam.owner) if (isKSuspendFunction)
else { it.overriddenSymbols += functionClass.getInvokeFunction().symbol
// The signatures of SAM and [invoke] coincide - no need to build additional function. }
val properInvoke = if (sam.isSuspend)
suspendFunctionInvoke
else
functionInvoke
if (properInvoke != null)
properInvoke.overriddenSymbols += sam
} }
} }
@@ -329,7 +315,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
functionReferenceClass.addFakeOverrides(context.irBuiltIns) functionReferenceClass.addFakeOverrides(context.irBuiltIns)
return BuiltFunctionReference(functionReferenceClass, constructor) return BuiltFunctionReference(functionReferenceClass, buildConstructor())
} }
private fun buildConstructor(): IrConstructor = private fun buildConstructor(): IrConstructor =
@@ -2864,6 +2864,10 @@ standaloneTest("lambda14") {
flags = ['-tr'] flags = ['-tr']
} }
task funInterface_implIsNotFunction(type: KonanLocalTest) {
source = "codegen/funInterface/implIsNotFunction.kt"
}
task objectExpression1(type: KonanLocalTest) { task objectExpression1(type: KonanLocalTest) {
goldValue = "aabb\n" goldValue = "aabb\n"
source = "codegen/objectExpression/expr1.kt" source = "codegen/objectExpression/expr1.kt"
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package codegen.funInterface.implIsNotFunction
import kotlin.test.*
fun interface Foo {
fun invoke(): String
}
fun foo(f: Foo) = f is Function<*>
@Test
fun test() {
assertFalse(foo { "zzz" })
}