KT-53804 Restore old and incorrect logic of generating InnerClasses attributes for kotlin-stdlib
diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt
index bcca78b..a925a3a 100644
--- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt
+++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt
@@ -359,6 +359,8 @@
         else
             null
 
+    val oldInnerClassesLogic = configuration.getBoolean(JVMConfigurationKeys.OLD_INNER_CLASSES_LOGIC)
+
     init {
         this.interceptedBuilderFactory = builderFactory
             .wrapWith(
diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt
index 0df0a51..6607efd 100644
--- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt
+++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt
@@ -527,6 +527,12 @@
     )
     var noNewJavaAnnotationTargets: Boolean by FreezableVar(false)
 
+    @Argument(
+        value = "-Xuse-old-innerclasses-logic",
+        description = "Use old logic for generation of InnerClasses attributes"
+    )
+    var oldInnerClassesLogic: Boolean by FreezableVar(false)
+
     override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> {
         val result = super.configureAnalysisFlags(collector, languageVersion)
         result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt
index 92a55de..39014d7 100644
--- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt
@@ -318,6 +318,7 @@
     put(JVMConfigurationKeys.ENABLE_DEBUG_MODE, arguments.enableDebugMode)
     put(JVMConfigurationKeys.IGNORE_CONST_OPTIMIZATION_ERRORS, arguments.ignoreConstOptimizationErrors)
     put(JVMConfigurationKeys.NO_NEW_JAVA_ANNOTATION_TARGETS, arguments.noNewJavaAnnotationTargets)
+    put(JVMConfigurationKeys.OLD_INNER_CLASSES_LOGIC, arguments.oldInnerClassesLogic)
 
     val assertionsMode =
         JVMAssertionsMode.fromStringOrNull(arguments.assertionsMode)
diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java
index f864282..02159f1 100644
--- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java
+++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java
@@ -162,4 +162,7 @@
 
     public static final CompilerConfigurationKey<Boolean> NO_NEW_JAVA_ANNOTATION_TARGETS =
             CompilerConfigurationKey.create("Do not generate Java 1.8+ targets for Kotlin annotation classes");
+
+    public static final CompilerConfigurationKey<Boolean> OLD_INNER_CLASSES_LOGIC =
+            CompilerConfigurationKey.create("Use old logic for generation of InnerClasses attributes");
 }
diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java
index 960a114..480f0f1 100644
--- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java
+++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java
@@ -4055,10 +4055,22 @@
         }
 
         @Test
+        @TestMetadata("kt53804.kt")
+        public void testKt53804() throws Exception {
+            runTest("compiler/testData/codegen/bytecodeText/innerClasses/kt53804.kt");
+        }
+
+        @Test
         @TestMetadata("nestedClassInAnnotationArgument.kt")
         public void testNestedClassInAnnotationArgument() throws Exception {
             runTest("compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgument.kt");
         }
+
+        @Test
+        @TestMetadata("nestedClassInAnnotationArgumentOldMode.kt")
+        public void testNestedClassInAnnotationArgumentOldMode() throws Exception {
+            runTest("compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgumentOldMode.kt");
+        }
     }
 
     @Nested
diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt
index c18234a..3928a18 100644
--- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt
+++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt
@@ -87,16 +87,19 @@
     //       under incremental compilation, as calls to `inline fun`s declared in this class cause them to be generated out of order.
     private val innerClasses = linkedSetOf<IrClass>()
 
-    val typeMapper = object : IrTypeMapper(context) {
-        override fun mapType(type: IrType, mode: TypeMappingMode, sw: JvmSignatureWriter?): Type {
-            var t = type
-            while (t.isArray()) {
-                t = t.getArrayElementType(context.irBuiltIns)
+    val typeMapper =
+        if (context.state.oldInnerClassesLogic)
+            context.defaultTypeMapper
+        else object : IrTypeMapper(context) {
+            override fun mapType(type: IrType, mode: TypeMappingMode, sw: JvmSignatureWriter?): Type {
+                var t = type
+                while (t.isArray()) {
+                    t = t.getArrayElementType(context.irBuiltIns)
+                }
+                t.classOrNull?.owner?.let(::addInnerClassInfo)
+                return super.mapType(type, mode, sw)
             }
-            t.classOrNull?.owner?.let(::addInnerClassInfo)
-            return super.mapType(type, mode, sw)
         }
-    }
 
     val methodSignatureMapper = MethodSignatureMapper(context, typeMapper)
 
diff --git a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/directives/LanguageSettingsDirectives.kt b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/directives/LanguageSettingsDirectives.kt
index b9236d3..e94b4f3 100644
--- a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/directives/LanguageSettingsDirectives.kt
+++ b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/directives/LanguageSettingsDirectives.kt
@@ -75,6 +75,7 @@
     val PARAMETERS_METADATA by directive("Add parameters metadata for 1.8 reflection")
     val USE_TYPE_TABLE by directive("Use type table in metadata serialization")
     val NO_NEW_JAVA_ANNOTATION_TARGETS by directive("Do not generate Java annotation targets TYPE_USE/TYPE_PARAMETER for Kotlin annotation classes with Kotlin targets TYPE/TYPE_PARAMETER")
+    val OLD_INNER_CLASSES_LOGIC by directive("Use old logic for generation of InnerClasses attributes")
 
     // --------------------- Utils ---------------------
 
diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out
index 139d6f1..1c04505 100644
--- a/compiler/testData/cli/jvm/extraHelp.out
+++ b/compiler/testData/cli/jvm/extraHelp.out
@@ -108,6 +108,7 @@
                                * ignore
                                * strict
                                * warn (report a warning)
+  -Xuse-old-innerclasses-logic Use old logic for generation of InnerClasses attributes
   -Xprofile=<profilerPath:command:outputDir>
                              Debug option: Run compiler with async profiler and save snapshots to `outputDir`; `command` is passed to async-profiler on start.
                              `profilerPath` is a path to libasyncProfiler.so; async-profiler.jar should be on the compiler classpath.
diff --git a/compiler/testData/codegen/bytecodeText/innerClasses/kt53804.kt b/compiler/testData/codegen/bytecodeText/innerClasses/kt53804.kt
new file mode 100644
index 0000000..417529c
--- /dev/null
+++ b/compiler/testData/codegen/bytecodeText/innerClasses/kt53804.kt
@@ -0,0 +1,142 @@
+// OLD_INNER_CLASSES_LOGIC
+// TARGET_BACKEND: JVM_IR
+
+// FILE: classes.kt
+
+public class A0 {
+    public class B0 {
+        public class C0 {
+            public class D0
+        }
+    }
+}
+
+public class A1 {
+    public class B1 {
+        public class C1 {
+            public class D1
+        }
+    }
+}
+
+public class A2 {
+    public class B2 {
+        public class C2 {
+            public class D2
+        }
+    }
+}
+
+object A3 {
+    interface B3 {
+        interface C3 {
+            interface D3
+        }
+    }
+}
+
+public class A4 {
+    public class B4 {
+        public class C4 {
+            public class D4
+        }
+    }
+}
+
+public class A5 {
+    public class B5 {
+        public class C5 {
+            public class D5
+        }
+    }
+}
+
+public class A6 {
+    public class B6 {
+        public class C6 {
+            public class D6
+        }
+    }
+}
+
+@Target(AnnotationTarget.VALUE_PARAMETER)
+@Retention(AnnotationRetention.RUNTIME)
+annotation class ClassHolder(val value: kotlin.reflect.KClass<*>)
+
+public class A7 {
+    public class B7 {
+        public class C7 {
+            public class D7
+        }
+    }
+}
+
+@JvmInline
+public value class A8(private val value: Int) {
+    @JvmInline
+    public value class B8(private val value: Int) {
+        @JvmInline
+        public value class C8(private val value: Int) {
+            @JvmInline
+            public value class D8(private val value: Int)
+        }
+    }
+}
+
+
+inline fun <reified T> foo() = null
+
+
+// FILE: X.kt
+class X {
+    fun f0(t: List<Array<Array<Thread.State>>>) {}
+    fun f1(): A1.B1.C1? = null
+    fun f2() {
+        foo<A2.B2.C2>()
+    }
+    fun f3(x: Any): Any? = x as? A3.B3.C3
+    fun f4(): String {
+        val x = listOf<A4.B4.C4>()
+        return x.toString()
+    }
+
+    class Y {
+        fun f5(): String {
+            val x: A5.B5.C5? = null
+            return x.toString()
+        }
+        fun f6(): A6.B6.C6? = null
+
+        fun f7(@ClassHolder(A7.B7.C7::class) x: Int) {}
+
+        fun f8() = A8.B8.C8::class.toString()
+    }
+}
+
+
+// @X.class:
+// 1 INNERCLASS
+// 0 INNERCLASS java.lang.Thread\$State java.lang.Thread State
+// 0 INNERCLASS A0\$B0 A0 B0
+// 0 INNERCLASS A0\$B0\$C0 A0\$B0 C0
+// 0 INNERCLASS A1\$B1 A1 B1
+// 0 INNERCLASS A1\$B1\$C1 A1\$B1 C1
+// 0 INNERCLASS A2\$B2 A2 B2
+// 0 INNERCLASS A2\$B2\$C2 A2\$B2 C2
+// 0 INNERCLASS A3\$B3 A3 B3
+// 0 INNERCLASS A3\$B3\$C3 A3\$B3 C3
+// 0 INNERCLASS A4\$B4 A4 B4
+// 0 INNERCLASS A4\$B4\$C4 A4\$B4 C4
+// 1 INNERCLASS X\$Y X Y
+
+// @X$Y.class:
+// 3 INNERCLASS
+// 1 INNERCLASS X\$Y X Y
+// 0 INNERCLASS A5\$B5 A5 B5
+// 0 INNERCLASS A5\$B5\$C5 A5\$B5 C5
+// 0 INNERCLASS A6\$B6 A6 B6
+// 0 INNERCLASS A6\$B6\$C6 A6\$B6 C6
+// 1 INNERCLASS A7\$B7 A7 B7
+// 1 INNERCLASS A7\$B7\$C7 A7\$B7 C7
+// 0 INNERCLASS A8\$B8 A8 B8
+// 0 INNERCLASS A8\$B8\$C8 A8\$B8 C8
diff --git a/compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgumentOldMode.kt b/compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgumentOldMode.kt
new file mode 100644
index 0000000..856b4f8
--- /dev/null
+++ b/compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgumentOldMode.kt
@@ -0,0 +1,46 @@
+// OLD_INNER_CLASSES_LOGIC
+// TARGET_BACKEND: JVM_IR
+
+// FILE: annotations.kt
+
+import kotlin.reflect.*
+
+annotation class Anno(
+    val k: KClass<*>,
+    val e: C.NestedEnum,
+    val a: C.NestedAnno,
+)
+
+annotation class AnnoWithDefault(val k: KClass<*> = Nested0::class) {
+    class Nested0
+}
+
+class C {
+    class Nested1
+
+    enum class NestedEnum { E }
+
+    annotation class NestedAnno(val k: KClass<*>) {
+        class Nested2
+    }
+}
+
+// FILE: usage.kt
+
+interface I {
+    @Anno(
+        C.Nested1::class,
+        C.NestedEnum.E,
+        C.NestedAnno(C.NestedAnno.Nested2::class),
+    )
+    @AnnoWithDefault
+    fun foo(): String = "OK"
+}
+
+// @I.class:
+// 5 INNERCLASS
+// 1 INNERCLASS C\$Nested1 C Nested1
+// 1 INNERCLASS C\$NestedEnum C NestedEnum
+// 1 INNERCLASS C\$NestedAnno C NestedAnno
+// 1 INNERCLASS C\$NestedAnno\$Nested2 C\$NestedAnno Nested2
+// 1 INNERCLASS I\$DefaultImpls I DefaultImpls
\ No newline at end of file
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java
index dfb37ee..10e1a51 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java
@@ -4055,10 +4055,22 @@
         }
 
         @Test
+        @TestMetadata("kt53804.kt")
+        public void testKt53804() throws Exception {
+            runTest("compiler/testData/codegen/bytecodeText/innerClasses/kt53804.kt");
+        }
+
+        @Test
         @TestMetadata("nestedClassInAnnotationArgument.kt")
         public void testNestedClassInAnnotationArgument() throws Exception {
             runTest("compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgument.kt");
         }
+
+        @Test
+        @TestMetadata("nestedClassInAnnotationArgumentOldMode.kt")
+        public void testNestedClassInAnnotationArgumentOldMode() throws Exception {
+            runTest("compiler/testData/codegen/bytecodeText/innerClasses/nestedClassInAnnotationArgumentOldMode.kt");
+        }
     }
 
     @Nested
diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt
index 639fae9..eae4e1c 100644
--- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt
+++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/configuration/JvmEnvironmentConfigurator.kt
@@ -49,6 +49,7 @@
 import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.PARAMETERS_METADATA
 import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.JDK_RELEASE
 import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.NO_NEW_JAVA_ANNOTATION_TARGETS
+import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.OLD_INNER_CLASSES_LOGIC
 import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.USE_TYPE_TABLE
 import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
 import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
@@ -175,6 +176,7 @@
         register(USE_TYPE_TABLE, JVMConfigurationKeys.USE_TYPE_TABLE)
         register(ENABLE_DEBUG_MODE, JVMConfigurationKeys.ENABLE_DEBUG_MODE)
         register(NO_NEW_JAVA_ANNOTATION_TARGETS, JVMConfigurationKeys.NO_NEW_JAVA_ANNOTATION_TARGETS)
+        register(OLD_INNER_CLASSES_LOGIC, JVMConfigurationKeys.OLD_INNER_CLASSES_LOGIC)
     }
 
     override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule) {
diff --git a/libraries/stdlib/jvm/build.gradle b/libraries/stdlib/jvm/build.gradle
index 66a9af9..aebc2d2 100644
--- a/libraries/stdlib/jvm/build.gradle
+++ b/libraries/stdlib/jvm/build.gradle
@@ -118,6 +118,7 @@
                 "-Xbuiltins-from-sources",
                 "-XXLanguage:+RangeUntilOperator",
                 "-Xno-new-java-annotation-targets",
+                "-Xuse-old-innerclasses-logic",
         ]
         moduleName = "kotlin-stdlib"
     }