From 41f56729f9fb7bb582c80ff2eb2d0a989adc646f Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 4 Dec 2020 12:05:27 +0100 Subject: [PATCH] FIR: serialize correct fqnames for local classes --- .../compiler/KotlinToJVMBytecodeCompiler.kt | 2 +- .../FirElementAwareStringTable.kt | 5 +-- .../jvm/FirJvmElementAwareStringTable.kt | 32 ++++++++++--------- .../backend/jvm/FirJvmSerializerExtension.kt | 8 +++-- .../fir/backend/jvm/FirMetadataSerializer.kt | 8 +++-- .../fir/backend/Fir2IrClassifierStorage.kt | 2 +- .../ir/FirBlackBoxCodegenTestGenerated.java | 5 +++ .../reflection/properties/withLocalType.kt | 10 ++++++ .../kotlin/codegen/GenerationUtils.kt | 2 +- .../codegen/BlackBoxCodegenTestGenerated.java | 5 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 +++ 12 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 compiler/testData/codegen/box/reflection/properties/withLocalType.kt diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index bf750a4a152..55339968a7a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -391,7 +391,7 @@ object KotlinToJVMBytecodeCompiler { codegenFactory.generateModuleInFrontendIRMode( generationState, moduleFragment, symbolTable, sourceManager, extensions ) { context, irClass, _, serializationBindings, parent -> - FirMetadataSerializer(session, context, irClass, serializationBindings, parent) + FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent) } CodegenFactory.doCheckCancelled(generationState) generationState.factory.done() diff --git a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementAwareStringTable.kt b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementAwareStringTable.kt index 381c1291da4..2d7581270c6 100644 --- a/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementAwareStringTable.kt +++ b/compiler/fir/fir-serialization/src/org/jetbrains/kotlin/fir/serialization/FirElementAwareStringTable.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.serialization +import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.metadata.serialization.StringTable @@ -16,11 +17,11 @@ interface FirElementAwareStringTable : StringTable { fun getFqNameIndex(classLikeDeclaration: FirClassLikeDeclaration<*>): Int { val classId = classLikeDeclaration.symbol.classId.takeIf { !it.isLocal } - ?: getLocalClassIdReplacement(classLikeDeclaration) + ?: getLocalClassIdReplacement(classLikeDeclaration as FirClass<*>) ?: throw IllegalStateException("Cannot get FQ name of local class: ${classLikeDeclaration.render()}") return getQualifiedClassNameIndex(classId) } - fun getLocalClassIdReplacement(classLikeDeclaration: FirClassLikeDeclaration<*>): ClassId? = null + fun getLocalClassIdReplacement(firClass: FirClass<*>): ClassId? = null } diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmElementAwareStringTable.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmElementAwareStringTable.kt index fcda148cf8a..0734e6e0dec 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmElementAwareStringTable.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmElementAwareStringTable.kt @@ -5,30 +5,32 @@ package org.jetbrains.kotlin.fir.backend.jvm -import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration +import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper +import org.jetbrains.kotlin.backend.jvm.codegen.mapClass +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents +import org.jetbrains.kotlin.fir.declarations.FirClass import org.jetbrains.kotlin.fir.serialization.FirElementAwareStringTable +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmNameResolver import org.jetbrains.kotlin.metadata.jvm.serialization.JvmStringTable import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName class FirJvmElementAwareStringTable( + private val typeMapper: IrTypeMapper, + private val components: Fir2IrComponents, nameResolver: JvmNameResolver? = null ) : JvmStringTable(nameResolver), FirElementAwareStringTable { - override fun getLocalClassIdReplacement(classLikeDeclaration: FirClassLikeDeclaration<*>): ClassId { - return when (classLikeDeclaration.symbol.classId.outerClassId) { - // TODO: how to determine parent declaration for FIR local class properly? - //is ClassifierDescriptorWithTypeParameters -> getLocalClassIdReplacement(container).createNestedClassId(descriptor.name) -// null -> { -// throw IllegalStateException( -// "getLocalClassIdReplacement should only be called for local classes: ${classLikeDeclaration.render()}" -// ) -// } + override fun getLocalClassIdReplacement(firClass: FirClass<*>): ClassId = + components.classifierStorage.getCachedIrClass(firClass)?.getLocalClassIdReplacement() + ?: throw AssertionError("not a local class: ${firClass.symbol.classId}") + + private fun IrClass.getLocalClassIdReplacement(): ClassId = + when (val parent = parent) { + is IrClass -> parent.getLocalClassIdReplacement().createNestedClassId(name) else -> { - classLikeDeclaration.symbol.classId - // TODO: typeMapper.mapClass - //val fqName = FqName(typeMapper.mapClass(descriptor).internalName.replace('/', '.')) - //ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true) + val fqName = FqName(typeMapper.mapClass(this).internalName.replace('/', '.')) + ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true) } } - } } \ No newline at end of file diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt index af4b627c07a..80d41bf2e3d 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmSerializerExtension.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.backend.jvm +import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.codegen.state.GenerationState @@ -12,6 +13,7 @@ import org.jetbrains.kotlin.config.JvmDefaultMode import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.FirMetadataSource import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.firProvider @@ -41,10 +43,12 @@ class FirJvmSerializerExtension( state: GenerationState, private val irClass: IrClass, private val localDelegatedProperties: List, - private val approximator: AbstractTypeApproximator + private val approximator: AbstractTypeApproximator, + typeMapper: IrTypeMapper, + components: Fir2IrComponents ) : FirSerializerExtension() { private val globalBindings = state.globalSerializationBindings - override val stringTable = FirJvmElementAwareStringTable() + override val stringTable = FirJvmElementAwareStringTable(typeMapper, components) private val useTypeTable = state.useTypeTableInSerializer private val moduleName = state.moduleName private val classBuilderMode = state.classBuilderMode diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt index 0337a03af47..d56749f511a 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirMetadataSerializer.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.codegen.MetadataSerializer import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.FirMetadataSource import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildAnonymousFunction @@ -39,6 +40,7 @@ class FirMetadataSerializer( private val context: JvmBackendContext, private val irClass: IrClass, private val serializationBindings: JvmSerializationBindings, + components: Fir2IrComponents, parent: MetadataSerializer? ) : MetadataSerializer { private val approximator = object : AbstractTypeApproximator(session.typeContext) { @@ -144,8 +146,10 @@ class FirMetadataSerializer( (it.owner.metadata as FirMetadataSource.Property).fir.copyToFreeProperty() } ?: emptyList() - private val serializerExtension = - FirJvmSerializerExtension(session, serializationBindings, context.state, irClass, localDelegatedProperties, approximator) + private val serializerExtension = FirJvmSerializerExtension( + session, serializationBindings, context.state, irClass, localDelegatedProperties, approximator, + context.typeMapper, components + ) private val serializer: FirElementSerializer? = when (val metadata = irClass.metadata) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt index f979e551b70..02e48d99049 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt @@ -135,7 +135,7 @@ class Fir2IrClassifierStorage( return this } - internal fun getCachedIrClass(klass: FirClass<*>): IrClass? { + fun getCachedIrClass(klass: FirClass<*>): IrClass? { return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.Local) { localStorage.getLocalClass(klass) } else { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 6796fc5b928..9a67a955b38 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -28465,6 +28465,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); } + @TestMetadata("withLocalType.kt") + public void testWithLocalType() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt"); + } + @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/testData/codegen/box/reflection/properties/withLocalType.kt b/compiler/testData/codegen/box/reflection/properties/withLocalType.kt new file mode 100644 index 00000000000..4a2df45fa38 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/properties/withLocalType.kt @@ -0,0 +1,10 @@ +// TARGET_BACKEND: JVM +// WITH_REFLECT +// WITH_RUNTIME +import kotlin.reflect.full.declaredMemberProperties + +fun box(): String { + class A(val x: String) + class B(val y: A) + return (B::class.declaredMemberProperties.single().invoke(B(A("OK"))) as A).x +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt index 64e4599617e..540eb80eb97 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt @@ -144,7 +144,7 @@ object GenerationUtils { codegenFactory.generateModuleInFrontendIRMode( generationState, moduleFragment, symbolTable, sourceManager, extensions ) { context, irClass, _, serializationBindings, parent -> - FirMetadataSerializer(session, context, irClass, serializationBindings, parent) + FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent) } generationState.factory.done() diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 1a8ed41a92b..ac17b7bb56b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -28831,6 +28831,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); } + @TestMetadata("withLocalType.kt") + public void testWithLocalType() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt"); + } + @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index c38c8b2a820..9cbfe8a2ff2 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -26465,6 +26465,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); } + @TestMetadata("withLocalType.kt") + public void testWithLocalType() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt"); + } + @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 067da877c88..06fabd766a5 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -28465,6 +28465,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/reflection/properties/simpleGetProperties.kt"); } + @TestMetadata("withLocalType.kt") + public void testWithLocalType() throws Exception { + runTest("compiler/testData/codegen/box/reflection/properties/withLocalType.kt"); + } + @TestMetadata("compiler/testData/codegen/box/reflection/properties/accessors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)