Move extension receiver to value parameters for static functions created

during InlineClassLowering phase.

This was the only place where both dispatch and extension receivers were
NOT moved to value parameters, which meant that the receivers were not
following the conventional ordering.

Merged createStaticBodilessMethod with createStaticFunctionWithReceivers
and the latter was moved to backend/common/ir/IrUtils.kt.
This commit is contained in:
Mark Punzalan
2019-06-27 21:42:44 -07:00
committed by max-kammerer
parent 1abdf0561a
commit 969478481e
13 changed files with 129 additions and 197 deletions
@@ -20,9 +20,11 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.Scope
@@ -499,3 +501,58 @@ fun IrClass.addFakeOverrides() {
declarations += fakeOverriddenFunctions.values
}
fun createStaticFunctionWithReceivers(
irParent: IrDeclarationParent,
name: Name,
oldFunction: IrFunction,
dispatchReceiverType: IrType? = oldFunction.dispatchReceiverParameter?.type,
origin: IrDeclarationOrigin = oldFunction.origin,
copyBody: Boolean = true
): IrSimpleFunction {
val descriptor = WrappedSimpleFunctionDescriptor(Annotations.EMPTY, oldFunction.descriptor.source)
return IrFunctionImpl(
oldFunction.startOffset, oldFunction.endOffset,
origin,
IrSimpleFunctionSymbolImpl(descriptor),
name,
oldFunction.visibility,
Modality.FINAL,
oldFunction.returnType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false
).apply {
descriptor.bind(this)
parent = irParent
copyTypeParametersFrom(oldFunction)
annotations.addAll(oldFunction.annotations)
var offset = 0
val dispatchReceiver = oldFunction.dispatchReceiverParameter?.copyTo(
this,
name = Name.identifier("this"),
index = offset++,
type = dispatchReceiverType!!
)
val extensionReceiver = oldFunction.extensionReceiverParameter?.copyTo(
this,
name = Name.identifier("receiver"),
index = offset++
)
valueParameters.addAll(listOfNotNull(dispatchReceiver, extensionReceiver) +
oldFunction.valueParameters.map { it.copyTo(this, index = it.index + offset) }
)
val mapping: Map<IrValueParameter, IrValueParameter> =
(listOfNotNull(oldFunction.dispatchReceiverParameter, oldFunction.extensionReceiverParameter) + oldFunction.valueParameters)
.zip(valueParameters).toMap()
if (copyBody) {
body = oldFunction.body
?.transform(VariableRemapper(mapping), null)
?.patchDeclarationParents(this)
}
metadata = oldFunction.metadata
}
}
@@ -8,18 +8,13 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.backend.common.ir.createStaticFunctionWithReceivers
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -142,10 +137,12 @@ class InlineClassLowering(val context: BackendContext) {
staticMethod.valueParameters[0]
function.extensionReceiverParameter ->
staticMethod.extensionReceiverParameter!!
staticMethod.valueParameters[1]
in function.valueParameters ->
staticMethod.valueParameters[valueDeclaration.index + 1]
in function.valueParameters -> {
val offset = if (function.extensionReceiverParameter != null) 2 else 1
staticMethod.valueParameters[valueDeclaration.index + offset]
}
else -> return expression
}
@@ -163,13 +160,14 @@ class InlineClassLowering(val context: BackendContext) {
+irReturn(
irCall(staticMethod).apply {
val parameters =
listOf(function.dispatchReceiverParameter!!) + function.valueParameters
listOfNotNull(
function.dispatchReceiverParameter!!,
function.extensionReceiverParameter
) + function.valueParameters
for ((index, valueParameter) in parameters.withIndex()) {
putValueArgument(index, irGet(valueParameter))
}
extensionReceiver = function.extensionReceiverParameter?.let { irGet(it) }
}
)
}
@@ -190,7 +188,7 @@ class InlineClassLowering(val context: BackendContext) {
return expression
}
return irCall(expression, getOrCreateStaticMethod(function), dispatchReceiverAsArgument = false)
return irCall(expression, getOrCreateStaticMethod(function))
}
override fun visitCall(expression: IrCall): IrExpression {
@@ -208,7 +206,7 @@ class InlineClassLowering(val context: BackendContext) {
return irCall(
expression,
getOrCreateStaticMethod(function),
dispatchReceiverAsArgument = (function is IrSimpleFunction)
receiversAsArguments = (function is IrSimpleFunction)
)
}
@@ -219,11 +217,7 @@ class InlineClassLowering(val context: BackendContext) {
return when {
!klass.isInline -> expression
function.isPrimary -> irConstructorCall(expression, function)
else -> irCall(expression, getOrCreateStaticMethod(function)).apply {
(0 until expression.valueArgumentsCount).forEach {
putValueArgument(it, expression.getValueArgument(it)!!)
}
}
else -> irCall(expression, getOrCreateStaticMethod(function))
}
}
@@ -242,36 +236,6 @@ class InlineClassLowering(val context: BackendContext) {
else -> Name.identifier(asString() + INLINE_CLASS_IMPL_SUFFIX)
}
private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction {
val descriptor = WrappedSimpleFunctionDescriptor()
return IrFunctionImpl(
function.startOffset,
function.endOffset,
function.origin,
IrSimpleFunctionSymbolImpl(descriptor),
function.name.toInlineClassImplementationName(),
function.visibility,
Modality.FINAL,
function.returnType,
function.isInline,
function.isExternal,
(function is IrSimpleFunction && function.isTailrec),
(function is IrSimpleFunction && function.isSuspend)
).apply {
descriptor.bind(this)
copyTypeParametersFrom(function)
annotations += function.annotations
dispatchReceiverParameter = null
extensionReceiverParameter = function.extensionReceiverParameter?.copyTo(this)
if (function is IrSimpleFunction) {
valueParameters.add(function.dispatchReceiverParameter!!.let { p -> p.copyTo(this, index = p.index + 1) })
valueParameters += function.valueParameters.map { p -> p.copyTo(this, index = p.index + 1) }
} else {
valueParameters += function.valueParameters.map { p -> p.copyTo(this) }
}
parent = function.parent
assert(isStaticMethodOfClass)
}
}
private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction =
createStaticFunctionWithReceivers(function.parent, function.name.toInlineClassImplementationName(), function, copyBody = false)
}