[K/N] Transform FunctionReference without bound values to ConstantValue

This commit is contained in:
Pavel Kunyavskiy
2021-07-15 16:45:23 +03:00
committed by Space
parent e4a4cd3e16
commit 504d72011b
3 changed files with 42 additions and 26 deletions
@@ -146,38 +146,33 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
fun transformFunctionReference(expression: IrFunctionReference, samSuperType: IrType? = null): IrExpression {
val parent: IrDeclarationContainer = (currentClass?.irElement as? IrClass) ?: irFile
val loweredFunctionReference = FunctionReferenceBuilder(irFile, parent, expression, samSuperType).build()
generatedClasses.add(loweredFunctionReference.functionReferenceClass)
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol,
expression.startOffset, expression.endOffset)
return irBuilder.irCall(loweredFunctionReference.functionReferenceConstructor.symbol).apply {
expression.getArguments().forEachIndexed { index, argument ->
putValueArgument(index, argument.second)
}
}
val (clazz, newExpression) = FunctionReferenceBuilder(irFile, parent, expression, context, irBuilder, samSuperType).build()
generatedClasses.add(clazz)
return newExpression
}
}, data = null)
irFile.declarations += generatedClasses
}
private class BuiltFunctionReference(val functionReferenceClass: IrClass,
val functionReferenceConstructor: IrConstructor)
private val VOLATILE_LAMBDA_FQ_NAME = FqName.fromSegments(listOf("kotlin", "native", "internal", "VolatileLambda"))
private val symbols = context.ir.symbols
private val irBuiltIns = context.irBuiltIns
private val getContinuationSymbol = symbols.getContinuation
private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol
private inner class FunctionReferenceBuilder(
class FunctionReferenceBuilder(
val irFile: IrFile,
val parent: IrDeclarationParent,
val functionReference: IrFunctionReference,
val samSuperType: IrType?
val context: Context,
val irBuilder: IrBuilderWithScope,
val samSuperType: IrType? = null,
) {
data class BuiltFunctionReference(val functionReferenceClass: IrClass, val functionReferenceExpression: IrExpression)
private val irBuiltIns = context.irBuiltIns
private val symbols = context.ir.symbols
private val getContinuationSymbol = symbols.getContinuation
private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol
private val startOffset = functionReference.startOffset
private val endOffset = functionReference.endOffset
private val referencedFunction = functionReference.symbol.owner
@@ -243,7 +238,7 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
private val kSuspendFunctionImplSymbol = symbols.kSuspendFunctionImpl
private val kSuspendFunctionImplConstructorSymbol = kSuspendFunctionImplSymbol.constructors.single()
fun build(): BuiltFunctionReference {
private fun buildClass(): IrClass {
val superClass = when {
isKSuspendFunction -> kSuspendFunctionImplSymbol.typeWith(referencedFunction.returnType)
isLambda -> irBuiltIns.anyType
@@ -296,11 +291,11 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
functionReferenceClass.addFakeOverrides(context.typeSystem)
return BuiltFunctionReference(functionReferenceClass, buildConstructor())
return functionReferenceClass
}
private fun buildConstructor(): IrConstructor =
IrConstructorImpl(
private fun buildConstructor(): IrConstructor {
return IrConstructorImpl(
startOffset, endOffset,
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
IrConstructorSymbolImpl(),
@@ -348,6 +343,23 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
}
}
}
}
fun build(): BuiltFunctionReference {
val clazz = buildClass()
val constructor = buildConstructor()
val arguments = functionReference.getArguments()
val expression = if (arguments.isEmpty()) {
irBuilder.irConstantObject(clazz, emptyMap())
} else {
irBuilder.irCall(constructor).apply {
arguments.forEachIndexed { index, argument ->
putValueArgument(index, argument.second)
}
}
}
return BuiltFunctionReference(clazz, expression)
}
private fun getFlags() =
(if (referencedFunction.isSuspend) 1 else 0) + getAdaptedCallableReferenceFlags() shl 1
@@ -385,8 +397,8 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
return false
}
private fun buildInvokeMethod(superFunction: IrSimpleFunction): IrSimpleFunction =
IrFunctionImpl(
private fun buildInvokeMethod(superFunction: IrSimpleFunction): IrSimpleFunction {
return IrFunctionImpl(
startOffset, endOffset,
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
IrSimpleFunctionSymbolImpl(),
@@ -452,5 +464,6 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
)
}
}
}
}
}
@@ -8,8 +8,9 @@ import kotlin.native.concurrent.*
import kotlin.native.internal.*
fun mainLegacyMM() {
val wrong = "wrong"
assertFailsWith<InvalidMutabilityException> {
setUnhandledExceptionHook { _ -> println("wrong") }
setUnhandledExceptionHook { _ -> println(wrong) }
}
val x = 42
@@ -49,14 +49,16 @@ fun withLock(op: () -> Unit) {
}
} else {
assertFailsWith<IllegalStateException> {
val message = "shall not happen"
worker.executeAfter {
println("shall not happen")
println(message)
}
}
}
assertFailsWith<IllegalArgumentException> {
val message = "shall not happen"
worker.executeAfter(-1, {
println("shall not happen")
println(message)
}.freeze())
}