From af05646fe388a6fe1833356e0ade8aeeee65f290 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 11 Apr 2023 12:14:08 +0300 Subject: [PATCH] [FIR] Don't expand typealiases in annotations during type deserialization During extracting type attributes from annotations we should expand typealiases of annotation type to handle cases when user makes a typealias on some special annotation, like `kotlin.internal.Exact`. And to exapnd typealias we should resolve annotation class id to symbol. This leads to a cycle during class deserialization, if some nested annotation is used as type annotation in some declaration in the same class ``` interface SomeInterface { interface NestedInterface : @Ann Some interface Some @Target(AnnotationTarget.TYPE) annotation class Ann } ``` Attempt to find symbol for SomeInterface.Ann during deserialization of SomeInterface.NestedInterface wil lead to second attempt to deserialize class SomeInterface, which eventually leads to StackOverFlow. And at the same time expanding typealiases for annotations from binaries has not much sense, because types in binaries are already expanded So to fix this issue it's enough to just not expand typealiases on type annotations for types of deserialized declarations ^KT-57876 Fixed --- .../fir/deserialization/FirTypeDeserializer.kt | 4 ++-- ...FirLightTreeBlackBoxCodegenTestGenerated.java | 12 ++++++++++++ .../FirPsiBlackBoxCodegenTestGenerated.java | 12 ++++++++++++ .../src/org/jetbrains/kotlin/fir/CopyUtils.kt | 12 +++++++++++- .../providers/impl/FirTypeResolverImpl.kt | 7 ++++--- .../deserializationOfNestedAnnotationOnType_1.kt | 16 ++++++++++++++++ .../deserializationOfNestedAnnotationOnType_2.kt | 14 ++++++++++++++ .../codegen/IrBlackBoxCodegenTestGenerated.java | 12 ++++++++++++ ...lackBoxCodegenWithIrInlinerTestGenerated.java | 12 ++++++++++++ 9 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt create mode 100644 compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt index 47aa6231848..e46277fa77f 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirTypeDeserializer.kt @@ -111,13 +111,13 @@ class FirTypeDeserializer( fun typeRef(proto: ProtoBuf.Type): FirTypeRef { return buildResolvedTypeRef { annotations += annotationDeserializer.loadTypeAnnotations(proto, nameResolver) - type = type(proto, annotations.computeTypeAttributes(moduleData.session)) + type = type(proto, annotations.computeTypeAttributes(moduleData.session, shouldExpandTypeAliases = false)) } } private fun attributesFromAnnotations(proto: ProtoBuf.Type): ConeAttributes = annotationDeserializer.loadTypeAnnotations(proto, nameResolver) - .computeTypeAttributes(moduleData.session) + .computeTypeAttributes(moduleData.session, shouldExpandTypeAliases = false) fun type(proto: ProtoBuf.Type): ConeKotlinType { return type(proto, attributesFromAnnotations(proto)) diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java index 935e319dd63..f5071b902b3 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java @@ -149,6 +149,18 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/annotations/delegatedPropertySetter.kt"); } + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_1.kt") + public void testDeserializationOfNestedAnnotationOnType_1() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt"); + } + + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_2.kt") + public void testDeserializationOfNestedAnnotationOnType_2() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt"); + } + @Test @TestMetadata("divisionByZeroInJava.kt") public void testDivisionByZeroInJava() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java index 63b0394a0dd..b1caaed2d9e 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java @@ -149,6 +149,18 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/annotations/delegatedPropertySetter.kt"); } + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_1.kt") + public void testDeserializationOfNestedAnnotationOnType_1() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt"); + } + + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_2.kt") + public void testDeserializationOfNestedAnnotationOnType_2() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt"); + } + @Test @TestMetadata("divisionByZeroInJava.kt") public void testDivisionByZeroInJava() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt index ffbc44522f0..5c2295cfd41 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/CopyUtils.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.expressions.* @@ -72,10 +73,15 @@ fun FirTypeRef.errorTypeFromPrototype( } } +/** + * [shouldExpandTypeAliases] should be set to `false` if this function is called during deserialization of some binary declaration + * For details see KT-57876 + */ fun List.computeTypeAttributes( session: FirSession, predefined: List> = emptyList(), containerDeclaration: FirDeclaration? = null, + shouldExpandTypeAliases: Boolean ): ConeAttributes { if (this.isEmpty()) { if (predefined.isEmpty()) return ConeAttributes.Empty @@ -85,7 +91,11 @@ fun List.computeTypeAttributes( attributes += predefined val customAnnotations = mutableListOf() for (annotation in this) { - when (annotation.tryExpandClassId(session)) { + val classId = when (shouldExpandTypeAliases) { + true -> annotation.tryExpandClassId(session) + false -> annotation.typeRef.coneType.classId + } + when (classId) { CompilerConeAttributes.Exact.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.Exact CompilerConeAttributes.NoInfer.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.NoInfer CompilerConeAttributes.ExtensionFunctionType.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.ExtensionFunctionType diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt index 69ce6756242..f50baad3474 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt @@ -319,7 +319,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { return ConeErrorType( diagnostic, typeArguments = resultingArguments, - attributes = typeRef.annotations.computeTypeAttributes(session) + attributes = typeRef.annotations.computeTypeAttributes(session, shouldExpandTypeAliases = true) ) } @@ -337,7 +337,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { return symbol.constructType( resultingArguments, typeRef.isMarkedNullable, - typeRef.annotations.computeTypeAttributes(session, containerDeclaration = containerDeclaration) + typeRef.annotations.computeTypeAttributes(session, containerDeclaration = containerDeclaration, shouldExpandTypeAliases = true) ).also { val lookupTag = it.lookupTag if (lookupTag is ConeClassLikeLookupTagImpl && symbol is FirClassLikeSymbol<*>) { @@ -479,7 +479,8 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { add(CompilerConeAttributes.ContextFunctionTypeParams(typeRef.contextReceiverTypeRefs.size)) } }, - containerDeclaration + containerDeclaration, + shouldExpandTypeAliases = true ) return ConeClassLikeTypeImpl( classId.toLookupTag(), diff --git a/compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt b/compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt new file mode 100644 index 00000000000..9e1def30a84 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt @@ -0,0 +1,16 @@ +// TARGET_BACKEND: JVM_IR +// ISSUE: KT-57876 + +// MODULE: lib +interface EnvironmentKeyProvider { + interface NestedInterface : @EnvironmentKeyDescription Some + + interface Some + + @Target(AnnotationTarget.TYPE) + annotation class EnvironmentKeyDescription +} + +// MODULE: main(lib) +fun bar(arg: EnvironmentKeyProvider.NestedInterface) {} +fun box() = "OK" diff --git a/compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt b/compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt new file mode 100644 index 00000000000..c5715e2fd6e --- /dev/null +++ b/compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt @@ -0,0 +1,14 @@ +// TARGET_BACKEND: JVM_IR +// ISSUE: KT-57876 + +// MODULE: lib +interface EnvironmentKeyProvider { + @Target(AnnotationTarget.TYPE) + annotation class EnvironmentKeyDescription + + fun getKnownKeys(arg: @EnvironmentKeyDescription String) +} + +// MODULE: main(lib) +fun foo(arg: EnvironmentKeyProvider) {} +fun box() = "OK" diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index b9308aa892d..cabaa96db23 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -149,6 +149,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/annotations/delegatedPropertySetter.kt"); } + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_1.kt") + public void testDeserializationOfNestedAnnotationOnType_1() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt"); + } + + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_2.kt") + public void testDeserializationOfNestedAnnotationOnType_2() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt"); + } + @Test @TestMetadata("divisionByZeroInJava.kt") public void testDivisionByZeroInJava() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java index 153358a390f..91ede3fff91 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java @@ -149,6 +149,18 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/annotations/delegatedPropertySetter.kt"); } + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_1.kt") + public void testDeserializationOfNestedAnnotationOnType_1() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_1.kt"); + } + + @Test + @TestMetadata("deserializationOfNestedAnnotationOnType_2.kt") + public void testDeserializationOfNestedAnnotationOnType_2() throws Exception { + runTest("compiler/testData/codegen/box/annotations/deserializationOfNestedAnnotationOnType_2.kt"); + } + @Test @TestMetadata("divisionByZeroInJava.kt") public void testDivisionByZeroInJava() throws Exception {