Fix type arguments mapping

This commit is contained in:
Dmitry Petrov
2018-03-19 14:08:04 +03:00
parent eb5904ea8e
commit 135d3ab57a
33 changed files with 365 additions and 165 deletions
@@ -269,6 +269,16 @@ fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuild
return call
}
fun getTypeArguments(resolvedCall: ResolvedCall<*>?): Map<TypeParameterDescriptor, KotlinType>? {
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<TypeParameterDescriptor, KotlinType>? {
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)
}
@@ -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)
}
@@ -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(
@@ -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
)
@@ -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<TypeParameterDescriptor, KotlinType>()
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<TypeParameterDescriptor, KotlinType>? =
if (overridden.original.typeParameters.isEmpty())
null
else
zipTypeParametersToDefaultTypes(overridden.original, delegated)
private fun zipTypeParametersToDefaultTypes(
keys: FunctionDescriptor,
values: FunctionDescriptor
): Map<TypeParameterDescriptor, KotlinType> {
val typeArguments = newHashMapWithExpectedSize<TypeParameterDescriptor, KotlinType>(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) {
@@ -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)
}
)
}
}
@@ -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<TypeParameterDescriptor, KotlinType>?,
val isExtensionInvokeCall: Boolean = false
) {
var superQualifier: ClassDescriptor? = null
@@ -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<TypeParameterDescriptor, KotlinType>? = null
): IrCall =
IrCallImpl(startOffset, endOffset, type, callee, callee.descriptor, typeArguments)
fun IrBuilderWithScope.irCall(callee: IrFunctionSymbol): IrCall =
irCall(callee, callee.descriptor.returnType!!)
@@ -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<TypeParameterDescriptor, KotlinType>?
) : 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<TypeParameterDescriptor, KotlinType>? = null
) : this(startOffset, endOffset, IrConstructorSymbolImpl(descriptor), typeArguments)
override val descriptor: ClassConstructorDescriptor get() = symbol.descriptor
@@ -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 <reified T : IrElement> 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<TypeParameterDescriptor, KotlinType>? {
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() }
}
}
@@ -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 <reified T : IrElement> 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 : IrMemberAccessExpression> T.transformReceiverArguments(original: T): T =
@@ -353,29 +353,24 @@ open class DeepCopyIrTreeWithSymbols(private val symbolRemapper: SymbolRemapper)
}
}
private fun IrMemberAccessExpression.getTypeArgumentsMap(): Map<TypeParameterDescriptor, KotlinType>? {
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(
@@ -177,7 +177,7 @@ class DumpIrTreeVisitor(out: Appendable) : IrElementVisitor<Unit, String> {
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")
}
}
@@ -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<TypeParameterDescriptor, KotlinType>? {
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<TypeParameterDescriptor, KotlinType>? {
if (this is IrMemberAccessExpressionBase) return typeArguments
val typeParameters = descriptor.original.typeParameters
return if (typeParameters.isEmpty())
null
else
typeParameters.associateBy({ it }, { getTypeArgument(it)!! })
}
+1 -1
View File
@@ -82,7 +82,7 @@ FILE fqName:<root> fileName:/classes.kt
CONSTRUCTOR visibility:private <> () returnType:TestEnumClass flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: TestEnumClass
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnumClass'
FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum<TestEnumClass>) returnType:Any flags:
overridden:
@@ -493,7 +493,7 @@ FILE fqName:<root> fileName:/dataClassWithArrayMembers.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='copy(Array<T> = ...): Test2<T>'
CALL 'constructor Test2(Array<T>)' type=Test2<T> origin=null
<T>: null
<T>: T
genericArray: GET_VAR 'value-parameter genericArray: Array<T> = ...' type=kotlin.Array<T> origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:Test2<T>) returnType:String flags:
overridden:
+1 -1
View File
@@ -36,7 +36,7 @@ FILE fqName:<root> fileName:/dataClassesGeneric.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='copy(T = ...): Test1<T>'
CALL 'constructor Test1(T)' type=Test1<T> origin=null
<T>: null
<T>: 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<T>) returnType:String flags:
overridden:
@@ -43,7 +43,7 @@ FILE fqName:<root> fileName:/delegatingConstructorCallToTypeAliasConstructor.kt
CONSTRUCTOR visibility:public <> () returnType:C1 flags:
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)'
<T>: null
<T>: 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:<root> fileName:/delegatingConstructorCallToTypeAliasConstructor.kt
CONSTRUCTOR visibility:public <> () returnType:C2 flags:
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)'
<T>: null
<T>: 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
+5 -5
View File
@@ -6,7 +6,7 @@ FILE fqName:<root> fileName:/enum.kt
CONSTRUCTOR visibility:private <> () returnType:TestEnum1 flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: TestEnum1
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum1'
ENUM_ENTRY name:TEST1
init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()'
@@ -65,7 +65,7 @@ FILE fqName:<root> fileName:/enum.kt
VALUE_PARAMETER name:x index:0 type:kotlin.Int flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: 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:<root> fileName:/enum.kt
CONSTRUCTOR visibility:private <> () returnType:TestEnum3 flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: TestEnum3
INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum3'
ENUM_ENTRY name:TEST
init: ENUM_CONSTRUCTOR_CALL 'constructor TEST()'
@@ -252,7 +252,7 @@ FILE fqName:<root> fileName:/enum.kt
VALUE_PARAMETER name:x index:0 type:kotlin.Int flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: 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:<root> fileName:/enum.kt
CONST Int type=kotlin.Int value=0
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: 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
@@ -7,7 +7,7 @@ FILE fqName:<root> fileName:/enumWithSecondaryCtor.kt
VALUE_PARAMETER name:x index:0 type:kotlin.Int flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: 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:<root> fileName:/enumWithSecondaryCtor.kt
VALUE_PARAMETER name:x index:0 type:kotlin.Int flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: 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:<root> fileName:/enumWithSecondaryCtor.kt
VALUE_PARAMETER name:x index:0 type:kotlin.Int flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: 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
@@ -57,7 +57,7 @@ FILE fqName:<root> fileName:/expectedEnumClass.kt
CONSTRUCTOR visibility:private <> () returnType:MyEnum flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: MyEnum
INSTANCE_INITIALIZER_CALL classDescriptor='MyEnum'
ENUM_ENTRY name:FOO
init: ENUM_CONSTRUCTOR_CALL 'constructor MyEnum()'
@@ -59,7 +59,7 @@ FILE fqName:<root> fileName:/dataClassMembers.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='copy(T = ..., String = ...): Test<T>'
CALL 'constructor Test(T, String = ...)' type=Test<T> origin=null
<T>: null
<T>: 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<T>) returnType:String flags:
@@ -58,7 +58,7 @@ FILE fqName:<root> fileName:/delegatedMembers.kt
VALUE_PARAMETER name:x index:1 type:X flags:
BLOCK_BODY
CALL 'qux(TT, X): Unit' type=kotlin.Unit origin=null
<X>: null
<X>: X
$this: GET_FIELD '`Test$IBase$delegate`: IBase<TT>' type=IBase<TT> origin=null
receiver: GET_VAR 'this@Test: Test<TT>' type=Test<TT> origin=null
t: GET_VAR 'value-parameter t: TT' type=TT origin=null
@@ -6,7 +6,7 @@ FILE fqName:<root> fileName:/enumEntryAsReceiver.kt
CONSTRUCTOR visibility:private <> () returnType:X flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: X
INSTANCE_INITIALIZER_CALL classDescriptor='X'
ENUM_ENTRY name:B
init: ENUM_CONSTRUCTOR_CALL 'constructor B()'
@@ -0,0 +1,3 @@
class GenericClass<T>(val value: T) {
fun withNewValue(newValue: T) = GenericClass(newValue)
}
@@ -0,0 +1,44 @@
FILE fqName:<root> fileName:/memberTypeArguments.kt
CLASS CLASS name:GenericClass modality:FINAL visibility:public flags:
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:GenericClass<T> 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<T> 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:<get-value> visibility:public modality:FINAL <> ($this:GenericClass<T>) returnType:T flags:
$this: VALUE_PARAMETER name:<this> type:GenericClass<T> flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-value>(): T'
GET_FIELD 'value: T' type=T origin=null
receiver: GET_VAR 'this@GenericClass: GenericClass<T>' type=GenericClass<T> origin=null
FUN name:withNewValue visibility:public modality:FINAL <> ($this:GenericClass<T>, newValue:T) returnType:GenericClass<T> flags:
$this: VALUE_PARAMETER name:<this> type:GenericClass<T> flags:
VALUE_PARAMETER name:newValue index:0 type:T flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='withNewValue(T): GenericClass<T>'
CALL 'constructor GenericClass(T)' type=GenericClass<T> origin=null
<T>: 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:<this> 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:<this> 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:<this> type:kotlin.Any flags:
@@ -27,7 +27,7 @@ FILE fqName:<root> fileName:/objectAsCallable.kt
CONSTRUCTOR visibility:private <> () returnType:En flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: En
INSTANCE_INITIALIZER_CALL classDescriptor='En'
ENUM_ENTRY name:X
init: ENUM_CONSTRUCTOR_CALL 'constructor En()'
@@ -39,5 +39,5 @@ FILE fqName:<root> fileName:/specializedTypeAliasConstructorCall.kt
BLOCK_BODY
RETURN type=kotlin.Nothing from='test(): IntAlias /* = Cell<Int> */'
CALL 'constructor Cell(Int)' type=Cell<kotlin.Int> origin=null
<T>: null
<T>: Int
value: CONST Int type=kotlin.Int value=42
+1 -1
View File
@@ -6,7 +6,7 @@ FILE fqName:<root> fileName:/values.kt
CONSTRUCTOR visibility:private <> () returnType:Enum flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: Enum
INSTANCE_INITIALIZER_CALL classDescriptor='Enum'
ENUM_ENTRY name:A
init: ENUM_CONSTRUCTOR_CALL 'constructor Enum()'
@@ -40,10 +40,10 @@ FILE fqName:<root> fileName:/typeAliasCtorForGenericClass.kt
BLOCK_BODY
VAR name:b type:B<kotlin.Int> /* = A<kotlin.Int> */ flags:val
CALL 'constructor A(Int)' type=A<kotlin.Int> origin=null
<Q>: null
<Q>: Int
q: CONST Int type=kotlin.Int value=2
VAR name:b2 type:B2<kotlin.Int> /* = A<A<kotlin.Int>> */ flags:val
CALL 'constructor A(A<Int>)' type=A<A<kotlin.Int>> origin=null
<Q>: null
<Q>: A<Int>
q: GET_VAR 'b: B<Int> /* = A<Int> */' type=B<kotlin.Int> /* = A<kotlin.Int> */ origin=null
+1 -1
View File
@@ -6,7 +6,7 @@ FILE fqName:<root> fileName:/enumEntry.kt
CONSTRUCTOR visibility:private <> () returnType:Z flags:
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)'
<E : Enum<E>>: null
<E : Enum<E>>: Z
INSTANCE_INITIALIZER_CALL classDescriptor='Z'
ENUM_ENTRY name:ENTRY
init: ENUM_CONSTRUCTOR_CALL 'constructor ENTRY()'
+1 -1
View File
@@ -2,5 +2,5 @@
// WITH_RUNTIME
// FULL_JDK
fun <K, V> Map<out K, V>.plus(pair: Pair<K, V>): Map<K, V> =
fun <K1, V1> Map<out K1, V1>.plus(pair: Pair<K1, V1>): Map<K1, V1> =
if (this.isEmpty()) mapOf(pair) else LinkedHashMap(this).apply { put(pair.first, pair.second) }
+29 -30
View File
@@ -1,43 +1,42 @@
FILE fqName:<root> fileName:/builtinMap.kt
FUN name:plus visibility:public modality:FINAL <K, V> ($receiver:kotlin.collections.Map<out K, V>, pair:kotlin.Pair<K, V>) returnType:Map<K, V> flags:
TYPE_PARAMETER name:K index:0 variance: upperBounds:[kotlin.Any?]
FUN name:plus visibility:public modality:FINAL <K1, V1> ($receiver:kotlin.collections.Map<out K1, V1>, pair:kotlin.Pair<K1, V1>) returnType:Map<K1, V1> 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:<this> type:kotlin.collections.Map<out K, V> flags:
VALUE_PARAMETER name:pair index:0 type:kotlin.Pair<K, V> flags:
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.Map<out K1, V1> flags:
VALUE_PARAMETER name:pair index:0 type:kotlin.Pair<K1, V1> flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='plus(Pair<K, V>) on Map<out K, V>: Map<K, V>'
WHEN type=kotlin.collections.Map<K, V> origin=null
RETURN type=kotlin.Nothing from='plus(Pair<K1, V1>) on Map<out K1, V1>: Map<K1, V1>'
WHEN type=kotlin.collections.Map<K1, V1> origin=null
BRANCH
if: CALL 'isEmpty(): Boolean' type=kotlin.Boolean origin=null
$this: GET_VAR 'this@plus: Map<out K, V>' type=kotlin.collections.Map<out K, V> origin=null
then: CALL 'mapOf(Pair<K, V>): Map<K, V>' type=kotlin.collections.Map<K, V> origin=null
<K>: K
<V>: V
pair: GET_VAR 'value-parameter pair: Pair<K, V>' type=kotlin.Pair<K, V> origin=null
$this: GET_VAR 'this@plus: Map<out K1, V1>' type=kotlin.collections.Map<out K1, V1> origin=null
then: CALL 'mapOf(Pair<K1, V1>): Map<K1, V1>' type=kotlin.collections.Map<K1, V1> origin=null
<K>: K1
<V>: V1
pair: GET_VAR 'value-parameter pair: Pair<K1, V1>' type=kotlin.Pair<K1, V1> origin=null
BRANCH
if: CONST Boolean type=kotlin.Boolean value=true
then: CALL 'apply(LinkedHashMap<K!, V!> /* = LinkedHashMap<K!, V!> */.() -> Unit) on LinkedHashMap<K!, V!> /* = LinkedHashMap<K!, V!> */: LinkedHashMap<K!, V!> /* = LinkedHashMap<K!, V!> */' type=kotlin.collections.LinkedHashMap<K!, V!> /* = java.util.LinkedHashMap<K!, V!> */ origin=null
<T>: LinkedHashMap<K!, V!> /* = LinkedHashMap<K!, V!> */
$receiver: CALL 'constructor LinkedHashMap((MutableMap<out K!, out V!>..Map<out K!, V!>?))' type=java.util.LinkedHashMap<K!, V!> origin=null
<K : Any!>: null
<V : Any!>: null
p0: GET_VAR 'this@plus: Map<out K, V>' type=kotlin.collections.Map<out K, V> origin=null
block: BLOCK type=kotlin.collections.LinkedHashMap<K!, V!> /* = java.util.LinkedHashMap<K!, V!> */.() -> kotlin.Unit origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:kotlin.collections.LinkedHashMap<K!, V!> /* = java.util.LinkedHashMap<K!, V!> */) returnType:Unit flags:
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.LinkedHashMap<K!, V!> /* = java.util.LinkedHashMap<K!, V!> */ flags:
then: CALL 'apply(LinkedHashMap<K1!, V1!> /* = LinkedHashMap<K1!, V1!> */.() -> Unit) on LinkedHashMap<K1!, V1!> /* = LinkedHashMap<K1!, V1!> */: LinkedHashMap<K1!, V1!> /* = LinkedHashMap<K1!, V1!> */' type=kotlin.collections.LinkedHashMap<K1!, V1!> /* = java.util.LinkedHashMap<K1!, V1!> */ origin=null
<T>: LinkedHashMap<K1!, V1!> /* = LinkedHashMap<K1!, V1!> */
$receiver: CALL 'constructor LinkedHashMap((MutableMap<out K1!, out V1!>..Map<out K1!, V1!>?))' type=java.util.LinkedHashMap<K1!, V1!> origin=null
<K : Any!>: K1!
<V : Any!>: V1!
p0: GET_VAR 'this@plus: Map<out K1, V1>' type=kotlin.collections.Map<out K1, V1> origin=null
block: BLOCK type=kotlin.collections.LinkedHashMap<K1!, V1!> /* = java.util.LinkedHashMap<K1!, V1!> */.() -> kotlin.Unit origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:kotlin.collections.LinkedHashMap<K1!, V1!> /* = java.util.LinkedHashMap<K1!, V1!> */) returnType:Unit flags:
$receiver: VALUE_PARAMETER name:<this> type:kotlin.collections.LinkedHashMap<K1!, V1!> /* = java.util.LinkedHashMap<K1!, V1!> */ flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='<anonymous>() on LinkedHashMap<K!, V!> /* = LinkedHashMap<K!, V!> */: Unit'
RETURN type=kotlin.Nothing from='<anonymous>() on LinkedHashMap<K1!, V1!> /* = LinkedHashMap<K1!, V1!> */: 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@<anonymous>: LinkedHashMap<(K..K?), (V..V?)>' type=kotlin.collections.LinkedHashMap<K!, V!> /* = java.util.LinkedHashMap<K!, V!> */ origin=null
key: CALL '<get-first>(): K' type=K origin=GET_PROPERTY
$this: GET_VAR 'value-parameter pair: Pair<K, V>' type=kotlin.Pair<K, V> origin=null
value: CALL '<get-second>(): V' type=V origin=GET_PROPERTY
$this: GET_VAR 'value-parameter pair: Pair<K, V>' type=kotlin.Pair<K, V> origin=null
FUNCTION_REFERENCE '<anonymous>() on LinkedHashMap<K!, V!> /* = LinkedHashMap<K!, V!> */: Unit' type=kotlin.collections.LinkedHashMap<K!, V!> /* = java.util.LinkedHashMap<K!, V!> */.() -> kotlin.Unit origin=LAMBDA
CALL 'put(K1!, V1!): V1?' type=V1? origin=null
$this: GET_VAR 'this@<anonymous>: LinkedHashMap<(K1..K1?), (V1..V1?)>' type=kotlin.collections.LinkedHashMap<K1!, V1!> /* = java.util.LinkedHashMap<K1!, V1!> */ origin=null
key: CALL '<get-first>(): K1' type=K1 origin=GET_PROPERTY
$this: GET_VAR 'value-parameter pair: Pair<K1, V1>' type=kotlin.Pair<K1, V1> origin=null
value: CALL '<get-second>(): V1' type=V1 origin=GET_PROPERTY
$this: GET_VAR 'value-parameter pair: Pair<K1, V1>' type=kotlin.Pair<K1, V1> origin=null
FUNCTION_REFERENCE '<anonymous>() on LinkedHashMap<K1!, V1!> /* = LinkedHashMap<K1!, V1!> */: Unit' type=kotlin.collections.LinkedHashMap<K1!, V1!> /* = java.util.LinkedHashMap<K1!, V1!> */.() -> kotlin.Unit origin=LAMBDA
@@ -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");