diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ExternalPackageParentPatcher.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ExternalPackageParentPatcher.kt deleted file mode 100644 index 3d940dd4090..00000000000 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ExternalPackageParentPatcher.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2010-2020 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.fir.backend - -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid - -// TODO: should be a lowering -internal class ExternalPackageParentPatcher( - private val components: Fir2IrComponents, - private val fir2IrExtensions: Fir2IrExtensions -) : IrElementVisitorVoid { - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) - } - - override fun visitMemberAccess(expression: IrMemberAccessExpression<*>) { - super.visitMemberAccess(expression) - val callee = expression.symbol.owner as? IrMemberWithContainerSource ?: return - if (callee.parent is IrExternalPackageFragment) { - val parentClass = fir2IrExtensions.generateOrGetFacadeClass(callee, components) ?: return - parentClass.parent = callee.parent - callee.parent = parentClass - when (callee) { - is IrProperty -> handleProperty(callee, parentClass) - is IrSimpleFunction -> callee.correspondingPropertySymbol?.owner?.let { handleProperty(it, parentClass) } - } - } - } - - private fun handleProperty(property: IrProperty, newParent: IrClass) { - property.parent = newParent - property.getter?.parent = newParent - property.setter?.parent = newParent - property.backingField?.parent = newParent - } -} \ No newline at end of file diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 470becadf31..b050a9d0957 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.KtPsiSourceFileLinesMapping import org.jetbrains.kotlin.KtSourceFileLinesMappingFromLineStartOffsets -import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.AnalysisFlags @@ -32,12 +31,9 @@ import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode -import org.jetbrains.kotlin.ir.interpreter.transformer.preprocessForConstTransformer import org.jetbrains.kotlin.ir.interpreter.transformer.transformConst import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl -import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.platform.isJs import org.jetbrains.kotlin.psi.KtFile class Fir2IrConverter( @@ -54,7 +50,6 @@ class Fir2IrConverter( allFirFiles: List, irModuleFragment: IrModuleFragmentImpl, fir2irVisitor: Fir2IrVisitor, - fir2IrExtensions: Fir2IrExtensions, runPreCacheBuiltinClasses: Boolean ) { session.lazyDeclarationResolver.disableLazyResolveContractChecks() @@ -98,8 +93,6 @@ class Fir2IrConverter( } evaluateConstants(irModuleFragment, configuration) - - irModuleFragment.acceptVoid(ExternalPackageParentPatcher(components, fir2IrExtensions)) } fun bindFakeOverridesOrPostpone(declarations: List) { @@ -499,8 +492,7 @@ class Fir2IrConverter( } converter.runSourcesConversion( - allFirFiles, irModuleFragment, fir2irVisitor, fir2IrExtensions, - runPreCacheBuiltinClasses = initializedIrBuiltIns == null + allFirFiles, irModuleFragment, fir2irVisitor, runPreCacheBuiltinClasses = initializedIrBuiltIns == null ) return Fir2IrResult(irModuleFragment, components, moduleDescriptor) diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index 7d6441e105d..d1a0dbdd8a9 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -331,7 +331,8 @@ open class JvmIrCodegenFactory( val phases = if (evaluatorFragmentInfoForPsi2Ir != null) jvmFragmentLoweringPhases else jvmLoweringPhases val phaseConfig = customPhaseConfig ?: PhaseConfig(phases) val context = JvmBackendContext( - state, irModuleFragment.irBuiltins, symbolTable, phaseConfig, extensions, backendExtension, irSerializer, irPluginContext + state, irModuleFragment.irBuiltins, symbolTable, phaseConfig, extensions, + backendExtension, irSerializer, JvmIrDeserializerImpl(), irProviders, irPluginContext ) if (evaluatorFragmentInfoForPsi2Ir != null) { context.localDeclarationsLoweringData = mutableMapOf() diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index ba9974fb9f6..94b3bdf9539 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -473,7 +473,8 @@ private fun buildJvmLoweringPhases( nlevels = 1, actions = setOf(defaultDumper, validationAction), lower = - fragmentSharedVariablesLowering then + externalPackageParentPatcherPhase then + fragmentSharedVariablesLowering then validateIrBeforeLowering then processOptionalAnnotationsPhase then expectDeclarationsRemovingPhase then diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ExternalPackageParentPatcherLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ExternalPackageParentPatcherLowering.kt new file mode 100644 index 00000000000..f97fc1bd461 --- /dev/null +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/ExternalPackageParentPatcherLowering.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2023 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.jvm.lower + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmFileFacadeClass +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.ir.util.createParameterDeclarations +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.load.kotlin.FacadeClassSource + +internal val externalPackageParentPatcherPhase = makeIrModulePhase( + ::createLowering, + name = "ExternalPackageParentPatcherLowering", + description = "Replace parent from package fragment to FileKt class for top-level callables (K2 only)" +) + +private fun createLowering(context: CommonBackendContext): FileLoweringPass { + require(context is JvmBackendContext) + return when (context.configuration[CommonConfigurationKeys.USE_FIR]) { + true -> ExternalPackageParentPatcherLowering(context) + false, null -> FileLoweringPass.Empty + } +} + +class ExternalPackageParentPatcherLowering(val context: JvmBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.acceptVoid(Visitor()) + } + + private inner class Visitor : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitMemberAccess(expression: IrMemberAccessExpression<*>) { + visitElement(expression) + val callee = expression.symbol.owner as? IrMemberWithContainerSource ?: return + if (callee.parent is IrExternalPackageFragment) { + val parentClass = generateOrGetFacadeClass(callee) ?: return + parentClass.parent = callee.parent + callee.parent = parentClass + when (callee) { + is IrProperty -> handleProperty(callee, parentClass) + is IrSimpleFunction -> callee.correspondingPropertySymbol?.owner?.let { handleProperty(it, parentClass) } + } + } + } + + private fun generateOrGetFacadeClass(declaration: IrMemberWithContainerSource): IrClass? { + val deserializedSource = declaration.containerSource ?: return null + if (deserializedSource !is FacadeClassSource) return null + val facadeName = deserializedSource.facadeClassName ?: deserializedSource.className + return JvmFileFacadeClass( + if (deserializedSource.facadeClassName != null) IrDeclarationOrigin.JVM_MULTIFILE_CLASS else IrDeclarationOrigin.FILE_CLASS, + facadeName.fqNameForTopLevelClassMaybeWithDollars.shortName(), + deserializedSource, + deserializeIr = { irClass -> deserializeTopLevelClass(irClass) } + ).also { + it.createParameterDeclarations() + context.classNameOverride[it] = facadeName + } + } + + private fun deserializeTopLevelClass(irClass: IrClass): Boolean { + return context.irDeserializer.deserializeTopLevelClass( + irClass, context.irBuiltIns, context.symbolTable, context.irProviders, context.generatorExtensions + ) + } + + private fun handleProperty(property: IrProperty, newParent: IrClass) { + property.parent = newParent + property.getter?.parent = newParent + property.setter?.parent = newParent + property.backingField?.parent = newParent + } + } +} diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeAliasAnnotationMethodsLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeAliasAnnotationMethodsLowering.kt index 8ae6fda55c5..eb99368acb8 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeAliasAnnotationMethodsLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeAliasAnnotationMethodsLowering.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name + internal val typeAliasAnnotationMethodsPhase = makeIrFilePhase( ::TypeAliasAnnotationMethodsLowering, name = "TypeAliasAnnotationMethodsLowering", diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index e8a6f8da681..90c4c6ee4ff 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -31,8 +31,8 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin +import org.jetbrains.kotlin.ir.linkage.IrProvider import org.jetbrains.kotlin.ir.symbols.* -import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.util.* @@ -49,6 +49,8 @@ class JvmBackendContext( val generatorExtensions: JvmGeneratorExtensions, val backendExtension: JvmBackendExtension, val irSerializer: JvmIrSerializer?, + val irDeserializer: JvmIrDeserializer, + val irProviders: List, val irPluginContext: IrPluginContext?, ) : CommonBackendContext { @@ -63,12 +65,17 @@ class JvmBackendContext( generatorExtensions: JvmGeneratorExtensions, backendExtension: JvmBackendExtension, irSerializer: JvmIrSerializer?, - ) : this(state, irBuiltIns, symbolTable, phaseConfig, generatorExtensions, backendExtension, irSerializer, null) + irProviders: List, + irDeserializer: JvmIrDeserializer, + ) : this( + state, irBuiltIns, symbolTable, phaseConfig, generatorExtensions, + backendExtension, irSerializer, irDeserializer, irProviders, irPluginContext = null + ) data class LocalFunctionData( val localContext: LocalDeclarationsLowering.LocalFunctionContext, val newParameterToOld: Map, - val newParameterToCaptured: Map + val newParameterToCaptured: Map, ) // If not-null, this is populated by LocalDeclarationsLowering with the intermediate data @@ -219,7 +226,7 @@ class JvmBackendContext( override fun handleDeepCopy( fileSymbolMap: MutableMap, classSymbolMap: MutableMap, - functionSymbolMap: MutableMap + functionSymbolMap: MutableMap, ) { val oldClassesWithNameOverride = classNameOverride.keys.toList() for (klass in oldClassesWithNameOverride) { @@ -290,7 +297,7 @@ class JvmBackendContext( get() = false inner class JvmIr( - symbolTable: SymbolTable + symbolTable: SymbolTable, ) : Ir(this) { override val symbols = JvmSymbols(this@JvmBackendContext, symbolTable) @@ -300,7 +307,7 @@ class JvmBackendContext( override fun remapMultiFieldValueClassStructure( oldFunction: IrFunction, newFunction: IrFunction, - parametersMappingOrNull: Map? + parametersMappingOrNull: Map?, ) { val parametersMapping = parametersMappingOrNull ?: run { require(oldFunction.explicitParametersCount == newFunction.explicitParametersCount) { diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt index 30fb0bb7db7..98cae5ce890 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/IrInlineBodiesHandler.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.test.backend.handlers import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.lazy.AbstractIrLazyFunction import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression @@ -16,6 +17,7 @@ import org.jetbrains.kotlin.ir.util.resolveFakeOverride import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.test.backend.ir.IrBackendInput +import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.TestServices @@ -25,7 +27,7 @@ class IrInlineBodiesHandler(testServices: TestServices) : AbstractIrHandler(test override fun processModule(module: TestModule, info: IrBackendInput) { info.processAllIrModuleFragments(module) { irModule, _ -> irModule.acceptChildrenVoid(InlineFunctionsCollector()) - irModule.acceptChildrenVoid(InlineCallBodiesCheck()) + irModule.acceptChildrenVoid(InlineCallBodiesCheck(firEnabled = module.frontendKind == FrontendKinds.FIR)) } assertions.assertTrue((info as IrBackendInput.JvmIrBackendInput).backendInput.symbolTable.allUnbound.isEmpty()) @@ -46,7 +48,7 @@ class IrInlineBodiesHandler(testServices: TestServices) : AbstractIrHandler(test } } - inner class InlineCallBodiesCheck : IrElementVisitorVoid { + inner class InlineCallBodiesCheck(val firEnabled: Boolean) : IrElementVisitorVoid { override fun visitElement(element: IrElement) { element.acceptChildrenVoid(this) } @@ -68,7 +70,14 @@ class IrInlineBodiesHandler(testServices: TestServices) : AbstractIrHandler(test if (this !is AbstractIrLazyFunction) return body != null if (!isDeserializationEnabled) return false if (!isInline || isFakeOverride) return false - return getTopLevelDeclaration() is DeserializableClass + val topLevelDeclaration = getTopLevelDeclaration() + if (topLevelDeclaration is DeserializableClass) return true + return when (firEnabled) { + // In compilation with FIR parents of external top-levels functions are replaced + // in lowerings, not in fir2ir converter + true -> topLevelDeclaration.parent is IrExternalPackageFragment + false -> false + } } } }