From 135d3ab57a5a5ab3555144f83e45f1472df30559 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 19 Mar 2018 14:08:04 +0300 Subject: [PATCH] Fix type arguments mapping --- .../generators/ArgumentsGenerationUtils.kt | 109 +++++++++++++++--- .../psi2ir/generators/AssignmentGenerator.kt | 1 + .../kotlin/psi2ir/generators/BodyGenerator.kt | 42 ++++--- .../kotlin/psi2ir/generators/CallGenerator.kt | 12 +- .../psi2ir/generators/ClassGenerator.kt | 34 ++++-- .../generators/DataClassMembersGenerator.kt | 12 +- .../kotlin/psi2ir/intermediate/CallBuilder.kt | 6 +- .../kotlin/ir/builders/ExpressionHelpers.kt | 9 +- .../impl/IrEnumConstructorCallImpl.kt | 13 ++- .../kotlin/ir/util/DeepCopyIrTree.kt | 38 +++--- .../ir/util/DeepCopyIrTreeWithSymbols.kt | 43 +++---- .../jetbrains/kotlin/ir/util/DumpIrTree.kt | 2 +- .../kotlin/ir/util/remapTypeArguments.kt | 49 ++++++++ .../testData/ir/irText/classes/classes.txt | 2 +- .../classes/dataClassWithArrayMembers.txt | 2 +- .../ir/irText/classes/dataClassesGeneric.txt | 2 +- ...gConstructorCallToTypeAliasConstructor.txt | 4 +- compiler/testData/ir/irText/classes/enum.txt | 10 +- .../irText/classes/enumWithSecondaryCtor.txt | 6 +- .../multiplatform/expectedEnumClass.txt | 2 +- .../parameters/dataClassMembers.txt | 2 +- .../parameters/delegatedMembers.txt | 2 +- .../expressions/enumEntryAsReceiver.txt | 2 +- .../irText/expressions/memberTypeArguments.kt | 3 + .../expressions/memberTypeArguments.txt | 44 +++++++ .../irText/expressions/objectAsCallable.txt | 2 +- .../specializedTypeAliasConstructorCall.txt | 2 +- .../testData/ir/irText/expressions/values.txt | 2 +- .../typeAliasCtorForGenericClass.txt | 4 +- .../ir/irText/singletons/enumEntry.txt | 2 +- .../testData/ir/irText/stubs/builtinMap.kt | 2 +- .../testData/ir/irText/stubs/builtinMap.txt | 59 +++++----- .../kotlin/ir/IrTextTestCaseGenerated.java | 6 + 33 files changed, 365 insertions(+), 165 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/remapTypeArguments.kt create mode 100644 compiler/testData/ir/irText/expressions/memberTypeArguments.kt create mode 100644 compiler/testData/ir/irText/expressions/memberTypeArguments.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index a15f11e9fab..8919f063fd8 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -269,6 +269,16 @@ fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuild return call } +fun getTypeArguments(resolvedCall: ResolvedCall<*>?): Map? { + if (resolvedCall == null) return null + + val descriptor = resolvedCall.resultingDescriptor + if (descriptor.typeParameters.isEmpty()) return null + + return resolvedCall.typeArguments +} + + fun StatementGenerator.pregenerateExtensionInvokeCall(resolvedCall: ResolvedCall<*>): CallBuilder { val extensionInvoke = resolvedCall.resultingDescriptor val functionNClass = extensionInvoke.containingDeclaration as? ClassDescriptor @@ -278,6 +288,10 @@ fun StatementGenerator.pregenerateExtensionInvokeCall(resolvedCall: ResolvedCall val unsubstitutedPlainInvoke = unsubstitutedPlainInvokes.singleOrNull() ?: throw AssertionError("There should be a single 'invoke' in FunctionN class: $unsubstitutedPlainInvokes") + assert(unsubstitutedPlainInvoke.typeParameters.isEmpty()) { + "'operator fun invoke' should have no type parameters: $unsubstitutedPlainInvoke" + } + val expectedValueParametersCount = extensionInvoke.valueParameters.size + 1 assert(unsubstitutedPlainInvoke.valueParameters.size == expectedValueParametersCount) { "Plain 'invoke' should have $expectedValueParametersCount value parameters, got ${unsubstitutedPlainInvoke.valueParameters}" @@ -289,7 +303,12 @@ fun StatementGenerator.pregenerateExtensionInvokeCall(resolvedCall: ResolvedCall val ktCallElement = resolvedCall.call.callElement - val call = CallBuilder(resolvedCall, plainInvoke, isExtensionInvokeCall = true) + val call = CallBuilder( + resolvedCall, + plainInvoke, + typeArguments = null, // FunctionN#invoke has no type parameters of its own + isExtensionInvokeCall = true + ) val functionReceiverValue = run { val dispatchReceiver = @@ -329,15 +348,6 @@ private fun ResolvedCall<*>.isExtensionInvokeCall(): Boolean { return extensionReceiver != null } -fun getTypeArguments(resolvedCall: ResolvedCall<*>?): Map? { - if (resolvedCall == null) return null - - val descriptor = resolvedCall.resultingDescriptor - if (descriptor.typeParameters.isEmpty()) return null - - return resolvedCall.typeArguments -} - private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, resolvedCall: ResolvedCall<*>) { resolvedCall.valueArgumentsByIndex!!.forEachIndexed { index, valueArgument -> val valueParameter = call.descriptor.valueParameters[index] @@ -346,7 +356,7 @@ private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, reso } fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder { - val call = CallBuilder(resolvedCall, unwrapCallableDescriptor(resolvedCall.resultingDescriptor)) + val call = unwrapCallableDescriptorAndTypeArguments(resolvedCall) call.callReceiver = generateCallReceiver( resolvedCall.call.callElement, @@ -361,12 +371,73 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): return call } -fun unwrapCallableDescriptor(resultingDescriptor: CallableDescriptor): CallableDescriptor = - when (resultingDescriptor) { - is ImportedFromObjectCallableDescriptor<*> -> - resultingDescriptor.callableFromObject - is TypeAliasConstructorDescriptor -> - resultingDescriptor.underlyingConstructorDescriptor - else -> - resultingDescriptor +fun unwrapCallableDescriptorAndTypeArguments(resolvedCall: ResolvedCall<*>): CallBuilder { + val originalDescriptor = resolvedCall.resultingDescriptor + + val unwrappedDescriptor = when (originalDescriptor) { + is ImportedFromObjectCallableDescriptor<*> -> originalDescriptor.callableFromObject + is TypeAliasConstructorDescriptor -> originalDescriptor.underlyingConstructorDescriptor + else -> originalDescriptor } + + val originalTypeArguments = resolvedCall.typeArguments + val unsubstitutedUnwrappedDescriptor = unwrappedDescriptor.original + val unsubstitutedUnwrappedTypeParameters = unsubstitutedUnwrappedDescriptor.typeParameters + + val unwrappedTypeArguments = when (originalDescriptor) { + is ImportedFromObjectCallableDescriptor<*> -> { + assert(originalDescriptor.typeParameters.size == unsubstitutedUnwrappedTypeParameters.size) { + "Mismatching original / unwrapped type parameters: " + + "originalDescriptor: $originalDescriptor; " + + "unsubstitutedUnwrappedDescriptor: $unsubstitutedUnwrappedDescriptor" + } + + if (unsubstitutedUnwrappedTypeParameters.isEmpty()) + null + else + unsubstitutedUnwrappedTypeParameters.associate { + val originalTypeParameter = originalDescriptor.typeParameters[it.index] + val originalTypeArgument = originalTypeArguments[originalTypeParameter] + ?: throw AssertionError("No type argument for $originalTypeParameter") + it to originalTypeArgument + } + } + + is TypeAliasConstructorDescriptor -> { + val substitutedType = originalDescriptor.returnType + if (substitutedType.arguments.isEmpty()) + null + else + unsubstitutedUnwrappedTypeParameters.associate { + it to substitutedType.arguments[it.index].type + } + } + + else -> { + if (originalTypeArguments.keys.all { it.containingDeclaration == unsubstitutedUnwrappedDescriptor }) + originalTypeArguments.takeIf { it.isNotEmpty() } + else { + assert(unsubstitutedUnwrappedTypeParameters.size == originalTypeArguments.size) { + "Mismatching type parameters and type arguments: " + + "unsubstitutedUnwrappedDescriptor: $unsubstitutedUnwrappedDescriptor; " + + "originalDescriptor: $originalDescriptor; " + + "originalTypeArguments: $originalTypeArguments" + } + + if (unsubstitutedUnwrappedTypeParameters.isEmpty()) + null + else { + originalTypeArguments.keys.associate { originalTypeParameter -> + val unwrappedTypeParameter = unsubstitutedUnwrappedTypeParameters[originalTypeParameter.index] + val originalTypeArgument = originalTypeArguments[originalTypeParameter] + ?: throw AssertionError("No type argument for $unwrappedTypeParameter <= $originalTypeParameter") + unwrappedTypeParameter to originalTypeArgument + } + } + + } + } + } + + return CallBuilder(resolvedCall, unwrappedDescriptor, unwrappedTypeArguments) +} diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt index f638374fc15..9a53205dbca 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -176,6 +176,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen val superQualifier = getSuperQualifier(resolvedCall) + // TODO property imported from an object createPropertyLValue(ktLeft, descriptor, propertyReceiver, getTypeArguments(resolvedCall), origin, superQualifier) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt index 4ac5f61d82c..aa542941628 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt @@ -142,8 +142,9 @@ class BodyGenerator( val delegatingConstructorResolvedCall = getResolvedCall(ktDelegatingConstructorCall) if (delegatingConstructorResolvedCall == null) { - if (constructorDescriptor.containingDeclaration.kind == ClassKind.ENUM_CLASS) { - generateEnumSuperConstructorCall(irBlockBody, ktConstructor) + val classDescriptor = constructorDescriptor.containingDeclaration + if (classDescriptor.kind == ClassKind.ENUM_CLASS) { + generateEnumSuperConstructorCall(irBlockBody, ktConstructor, classDescriptor) } else { generateAnySuperConstructorCall(irBlockBody, ktConstructor) } @@ -207,12 +208,14 @@ class BodyGenerator( val classDescriptor = getOrFail(BindingContext.CLASS, ktClassOrObject) when (classDescriptor.kind) { - ClassKind.ENUM_CLASS -> { - generateEnumSuperConstructorCall(irBlockBody, ktClassOrObject) - } + ClassKind.ENUM_CLASS -> generateEnumSuperConstructorCall(irBlockBody, ktClassOrObject, classDescriptor) + ClassKind.ENUM_ENTRY -> { - irBlockBody.statements.add(generateEnumEntrySuperConstructorCall(ktClassOrObject as KtEnumEntry, classDescriptor)) + irBlockBody.statements.add( + generateEnumEntrySuperConstructorCall(ktClassOrObject as KtEnumEntry, classDescriptor) + ) } + else -> { val statementGenerator = createStatementGenerator() @@ -252,12 +255,17 @@ class BodyGenerator( ) } - private fun generateEnumSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) { + private fun generateEnumSuperConstructorCall( + irBlockBody: IrBlockBodyImpl, + ktElement: KtElement, + classDescriptor: ClassDescriptor + ) { val enumConstructor = context.builtIns.enum.constructors.single() irBlockBody.statements.add( IrEnumConstructorCallImpl( ktElement.startOffset, ktElement.endOffset, - context.symbolTable.referenceConstructor(enumConstructor) + context.symbolTable.referenceConstructor(enumConstructor), + mapOf(enumConstructor.typeParameters.single() to classDescriptor.defaultType) ) ) } @@ -271,7 +279,8 @@ class BodyGenerator( val enumEntryConstructor = enumEntryDescriptor.unsubstitutedPrimaryConstructor!! return IrEnumConstructorCallImpl( ktEnumEntry.startOffset, ktEnumEntry.endOffset, - context.symbolTable.referenceConstructor(enumEntryConstructor) + context.symbolTable.referenceConstructor(enumEntryConstructor), + null // enums can't be generic (so far) ) } @@ -291,19 +300,8 @@ class BodyGenerator( } val enumDefaultConstructorCall = getResolvedCall(ktEnumEntry) - if (enumDefaultConstructorCall != null) { - return statementGenerator.generateEnumConstructorCall(enumDefaultConstructorCall, ktEnumEntry) - } - - // Default enum entry constructor - val enumClassConstructor = - enumClassDescriptor.constructors.singleOrNull { constructor -> - constructor.valueParameters.all(ValueParameterDescriptor::declaresDefaultValue) - } ?: throw AssertionError("Enum class $enumClassDescriptor should have a default constructor") - return IrEnumConstructorCallImpl( - ktEnumEntry.startOffset, ktEnumEntry.endOffset, - context.symbolTable.referenceConstructor(enumClassConstructor) - ) + ?: throw AssertionError("No default constructor call for enum entry $enumClassDescriptor") + return statementGenerator.generateEnumConstructorCall(enumDefaultConstructorCall, ktEnumEntry) } private fun StatementGenerator.generateEnumConstructorCall( diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index add749d1870..dbb84163a3f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -105,7 +105,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator ?: throw AssertionError("Class constructor expected: ${call.descriptor}") val constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original) val irCall = - IrDelegatingConstructorCallImpl(startOffset, endOffset, constructorSymbol, descriptor, getTypeArguments(call.original)) + IrDelegatingConstructorCallImpl(startOffset, endOffset, constructorSymbol, descriptor, call.typeArguments) irCall.dispatchReceiver = dispatchReceiver?.load() irCall.extensionReceiver = extensionReceiver?.load() addParametersToCall(startOffset, endOffset, call, irCall, descriptor.builtIns.unitType) @@ -121,7 +121,11 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver") if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver") val constructorSymbol = context.symbolTable.referenceConstructor(constructorDescriptor.original) - val irCall = IrEnumConstructorCallImpl(startOffset, endOffset, constructorSymbol) + val irCall = IrEnumConstructorCallImpl( + startOffset, endOffset, + constructorSymbol, + call.typeArguments + ) addParametersToCall(startOffset, endOffset, call, irCall, constructorDescriptor.returnType) } } @@ -142,7 +146,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator startOffset, endOffset, getterSymbol, getterDescriptor, - getTypeArguments(call.original), + call.typeArguments, dispatchReceiverValue?.load(), extensionReceiverValue?.load(), IrStatementOrigin.GET_PROPERTY, @@ -177,7 +181,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator returnType, functionSymbol, functionDescriptor, - getTypeArguments(call.original), + call.typeArguments, origin, superQualifierSymbol ) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt index 8d557745c1f..6d680217706 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ClassGenerator.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import org.jetbrains.kotlin.utils.newHashMapWithExpectedSize import java.lang.AssertionError class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) { @@ -215,7 +216,7 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe startOffset, endOffset, returnType, context.symbolTable.referenceFunction(overridden.original), substitutedOverridden, - null + getTypeArgumentsForOverriddenDescriptorDelegatingCall(delegated, overridden) ) irCall.dispatchReceiver = IrGetFieldImpl( @@ -245,13 +246,32 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe overridden: FunctionDescriptor ): FunctionDescriptor { // TODO PropertyAccessorDescriptor doesn't support 'substitute' right now :( - if (overridden is PropertyAccessorDescriptor) return overridden - - val typeArguments = HashMap() - for ((i, overriddenTypeParameter) in overridden.typeParameters.withIndex()) { - typeArguments[overriddenTypeParameter] = delegated.typeParameters[i].defaultType + return if (overridden is PropertyAccessorDescriptor) + overridden + else { + val typeArguments = zipTypeParametersToDefaultTypes(overridden, delegated) + overridden.substitute(typeArguments) } - return overridden.substitute(typeArguments) + } + + private fun getTypeArgumentsForOverriddenDescriptorDelegatingCall( + delegated: FunctionDescriptor, + overridden: FunctionDescriptor + ): Map? = + if (overridden.original.typeParameters.isEmpty()) + null + else + zipTypeParametersToDefaultTypes(overridden.original, delegated) + + private fun zipTypeParametersToDefaultTypes( + keys: FunctionDescriptor, + values: FunctionDescriptor + ): Map { + val typeArguments = newHashMapWithExpectedSize(keys.typeParameters.size) + for ((i, overriddenTypeParameter) in keys.typeParameters.withIndex()) { + typeArguments[overriddenTypeParameter] = values.typeParameters[i].defaultType + } + return typeArguments } private fun generateAdditionalMembersForDataClass(irClass: IrClass, ktClassOrObject: KtClassOrObject) { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt index a96355b291b..59d47f8f2bc 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DataClassMembersGenerator.kt @@ -126,9 +126,15 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De function.valueParameters.forEach { parameter -> putDefault(parameter, irGet(irThis(), getPropertyGetterSymbol(parameter))) } - +irReturn(irCall(constructorSymbol, dataClassConstructor.returnType).mapValueParameters { - irGet(irFunction.valueParameters[it.index].symbol) - }) + +irReturn( + irCall( + constructorSymbol, + dataClassConstructor.returnType, + dataClassConstructor.typeParameters.associate { it to it.defaultType } + ).mapValueParameters { + irGet(irFunction.valueParameters[it.index].symbol) + } + ) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt index 1a6834ff4ca..5af5c2c023f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/CallBuilder.kt @@ -16,10 +16,7 @@ package org.jetbrains.kotlin.psi2ir.intermediate -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor -import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.psi2ir.isValueArgumentReorderingRequired import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall @@ -28,6 +25,7 @@ import org.jetbrains.kotlin.types.KotlinType class CallBuilder( val original: ResolvedCall<*>, // TODO get rid of "original", sometimes we want to generate a call without ResolvedCall val descriptor: CallableDescriptor, + val typeArguments: Map?, val isExtensionInvokeCall: Boolean = false ) { var superQualifier: ClassDescriptor? = null diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt index 4f5440b8920..29ce9e6461f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/builders/ExpressionHelpers.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.ir.builders +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrVariable @@ -146,8 +147,12 @@ fun IrBuilderWithScope.irNotEquals(arg1: IrExpression, arg2: IrExpression) = fun IrBuilderWithScope.irGet(receiver: IrExpression, getterSymbol: IrFunctionSymbol): IrCall = IrGetterCallImpl(startOffset, endOffset, getterSymbol, getterSymbol.descriptor, null, receiver, null, IrStatementOrigin.GET_PROPERTY) -fun IrBuilderWithScope.irCall(callee: IrFunctionSymbol, type: KotlinType): IrCall = - IrCallImpl(startOffset, endOffset, type, callee, callee.descriptor, null) +fun IrBuilderWithScope.irCall( + callee: IrFunctionSymbol, + type: KotlinType, + typeArguments: Map? = null +): IrCall = + IrCallImpl(startOffset, endOffset, type, callee, callee.descriptor, typeArguments) fun IrBuilderWithScope.irCall(callee: IrFunctionSymbol): IrCall = irCall(callee, callee.descriptor.returnType!!) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt index 70a8e5c33dc..675f2228d53 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt @@ -17,29 +17,34 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.expressions.IrEnumConstructorCall import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns +import org.jetbrains.kotlin.types.KotlinType class IrEnumConstructorCallImpl( startOffset: Int, endOffset: Int, - override val symbol: IrConstructorSymbol + override val symbol: IrConstructorSymbol, + typeArguments: Map? ) : IrEnumConstructorCall, IrCallWithIndexedArgumentsBase( startOffset, endOffset, symbol.descriptor.builtIns.unitType, symbol.descriptor.valueParameters.size, - null + typeArguments ) { + @Deprecated("Creates unbound symbols") constructor( startOffset: Int, endOffset: Int, - descriptor: ClassConstructorDescriptor - ) : this(startOffset, endOffset, IrConstructorSymbolImpl(descriptor)) + descriptor: ClassConstructorDescriptor, + typeArguments: Map? = null + ) : this(startOffset, endOffset, IrConstructorSymbolImpl(descriptor), typeArguments) override val descriptor: ClassConstructorDescriptor get() = symbol.descriptor diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt index 5415dd50090..36bcedd51e3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.impl.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.types.KotlinType import java.util.* inline fun T.deepCopyOld(): T = @@ -154,6 +153,10 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { } } + @Deprecated("Replace with remapTypeArguments") + protected fun IrMemberAccessExpression.transformTypeArguments(newCallee: CallableDescriptor) = + remapTypeArguments(this, newCallee) + private fun FunctionDescriptor.getTypeParametersToTransform() = when { this is PropertyAccessorDescriptor -> correspondingProperty.typeParameters @@ -402,7 +405,7 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { expression.startOffset, expression.endOffset, expression.type, newCallee, - expression.transformTypeArguments(newCallee), + remapTypeArguments(expression, newCallee), mapStatementOrigin(expression.origin), mapSuperQualifier(expression.superQualifier) ) @@ -419,33 +422,24 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { Unit } - protected fun IrMemberAccessExpression.transformTypeArguments(newCallee: CallableDescriptor): Map? { - if (this is IrMemberAccessExpressionBase) return typeArguments - - val typeParameters = descriptor.original.typeParameters - return if (typeParameters.isEmpty()) - null - else - typeParameters.associateBy( - { newCallee.typeParameters[it.index] }, - { getTypeArgument(it)!! } - ) - } - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrDelegatingConstructorCall { val newCallee = mapDelegatedConstructorCallee(expression.descriptor) return IrDelegatingConstructorCallImpl( expression.startOffset, expression.endOffset, newCallee, - expression.transformTypeArguments(newCallee) + remapTypeArguments(expression, newCallee) ).transformValueArguments(expression) } - override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrEnumConstructorCall = - IrEnumConstructorCallImpl( + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrEnumConstructorCall { + val oldConstructor = expression.descriptor + val newConstructor = mapEnumConstructorCallee(oldConstructor) + return IrEnumConstructorCallImpl( expression.startOffset, expression.endOffset, - mapEnumConstructorCallee(expression.descriptor) + newConstructor, + remapTypeArguments(expression, newConstructor) ).transformValueArguments(expression) + } override fun visitGetClass(expression: IrGetClass): IrGetClass = IrGetClassImpl( @@ -460,7 +454,7 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { expression.startOffset, expression.endOffset, expression.type, newCallee.original, - expression.transformTypeArguments(newCallee), + remapTypeArguments(expression, newCallee), mapStatementOrigin(expression.origin) ).transformValueArguments(expression) } @@ -473,7 +467,7 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { return IrPropertyReferenceImpl( expression.startOffset, expression.endOffset, expression.type, newProperty, newFieldSymbol, newGetterSymbol, newSetterSymbol, - expression.transformTypeArguments(newProperty), + remapTypeArguments(expression, newProperty), mapStatementOrigin(expression.origin) ).transformValueArguments(expression) } @@ -638,4 +632,6 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { explicitReceiver = expression.explicitReceiver?.transform() expression.arguments.mapTo(arguments) { it.transform() } } + + } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt index 0ccc4bc0fcf..d739cfe64ab 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTreeWithSymbols.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.ir.util -import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* @@ -27,7 +26,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.types.KotlinType import java.util.* inline fun T.deepCopyWithSymbols(): T { @@ -327,16 +325,18 @@ open class DeepCopyIrTreeWithSymbols(private val symbolRemapper: SymbolRemapper) symbolRemapper.getReferencedFunction(expression.symbol), symbolRemapper.getReferencedClassOrNull(expression.superQualifierSymbol) ) - else -> + else -> { + val newCallee = symbolRemapper.getReferencedFunction(expression.symbol) IrCallImpl( expression.startOffset, expression.endOffset, expression.type, - symbolRemapper.getReferencedFunction(expression.symbol), + newCallee, expression.descriptor, // TODO substitute referenced descriptor - expression.getTypeArgumentsMap(), + remapTypeArguments(expression, newCallee.descriptor), mapStatementOrigin(expression.origin), symbolRemapper.getReferencedClassOrNull(expression.superQualifierSymbol) ) + } } private fun T.transformReceiverArguments(original: T): T = @@ -353,29 +353,24 @@ open class DeepCopyIrTreeWithSymbols(private val symbolRemapper: SymbolRemapper) } } - private fun IrMemberAccessExpression.getTypeArgumentsMap(): Map? { - if (this is IrMemberAccessExpressionBase) return typeArguments - - val typeParameters = descriptor.original.typeParameters - return if (typeParameters.isEmpty()) - null - else - typeParameters.associateBy({ it }, { getTypeArgument(it)!! }) + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrDelegatingConstructorCall { + val newConstructor = symbolRemapper.getReferencedConstructor(expression.symbol) + return IrDelegatingConstructorCallImpl( + expression.startOffset, expression.endOffset, + newConstructor, + expression.descriptor, + remapTypeArguments(expression, newConstructor.descriptor) + ).transformValueArguments(expression) } - override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrDelegatingConstructorCall = - IrDelegatingConstructorCallImpl( + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrEnumConstructorCall { + val newConstructor = symbolRemapper.getReferencedConstructor(expression.symbol) + return IrEnumConstructorCallImpl( expression.startOffset, expression.endOffset, - symbolRemapper.getReferencedConstructor(expression.symbol), - expression.descriptor, - expression.getTypeArgumentsMap() - ).transformValueArguments(expression) - - override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrEnumConstructorCall = - IrEnumConstructorCallImpl( - expression.startOffset, expression.endOffset, - symbolRemapper.getReferencedConstructor(expression.symbol) + newConstructor, + remapTypeArguments(expression, newConstructor.descriptor) ).transformValueArguments(expression) + } override fun visitGetClass(expression: IrGetClass): IrGetClass = IrGetClassImpl( diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index b888c73bbbe..86bbc532252 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -177,7 +177,7 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor { val typeArgument = expression.getTypeArgument(typeParameter) val renderedType = typeArgument?.let { DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.renderType(typeArgument) - } ?: "null" + } ?: "--- No type argument for $typeParameter declared in ${typeParameter.containingDeclaration}" printer.println("$renderedParameter: $renderedType") } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/remapTypeArguments.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/remapTypeArguments.kt new file mode 100644 index 00000000000..9d2510d6547 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/remapTypeArguments.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.util + +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrMemberAccessExpressionBase +import org.jetbrains.kotlin.types.KotlinType + +fun remapTypeArguments( + expression: IrMemberAccessExpression, + newDescriptor: CallableDescriptor +): Map? { + val oldDescriptor = expression.descriptor + val oldTypeArguments = expression.getTypeArgumentsMap() + val oldTypeParameters = oldDescriptor.original.typeParameters + val newTypeParameters = newDescriptor.original.typeParameters + + assert(oldTypeParameters.size == newTypeParameters.size) { + "Mismatching type parameters: oldDescriptor: $oldDescriptor; newDescriptor: $newDescriptor" + } + + return when { + oldDescriptor.original == newDescriptor.original -> oldTypeArguments + + oldTypeArguments == null || oldTypeArguments.isEmpty() -> null + + else -> newTypeParameters.associate { newTypeParameter -> + val oldTypeParameter = oldTypeParameters[newTypeParameter.index] + val newTypeArgument = expression.getTypeArgument(oldTypeParameter) + ?: throw AssertionError("No type argument for $newTypeParameter <= $oldTypeParameter") + newTypeParameter to newTypeArgument + } + } +} + +fun IrMemberAccessExpression.getTypeArgumentsMap(): Map? { + if (this is IrMemberAccessExpressionBase) return typeArguments + + val typeParameters = descriptor.original.typeParameters + return if (typeParameters.isEmpty()) + null + else + typeParameters.associateBy({ it }, { getTypeArgument(it)!! }) +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/classes/classes.txt b/compiler/testData/ir/irText/classes/classes.txt index 4c2d9457662..0a4defab34a 100644 --- a/compiler/testData/ir/irText/classes/classes.txt +++ b/compiler/testData/ir/irText/classes/classes.txt @@ -82,7 +82,7 @@ FILE fqName: fileName:/classes.kt CONSTRUCTOR visibility:private <> () returnType:TestEnumClass flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: TestEnumClass INSTANCE_INITIALIZER_CALL classDescriptor='TestEnumClass' FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum) returnType:Any flags: overridden: diff --git a/compiler/testData/ir/irText/classes/dataClassWithArrayMembers.txt b/compiler/testData/ir/irText/classes/dataClassWithArrayMembers.txt index 0d51685f464..ed25ec81104 100644 --- a/compiler/testData/ir/irText/classes/dataClassWithArrayMembers.txt +++ b/compiler/testData/ir/irText/classes/dataClassWithArrayMembers.txt @@ -493,7 +493,7 @@ FILE fqName: fileName:/dataClassWithArrayMembers.kt BLOCK_BODY RETURN type=kotlin.Nothing from='copy(Array = ...): Test2' CALL 'constructor Test2(Array)' type=Test2 origin=null - : null + : T genericArray: GET_VAR 'value-parameter genericArray: Array = ...' type=kotlin.Array origin=null FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:Test2) returnType:String flags: overridden: diff --git a/compiler/testData/ir/irText/classes/dataClassesGeneric.txt b/compiler/testData/ir/irText/classes/dataClassesGeneric.txt index e17f40a1393..9942cb45c5c 100644 --- a/compiler/testData/ir/irText/classes/dataClassesGeneric.txt +++ b/compiler/testData/ir/irText/classes/dataClassesGeneric.txt @@ -36,7 +36,7 @@ FILE fqName: fileName:/dataClassesGeneric.kt BLOCK_BODY RETURN type=kotlin.Nothing from='copy(T = ...): Test1' CALL 'constructor Test1(T)' type=Test1 origin=null - : null + : T x: GET_VAR 'value-parameter x: T = ...' type=T origin=null FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:Test1) returnType:String flags: overridden: diff --git a/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt b/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt index 193ff031aa9..ba172dc8db6 100644 --- a/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt +++ b/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt @@ -43,7 +43,7 @@ FILE fqName: fileName:/delegatingConstructorCallToTypeAliasConstructor.kt CONSTRUCTOR visibility:public <> () returnType:C1 flags: BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)' - : null + : String value: CONST String type=kotlin.String value=O INSTANCE_INITIALIZER_CALL classDescriptor='C1' PROPERTY FAKE_OVERRIDE name:value type:kotlin.String visibility:public modality:FINAL flags:val @@ -71,7 +71,7 @@ FILE fqName: fileName:/delegatingConstructorCallToTypeAliasConstructor.kt CONSTRUCTOR visibility:public <> () returnType:C2 flags: BLOCK_BODY DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)' - : null + : String value: CONST String type=kotlin.String value=K INSTANCE_INITIALIZER_CALL classDescriptor='C2' PROPERTY FAKE_OVERRIDE name:value type:kotlin.String visibility:public modality:FINAL flags:val diff --git a/compiler/testData/ir/irText/classes/enum.txt b/compiler/testData/ir/irText/classes/enum.txt index 815e57b001d..7a1204eceae 100644 --- a/compiler/testData/ir/irText/classes/enum.txt +++ b/compiler/testData/ir/irText/classes/enum.txt @@ -6,7 +6,7 @@ FILE fqName: fileName:/enum.kt CONSTRUCTOR visibility:private <> () returnType:TestEnum1 flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: TestEnum1 INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum1' ENUM_ENTRY name:TEST1 init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()' @@ -65,7 +65,7 @@ FILE fqName: fileName:/enum.kt VALUE_PARAMETER name:x index:0 type:kotlin.Int flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: TestEnum2 INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum2' PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public @@ -138,7 +138,7 @@ FILE fqName: fileName:/enum.kt CONSTRUCTOR visibility:private <> () returnType:TestEnum3 flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: TestEnum3 INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum3' ENUM_ENTRY name:TEST init: ENUM_CONSTRUCTOR_CALL 'constructor TEST()' @@ -252,7 +252,7 @@ FILE fqName: fileName:/enum.kt VALUE_PARAMETER name:x index:0 type:kotlin.Int flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: TestEnum4 INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum4' PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public @@ -461,7 +461,7 @@ FILE fqName: fileName:/enum.kt CONST Int type=kotlin.Int value=0 BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: TestEnum5 INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum5' PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public diff --git a/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.txt b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.txt index 73761372f90..6cab852d7a3 100644 --- a/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.txt +++ b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.txt @@ -7,7 +7,7 @@ FILE fqName: fileName:/enumWithSecondaryCtor.kt VALUE_PARAMETER name:x index:0 type:kotlin.Int flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: Test0 INSTANCE_INITIALIZER_CALL classDescriptor='Test0' PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public @@ -78,7 +78,7 @@ FILE fqName: fileName:/enumWithSecondaryCtor.kt VALUE_PARAMETER name:x index:0 type:kotlin.Int flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: Test1 INSTANCE_INITIALIZER_CALL classDescriptor='Test1' PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public @@ -152,7 +152,7 @@ FILE fqName: fileName:/enumWithSecondaryCtor.kt VALUE_PARAMETER name:x index:0 type:kotlin.Int flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: Test2 INSTANCE_INITIALIZER_CALL classDescriptor='Test2' PROPERTY name:x type:kotlin.Int visibility:public modality:FINAL flags:val FIELD PROPERTY_BACKING_FIELD name:x type:kotlin.Int visibility:public diff --git a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.txt b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.txt index eb0d1f371d4..1d2b85ee88f 100644 --- a/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.txt +++ b/compiler/testData/ir/irText/declarations/multiplatform/expectedEnumClass.txt @@ -57,7 +57,7 @@ FILE fqName: fileName:/expectedEnumClass.kt CONSTRUCTOR visibility:private <> () returnType:MyEnum flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: MyEnum INSTANCE_INITIALIZER_CALL classDescriptor='MyEnum' ENUM_ENTRY name:FOO init: ENUM_CONSTRUCTOR_CALL 'constructor MyEnum()' diff --git a/compiler/testData/ir/irText/declarations/parameters/dataClassMembers.txt b/compiler/testData/ir/irText/declarations/parameters/dataClassMembers.txt index 8628bb8a006..e48e22a763c 100644 --- a/compiler/testData/ir/irText/declarations/parameters/dataClassMembers.txt +++ b/compiler/testData/ir/irText/declarations/parameters/dataClassMembers.txt @@ -59,7 +59,7 @@ FILE fqName: fileName:/dataClassMembers.kt BLOCK_BODY RETURN type=kotlin.Nothing from='copy(T = ..., String = ...): Test' CALL 'constructor Test(T, String = ...)' type=Test origin=null - : null + : T x: GET_VAR 'value-parameter x: T = ...' type=T origin=null y: GET_VAR 'value-parameter y: String = ...' type=kotlin.String origin=null FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:Test) returnType:String flags: diff --git a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.txt b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.txt index db0d8ca9c34..66b9425dad1 100644 --- a/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.txt +++ b/compiler/testData/ir/irText/declarations/parameters/delegatedMembers.txt @@ -58,7 +58,7 @@ FILE fqName: fileName:/delegatedMembers.kt VALUE_PARAMETER name:x index:1 type:X flags: BLOCK_BODY CALL 'qux(TT, X): Unit' type=kotlin.Unit origin=null - : null + : X $this: GET_FIELD '`Test$IBase$delegate`: IBase' type=IBase origin=null receiver: GET_VAR 'this@Test: Test' type=Test origin=null t: GET_VAR 'value-parameter t: TT' type=TT origin=null diff --git a/compiler/testData/ir/irText/expressions/enumEntryAsReceiver.txt b/compiler/testData/ir/irText/expressions/enumEntryAsReceiver.txt index dd97420b499..8a9a623155d 100644 --- a/compiler/testData/ir/irText/expressions/enumEntryAsReceiver.txt +++ b/compiler/testData/ir/irText/expressions/enumEntryAsReceiver.txt @@ -6,7 +6,7 @@ FILE fqName: fileName:/enumEntryAsReceiver.kt CONSTRUCTOR visibility:private <> () returnType:X flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: X INSTANCE_INITIALIZER_CALL classDescriptor='X' ENUM_ENTRY name:B init: ENUM_CONSTRUCTOR_CALL 'constructor B()' diff --git a/compiler/testData/ir/irText/expressions/memberTypeArguments.kt b/compiler/testData/ir/irText/expressions/memberTypeArguments.kt new file mode 100644 index 00000000000..c913194ab8e --- /dev/null +++ b/compiler/testData/ir/irText/expressions/memberTypeArguments.kt @@ -0,0 +1,3 @@ +class GenericClass(val value: T) { + fun withNewValue(newValue: T) = GenericClass(newValue) +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/expressions/memberTypeArguments.txt b/compiler/testData/ir/irText/expressions/memberTypeArguments.txt new file mode 100644 index 00000000000..9851166a5f1 --- /dev/null +++ b/compiler/testData/ir/irText/expressions/memberTypeArguments.txt @@ -0,0 +1,44 @@ +FILE fqName: fileName:/memberTypeArguments.kt + CLASS CLASS name:GenericClass modality:FINAL visibility:public flags: + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:GenericClass flags: + superClasses: + CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Any modality:OPEN visibility:public flags: + TYPE_PARAMETER name:T index:0 variance: upperBounds:[kotlin.Any?] + superClassifiers: + CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Any modality:OPEN visibility:public flags: + CONSTRUCTOR visibility:public <> (value:T) returnType:GenericClass flags: + VALUE_PARAMETER name:value index:0 type:T flags: + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='GenericClass' + PROPERTY name:value type:T visibility:public modality:FINAL flags:val + FIELD PROPERTY_BACKING_FIELD name:value type:T visibility:public + EXPRESSION_BODY + GET_VAR 'value-parameter value: T' type=T origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:GenericClass) returnType:T flags: + $this: VALUE_PARAMETER name: type:GenericClass flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): T' + GET_FIELD 'value: T' type=T origin=null + receiver: GET_VAR 'this@GenericClass: GenericClass' type=GenericClass origin=null + FUN name:withNewValue visibility:public modality:FINAL <> ($this:GenericClass, newValue:T) returnType:GenericClass flags: + $this: VALUE_PARAMETER name: type:GenericClass flags: + VALUE_PARAMETER name:newValue index:0 type:T flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='withNewValue(T): GenericClass' + CALL 'constructor GenericClass(T)' type=GenericClass origin=null + : T + value: GET_VAR 'value-parameter newValue: T' type=T origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:Boolean flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags: + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:Int flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags: + overridden: + FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:String flags: + $this: VALUE_PARAMETER name: type:kotlin.Any flags: diff --git a/compiler/testData/ir/irText/expressions/objectAsCallable.txt b/compiler/testData/ir/irText/expressions/objectAsCallable.txt index be46d46a073..4d9e3022b3b 100644 --- a/compiler/testData/ir/irText/expressions/objectAsCallable.txt +++ b/compiler/testData/ir/irText/expressions/objectAsCallable.txt @@ -27,7 +27,7 @@ FILE fqName: fileName:/objectAsCallable.kt CONSTRUCTOR visibility:private <> () returnType:En flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: En INSTANCE_INITIALIZER_CALL classDescriptor='En' ENUM_ENTRY name:X init: ENUM_CONSTRUCTOR_CALL 'constructor En()' diff --git a/compiler/testData/ir/irText/expressions/specializedTypeAliasConstructorCall.txt b/compiler/testData/ir/irText/expressions/specializedTypeAliasConstructorCall.txt index 6d3c028bfe1..6e5e571e76e 100644 --- a/compiler/testData/ir/irText/expressions/specializedTypeAliasConstructorCall.txt +++ b/compiler/testData/ir/irText/expressions/specializedTypeAliasConstructorCall.txt @@ -39,5 +39,5 @@ FILE fqName: fileName:/specializedTypeAliasConstructorCall.kt BLOCK_BODY RETURN type=kotlin.Nothing from='test(): IntAlias /* = Cell */' CALL 'constructor Cell(Int)' type=Cell origin=null - : null + : Int value: CONST Int type=kotlin.Int value=42 diff --git a/compiler/testData/ir/irText/expressions/values.txt b/compiler/testData/ir/irText/expressions/values.txt index c88678e58cf..1cb23e8881a 100644 --- a/compiler/testData/ir/irText/expressions/values.txt +++ b/compiler/testData/ir/irText/expressions/values.txt @@ -6,7 +6,7 @@ FILE fqName: fileName:/values.kt CONSTRUCTOR visibility:private <> () returnType:Enum flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: Enum INSTANCE_INITIALIZER_CALL classDescriptor='Enum' ENUM_ENTRY name:A init: ENUM_CONSTRUCTOR_CALL 'constructor Enum()' diff --git a/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.txt b/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.txt index 40af356499b..2dae7a40775 100644 --- a/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.txt +++ b/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.txt @@ -40,10 +40,10 @@ FILE fqName: fileName:/typeAliasCtorForGenericClass.kt BLOCK_BODY VAR name:b type:B /* = A */ flags:val CALL 'constructor A(Int)' type=A origin=null - : null + : Int q: CONST Int type=kotlin.Int value=2 VAR name:b2 type:B2 /* = A> */ flags:val CALL 'constructor A(A)' type=A> origin=null - : null + : A q: GET_VAR 'b: B /* = A */' type=B /* = A */ origin=null diff --git a/compiler/testData/ir/irText/singletons/enumEntry.txt b/compiler/testData/ir/irText/singletons/enumEntry.txt index d31721da508..0382212e55f 100644 --- a/compiler/testData/ir/irText/singletons/enumEntry.txt +++ b/compiler/testData/ir/irText/singletons/enumEntry.txt @@ -6,7 +6,7 @@ FILE fqName: fileName:/enumEntry.kt CONSTRUCTOR visibility:private <> () returnType:Z flags: BLOCK_BODY ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' - >: null + >: Z INSTANCE_INITIALIZER_CALL classDescriptor='Z' ENUM_ENTRY name:ENTRY init: ENUM_CONSTRUCTOR_CALL 'constructor ENTRY()' diff --git a/compiler/testData/ir/irText/stubs/builtinMap.kt b/compiler/testData/ir/irText/stubs/builtinMap.kt index e02636758d2..7b032308b0e 100644 --- a/compiler/testData/ir/irText/stubs/builtinMap.kt +++ b/compiler/testData/ir/irText/stubs/builtinMap.kt @@ -2,5 +2,5 @@ // WITH_RUNTIME // FULL_JDK -fun Map.plus(pair: Pair): Map = +fun Map.plus(pair: Pair): Map = if (this.isEmpty()) mapOf(pair) else LinkedHashMap(this).apply { put(pair.first, pair.second) } \ No newline at end of file diff --git a/compiler/testData/ir/irText/stubs/builtinMap.txt b/compiler/testData/ir/irText/stubs/builtinMap.txt index 40c01d3b484..8371edb9e7c 100644 --- a/compiler/testData/ir/irText/stubs/builtinMap.txt +++ b/compiler/testData/ir/irText/stubs/builtinMap.txt @@ -1,43 +1,42 @@ FILE fqName: fileName:/builtinMap.kt - FUN name:plus visibility:public modality:FINAL ($receiver:kotlin.collections.Map, pair:kotlin.Pair) returnType:Map flags: - TYPE_PARAMETER name:K index:0 variance: upperBounds:[kotlin.Any?] + FUN name:plus visibility:public modality:FINAL ($receiver:kotlin.collections.Map, pair:kotlin.Pair) returnType:Map flags: + TYPE_PARAMETER name:K1 index:0 variance: upperBounds:[kotlin.Any?] superClassifiers: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Any modality:OPEN visibility:public flags: - TYPE_PARAMETER name:V index:1 variance: upperBounds:[kotlin.Any?] + TYPE_PARAMETER name:V1 index:1 variance: upperBounds:[kotlin.Any?] superClassifiers: CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Any modality:OPEN visibility:public flags: - $receiver: VALUE_PARAMETER name: type:kotlin.collections.Map flags: - VALUE_PARAMETER name:pair index:0 type:kotlin.Pair flags: + $receiver: VALUE_PARAMETER name: type:kotlin.collections.Map flags: + VALUE_PARAMETER name:pair index:0 type:kotlin.Pair flags: BLOCK_BODY - RETURN type=kotlin.Nothing from='plus(Pair) on Map: Map' - WHEN type=kotlin.collections.Map origin=null + RETURN type=kotlin.Nothing from='plus(Pair) on Map: Map' + WHEN type=kotlin.collections.Map origin=null BRANCH if: CALL 'isEmpty(): Boolean' type=kotlin.Boolean origin=null - $this: GET_VAR 'this@plus: Map' type=kotlin.collections.Map origin=null - then: CALL 'mapOf(Pair): Map' type=kotlin.collections.Map origin=null - : K - : V - pair: GET_VAR 'value-parameter pair: Pair' type=kotlin.Pair origin=null + $this: GET_VAR 'this@plus: Map' type=kotlin.collections.Map origin=null + then: CALL 'mapOf(Pair): Map' type=kotlin.collections.Map origin=null + : K1 + : V1 + pair: GET_VAR 'value-parameter pair: Pair' type=kotlin.Pair origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: CALL 'apply(LinkedHashMap /* = LinkedHashMap */.() -> Unit) on LinkedHashMap /* = LinkedHashMap */: LinkedHashMap /* = LinkedHashMap */' type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */ origin=null - : LinkedHashMap /* = LinkedHashMap */ - $receiver: CALL 'constructor LinkedHashMap((MutableMap..Map?))' type=java.util.LinkedHashMap origin=null - : null - : null - p0: GET_VAR 'this@plus: Map' type=kotlin.collections.Map origin=null - block: BLOCK type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */.() -> kotlin.Unit origin=LAMBDA - FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */) returnType:Unit flags: - $receiver: VALUE_PARAMETER name: type:kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */ flags: + then: CALL 'apply(LinkedHashMap /* = LinkedHashMap */.() -> Unit) on LinkedHashMap /* = LinkedHashMap */: LinkedHashMap /* = LinkedHashMap */' type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */ origin=null + : LinkedHashMap /* = LinkedHashMap */ + $receiver: CALL 'constructor LinkedHashMap((MutableMap..Map?))' type=java.util.LinkedHashMap origin=null + : K1! + : V1! + p0: GET_VAR 'this@plus: Map' type=kotlin.collections.Map origin=null + block: BLOCK type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */.() -> kotlin.Unit origin=LAMBDA + FUN LOCAL_FUNCTION_FOR_LAMBDA name: visibility:local modality:FINAL <> ($receiver:kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */) returnType:Unit flags: + $receiver: VALUE_PARAMETER name: type:kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */ flags: BLOCK_BODY - RETURN type=kotlin.Nothing from='() on LinkedHashMap /* = LinkedHashMap */: Unit' + RETURN type=kotlin.Nothing from='() on LinkedHashMap /* = LinkedHashMap */: Unit' TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit typeOperand: CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public flags: - CALL 'put(K!, V!): V?' type=V? origin=null - $this: GET_VAR 'this@: LinkedHashMap<(K..K?), (V..V?)>' type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */ origin=null - key: CALL '(): K' type=K origin=GET_PROPERTY - $this: GET_VAR 'value-parameter pair: Pair' type=kotlin.Pair origin=null - value: CALL '(): V' type=V origin=GET_PROPERTY - $this: GET_VAR 'value-parameter pair: Pair' type=kotlin.Pair origin=null - FUNCTION_REFERENCE '() on LinkedHashMap /* = LinkedHashMap */: Unit' type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */.() -> kotlin.Unit origin=LAMBDA - + CALL 'put(K1!, V1!): V1?' type=V1? origin=null + $this: GET_VAR 'this@: LinkedHashMap<(K1..K1?), (V1..V1?)>' type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */ origin=null + key: CALL '(): K1' type=K1 origin=GET_PROPERTY + $this: GET_VAR 'value-parameter pair: Pair' type=kotlin.Pair origin=null + value: CALL '(): V1' type=V1 origin=GET_PROPERTY + $this: GET_VAR 'value-parameter pair: Pair' type=kotlin.Pair origin=null + FUNCTION_REFERENCE '() on LinkedHashMap /* = LinkedHashMap */: Unit' type=kotlin.collections.LinkedHashMap /* = java.util.LinkedHashMap */.() -> kotlin.Unit origin=LAMBDA diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 09f2130d57a..2d11f56b072 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -849,6 +849,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("memberTypeArguments.kt") + public void testMemberTypeArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/memberTypeArguments.kt"); + doTest(fileName); + } + @TestMetadata("membersImportedFromObject.kt") public void testMembersImportedFromObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/membersImportedFromObject.kt");