[IR, JS] Refactoring: Introduce JsUnlinkedDeclarationsSupport

^KT-50775
This commit is contained in:
Dmitriy Dolovov
2022-01-13 17:26:17 +03:00
parent 0b1a7d05a9
commit 319125607e
7 changed files with 106 additions and 58 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.overrides.FileLocalAwareLinker
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.backend.common.serialization.linkerissues.* import org.jetbrains.kotlin.backend.common.serialization.linkerissues.*
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsProcessor import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsProcessor
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -37,7 +38,6 @@ abstract class KotlinIrLinker(
val builtIns: IrBuiltIns, val builtIns: IrBuiltIns,
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
private val exportedDependencies: List<ModuleDescriptor>, private val exportedDependencies: List<ModuleDescriptor>,
private val allowUnboundSymbols: Boolean = false,
val symbolProcessor: IrSymbolDeserializer.(IrSymbol, IdSignature) -> IrSymbol = { s, _ -> s }, val symbolProcessor: IrSymbolDeserializer.(IrSymbol, IdSignature) -> IrSymbol = { s, _ -> s },
) : IrDeserializer, FileLocalAwareLinker { ) : IrDeserializer, FileLocalAwareLinker {
@@ -59,13 +59,14 @@ abstract class KotlinIrLinker(
private lateinit var linkerExtensions: Collection<IrDeserializer.IrLinkerExtension> private lateinit var linkerExtensions: Collection<IrDeserializer.IrLinkerExtension>
protected open val unlinkedDeclarationsSupport: UnlinkedDeclarationsSupport = UnlinkedDeclarationsSupport.DISABLED
protected open val userVisibleIrModulesSupport: UserVisibleIrModulesSupport = UserVisibleIrModulesSupport.DEFAULT protected open val userVisibleIrModulesSupport: UserVisibleIrModulesSupport = UserVisibleIrModulesSupport.DEFAULT
fun handleSignatureIdNotFoundInModuleWithDependencies( fun handleSignatureIdNotFoundInModuleWithDependencies(
idSignature: IdSignature, idSignature: IdSignature,
moduleDeserializer: IrModuleDeserializer moduleDeserializer: IrModuleDeserializer
): IrModuleDeserializer { ): IrModuleDeserializer {
if (allowUnboundSymbols) { if (unlinkedDeclarationsSupport.allowUnboundSymbols) {
return object : IrModuleDeserializer(null, KotlinAbiVersion.CURRENT) { return object : IrModuleDeserializer(null, KotlinAbiVersion.CURRENT) {
override fun contains(idSig: IdSignature): Boolean = false override fun contains(idSig: IdSignature): Boolean = false
@@ -169,7 +170,7 @@ abstract class KotlinIrLinker(
?: tryResolveCustomDeclaration(symbol) ?: tryResolveCustomDeclaration(symbol)
?: return null ?: return null
} catch (e: IrSymbolTypeMismatchException) { } catch (e: IrSymbolTypeMismatchException) {
if (!allowUnboundSymbols) { if (!unlinkedDeclarationsSupport.allowUnboundSymbols) {
throw SymbolTypeMismatch(e, deserializersForModules.values, userVisibleIrModulesSupport).raiseIssue(messageLogger) throw SymbolTypeMismatch(e, deserializersForModules.values, userVisibleIrModulesSupport).raiseIssue(messageLogger)
} }
} }
@@ -220,7 +221,7 @@ abstract class KotlinIrLinker(
private fun markUnlinkedClassifiers(): Set<IrClassifierSymbol> { private fun markUnlinkedClassifiers(): Set<IrClassifierSymbol> {
if (!allowUnboundSymbols) return emptySet() if (!unlinkedDeclarationsSupport.allowUnboundSymbols) return emptySet()
val entries = fakeOverrideBuilder.fakeOverrideCandidates val entries = fakeOverrideBuilder.fakeOverrideCandidates
val result = mutableSetOf<IrClassifierSymbol>() val result = mutableSetOf<IrClassifierSymbol>()
@@ -299,8 +300,8 @@ abstract class KotlinIrLinker(
fakeOverrideBuilder.provideFakeOverrides() fakeOverrideBuilder.provideFakeOverrides()
triedToDeserializeDeclarationForSymbol.clear() triedToDeserializeDeclarationForSymbol.clear()
if (allowUnboundSymbols) { unlinkedDeclarationsSupport.whenUnboundSymbolsAllowed { unlinkedMarkerTypeHandler ->
val t = UnlinkedDeclarationsProcessor(builtIns, unlinkedClassifiers, messageLogger) val t = UnlinkedDeclarationsProcessor(builtIns, unlinkedClassifiers, unlinkedMarkerTypeHandler, messageLogger)
t.addLinkageErrorIntoUnlinkedClasses() t.addLinkageErrorIntoUnlinkedClasses()
applyToModules(t.signatureTransformer()) applyToModules(t.signatureTransformer())
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.backend.common.serialization.unlinked package org.jetbrains.kotlin.backend.common.serialization.unlinked
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport.UnlinkedMarkerTypeHandler
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
@@ -15,21 +16,19 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.fileOrNull import org.jetbrains.kotlin.ir.util.fileOrNull
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.types.Variance
internal class UnlinkedDeclarationsProcessor( internal class UnlinkedDeclarationsProcessor(
private val builtIns: IrBuiltIns, private val builtIns: IrBuiltIns,
private val unlinkedClassifiers: Set<IrClassifierSymbol>, private val unlinkedClassifiers: Set<IrClassifierSymbol>,
private val unlinkedMarkerTypeHandler: UnlinkedMarkerTypeHandler,
private val messageLogger: IrMessageLogger private val messageLogger: IrMessageLogger
) { ) {
@@ -64,8 +63,6 @@ internal class UnlinkedDeclarationsProcessor(
} }
} }
private val errorType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
private fun IrDeclaration.location(): IrMessageLogger.Location? = fileOrNull?.location(startOffset) private fun IrDeclaration.location(): IrMessageLogger.Location? = fileOrNull?.location(startOffset)
private fun IrFile.location(offset: Int): IrMessageLogger.Location { private fun IrFile.location(offset: Int): IrMessageLogger.Location {
@@ -95,12 +92,12 @@ internal class UnlinkedDeclarationsProcessor(
fun IrValueParameter.fixType() { fun IrValueParameter.fixType() {
if (type.isUnlinked()) { if (type.isUnlinked()) {
linked = false linked = false
type = errorType type = unlinkedMarkerTypeHandler.unlinkedMarkerType
defaultValue = null defaultValue = null
} }
varargElementType?.let { varargElementType?.let {
if (it.isUnlinked()) { if (it.isUnlinked()) {
varargElementType = errorType varargElementType = unlinkedMarkerTypeHandler.unlinkedMarkerType
} }
} }
} }
@@ -109,12 +106,12 @@ internal class UnlinkedDeclarationsProcessor(
declaration.valueParameters.forEach { it.fixType() } declaration.valueParameters.forEach { it.fixType() }
if (declaration.returnType.isUnlinked()) { if (declaration.returnType.isUnlinked()) {
linked = false linked = false
declaration.returnType = errorType declaration.returnType = unlinkedMarkerTypeHandler.unlinkedMarkerType
} }
declaration.typeParameters.forEach { declaration.typeParameters.forEach {
if (it.superTypes.any { s -> s.isUnlinked() }) { if (it.superTypes.any { s -> s.isUnlinked() }) {
linked = false linked = false
it.superTypes = listOf(errorType) it.superTypes = listOf(unlinkedMarkerTypeHandler.unlinkedMarkerType)
} }
} }
if (linked) { if (linked) {
@@ -138,7 +135,7 @@ internal class UnlinkedDeclarationsProcessor(
val kind = if (declaration.correspondingPropertySymbol != null) "Property" else "Field" val kind = if (declaration.correspondingPropertySymbol != null) "Property" else "Field"
declaration.reportWarning(kind, fqn.asString()) declaration.reportWarning(kind, fqn.asString())
declaration.type = errorType declaration.type = unlinkedMarkerTypeHandler.unlinkedMarkerType
declaration.initializer = null declaration.initializer = null
} else { } else {
declaration.transformChildrenVoid() declaration.transformChildrenVoid()
@@ -172,19 +169,24 @@ internal class UnlinkedDeclarationsProcessor(
} }
private fun IrFieldSymbol.isUnlinked(): Boolean { private fun IrFieldSymbol.isUnlinked(): Boolean {
return owner.type is IrErrorType return owner.type.isUnlinkedMarkerType()
} }
private fun IrFunctionSymbol.isUnlinked(): Boolean { private fun IrFunctionSymbol.isUnlinked(): Boolean {
val function = owner val function = owner
if (function.returnType is IrErrorType) return true if (function.returnType.isUnlinkedMarkerType()) return true
if (function.dispatchReceiverParameter?.type is IrErrorType) return true if (function.dispatchReceiverParameter?.type?.isUnlinkedMarkerType() == true) return true
if (function.extensionReceiverParameter?.type is IrErrorType) return true if (function.extensionReceiverParameter?.type?.isUnlinkedMarkerType() == true) return true
if (function.valueParameters.any { it.type is IrErrorType }) return true if (function.valueParameters.any { it.type.isUnlinkedMarkerType() }) return true
if (function.typeParameters.any { tp -> tp.superTypes.any { st -> st is IrErrorType } }) return true if (function.typeParameters.any { tp -> tp.superTypes.any { st -> st.isUnlinkedMarkerType() } }) return true
return false return false
} }
// That's not the same as IrType.isUnlinked()!
private fun IrType.isUnlinkedMarkerType(): Boolean {
return with(unlinkedMarkerTypeHandler) { isUnlinkedMarkerType() }
}
private fun IrElement.throwLinkageError(message: String?): IrCall { private fun IrElement.throwLinkageError(message: String?): IrCall {
return IrCallImpl(startOffset, endOffset, builtIns.nothingType, builtIns.linkageErrorSymbol, 0, 1, errorOrigin).also { call -> return IrCallImpl(startOffset, endOffset, builtIns.nothingType, builtIns.linkageErrorSymbol, 0, 1, errorOrigin).also { call ->
val messageLiteral = "Linkage error of symbol: ${message ?: ""}" val messageLiteral = "Linkage error of symbol: ${message ?: ""}"
@@ -224,7 +226,7 @@ internal class UnlinkedDeclarationsProcessor(
} }
override fun visitExpression(expression: IrExpression): IrExpression { override fun visitExpression(expression: IrExpression): IrExpression {
if (expression.type.isUnlinked() || expression.type is IrErrorType) { if (expression.type.isUnlinked() || expression.type.isUnlinkedMarkerType()) {
reportWarning("Expression type contains unlinked symbol", currentFile?.location(expression.startOffset)) reportWarning("Expression type contains unlinked symbol", currentFile?.location(expression.startOffset))
return expression.throwLinkageError("Unlinked type of expression") return expression.throwLinkageError("Unlinked type of expression")
} }
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization.unlinked
import org.jetbrains.kotlin.ir.types.IrType
interface UnlinkedDeclarationsSupport {
val allowUnboundSymbols: Boolean
fun <T : Any> whenUnboundSymbolsAllowed(action: (UnlinkedMarkerTypeHandler) -> T): T?
interface UnlinkedMarkerTypeHandler {
val unlinkedMarkerType: IrType
fun IrType.isUnlinkedMarkerType(): Boolean
}
companion object {
val DISABLED = object : UnlinkedDeclarationsSupport {
override val allowUnboundSymbols get() = false
override fun <T : Any> whenUnboundSymbolsAllowed(action: (UnlinkedMarkerTypeHandler) -> T): T? = null
}
}
}
@@ -31,10 +31,7 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.*
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
@@ -364,18 +361,18 @@ fun getIrModuleInfoForKlib(
val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable) val irBuiltIns = IrBuiltInsOverDescriptors(moduleDescriptor.builtIns, typeTranslator, symbolTable)
val allowUnboundSymbols = configuration[JSConfigurationKeys.PARTIAL_LINKAGE] ?: false val allowUnboundSymbols = configuration[JSConfigurationKeys.PARTIAL_LINKAGE] ?: false
val unlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(allowUnboundSymbols)
val irLinker = val irLinker = JsIrLinker(
JsIrLinker( currentModule = null,
null, messageLogger = messageLogger,
messageLogger, builtIns = irBuiltIns,
irBuiltIns, symbolTable = symbolTable,
symbolTable, translationPluginContext = null,
null, icData = null,
null, friendModules = friendModules,
friendModules, unlinkedDeclarationsSupport = unlinkedDeclarationsSupport
allowUnboundSymbols )
)
val deserializedModuleFragmentsToLib = deserializeDependencies(sortedDependencies, irLinker, mainModuleLib, filesToLoad, mapping) val deserializedModuleFragmentsToLib = deserializeDependencies(sortedDependencies, irLinker, mainModuleLib, filesToLoad, mapping)
val deserializedModuleFragments = deserializedModuleFragmentsToLib.keys.toList() val deserializedModuleFragments = deserializedModuleFragmentsToLib.keys.toList()
@@ -416,18 +413,18 @@ fun getIrModuleInfoForSourceFiles(
} }
val allowUnboundSymbols = configuration[JSConfigurationKeys.PARTIAL_LINKAGE] ?: false val allowUnboundSymbols = configuration[JSConfigurationKeys.PARTIAL_LINKAGE] ?: false
val unlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(allowUnboundSymbols)
val irLinker = val irLinker = JsIrLinker(
JsIrLinker( currentModule = psi2IrContext.moduleDescriptor,
psi2IrContext.moduleDescriptor, messageLogger = messageLogger,
messageLogger, builtIns = irBuiltIns,
irBuiltIns, symbolTable = symbolTable,
symbolTable, translationPluginContext = feContext,
feContext, icData = null,
null, friendModules = friendModules,
friendModules, unlinkedDeclarationsSupport = unlinkedDeclarationsSupport
allowUnboundSymbols )
)
val deserializedModuleFragmentsToLib = deserializeDependencies(allSortedDependencies, irLinker, null,null, mapping) val deserializedModuleFragmentsToLib = deserializeDependencies(allSortedDependencies, irLinker, null,null, mapping)
val deserializedModuleFragments = deserializedModuleFragmentsToLib.keys.toList() val deserializedModuleFragments = deserializedModuleFragmentsToLib.keys.toList()
(irBuiltIns as IrBuiltInsOverDescriptors).functionFactory = (irBuiltIns as IrBuiltInsOverDescriptors).functionFactory =
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideBuilder
import org.jetbrains.kotlin.backend.common.serialization.* import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrBuiltIns import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.builders.TranslationPluginContext import org.jetbrains.kotlin.ir.builders.TranslationPluginContext
@@ -23,14 +24,13 @@ class JsIrLinker(
override val translationPluginContext: TranslationPluginContext?, override val translationPluginContext: TranslationPluginContext?,
private val icData: ICData? = null, private val icData: ICData? = null,
friendModules: Map<String, Collection<String>> = emptyMap(), friendModules: Map<String, Collection<String>> = emptyMap(),
allowUnboundSymbols: Boolean = false override val unlinkedDeclarationsSupport: UnlinkedDeclarationsSupport = JsUnlinkedDeclarationsSupport(allowUnboundSymbols = false)
) : KotlinIrLinker( ) : KotlinIrLinker(
currentModule, currentModule = currentModule,
messageLogger, messageLogger = messageLogger,
builtIns, builtIns = builtIns,
symbolTable, symbolTable = symbolTable,
emptyList(), exportedDependencies = emptyList(),
allowUnboundSymbols,
symbolProcessor = { symbol, idSig -> symbolProcessor = { symbol, idSig ->
if (idSig.isLocal) { if (idSig.isLocal) {
symbol.privateSignature = IdSignature.CompositeSignature(IdSignature.FileSignature(fileSymbol), idSig) symbol.privateSignature = IdSignature.CompositeSignature(IdSignature.FileSignature(fileSymbol), idSig)
@@ -0,0 +1,23 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport
import org.jetbrains.kotlin.backend.common.serialization.unlinked.UnlinkedDeclarationsSupport.UnlinkedMarkerTypeHandler
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrErrorTypeImpl
import org.jetbrains.kotlin.types.Variance
class JsUnlinkedDeclarationsSupport(override val allowUnboundSymbols: Boolean) : UnlinkedDeclarationsSupport {
private val handler = object : UnlinkedMarkerTypeHandler {
override val unlinkedMarkerType = IrErrorTypeImpl(null, emptyList(), Variance.INVARIANT)
override fun IrType.isUnlinkedMarkerType() = this is IrErrorType
}
override fun <T : Any> whenUnboundSymbolsAllowed(action: (UnlinkedMarkerTypeHandler) -> T): T? =
if (allowUnboundSymbols) action(handler) else null
}
@@ -322,8 +322,8 @@ internal class KonanIrLinker(
private val cachedLibraries: CachedLibraries, private val cachedLibraries: CachedLibraries,
private val lazyIrForCaches: Boolean, private val lazyIrForCaches: Boolean,
override val userVisibleIrModulesSupport: UserVisibleIrModulesSupport, override val userVisibleIrModulesSupport: UserVisibleIrModulesSupport,
allowUnboundSymbols: Boolean allowUnboundSymbols: Boolean // TODO
) : KotlinIrLinker(currentModule, messageLogger, builtIns, symbolTable, exportedDependencies, allowUnboundSymbols) { ) : KotlinIrLinker(currentModule, messageLogger, builtIns, symbolTable, exportedDependencies) {
companion object { companion object {
private val C_NAMES_NAME = Name.identifier("cnames") private val C_NAMES_NAME = Name.identifier("cnames")