From 0d8fff718648456a66dd47f3113978d90ea2efc8 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Wed, 10 Mar 2021 21:47:03 +0300 Subject: [PATCH] [KLIB] Fix annotation type deserialization Instead of hardcoded `Unit` restore it basing on annotation class and constructor's type arguments --- .../kotlin/ir/types/impl/IrSimpleTypeImpl.kt | 59 ++++++++++++++----- .../serialization/IrBodyDeserializer.kt | 54 ++++++++++++++++- 2 files changed, 94 insertions(+), 19 deletions(-) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt index dac83e8297e..d5b10de090e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/impl/IrSimpleTypeImpl.kt @@ -12,27 +12,19 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.Variance -class IrSimpleTypeImpl( - kotlinType: KotlinType?, - override val classifier: IrClassifierSymbol, - override val hasQuestionMark: Boolean, - override val arguments: List, - override val annotations: List, - override val abbreviation: IrTypeAbbreviation? = null -) : IrTypeBase(kotlinType), IrSimpleType { +abstract class IrAbstractSimpleType(kotlinType: KotlinType?) : IrTypeBase(kotlinType), IrSimpleType { + override val variance: Variance get() = Variance.INVARIANT - constructor( - classifier: IrClassifierSymbol, - hasQuestionMark: Boolean, - arguments: List, - annotations: List, - abbreviation: IrTypeAbbreviation? = null - ) : this(null, classifier, hasQuestionMark, arguments, annotations, abbreviation) + abstract override val classifier: IrClassifierSymbol + abstract override val hasQuestionMark: Boolean + abstract override val arguments: List + abstract override val annotations: List + abstract override val abbreviation: IrTypeAbbreviation? override fun equals(other: Any?): Boolean = - other is IrSimpleTypeImpl && + other is IrAbstractSimpleType && FqNameEqualityChecker.areEqual(classifier, other.classifier) && hasQuestionMark == other.hasQuestionMark && arguments == other.arguments @@ -43,6 +35,41 @@ class IrSimpleTypeImpl( arguments.hashCode() } +abstract class IrDelegatedSimpleType : IrAbstractSimpleType(null) { + + protected abstract val delegate: IrSimpleType + + override val classifier: IrClassifierSymbol + get() = delegate.classifier + override val hasQuestionMark: Boolean + get() = delegate.hasQuestionMark + override val arguments: List + get() = delegate.arguments + override val abbreviation: IrTypeAbbreviation? + get() = delegate.abbreviation + override val annotations: List + get() = delegate.annotations +} + + +class IrSimpleTypeImpl( + kotlinType: KotlinType?, + override val classifier: IrClassifierSymbol, + override val hasQuestionMark: Boolean, + override val arguments: List, + override val annotations: List, + override val abbreviation: IrTypeAbbreviation? = null +) : IrAbstractSimpleType(kotlinType) { + + constructor( + classifier: IrClassifierSymbol, + hasQuestionMark: Boolean, + arguments: List, + annotations: List, + abbreviation: IrTypeAbbreviation? = null + ) : this(null, classifier, hasQuestionMark, arguments, annotations, abbreviation) +} + class IrSimpleTypeBuilder { var kotlinType: KotlinType? = null var classifier: IrClassifierSymbol? = null diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt index fc2b62e62f3..2cc2279d0a3 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/serialization/IrBodyDeserializer.kt @@ -18,6 +18,8 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.* +import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlockBody as ProtoBlockBody import org.jetbrains.kotlin.backend.common.serialization.proto.IrBranch as ProtoBranch @@ -34,10 +36,10 @@ import org.jetbrains.kotlin.backend.common.serialization.proto.IrDoWhile as Prot import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicMemberExpression as ProtoDynamicMemberExpression import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicOperatorExpression as ProtoDynamicOperatorExpression import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumConstructorCall as ProtoEnumConstructorCall +import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorCallExpression as ProtoErrorCallExpression +import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorExpression as ProtoErrorExpression import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionExpression as ProtoFunctionExpression -import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorExpression as ProtoErrorExpression -import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorCallExpression as ProtoErrorCallExpression import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionReference as ProtoFunctionReference import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetClass as ProtoGetClass import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetEnumValue as ProtoGetEnumValue @@ -188,7 +190,53 @@ class IrBodyDeserializer( } fun deserializeAnnotation(proto: ProtoConstructorCall): IrConstructorCall { - return deserializeConstructorCall(proto, 0, 0, builtIns.unitType) // TODO: need a proper deserialization here + + // TODO: probably a bit more abstraction possible here up to `IrMemberAccessExpression` + // but at this point further complexization looks overengineered + class IrAnnotationType : IrDelegatedSimpleType() { + + var irConstructorCall: IrConstructorCall? = null + + override val delegate: IrSimpleType by lazy { resolveType() } + + private fun resolveType(): IrSimpleType { + val constructorCall = irConstructorCall ?: error("irConstructorCall should not be null at this stage") + irConstructorCall = null + + val klass = constructorCall.symbol.owner.parentAsClass + + val typeParameters = extractTypeParameters(klass) + + val typeArguments = ArrayList(typeParameters.size) + val typeParameterSymbols = ArrayList(typeParameters.size) + val rawType = with(IrSimpleTypeBuilder()) { + arguments = typeParameters.run { + mapTo(ArrayList(size)) { + classifier = it.symbol + buildTypeProjection() + } + } + classifier = klass.symbol + buildSimpleType() + } + + + for (i in typeParameters.indices) { + val typeParameter = typeParameters[i] + val callTypeArgument = constructorCall.getTypeArgument(i) ?: error("No type argument for id $i") + val typeArgument = makeTypeProjection(callTypeArgument, typeParameter.variance) + typeArguments.add(typeArgument) + typeParameterSymbols.add(typeParameter.symbol) + } + + val substitutor = IrTypeSubstitutor(typeParameterSymbols, typeArguments, builtIns) + return substitutor.substitute(rawType) as IrSimpleType + } + } + + val irType = IrAnnotationType() + // TODO: use real coordinates + return deserializeConstructorCall(proto, 0, 0, irType).also { irType.irConstructorCall = it } } fun deserializeConstructorCall(proto: ProtoConstructorCall, start: Int, end: Int, type: IrType): IrConstructorCall {