From 8771ce94ef47814a345b02b1b129f4b9fb159874 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Wed, 22 Dec 2021 19:01:06 +0300 Subject: [PATCH] Fir2Ir: deal with toplevel privates --- .../fir/backend/jvm/FirJvmMangleComputer.kt | 4 ++ .../kotlin/fir/backend/FirIrProvider.kt | 14 +++- .../signaturer/FirBasedSignatureComposer.kt | 64 ++++++++++++++++--- .../kotlin/fir/signaturer/FirManglerUtil.kt | 8 +++ 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt index d00ae0cd5ec..17f01ae4819 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmMangleComputer.kt @@ -322,6 +322,10 @@ open class FirJvmMangleComputer( override fun visitConstructor(constructor: FirConstructor, data: Boolean) = constructor.mangleFunction(isCtor = true, isStatic = false, constructor) + override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Boolean) { + propertyAccessor.mangleFunction(isCtor = false, propertyAccessor.isStatic, propertyAccessor.propertySymbol!!.fir) + } + override fun computeMangle(declaration: FirDeclaration): String { declaration.accept(this, true) return builder.toString() diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt index f9ea3485567..3123aea7b78 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt @@ -113,8 +113,7 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider { } } - // The next line should have singleOrNull, but in some cases we get multiple references to the same FIR declaration. - val firDeclaration = firCandidates.firstOrNull { fir2IrComponents.signatureComposer.composeSignature(it) == signature } + val firDeclaration = findDeclarationByHash(firCandidates, signature.id) ?: return null return when (kind) { @@ -138,4 +137,15 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider { else -> error("Don't know how to deal with this symbol kind: $kind") } } + + private fun findDeclarationByHash(candidates: Collection, hash: Long?): FirDeclaration? = + candidates.firstOrNull { candidate -> + if (hash == null) { + // We don't compute id for type aliases and classes. + candidate is FirClass || candidate is FirTypeAlias + } else { + // The next line should have singleOrNull, but in some cases we get multiple references to the same FIR declaration. + with(fir2IrComponents.signatureComposer.mangler) { candidate.signatureMangle(compatibleMode = false) == hash } + } + } } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt index 5ebab3d7e2a..fc7b8cd2b47 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirBasedSignatureComposer.kt @@ -9,6 +9,8 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.Fir2IrSignatureComposer import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter +import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.fir.declarations.utils.isExpect import org.jetbrains.kotlin.fir.declarations.utils.visibility @@ -16,7 +18,7 @@ import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.visitors.FirVisitor import org.jetbrains.kotlin.ir.util.IdSignature -@NoMutableState +// @NoMutableState -- we'll restore this annotation once we get rid of withFileSignature(). class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignatureComposer { var fileSignature: IdSignature.FileSignature? = null @@ -80,7 +82,7 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat } catch (t: Throwable) { throw IllegalStateException("Error while composing signature for ${declaration.render()}", t) } - return when (declaration) { + val publicSignature = when (declaration) { is FirRegularClass -> { // TODO: private classes are probably not acceptable here too val classId = declaration.classId @@ -96,7 +98,7 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat ) } is FirCallableDeclaration -> { - if (declaration.visibility == Visibilities.Private) return null + if (declaration.visibility == Visibilities.Private && !isTopLevelPrivate(declaration, containingClass)) return null val containingClassId = containingClass?.classId val classId = containingClassId ?: declaration.containingClass()?.classId @@ -111,6 +113,11 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat } else -> error("Unsupported FIR declaration in signature composer: ${declaration.render()}") } + return if (isTopLevelPrivate(declaration, containingClass)) { + val fileSig = fileSignature ?: return null + IdSignature.CompositeSignature(fileSig, publicSignature) + } else + publicSignature } override fun composeAccessorSignature( @@ -118,12 +125,51 @@ class FirBasedSignatureComposer(override val mangler: FirMangler) : Fir2IrSignat isSetter: Boolean, containingClass: ConeClassLikeLookupTag? ): IdSignature? { - val propertySignature = composeSignature(property, containingClass) as? IdSignature.CommonSignature ?: return null - val accessorFqName = if (isSetter) { - propertySignature.declarationFqName + "." - } else { - propertySignature.declarationFqName + "." + val propSig: IdSignature.CommonSignature + val fileSig: IdSignature.FileSignature? + when (val propertySignature = composeSignature(property, containingClass)) { + is IdSignature.CompositeSignature -> { + propSig = propertySignature.inner as? IdSignature.CommonSignature ?: return null + fileSig = propertySignature.container as? IdSignature.FileSignature ?: return null + } + is IdSignature.CommonSignature -> { + propSig = propertySignature + fileSig = null + } + else -> return null } - return IdSignature.CommonSignature(propertySignature.packageFqName, accessorFqName, propertySignature.id, propertySignature.mask) + val id = with(mangler) { + if (isSetter) { + property.setterOrDefault().signatureMangle(compatibleMode = false) + } else { + property.getterOrDefault().signatureMangle(compatibleMode = false) + } + } + val accessorFqName = if (isSetter) { + propSig.declarationFqName + "." + } else { + propSig.declarationFqName + "." + } + val commonSig = IdSignature.CommonSignature(propSig.packageFqName, accessorFqName, id, propSig.mask) + val accessorSig = IdSignature.AccessorSignature(propSig, commonSig) + return if (fileSig != null) { + IdSignature.CompositeSignature(fileSig, accessorSig) + } else accessorSig } + + private fun isTopLevelPrivate(declaration: FirDeclaration, containingClass: ConeClassLikeLookupTag?): Boolean = + containingClass == null && declaration is FirMemberDeclaration && declaration.visibility == Visibilities.Private + + private fun FirProperty.getterOrDefault() = + getter ?: FirDefaultPropertyGetter( + source = null, + moduleData, origin, returnTypeRef, visibility, symbol + ) + + private fun FirProperty.setterOrDefault() = + setter ?: FirDefaultPropertySetter( + source = null, + moduleData, origin, returnTypeRef, visibility, symbol + ) + } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirManglerUtil.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirManglerUtil.kt index ecc17741c5b..76e9585c7aa 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirManglerUtil.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/signaturer/FirManglerUtil.kt @@ -14,5 +14,13 @@ val FirCallableDeclaration.irName: Name is FirConstructor -> SpecialNames.INIT is FirSimpleFunction -> this.name is FirVariable -> this.name + is FirPropertyAccessor -> { + val prefix = when { + isGetter -> " " error("unknown property accessor kind $this") + } + Name.special(prefix + propertySymbol!!.fir.name + ">") + } else -> SpecialNames.ANONYMOUS }