From 290adda8fcb03ade131785f30d198c76a35167b0 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 17 Oct 2023 17:20:57 +0200 Subject: [PATCH] Calculate empty array literal types in FIR2IR instead of deserializer This commit handles situations when some annotation in deserialized code has an empty array literal argument [] or even non-empty [something]. Before this commit, we tried to guess a type of this array by "resolving" the relevant annotation class and looking into the corresponding parameter. Sometimes it can work, but also it can provoke recursive resolve e.g. when the annotation class is a nested class in the same scope. In this commit we changed the behavior in the following way: - first, for non-empty array literals in deserialized code we just take the array type from the corresponding array literal element - second, for empty array literals we no more try to "guess" anything. Instead we approximate array type as Array, and later at FIR2IR stage we use the corresponding parameter type instead. At FIR2IR stage, everything is already resolved and problems with recursions are no more possible. #KT-62598 Fixed --- ...LFirBlackBoxCodegenBasedTestGenerated.java | 12 ++ ...rsedBlackBoxCodegenBasedTestGenerated.java | 12 ++ .../kotlin/fir/backend/ConversionUtils.kt | 10 +- .../kotlin/fir/backend/Fir2IrVisitor.kt | 20 ++-- .../generators/CallAndReferenceGenerator.kt | 13 ++- .../kotlin/fir/lazy/Fir2IrLazyProperty.kt | 5 +- ...LightTreeBlackBoxCodegenTestGenerated.java | 6 + ...hIrFakeOverrideGeneratorTestGenerated.java | 6 + .../FirPsiBlackBoxCodegenTestGenerated.java | 6 + .../java/deserialization/AnnotationsLoader.kt | 38 +++--- .../AnnotationInstantiationWithArray.ir.txt | 110 ++++++++++++++++++ .../AnnotationInstantiationWithArray.kt | 33 ++++++ .../fir/StackOverflowInAnnotationLoader.kt | 3 +- .../IrBlackBoxCodegenTestGenerated.java | 6 + ...kBoxCodegenWithIrInlinerTestGenerated.java | 6 + .../LightAnalysisModeTestGenerated.java | 5 + 16 files changed, 249 insertions(+), 42 deletions(-) create mode 100644 compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.ir.txt create mode 100644 compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java index 90eb4324cb8..f98c4e5dbeb 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirBlackBoxCodegenBasedTestGenerated.java @@ -533,6 +533,12 @@ public class LLFirBlackBoxCodegenBasedTestGenerated extends AbstractLLFirBlackBo runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @Test + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @Test @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() throws Exception { @@ -19574,6 +19580,12 @@ public class LLFirBlackBoxCodegenBasedTestGenerated extends AbstractLLFirBlackBo runTest("compiler/testData/codegen/box/fir/selectingLambdas.kt"); } + @Test + @TestMetadata("StackOverflowInAnnotationLoader.kt") + public void testStackOverflowInAnnotationLoader() throws Exception { + runTest("compiler/testData/codegen/box/fir/StackOverflowInAnnotationLoader.kt"); + } + @Test @TestMetadata("staticImportFromEnum.kt") public void testStaticImportFromEnum() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java index b19c064a1a3..71f1184e8d1 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirReversedBlackBoxCodegenBasedTestGenerated.java @@ -533,6 +533,12 @@ public class LLFirReversedBlackBoxCodegenBasedTestGenerated extends AbstractLLFi runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @Test + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @Test @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() throws Exception { @@ -19574,6 +19580,12 @@ public class LLFirReversedBlackBoxCodegenBasedTestGenerated extends AbstractLLFi runTest("compiler/testData/codegen/box/fir/selectingLambdas.kt"); } + @Test + @TestMetadata("StackOverflowInAnnotationLoader.kt") + public void testStackOverflowInAnnotationLoader() throws Exception { + runTest("compiler/testData/codegen/box/fir/StackOverflowInAnnotationLoader.kt"); + } + @Test @TestMetadata("staticImportFromEnum.kt") public void testStaticImportFromEnum() throws Exception { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index fcfa50b7fb5..509c9c0e1c8 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -774,12 +774,10 @@ fun IrActualizedResult?.extractFirDeclarations(): Set? { // This method is intended to be used for default values of annotation parameters (compile-time strings, numbers, enum values, KClasses) // where they are needed and may produce incorrect results for values that may be encountered outside annotations. -fun FirExpression.asCompileTimeIrInitializer(components: Fir2IrComponents): IrExpressionBody? { - return when (val elem = this.accept(Fir2IrVisitor(components, Fir2IrConversionScope(components.configuration)), null)) { - is IrExpressionBody -> elem - is IrExpression -> components.irFactory.createExpressionBody(elem) - else -> null - } +fun FirExpression.asCompileTimeIrInitializer(components: Fir2IrComponents, expectedType: ConeKotlinType? = null): IrExpressionBody { + val visitor = Fir2IrVisitor(components, Fir2IrConversionScope(components.configuration)) + val expression = visitor.convertToIrExpression(this, expectedType = expectedType) + return components.irFactory.createExpressionBody(expression) } /** diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 89fa6e73a47..a2d800daf17 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -894,7 +894,12 @@ class Fir2IrVisitor( internal fun convertToIrExpression( expression: FirExpression, - isDelegate: Boolean = false + isDelegate: Boolean = false, + // This argument is used for a corner case with deserialized empty array literals + // These array literals normally have a type of Array, + // so FIR2IR should instead use a type of corresponding property + // See also KT-62598 + expectedType: ConeKotlinType? = null, ): IrExpression { return when (expression) { is FirBlock -> expression.convertToIrExpressionOrBlock( @@ -908,6 +913,7 @@ class Fir2IrVisitor( else -> { when (val unwrappedExpression = expression.unwrapArgument()) { is FirCallableReferenceAccess -> convertCallableReferenceAccess(unwrappedExpression, isDelegate) + is FirArrayLiteral -> convertToArrayLiteral(unwrappedExpression, expectedType) else -> expression.accept(this, null) as IrExpression } } @@ -1577,9 +1583,13 @@ class Fir2IrVisitor( classifierStorage.getOrCreateIrClass(it).symbol } - private fun convertToArrayLiteral(arrayLiteral: FirArrayLiteral): IrVararg { + private fun convertToArrayLiteral( + arrayLiteral: FirArrayLiteral, + // See comment to convertToIrExpression + expectedType: ConeKotlinType?, + ): IrVararg { return arrayLiteral.convertWithOffsets { startOffset, endOffset -> - val arrayType = arrayLiteral.resolvedType.toIrType() + val arrayType = (expectedType ?: arrayLiteral.resolvedType).toIrType() val elementType = arrayType.getArrayElementType(irBuiltIns) IrVarargImpl( startOffset, endOffset, @@ -1590,10 +1600,6 @@ class Fir2IrVisitor( } } - override fun visitArrayLiteral(arrayLiteral: FirArrayLiteral, data: Any?): IrElement = whileAnalysing(session, arrayLiteral) { - return convertToArrayLiteral(arrayLiteral) - } - override fun visitAugmentedArraySetCall( augmentedArraySetCall: FirAugmentedArraySetCall, data: Any? diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 97e067b6a0b..7fbe28fc42a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -1032,10 +1032,17 @@ class CallAndReferenceGenerator( parameter: FirValueParameter?, substitutor: ConeSubstitutor, ): IrExpression { - var irArgument = visitor.convertToIrExpression(argument) - if (parameter != null) { + val parameterConeType = parameter?.returnTypeRef?.coneType + // Normally argument type should be correct itself. + // However, for deserialized annotations it's possible to have imprecise Array type + // for empty integer literal arguments. + // In this case we have to use parameter type itself which is more precise, like Array or IntArray. + // See KT-62598 and its fix for details. + val expectedType = parameterConeType.takeIf { visitor.annotationMode && parameterConeType?.isArrayType == true } + var irArgument = visitor.convertToIrExpression(argument, expectedType = expectedType) + if (parameterConeType != null) { with(visitor.implicitCastInserter) { - irArgument = irArgument.cast(argument, argument.resolvedType, parameter.returnTypeRef.coneType) + irArgument = irArgument.cast(argument, argument.resolvedType, parameterConeType) } } with(adapterGenerator) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt index 7475486732c..3658ed0561e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.resolvedType import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* @@ -95,7 +96,9 @@ class Fir2IrLazyProperty( private fun toIrInitializer(initializer: FirExpression?): IrExpressionBody? { // Annotations need full initializer information to instantiate them correctly return when { - containingClass?.classKind?.isAnnotationClass == true -> initializer?.asCompileTimeIrInitializer(components) + containingClass?.classKind?.isAnnotationClass == true -> initializer?.asCompileTimeIrInitializer( + components, fir.returnTypeRef.coneType + ) // Setting initializers to every other class causes some cryptic errors in lowerings initializer is FirConstExpression<*> -> { val constType = with(typeConverter) { initializer.resolvedType.toIrType() } 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 2ebc34439a1..d9ca30d4bdb 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 @@ -534,6 +534,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @Test + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @Test @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java index 7dfadd62224..035872fe736 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java @@ -534,6 +534,12 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @Test + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @Test @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() 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 0523fa4c5a2..6aca275fbf7 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 @@ -534,6 +534,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @Test + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @Test @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() throws Exception { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt index b6eee699ce9..a621e54b18b 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt @@ -7,18 +7,11 @@ package org.jetbrains.kotlin.fir.java.deserialization import org.jetbrains.kotlin.SpecialJvmAnnotations import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement import org.jetbrains.kotlin.fir.deserialization.toQualifiedPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.java.createConstantOrError import org.jetbrains.kotlin.fir.languageVersionSettings -import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.providers.getRegularClassSymbolByClassId -import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider -import org.jetbrains.kotlin.fir.scopes.getProperties -import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope -import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -99,10 +92,22 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko override fun visitEnd() { visitExpression(name, buildArrayLiteral { @OptIn(UnresolvedExpressionTypeAccess::class) + // 1. Calculate array literal type using its element, if any + // 2. If array literal is empty, try to "guess" type (works only for default values) + // 3. If both ways don't work, use Array as an approximation; later FIR2IR will calculate more precise type + // See KT-62598 + // Note: we suppose that (1) can be dropped without real semantic changes; + // in this case array literal argument types will be always Array at FIR level (even for non-empty literals), + // but at IR level we will still have a real array type, like Array or IntArray + // Maybe we can drop also (2), see KT-62929, with the same consequences + // Anyway, FIR provides no guarantees on having exact type of deserialized array literals in annotations, + // including non-empty ones. elements.firstOrNull()?.coneTypeOrNull?.createOutArrayType()?.let { coneTypeOrNull = it } ?: guessArrayTypeIfNeeded(name, elements)?.let { coneTypeOrNull = it.coneTypeOrNull + } ?: run { + coneTypeOrNull = StandardClassIds.Any.constructClassLikeType().createOutArrayType() } argumentList = buildArgumentList { arguments += elements @@ -136,7 +141,6 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko return object : AnnotationsLoaderVisitorImpl(enumEntryReferenceCreator) { private val argumentMap = mutableMapOf() - private val scopeSession: ScopeSession = ScopeSession() override fun visitExpression(name: Name?, expr: FirExpression) { if (name != null) argumentMap[name] = expr @@ -145,21 +149,9 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko override val visitNullNames: Boolean = false override fun guessArrayTypeIfNeeded(name: Name?, arrayOfElements: List): FirTypeRef? { - // Needed if we load a default value which is another annotation that has array value in it. e.g.: - // To instantiate Deprecated() we need a default value for ReplaceWith() that has imports: Array with default value []. - if (name == null) return null - // Note: generally we are not allowed to resolve anything, as this is might lead to recursive resolve problems - // However, K1 deserializer did exactly the same and no issues were reported. - val classSymbol = session.symbolProvider.getRegularClassSymbolByClassId(annotationClassId) ?: return null - // We need to enhance java classes, but we can't call unsubstitutedScope unconditionally because - // for Kotlin types, it will resolve the class to the SUPER_TYPES phase which can lead to a contract violation. - val scope = if (classSymbol.isJavaOrEnhancement) { - classSymbol.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false, memberRequiredPhase = null) - } else { - classSymbol.declaredMemberScope(session, memberRequiredPhase = null) - } - val propS = scope.getProperties(name).firstOrNull() - return propS?.resolvedReturnTypeRef + // Array will be created, later FIR2IR will use more precise type + // See KT-62598 + return null } override fun visitEnd() { diff --git a/compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.ir.txt b/compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.ir.txt new file mode 100644 index 00000000000..0b1fd24cf6e --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.ir.txt @@ -0,0 +1,110 @@ +Module: lib +FILE fqName:a fileName:/AnnotationInstantiationWithArrayLib.kt + CLASS ANNOTATION_CLASS name:Outer modality:OPEN visibility:public superTypes:[kotlin.Annotation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:a.Outer + CONSTRUCTOR visibility:public <> (array:kotlin.Array) returnType:a.Outer [primary] + VALUE_PARAMETER name:array index:0 type:kotlin.Array + EXPRESSION_BODY + VARARG type=kotlin.Array varargElementType=a.Outer.Inner + CONSTRUCTOR_CALL 'public constructor (v: kotlin.IntArray) declared in a.Outer.Inner' type=a.Outer.Inner origin=null + v: VARARG type=kotlin.IntArray varargElementType=kotlin.Int + CONST Int type=kotlin.Int value=1 + CONSTRUCTOR_CALL 'public constructor (v: kotlin.IntArray) declared in a.Outer.Inner' type=a.Outer.Inner origin=null + v: VARARG type=kotlin.IntArray varargElementType=kotlin.Int + CONST Int type=kotlin.Int value=2 + CONSTRUCTOR_CALL 'public constructor (v: kotlin.IntArray) declared in a.Outer.Inner' type=a.Outer.Inner origin=null + v: VARARG type=kotlin.IntArray varargElementType=kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:Outer modality:OPEN visibility:public superTypes:[kotlin.Annotation]' + PROPERTY name:array visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:array type:kotlin.Array visibility:private [final] + EXPRESSION_BODY + GET_VAR 'array: kotlin.Array declared in a.Outer.' type=kotlin.Array origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:a.Outer) returnType:kotlin.Array + correspondingProperty: PROPERTY name:array visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:a.Outer + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Array declared in a.Outer' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:array type:kotlin.Array visibility:private [final]' type=kotlin.Array origin=null + receiver: GET_VAR ': a.Outer declared in a.Outer.' type=a.Outer origin=null + CLASS ANNOTATION_CLASS name:Inner modality:OPEN visibility:public superTypes:[kotlin.Annotation] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:a.Outer.Inner + CONSTRUCTOR visibility:public <> (v:kotlin.IntArray) returnType:a.Outer.Inner [primary] + VALUE_PARAMETER name:v index:0 type:kotlin.IntArray + EXPRESSION_BODY + VARARG type=kotlin.IntArray varargElementType=kotlin.Int + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:Inner modality:OPEN visibility:public superTypes:[kotlin.Annotation]' + PROPERTY name:v visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:v type:kotlin.IntArray visibility:private [final] + EXPRESSION_BODY + GET_VAR 'v: kotlin.IntArray declared in a.Outer.Inner.' type=kotlin.IntArray origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:a.Outer.Inner) returnType:kotlin.IntArray + correspondingProperty: PROPERTY name:v visibility:public modality:FINAL [val] + $this: VALUE_PARAMETER name: type:a.Outer.Inner + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.IntArray declared in a.Outer.Inner' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:v type:kotlin.IntArray visibility:private [final]' type=kotlin.IntArray origin=null + receiver: GET_VAR ': a.Outer.Inner declared in a.Outer.Inner.' type=a.Outer.Inner origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Annotation + $this: VALUE_PARAMETER name: type:kotlin.Any +Module: app +FILE fqName:test fileName:/AnnotationInstantiationWithArrayApp.kt + CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any] + $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:test.C + CONSTRUCTOR visibility:public <> () returnType:test.C [primary] + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'public constructor () declared in kotlin.Any' + INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:C modality:FINAL visibility:public superTypes:[kotlin.Any]' + FUN name:six visibility:public modality:FINAL <> ($this:test.C) returnType:a.Outer + $this: VALUE_PARAMETER name: type:test.C + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun six (): a.Outer declared in test.C' + CONSTRUCTOR_CALL 'public constructor (array: kotlin.Array) declared in a.Outer' type=a.Outer origin=null + FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator] + overridden: + public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + VALUE_PARAMETER name:other index:0 type:kotlin.Any? + FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override] + overridden: + public open fun hashCode (): kotlin.Int declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override] + overridden: + public open fun toString (): kotlin.String declared in kotlin.Any + $this: VALUE_PARAMETER name: type:kotlin.Any + FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.String + BLOCK_BODY + TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit + CALL 'public open fun toString (): kotlin.String declared in a.Outer' type=kotlin.String origin=null + $this: CALL 'public final fun six (): a.Outer declared in test.C' type=a.Outer origin=null + $this: CONSTRUCTOR_CALL 'public constructor () declared in test.C' type=test.C origin=null + RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in test' + CONST String type=kotlin.String value="OK" diff --git a/compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt b/compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt new file mode 100644 index 00000000000..cbd7e93dc62 --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt @@ -0,0 +1,33 @@ +// TARGET_BACKEND: JVM_IR +// FIR_IDENTICAL +// DUMP_IR +// WITH_STDLIB +// ISSUE: KT-62598 +// This test is a simplified version of annotations/instances/multimoduleCreation.kt with potential deserialized annotation resolve problems + +// MODULE: lib +// FILE: AnnotationInstantiationWithArrayLib.kt + +package a + +annotation class Outer( + val array: Array = [Inner([1]), Inner([2]), Inner([])] +) { + annotation class Inner(val v: IntArray = []) +} + +// MODULE: app(lib) +// FILE: AnnotationInstantiationWithArrayApp.kt + +package test + +import a.* + +class C { + fun six(): Outer = Outer() +} + +fun box(): String { + C().six().toString() + return "OK" +} diff --git a/compiler/testData/codegen/box/fir/StackOverflowInAnnotationLoader.kt b/compiler/testData/codegen/box/fir/StackOverflowInAnnotationLoader.kt index 707cebc0861..e670a54d715 100644 --- a/compiler/testData/codegen/box/fir/StackOverflowInAnnotationLoader.kt +++ b/compiler/testData/codegen/box/fir/StackOverflowInAnnotationLoader.kt @@ -52,7 +52,6 @@ interface HolderWithEmpty { import Holder import ByteHolder import HolderWithDefault -// This line still provokes SOE in K2 -//import HolderWithEmpty +import HolderWithEmpty 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 259880650f6..bd6583f413a 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 @@ -534,6 +534,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @Test + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @Test @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() 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 b84279f147c..870f8d280ca 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 @@ -534,6 +534,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @Test + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @Test @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 9022fff780c..9feb71498f1 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -483,6 +483,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefaultLowered.kt"); } + @TestMetadata("AnnotationInstantiationWithArray.kt") + public void testAnnotationInstantiationWithArray() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/AnnotationInstantiationWithArray.kt"); + } + @TestMetadata("annotationJvmHashCode.kt") public void testAnnotationJvmHashCode() throws Exception { runTest("compiler/testData/codegen/box/annotations/instances/annotationJvmHashCode.kt");