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,24 +263,29 @@ 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 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 sam = samSuperClass!!.functions.single { it.owner.modality == Modality.ABSTRACT }
buildInvokeMethod(sam.owner)
} else {
val numberOfParameters = unboundFunctionParameters.size val numberOfParameters = unboundFunctionParameters.size
val functionParameterTypes = unboundFunctionParameters.map { it.type } val functionParameterTypes = unboundFunctionParameters.map { it.type }
val superTypes = mutableListOf<IrType>()
val functionClass: IrClass val functionClass: IrClass
val suspendFunctionClass: IrClass? val suspendFunctionClass: IrClass?
if (isKSuspendFunction) { if (isKSuspendFunction) {
superTypes += kSuspendFunctionImplSymbol.typeWith(referencedFunction.returnType)
functionClass = symbols.functionN(numberOfParameters + 1).owner functionClass = symbols.functionN(numberOfParameters + 1).owner
val continuationType = continuationClassSymbol.typeWith(referencedFunction.returnType) val continuationType = continuationClassSymbol.typeWith(referencedFunction.returnType)
superTypes += functionClass.typeWith(functionParameterTypes + continuationType + irBuiltIns.anyNType) superTypes += functionClass.typeWith(functionParameterTypes + continuationType + irBuiltIns.anyNType)
suspendFunctionClass = symbols.kSuspendFunctionN(numberOfParameters).owner suspendFunctionClass = symbols.kSuspendFunctionN(numberOfParameters).owner
superTypes += suspendFunctionClass.typeWith(functionParameterTypes + referencedFunction.returnType) superTypes += suspendFunctionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
} } else {
else {
superTypes += if (isLambda)
irBuiltIns.anyType
else
kFunctionImplSymbol.typeWith(referencedFunction.returnType)
functionClass = (if (isKFunction) symbols.kFunctionN(numberOfParameters) else symbols.functionN(numberOfParameters)).owner functionClass = (if (isKFunction) symbols.kFunctionN(numberOfParameters) else symbols.functionN(numberOfParameters)).owner
superTypes += functionClass.typeWith(functionParameterTypes + referencedFunction.returnType) superTypes += functionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
@@ -296,40 +301,21 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
} }
} }
val constructor = buildConstructor() if (!isKSuspendFunction)
val functionInvoke = if (isKSuspendFunction)
null
else
buildInvokeMethod(functionClass.getInvokeFunction()) buildInvokeMethod(functionClass.getInvokeFunction())
val suspendFunctionInvoke = if (suspendFunctionClass == null) if (suspendFunctionClass != null) {
null
else {
buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also { buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also {
if (isKSuspendFunction) if (isKSuspendFunction)
it.overriddenSymbols += functionClass.getInvokeFunction().symbol it.overriddenSymbols += functionClass.getInvokeFunction().symbol
} }
} }
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
}
} }
functionReferenceClass.superTypes += superTypes functionReferenceClass.superTypes += superTypes
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" })
}