JVM_IR: correct some type parameter bugs

This commit is contained in:
Georgy Bronnikov
2019-04-15 00:27:37 +03:00
parent 3e6171aefc
commit ad70a68671
17 changed files with 84 additions and 42 deletions
@@ -153,6 +153,7 @@ fun IrValueParameter.copyTo(
descriptor.bind(it)
it.parent = irFunction
it.defaultValue = defaultValueCopy
it.annotations.addAll(annotations.map { it.deepCopyWithSymbols() })
}
}
@@ -252,6 +253,12 @@ fun IrFunction.copyValueParametersToStatic(
}
}
fun IrFunctionAccessExpression.passTypeArgumentsFrom(irFunction: IrTypeParametersContainer, offset: Int = 0) {
irFunction.typeParameters.forEachIndexed { i, param ->
putTypeArgument(i + offset, param.defaultType)
}
}
/*
Type parameters should correspond to the function where they are defined.
`source` is where the type is originally taken from.
@@ -463,4 +470,7 @@ fun IrClass.addFakeOverrides() {
.toMutableMap()
declarations += fakeOverriddenFunctions.values
}
}
fun IrValueParameter.isInlineParameter() =
!isNoinline && !type.isNullable() && type.isFunctionOrKFunction()
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement
@@ -136,11 +134,10 @@ open class DefaultArgumentStubGenerator(
endOffset = irFunction.endOffset,
type = context.irBuiltIns.unitType,
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor,
typeArgumentsCount = irFunction.typeParameters.size
typeArgumentsCount = newIrFunction.parentAsClass.typeParameters.size + newIrFunction.typeParameters.size
).apply {
newIrFunction.typeParameters.forEachIndexed { i, param ->
putTypeArgument(i, param.defaultType)
}
passTypeArgumentsFrom(newIrFunction.parentAsClass)
passTypeArgumentsFrom(newIrFunction)
dispatchReceiver = newIrFunction.dispatchReceiverParameter?.let { irGet(it) }
params.forEachIndexed { i, variable -> putValueArgument(i, irGet(variable)) }
@@ -164,9 +161,7 @@ open class DefaultArgumentStubGenerator(
params: MutableList<IrVariable>
): IrExpression {
val dispatchCall = irCall(irFunction).apply {
newIrFunction.typeParameters.forEachIndexed { i, param ->
putTypeArgument(i, param.defaultType)
}
passTypeArgumentsFrom(newIrFunction)
dispatchReceiver = newIrFunction.dispatchReceiverParameter?.let { irGet(it) }
extensionReceiver = newIrFunction.extensionReceiverParameter?.let { irGet(it) }
@@ -148,6 +148,7 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
expression.startOffset, expression.endOffset, expression.type, newCallee.symbol, expression.origin
)
newCall.copyTypeArgumentsFrom(expression)
newCall.putValueArgument(0, dispatchReceiver)
for (i in 1..newCallee.valueParameters.lastIndex) {
newCall.putValueArgument(i, expression.getValueArgument(i - 1))
@@ -166,7 +167,7 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(classConstructor)
val newCall = IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee.symbol, newCallee.descriptor,
classConstructor.typeParameters.size
expression.typeArgumentsCount
).apply { copyTypeArgumentsFrom(expression) }
newCall.putValueArgument(0, dispatchReceiver)
@@ -129,7 +129,7 @@ private class AnnotationLowering(private val context: JvmBackendContext) : FileL
?.takeIf { (it.parent as? IrClass)?.isAnnotationClass ?: false }
?: return super.visitCall(expression)
val field = function.correspondingProperty?.backingField
val field = function.correspondingPropertySymbol?.owner?.backingField
?: return super.visitCall(expression)
// Wrap the property access with a call to getOrCreateKClass(es) and fix the type
@@ -154,7 +154,7 @@ private class AnnotationLowering(private val context: JvmBackendContext) : FileL
}
private fun IrCall.isGetJava(): Boolean =
context.irIntrinsics.getIntrinsic(descriptor.original) is KClassJavaProperty
context.irIntrinsics.getIntrinsic(descriptor) is KClassJavaProperty
}
private fun IrClassSymbol.getFunctionByName(name: String, numParams: Int): IrSimpleFunctionSymbol =
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.util.defaultType
@@ -233,6 +234,7 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
).apply {
descriptor.bind(this)
parent = irClass
copyTypeParametersFrom(target)
// Have to specify type explicitly to prevent an attempt to remap it.
dispatchReceiverParameter = irClass.thisReceiver?.copyTo(this, type = irClass.defaultType)
@@ -275,6 +277,7 @@ private class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass
origin = IrStatementOrigin.BRIDGE_DELEGATION,
superQualifierSymbol = if (invokeStatically) maybeOrphanedTarget.parentAsClass.symbol else null
).apply {
passTypeArgumentsFrom(this@createBridgeBody)
dispatchReceiver = irImplicitCast(irGet(dispatchReceiverParameter!!), dispatchReceiverParameter!!.type)
extensionReceiverParameter?.let {
extensionReceiver = irImplicitCast(irGet(it), extensionReceiverParameter!!.type)
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
@@ -107,7 +108,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
) {
val vararg = IrVarargImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.ir.symbols.array.typeWith(),
context.ir.symbols.array.typeWith(context.irBuiltIns.anyNType),
context.irBuiltIns.anyClass.typeWith(),
(0 until argumentsCount).map { i -> expression.getValueArgument(i)!! }
)
@@ -172,11 +173,14 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
private val boundCalleeParameters = irFunctionReference.getArgumentsWithIr().map { it.first }
private val unboundCalleeParameters = calleeParameters - boundCalleeParameters
private val typeArgumentsMap = callee.typeParameters.associate { typeParam ->
typeParam to irFunctionReference.getTypeArgument(typeParam.index)!!
private val typeParameters = if (callee is IrConstructor)
callee.parentAsClass.typeParameters + callee.typeParameters
else
callee.typeParameters
private val typeArgumentsMap = typeParameters.associate { typeParam ->
typeParam.symbol to irFunctionReference.getTypeArgument(typeParam.index)!!
}
private lateinit var functionReferenceClass: IrClass
private lateinit var functionReferenceThis: IrValueParameterSymbol
private lateinit var argumentToFieldMap: Map<IrValueParameter, IrField>
@@ -189,9 +193,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
fun build(): BuiltFunctionReference {
val returnType = irFunctionReference.symbol.owner.returnType
val functionReferenceClassSuperTypes: MutableList<IrType> = mutableListOf(
functionReferenceOrLambda.owner.defaultType // type arguments?
)
val functionReferenceClassSuperTypes: MutableList<IrType> = mutableListOf(functionReferenceOrLambda.owner.defaultType)
val numberOfParameters = unboundCalleeParameters.size
useVararg = (numberOfParameters > MAX_ARGCOUNT_WITHOUT_VARARG)
@@ -392,6 +394,10 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
}
+irReturn(
irCall(irFunctionReference.symbol).apply {
for ((typeParameter, typeArgument) in typeArgumentsMap) {
putTypeArgument(typeParameter.owner.index, typeArgument)
}
var unboundIndex = 0
calleeParameters.forEach { parameter ->
@@ -592,7 +598,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
}
// TODO: Move to IrUtils
private fun IrType.substitute(substitutionMap: Map<IrTypeParameter, IrType>): IrType {
private fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType {
if (this !is IrSimpleType) return this
substitutionMap[classifier]?.let { return it }
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name
@@ -148,6 +150,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
+irReturn(
irCall(defaultImplFun.symbol, irFunction.returnType).apply {
var offset = 0
passTypeArgumentsFrom(irFunction)
irFunction.dispatchReceiverParameter?.let { putValueArgument(offset++, irGet(it)) }
irFunction.extensionReceiverParameter?.let { putValueArgument(offset++, irGet(it)) }
irFunction.valueParameters.mapIndexed { i, parameter -> putValueArgument(i + offset, irGet(parameter)) }
@@ -10,6 +10,7 @@ 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.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.common.lower.replaceThisByStaticReference
@@ -129,6 +130,8 @@ private class CompanionObjectJvmStaticLowering(val context: JvmBackendContext) :
val companionInstanceFieldSymbol = companionInstanceField.symbol
val call = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target.returnType, target.symbol)
call.passTypeArgumentsFrom(proxy)
call.dispatchReceiver = IrGetFieldImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
@@ -211,4 +214,4 @@ private class MakeCallsStatic(
private fun isJvmStaticFunction(declaration: IrDeclaration): Boolean =
declaration is IrSimpleFunction &&
(declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) ||
declaration.correspondingProperty?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true)
declaration.correspondingPropertySymbol?.owner?.hasAnnotation(JVM_STATIC_ANNOTATION_FQ_NAME) == true)
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
@@ -342,14 +343,20 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
expression.getter?.owner?.let { getter ->
buildOverride(superClass.functions.single { it.name.asString() == "get" }) { valueParameters ->
irGet(getter.returnType, null, getter.symbol).apply { setReceiversOn(this, valueParameters) }
irGet(getter.returnType, null, getter.symbol).apply {
copyTypeArgumentsFrom(expression)
setReceiversOn(this, valueParameters)
}
}
}
expression.setter?.owner?.let { setter ->
buildOverride(superClass.functions.single { it.name.asString() == "set" }) { valueParameters ->
val value = irGet(valueParameters.last())
irSet(setter.returnType, null, setter.symbol, value).apply { setReceiversOn(this, valueParameters) }
irSet(setter.returnType, null, setter.symbol, value).apply {
copyTypeArgumentsFrom(expression)
setReceiversOn(this, valueParameters)
}
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.copyValueParametersToStatic
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.ir.remapTypeParameters
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
@@ -125,7 +126,8 @@ private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElem
IrDelegatingConstructorCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.irBuiltIns.unitType,
targetSymbol, targetSymbol.descriptor, targetSymbol.owner.typeParameters.size
targetSymbol, targetSymbol.descriptor,
targetSymbol.owner.parentAsClass.typeParameters.size + targetSymbol.owner.typeParameters.size
).also {
copyAllParamsToArgs(it, accessor)
}
@@ -326,11 +328,15 @@ private class SyntheticAccessorLowering(val context: JvmBackendContext) : IrElem
call: IrFunctionAccessExpression,
syntheticFunction: IrFunction
) {
var typeArgumentOffset = 0
if (syntheticFunction is IrConstructor) {
call.passTypeArgumentsFrom(syntheticFunction.parentAsClass)
typeArgumentOffset = syntheticFunction.parentAsClass.typeParameters.size
}
call.passTypeArgumentsFrom(syntheticFunction, offset = typeArgumentOffset)
var offset = 0
val delegateTo = call.symbol.owner
syntheticFunction.typeParameters.forEachIndexed { i, typeParam ->
call.putTypeArgument(i, IrSimpleTypeImpl(typeParam.symbol, false, emptyList(), emptyList()))
}
delegateTo.dispatchReceiverParameter?.let {
call.dispatchReceiver =
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol)
@@ -205,19 +205,19 @@ fun IrBuilderWithScope.irGet(type: IrType, receiver: IrExpression?, getterSymbol
type,
getterSymbol as IrSimpleFunctionSymbol,
getterSymbol.descriptor,
typeArgumentsCount = 0,
typeArgumentsCount = getterSymbol.owner.typeParameters.size,
dispatchReceiver = receiver,
extensionReceiver = null,
origin = IrStatementOrigin.GET_PROPERTY
)
fun IrBuilderWithScope.irSet(type: IrType, receiver: IrExpression?, getterSymbol: IrFunctionSymbol, value: IrExpression): IrCall =
fun IrBuilderWithScope.irSet(type: IrType, receiver: IrExpression?, setterSymbol: IrFunctionSymbol, value: IrExpression): IrCall =
IrSetterCallImpl(
startOffset, endOffset,
type,
getterSymbol as IrSimpleFunctionSymbol,
getterSymbol.descriptor,
typeArgumentsCount = 0,
setterSymbol as IrSimpleFunctionSymbol,
setterSymbol.descriptor,
typeArgumentsCount = setterSymbol.owner.typeParameters.size,
dispatchReceiver = receiver,
extensionReceiver = null,
argument = value,
@@ -8,5 +8,9 @@ package org.jetbrains.kotlin.ir.declarations
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
interface IrAnnotationContainer {
val annotations: MutableList<IrConstructorCall>
val annotations: List<IrConstructorCall>
}
interface IrMutableAnnotationContainer: IrAnnotationContainer {
override val annotations: MutableList<IrConstructorCall>
}
@@ -32,7 +32,7 @@ interface IrMetadataSourceOwner : IrElement {
val metadata: MetadataSource?
}
interface IrDeclaration : IrStatement, IrAnnotationContainer, IrMetadataSourceOwner {
interface IrDeclaration : IrStatement, IrMutableAnnotationContainer, IrMetadataSourceOwner {
val descriptor: DeclarationDescriptor
var origin: IrDeclarationOrigin
@@ -38,7 +38,7 @@ interface IrExternalPackageFragment : IrPackageFragment {
override val symbol: IrExternalPackageFragmentSymbol
}
interface IrFile : IrPackageFragment, IrAnnotationContainer, IrMetadataSourceOwner {
interface IrFile : IrPackageFragment, IrMutableAnnotationContainer, IrMetadataSourceOwner {
override val symbol: IrFileSymbol
val fileEntry: SourceManager.FileEntry
@@ -6,8 +6,10 @@
package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.types.KotlinType
@@ -60,6 +62,9 @@ val CallableDescriptor.typeParametersCount: Int
fun IrMemberAccessExpression.getTypeArgumentOrDefault(typeParameterDescriptor: TypeParameterDescriptor) =
getTypeArgument(typeParameterDescriptor)?.toKotlinType() ?: typeParameterDescriptor.defaultType
fun IrMemberAccessExpression.getTypeArgumentOrDefault(irTypeParameter: IrTypeParameter) =
getTypeArgument(irTypeParameter.index) ?: irTypeParameter.defaultType
interface IrFunctionAccessExpression : IrMemberAccessExpression, IrDeclarationReference {
override val descriptor: FunctionDescriptor
override val symbol: IrFunctionSymbol
@@ -5,12 +5,11 @@
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.types.Variance
interface IrType {
val annotations: List<IrConstructorCall>
interface IrType : IrAnnotationContainer {
/**
* @return true if this type is equal to [other] symbolically. Note that this is NOT EQUIVALENT to the full type checking algorithm
@@ -188,7 +188,7 @@ open class DeepCopyIrTreeWithSymbols(
}
}
private fun IrAnnotationContainer.transformAnnotations(declaration: IrAnnotationContainer) {
private fun IrMutableAnnotationContainer.transformAnnotations(declaration: IrAnnotationContainer) {
declaration.annotations.transformTo(annotations)
}
@@ -211,7 +211,7 @@ open class DeepCopyIrTreeWithSymbols(
this.getter = declaration.getter?.transform()
this.setter = declaration.setter?.transform()
this.backingField?.let {
it.correspondingProperty = this
it.correspondingPropertySymbol = symbol
}
}