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()
fun build(): BuiltFunctionReference {
val numberOfParameters = unboundFunctionParameters.size
val functionParameterTypes = unboundFunctionParameters.map { it.type }
val superTypes = mutableListOf<IrType>()
val functionClass: IrClass
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 superClass = when {
isKSuspendFunction -> kSuspendFunctionImplSymbol.typeWith(referencedFunction.returnType)
isLambda -> irBuiltIns.anyType
else -> kFunctionImplSymbol.typeWith(referencedFunction.returnType)
}
val superTypes = mutableListOf(superClass)
if (samSuperType != null) {
superTypes += samSuperType
val constructor = buildConstructor()
val functionInvoke = if (isKSuspendFunction)
null
else
buildInvokeMethod(functionClass.getInvokeFunction())
val suspendFunctionInvoke = if (suspendFunctionClass == null)
null
else {
buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also {
if (isKSuspendFunction)
it.overriddenSymbols += functionClass.getInvokeFunction().symbol
val sam = samSuperClass!!.functions.single { it.owner.modality == Modality.ABSTRACT }
buildInvokeMethod(sam.owner)
} else {
val numberOfParameters = unboundFunctionParameters.size
val functionParameterTypes = unboundFunctionParameters.map { it.type }
val functionClass: IrClass
val suspendFunctionClass: IrClass?
if (isKSuspendFunction) {
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 {
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 }
val sam = samSuperClass?.functions?.single { it.owner.modality == Modality.ABSTRACT }
if (sam != null) {
if (sam.owner.extensionReceiverParameter != null)
buildInvokeMethod(sam.owner)
else {
// 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
if (!isKSuspendFunction)
buildInvokeMethod(functionClass.getInvokeFunction())
if (suspendFunctionClass != null) {
buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also {
if (isKSuspendFunction)
it.overriddenSymbols += functionClass.getInvokeFunction().symbol
}
}
}
@@ -329,7 +315,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
functionReferenceClass.addFakeOverrides(context.irBuiltIns)
return BuiltFunctionReference(functionReferenceClass, constructor)
return BuiltFunctionReference(functionReferenceClass, buildConstructor())
}
private fun buildConstructor(): IrConstructor =
@@ -2864,6 +2864,10 @@ standaloneTest("lambda14") {
flags = ['-tr']
}
task funInterface_implIsNotFunction(type: KonanLocalTest) {
source = "codegen/funInterface/implIsNotFunction.kt"
}
task objectExpression1(type: KonanLocalTest) {
goldValue = "aabb\n"
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" })
}