From 7d370300951908bf6d83d9ea587472e83f82cb89 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 1 Dec 2020 19:04:25 +0100 Subject: [PATCH 001/176] JVM IR, FIR: add JvmBackendExtension instead of MetadataSerializerFactory This might be a better place for future behavior that should be abstracted between FE 1.0 and FIR, in JVM IR. --- .../compiler/KotlinToJVMBytecodeCompiler.kt | 10 +++---- .../fir/backend/jvm/FirJvmBackendExtension.kt | 27 +++++++++++++++++ .../kotlin/backend/jvm/JvmBackendContext.kt | 5 +--- .../kotlin/backend/jvm/JvmBackendExtension.kt | 30 +++++++++++++++++++ .../kotlin/backend/jvm/JvmIrCodegenFactory.kt | 11 ++++--- .../backend/jvm/codegen/ClassCodegen.kt | 4 ++- .../backend/jvm/codegen/ClassCodegen.kt.201 | 4 ++- .../kotlin/test/backend/ir/IrBackendInput.kt | 4 +-- .../test/backend/ir/JvmIrBackendFacade.kt | 4 +-- .../classic/ClassicFrontend2IrConverter.kt | 8 ++--- .../frontend/fir/Fir2IrResultsConverter.kt | 7 ++--- .../kotlin/codegen/GenerationUtils.kt | 8 ++--- 12 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.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 55339968a7a..eebb41609a1 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 @@ -52,10 +52,10 @@ import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.diagnostics.* +import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver -import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer +import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.session.FirJvmModuleInfo @@ -389,10 +389,8 @@ object KotlinToJVMBytecodeCompiler { performanceManager?.notifyIRGenerationStarted() generationState.beforeCompile() codegenFactory.generateModuleInFrontendIRMode( - generationState, moduleFragment, symbolTable, sourceManager, extensions - ) { context, irClass, _, serializationBindings, parent -> - FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent) - } + generationState, moduleFragment, symbolTable, sourceManager, extensions, FirJvmBackendExtension(session, components) + ) CodegenFactory.doCheckCancelled(generationState) generationState.factory.done() diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt new file mode 100644 index 00000000000..98c7eed96d0 --- /dev/null +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt @@ -0,0 +1,27 @@ +/* + * 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.jvm + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmBackendExtension +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.ir.declarations.IrClass +import org.jetbrains.org.objectweb.asm.Type + +class FirJvmBackendExtension(private val session: FirSession, private val components: Fir2IrComponents) : JvmBackendExtension { + override fun createSerializer( + context: JvmBackendContext, + klass: IrClass, + type: Type, + bindings: JvmSerializationBindings, + parentSerializer: MetadataSerializer? + ): MetadataSerializer { + return FirMetadataSerializer(session, context, klass, bindings, components, parentSerializer) + } +} 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 10c4e2dde5a..dc4eb29d406 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 @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.backend.jvm.lower.CollectionStubComputer import org.jetbrains.kotlin.backend.jvm.lower.JvmInnerClassesSupport import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements -import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor @@ -41,8 +40,6 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.org.objectweb.asm.Type -typealias MetadataSerializerFactory = (JvmBackendContext, IrClass, Type, JvmSerializationBindings, MetadataSerializer?) -> MetadataSerializer - class JvmBackendContext( val state: GenerationState, val psiSourceManager: PsiSourceManager, @@ -51,7 +48,7 @@ class JvmBackendContext( private val symbolTable: SymbolTable, val phaseConfig: PhaseConfig, val generatorExtensions: JvmGeneratorExtensions, - val serializerFactory: MetadataSerializerFactory + val backendExtension: JvmBackendExtension, ) : CommonBackendContext { // If the JVM fqname of a class differs from what is implied by its parent, e.g. if it's a file class // annotated with @JvmPackageName, the correct name is recorded here. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt new file mode 100644 index 00000000000..98f6f16eedb --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt @@ -0,0 +1,30 @@ +/* + * 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.backend.jvm + +import org.jetbrains.kotlin.backend.jvm.codegen.DescriptorMetadataSerializer +import org.jetbrains.kotlin.backend.jvm.codegen.MetadataSerializer +import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.org.objectweb.asm.Type + +interface JvmBackendExtension { + fun createSerializer( + context: JvmBackendContext, klass: IrClass, type: Type, bindings: JvmSerializationBindings, parentSerializer: MetadataSerializer? + ): MetadataSerializer + + object Default : JvmBackendExtension { + override fun createSerializer( + context: JvmBackendContext, + klass: IrClass, + type: Type, + bindings: JvmSerializationBindings, + parentSerializer: MetadataSerializer? + ): MetadataSerializer { + return DescriptorMetadataSerializer(context, klass, type, bindings, parentSerializer) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index 28fa2b6499d..a451c47864c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen -import org.jetbrains.kotlin.backend.jvm.codegen.DescriptorMetadataSerializer import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.codegen.CodegenFactory @@ -120,7 +119,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory doGenerateFilesInternal( state, irModuleFragment, psi2irContext.symbolTable, psi2irContext.sourceManager, phaseConfig, - irProviders, extensions, ::DescriptorMetadataSerializer + irProviders, extensions, JvmBackendExtension.Default, ) } @@ -132,11 +131,11 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory phaseConfig: PhaseConfig, irProviders: List, extensions: JvmGeneratorExtensions, - serializerFactory: MetadataSerializerFactory, + backendExtension: JvmBackendExtension, ) { val context = JvmBackendContext( state, sourceManager, irModuleFragment.irBuiltins, irModuleFragment, - symbolTable, phaseConfig, extensions, serializerFactory + symbolTable, phaseConfig, extensions, backendExtension ) /* JvmBackendContext creates new unbound symbols, have to resolve them. */ ExternalDependenciesGenerator(symbolTable, irProviders, state.languageVersionSettings).generateUnboundSymbolsAsDependencies() @@ -178,7 +177,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory symbolTable: SymbolTable, sourceManager: PsiSourceManager, extensions: JvmGeneratorExtensions, - serializerFactory: MetadataSerializerFactory + backendExtension: JvmBackendExtension, ) { irModuleFragment.irBuiltins.functionFactory = IrFunctionFactory(irModuleFragment.irBuiltins, symbolTable) val irProviders = generateTypicalIrProviderList( @@ -186,7 +185,7 @@ class JvmIrCodegenFactory(private val phaseConfig: PhaseConfig) : CodegenFactory ) doGenerateFilesInternal( - state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, serializerFactory + state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, backendExtension, ) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 21758e69cd7..db877966a40 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -190,7 +190,9 @@ class ClassCodegen private constructor( } private val metadataSerializer: MetadataSerializer = - context.serializerFactory(context, irClass, type, visitor.serializationBindings, parentClassCodegen?.metadataSerializer) + context.backendExtension.createSerializer( + context, irClass, type, visitor.serializationBindings, parentClassCodegen?.metadataSerializer + ) private fun generateKotlinMetadataAnnotation() { // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 index f27ad043172..99b5bd200e4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 @@ -190,7 +190,9 @@ class ClassCodegen private constructor( } private val metadataSerializer: MetadataSerializer = - context.serializerFactory(context, irClass, type, visitor.serializationBindings, parentClassCodegen?.metadataSerializer) + context.backendExtension.createSerializer( + context, irClass, type, visitor.serializationBindings, parentClassCodegen?.metadataSerializer + ) private fun generateKotlinMetadataAnnotation() { // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt index 16fb993d6af..4cb962916b7 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.test.backend.ir import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig +import org.jetbrains.kotlin.backend.jvm.JvmBackendExtension import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions -import org.jetbrains.kotlin.backend.jvm.MetadataSerializerFactory import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.linkage.IrProvider @@ -25,7 +25,7 @@ data class IrBackendInput( val phaseConfig: PhaseConfig, val irProviders: List, val extensions: JvmGeneratorExtensions, - val serializerFactory: MetadataSerializerFactory + val backendExtension: JvmBackendExtension, ) : ResultingArtifact.BackendInput() { override val kind: BackendKinds.IrBackend get() = BackendKinds.IrBackend diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt index 600646290a5..12728f87de6 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt @@ -16,7 +16,7 @@ class JvmIrBackendFacade( module: TestModule, inputArtifact: IrBackendInput ): BinaryArtifacts.Jvm { - val (state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, serializerFactory) = inputArtifact + val (state, irModuleFragment, symbolTable, sourceManager, phaseConfig, irProviders, extensions, backendExtension) = inputArtifact val codegenFactory = state.codegenFactory as JvmIrCodegenFactory codegenFactory.doGenerateFilesInternal( @@ -27,7 +27,7 @@ class JvmIrBackendFacade( phaseConfig, irProviders, extensions, - serializerFactory + backendExtension, ) state.factory.done() diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt index 420fffd775e..f3b74d26dab 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt @@ -9,11 +9,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig -import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions -import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory -import org.jetbrains.kotlin.backend.jvm.JvmNameProvider -import org.jetbrains.kotlin.backend.jvm.codegen.DescriptorMetadataSerializer -import org.jetbrains.kotlin.backend.jvm.jvmPhases +import org.jetbrains.kotlin.backend.jvm.* import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.codegen.ClassBuilderFactories @@ -152,7 +148,7 @@ class ClassicFrontend2IrConverter( phaseConfig, irProviders, extensions, - ::DescriptorMetadataSerializer + JvmBackendExtension.Default, ) } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt index d54cda890ba..70b7987e483 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver -import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer +import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.ir.descriptors.IrFunctionFactory import org.jetbrains.kotlin.ir.util.generateTypicalIrProviderList @@ -89,8 +89,7 @@ class Fir2IrResultsConverter( phaseConfig, irProviders, extensions, - ) { context, irClass, _, serializationBindings, parent -> - FirMetadataSerializer(inputArtifact.session, context, irClass, serializationBindings, components, parent) - } + FirJvmBackendExtension(inputArtifact.session, components) + ) } } 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 540eb80eb97..6ea194f2c05 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt @@ -42,7 +42,7 @@ import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver -import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer +import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension import org.jetbrains.kotlin.fir.createSession import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries import org.jetbrains.kotlin.load.kotlin.PackagePartProvider @@ -142,10 +142,8 @@ object GenerationUtils { generationState.beforeCompile() codegenFactory.generateModuleInFrontendIRMode( - generationState, moduleFragment, symbolTable, sourceManager, extensions - ) { context, irClass, _, serializationBindings, parent -> - FirMetadataSerializer(session, context, irClass, serializationBindings, components, parent) - } + generationState, moduleFragment, symbolTable, sourceManager, extensions, FirJvmBackendExtension(session, components), + ) generationState.factory.done() return generationState From b7d32a875482496232e47a4405a125246171a70f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 7 Dec 2020 21:13:18 +0100 Subject: [PATCH 002/176] Minor, invert analysis flag that allows unstable dependencies --- .../kotlin/cli/common/arguments/K2JVMCompilerArguments.kt | 2 +- .../config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt | 2 +- .../kotlin/resolve/CompilerDeserializationConfiguration.kt | 2 +- .../kotlin/load/kotlin/DeserializedDescriptorResolver.kt | 2 +- .../deserialization/DeserializationConfiguration.kt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) 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 2137b548ada..0c217daed93 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 @@ -446,7 +446,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview - result[AnalysisFlags.reportErrorsOnIrDependencies] = !useIR && !useFir && !allowJvmIrDependencies + result[AnalysisFlags.allowUnstableDependencies] = allowJvmIrDependencies || useIR || useFir result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses return result } diff --git a/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt b/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt index 123e5bad772..3cab8a5ff3a 100644 --- a/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt +++ b/compiler/config/src/org/jetbrains/kotlin/config/AnalysisFlags.kt @@ -46,7 +46,7 @@ object AnalysisFlags { val ideMode by AnalysisFlag.Delegates.Boolean @JvmStatic - val reportErrorsOnIrDependencies by AnalysisFlag.Delegates.Boolean + val allowUnstableDependencies by AnalysisFlag.Delegates.Boolean @JvmStatic val libraryToSourceAnalysis by AnalysisFlag.Delegates.Boolean diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt index 84fe95ab7e3..23758d853c3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/CompilerDeserializationConfiguration.kt @@ -19,7 +19,7 @@ class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVers override val reportErrorsOnPreReleaseDependencies = !skipPrereleaseCheck && !languageVersionSettings.isPreRelease() && !KotlinCompilerVersion.isPreRelease() - override val reportErrorsOnIrDependencies = languageVersionSettings.getFlag(AnalysisFlags.reportErrorsOnIrDependencies) + override val allowUnstableDependencies = languageVersionSettings.getFlag(AnalysisFlags.allowUnstableDependencies) override val typeAliasesAllowed = languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt index 65278113123..24970d50c33 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt @@ -98,7 +98,7 @@ class DeserializedDescriptorResolver { classHeader.isPreRelease && classHeader.metadataVersion == KOTLIN_1_3_M1_METADATA_VERSION private val KotlinJvmBinaryClass.isInvisibleJvmIrDependency: Boolean - get() = components.configuration.reportErrorsOnIrDependencies && classHeader.isUnstableJvmIrBinary + get() = !components.configuration.allowUnstableDependencies && classHeader.isUnstableJvmIrBinary private fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set): Array? { val header = kotlinClass.classHeader diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializationConfiguration.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializationConfiguration.kt index 84050087374..0de6b01882e 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializationConfiguration.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/DeserializationConfiguration.kt @@ -15,7 +15,7 @@ interface DeserializationConfiguration { val reportErrorsOnPreReleaseDependencies: Boolean get() = false - val reportErrorsOnIrDependencies: Boolean + val allowUnstableDependencies: Boolean get() = false val typeAliasesAllowed: Boolean From cbd90c3af5b7b8ae935c50ddc040ccf6624ade09 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 7 Dec 2020 21:02:01 +0100 Subject: [PATCH 003/176] Refactor boolean IR ABI stability flag to enum Introduce an enum DeserializedContainerAbiStability with two values. This is needed in order to support another reason for ABI instability in a subsequent commit, namely "unstable because compiled by FIR". #KT-43592 --- .../kotlin/codegen/state/GenerationState.kt | 2 +- .../org/jetbrains/kotlin/cli/jvm/jvmArguments.kt | 4 +++- .../kotlin/config/JVMConfigurationKeys.java | 4 ++-- .../org/jetbrains/kotlin/config/JvmAbiStability.kt | 12 ++++++++++++ .../checkers/MissingDependencyClassChecker.kt | 3 ++- .../kotlin/backend/jvm/codegen/ClassCodegen.kt | 3 ++- .../kotlin/backend/jvm/codegen/ClassCodegen.kt.201 | 3 ++- .../descriptors/DeserializedContainerSource.kt | 9 ++++++++- .../load/kotlin/DeserializedDescriptorResolver.kt | 13 +++++++++---- .../kotlin/load/kotlin/JvmPackagePartSource.kt | 7 ++++--- .../load/kotlin/KotlinJvmBinarySourceElement.kt | 3 ++- .../js/KotlinJavascriptPackageFragment.kt | 5 +++-- 12 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt 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 1923db861c7..844cfe00604 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/GenerationState.kt @@ -298,7 +298,7 @@ class GenerationState private constructor( ?: if (languageVersionSettings.languageVersion >= LanguageVersion.LATEST_STABLE) JvmMetadataVersion.INSTANCE else JvmMetadataVersion(1, 1, 18) - val isIrWithStableAbi = configuration.getBoolean(JVMConfigurationKeys.IS_IR_WITH_STABLE_ABI) + val abiStability = configuration.get(JVMConfigurationKeys.ABI_STABILITY) val globalSerializationBindings = JvmSerializationBindings() var mapInlineClass: (ClassDescriptor) -> Type = { descriptor -> typeMapper.mapType(descriptor.defaultType) } 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 709ba73a6b3..0df11b8c373 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -172,7 +172,9 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters) put(JVMConfigurationKeys.IR, arguments.useIR && !arguments.noUseIR) - put(JVMConfigurationKeys.IS_IR_WITH_STABLE_ABI, arguments.isIrWithStableAbi) + + put(JVMConfigurationKeys.ABI_STABILITY, if (arguments.isIrWithStableAbi) JvmAbiStability.STABLE else JvmAbiStability.UNSTABLE) + put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, arguments.doNotClearBindingContext) put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions) put(JVMConfigurationKeys.DISABLE_RECEIVER_ASSERTIONS, arguments.noReceiverAssertions) 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 de4c0f9e015..41baa5d8707 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -117,8 +117,8 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey> KLIB_PATHS = CompilerConfigurationKey.create("Paths to .klib libraries"); - public static final CompilerConfigurationKey IS_IR_WITH_STABLE_ABI = - CompilerConfigurationKey.create("Is IR with stable ABI"); + public static final CompilerConfigurationKey ABI_STABILITY = + CompilerConfigurationKey.create("ABI stability of class files produced by the JVM IR backend"); public static final CompilerConfigurationKey DO_NOT_CLEAR_BINDING_CONTEXT = CompilerConfigurationKey.create("When using the IR backend, do not clear BindingContext between psi2ir and lowerings"); diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt new file mode 100644 index 00000000000..90fd1ca9d64 --- /dev/null +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt @@ -0,0 +1,12 @@ +/* + * 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.config + +enum class JvmAbiStability(val description: String) { + STABLE("stable"), + UNSTABLE("unstable"), + ; +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt index b1f6bcd4ef5..6bd2e0562be 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext import org.jetbrains.kotlin.resolve.calls.checkers.isComputingDeferredType import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor import org.jetbrains.kotlin.types.KotlinType @@ -58,7 +59,7 @@ object MissingDependencyClassChecker : CallChecker { if (source.isPreReleaseInvisible) { return PRE_RELEASE_CLASS.on(reportOn, source.presentableString) } - if (source.isInvisibleIrDependency) { + if (source.abiStability == DeserializedContainerAbiStability.IR_UNSTABLE) { return IR_COMPILED_CLASS.on(reportOn, source.presentableString) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index db877966a40..e5b0042e391 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField import org.jetbrains.kotlin.codegen.DescriptorAsmUtil import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.writeKotlinMetadata +import org.jetbrains.kotlin.config.JvmAbiStability import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -197,7 +198,7 @@ class ClassCodegen private constructor( private fun generateKotlinMetadataAnnotation() { // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG - if (state.isIrWithStableAbi) { + if (state.abiStability != JvmAbiStability.UNSTABLE) { extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 index 99b5bd200e4..70b0eb0d719 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField import org.jetbrains.kotlin.codegen.DescriptorAsmUtil import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.writeKotlinMetadata +import org.jetbrains.kotlin.config.JvmAbiStability import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -197,7 +198,7 @@ class ClassCodegen private constructor( private fun generateKotlinMetadataAnnotation() { // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG - if (state.isIrWithStableAbi) { + if (state.abiStability != JvmAbiStability.UNSTABLE) { extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt index 28748ed8c7e..f00c58b2d23 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt @@ -17,9 +17,16 @@ interface DeserializedContainerSource : SourceElement { // True iff this container was compiled by the new IR backend, this compiler is not using the IR backend right now, // and no additional flags to override this behavior were specified. - val isInvisibleIrDependency: Boolean + val abiStability: DeserializedContainerAbiStability // This string should only be used in error messages val presentableString: String } +enum class DeserializedContainerAbiStability { + // Either the container is stable, or this compiler is configured to ignore ABI stability of dependencies. + STABLE, + + // The container is unstable because it is compiled with unstable JVM IR backend, and this compiler is _not_ configured to ignore that. + IR_UNSTABLE, +} diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt index 24970d50c33..9a659433a4f 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.deserialization.ClassData import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope import javax.inject.Inject @@ -53,7 +54,7 @@ class DeserializedDescriptorResolver { JvmProtoBufUtil.readClassDataFrom(data, strings) } ?: return null val source = KotlinJvmBinarySourceElement( - kotlinClass, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible, kotlinClass.isInvisibleJvmIrDependency + kotlinClass, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible, kotlinClass.abiStability ) return ClassData(nameResolver, classProto, kotlinClass.classHeader.metadataVersion, source) } @@ -66,7 +67,7 @@ class DeserializedDescriptorResolver { } ?: return null val source = JvmPackagePartSource( kotlinClass, packageProto, nameResolver, kotlinClass.incompatibility, kotlinClass.isPreReleaseInvisible, - kotlinClass.isInvisibleJvmIrDependency + kotlinClass.abiStability ) return DeserializedPackageMemberScope( descriptor, packageProto, nameResolver, kotlinClass.classHeader.metadataVersion, source, components @@ -97,8 +98,12 @@ class DeserializedDescriptorResolver { get() = !components.configuration.skipPrereleaseCheck && classHeader.isPreRelease && classHeader.metadataVersion == KOTLIN_1_3_M1_METADATA_VERSION - private val KotlinJvmBinaryClass.isInvisibleJvmIrDependency: Boolean - get() = !components.configuration.allowUnstableDependencies && classHeader.isUnstableJvmIrBinary + private val KotlinJvmBinaryClass.abiStability: DeserializedContainerAbiStability + get() = when { + components.configuration.allowUnstableDependencies -> DeserializedContainerAbiStability.STABLE + classHeader.isUnstableJvmIrBinary -> DeserializedContainerAbiStability.IR_UNSTABLE + else -> DeserializedContainerAbiStability.STABLE + } private fun readData(kotlinClass: KotlinJvmBinaryClass, expectedKinds: Set): Array? { val header = kotlinClass.classHeader diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt index fd24fcd2342..418779741af 100644 --- a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt +++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/JvmPackagePartSource.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource class JvmPackagePartSource( @@ -25,7 +26,7 @@ class JvmPackagePartSource( nameResolver: NameResolver, override val incompatibility: IncompatibleVersionErrorData? = null, override val isPreReleaseInvisible: Boolean = false, - override val isInvisibleIrDependency: Boolean = false, + override val abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE, val knownJvmBinaryClass: KotlinJvmBinaryClass? = null ) : DeserializedContainerSource { constructor( @@ -34,7 +35,7 @@ class JvmPackagePartSource( nameResolver: NameResolver, incompatibility: IncompatibleVersionErrorData? = null, isPreReleaseInvisible: Boolean = false, - isInvisibleIrDependency: Boolean = false + abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE, ) : this( JvmClassName.byClassId(kotlinClass.classId), kotlinClass.classHeader.multifileClassName?.let { @@ -44,7 +45,7 @@ class JvmPackagePartSource( nameResolver, incompatibility, isPreReleaseInvisible, - isInvisibleIrDependency, + abiStability, kotlinClass ) diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt index 9d088888b7a..27114c687b2 100644 --- a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt +++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinarySourceElement.kt @@ -19,13 +19,14 @@ package org.jetbrains.kotlin.load.kotlin import org.jetbrains.kotlin.descriptors.SourceFile import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource class KotlinJvmBinarySourceElement( val binaryClass: KotlinJvmBinaryClass, override val incompatibility: IncompatibleVersionErrorData? = null, override val isPreReleaseInvisible: Boolean = false, - override val isInvisibleIrDependency: Boolean = false + override val abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE, ) : DeserializedContainerSource { override val presentableString: String get() = "Class '${binaryClass.classId.asSingleFqName().asString()}'" diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt index 484abea58c7..d2028c2f820 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/KotlinJavascriptPackageFragment.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.serialization.deserialization.* +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.getValue @@ -94,8 +95,8 @@ class KotlinJavascriptPackageFragment( override val isPreReleaseInvisible: Boolean = configuration.reportErrorsOnPreReleaseDependencies && (header.flags and 1) != 0 - override val isInvisibleIrDependency: Boolean - get() = false + override val abiStability: DeserializedContainerAbiStability + get() = DeserializedContainerAbiStability.STABLE override val presentableString: String get() = "Package '$fqName'" From 3f517d7e8d7dc7ceedd65678791df01101feab8d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 7 Dec 2020 21:26:23 +0100 Subject: [PATCH 004/176] Add new metadata flag for class files compiled with FIR Report a separate error when class files compiled with FIR are in dependencies, in addition to the one for class files compiled with FE 1.0 + JVM IR. #KT-43592 --- .../messages/AnalyzerWithCompilerReport.kt | 8 +++++++ .../kotlin/config/JVMConfigurationKeys.java | 2 +- .../fir/backend/jvm/FirJvmBackendExtension.kt | 7 ++++++ .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../checkers/MissingDependencyClassChecker.kt | 3 +++ .../kotlin/backend/jvm/JvmBackendExtension.kt | 8 +++++++ .../backend/jvm/codegen/ClassCodegen.kt | 6 +---- .../backend/jvm/codegen/ClassCodegen.kt.201 | 6 +---- .../kotlin/load/java/JvmAnnotationNames.java | 1 + .../DeserializedContainerSource.kt | 3 +++ .../kotlin/DeserializedDescriptorResolver.kt | 1 + .../load/kotlin/header/KotlinClassHeader.kt | 16 ++++++++----- .../idea/highlighter/KotlinPsiChecker.kt | 14 ++++++----- .../evaluate/KotlinEvaluatorBuilder.kt | 23 +++++++++++-------- .../stdlib/jvm/runtime/kotlin/Metadata.kt | 11 +++++---- 16 files changed, 74 insertions(+), 37 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt index 0c749ba5708..50ce24605f3 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt @@ -190,6 +190,14 @@ class AnalyzerWithCompilerReport( ) } + if (diagnostics.any { it.factory == Errors.FIR_COMPILED_CLASS }) { + messageCollector.report( + ERROR, + "Classes compiled by the new Kotlin compiler frontend were found in dependencies. " + + "Remove them from the classpath or use '-Xallow-jvm-ir-dependencies' to suppress errors" + ) + } + return hasErrors } 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 41baa5d8707..b8e6870b0a6 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -118,7 +118,7 @@ public class JVMConfigurationKeys { CompilerConfigurationKey.create("Paths to .klib libraries"); public static final CompilerConfigurationKey ABI_STABILITY = - CompilerConfigurationKey.create("ABI stability of class files produced by the JVM IR backend"); + CompilerConfigurationKey.create("ABI stability of class files produced by JVM IR and/or FIR"); public static final CompilerConfigurationKey DO_NOT_CLEAR_BINDING_CONTEXT = CompilerConfigurationKey.create("When using the IR backend, do not clear BindingContext between psi2ir and lowerings"); diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt index 98c7eed96d0..058449161fa 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmBackendExtension.kt @@ -9,9 +9,11 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmBackendExtension import org.jetbrains.kotlin.backend.jvm.codegen.MetadataSerializer import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings +import org.jetbrains.kotlin.config.JvmAbiStability import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.org.objectweb.asm.Type class FirJvmBackendExtension(private val session: FirSession, private val components: Fir2IrComponents) : JvmBackendExtension { @@ -24,4 +26,9 @@ class FirJvmBackendExtension(private val session: FirSession, private val compon ): MetadataSerializer { return FirMetadataSerializer(session, context, klass, bindings, components, parentSerializer) } + + override fun generateMetadataExtraFlags(abiStability: JvmAbiStability?): Int = + JvmAnnotationNames.METADATA_JVM_IR_FLAG or + JvmAnnotationNames.METADATA_FIR_FLAG or + (if (abiStability == JvmAbiStability.STABLE) JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG else 0) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index f0f38f9ac6f..ded6d7b0b80 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -119,6 +119,7 @@ public interface Errors { DiagnosticFactory1 MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 PRE_RELEASE_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 IR_COMPILED_CLASS = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 FIR_COMPILED_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory2> INCOMPATIBLE_CLASS = DiagnosticFactory2.create(ERROR); //Elements with "INVISIBLE_REFERENCE" error are marked as unresolved, unlike elements with "INVISIBLE_MEMBER" error diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 75f9a22e5b8..3a06a25353e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -402,6 +402,7 @@ public class DefaultErrorMessages { MAP.put(MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS, "Cannot access script provided property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING); MAP.put(PRE_RELEASE_CLASS, "{0} is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler", TO_STRING); MAP.put(IR_COMPILED_CLASS, "{0} is compiled by a new Kotlin compiler backend and cannot be loaded by the old compiler", TO_STRING); + MAP.put(FIR_COMPILED_CLASS, "{0} is compiled by the new Kotlin compiler frontend and cannot be loaded by the old compiler", TO_STRING); MAP.put(INCOMPATIBLE_CLASS, "{0} was compiled with an incompatible version of Kotlin. {1}", TO_STRING, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt index 6bd2e0562be..400650958cd 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt @@ -59,6 +59,9 @@ object MissingDependencyClassChecker : CallChecker { if (source.isPreReleaseInvisible) { return PRE_RELEASE_CLASS.on(reportOn, source.presentableString) } + if (source.abiStability == DeserializedContainerAbiStability.FIR_UNSTABLE) { + return FIR_COMPILED_CLASS.on(reportOn, source.presentableString) + } if (source.abiStability == DeserializedContainerAbiStability.IR_UNSTABLE) { return IR_COMPILED_CLASS.on(reportOn, source.presentableString) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt index 98f6f16eedb..a1f0e3cef0a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt @@ -8,7 +8,9 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.backend.jvm.codegen.DescriptorMetadataSerializer import org.jetbrains.kotlin.backend.jvm.codegen.MetadataSerializer import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings +import org.jetbrains.kotlin.config.JvmAbiStability import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.org.objectweb.asm.Type interface JvmBackendExtension { @@ -16,6 +18,8 @@ interface JvmBackendExtension { context: JvmBackendContext, klass: IrClass, type: Type, bindings: JvmSerializationBindings, parentSerializer: MetadataSerializer? ): MetadataSerializer + fun generateMetadataExtraFlags(abiStability: JvmAbiStability?): Int + object Default : JvmBackendExtension { override fun createSerializer( context: JvmBackendContext, @@ -26,5 +30,9 @@ interface JvmBackendExtension { ): MetadataSerializer { return DescriptorMetadataSerializer(context, klass, type, bindings, parentSerializer) } + + override fun generateMetadataExtraFlags(abiStability: JvmAbiStability?): Int = + JvmAnnotationNames.METADATA_JVM_IR_FLAG or + (if (abiStability == JvmAbiStability.STABLE) JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG else 0) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index e5b0042e391..2fbfafdef6c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField import org.jetbrains.kotlin.codegen.DescriptorAsmUtil import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.writeKotlinMetadata -import org.jetbrains.kotlin.config.JvmAbiStability import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -197,10 +196,7 @@ class ClassCodegen private constructor( private fun generateKotlinMetadataAnnotation() { // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. - var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG - if (state.abiStability != JvmAbiStability.UNSTABLE) { - extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG - } + val extraFlags = context.backendExtension.generateMetadataExtraFlags(state.abiStability) val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId] val metadata = irClass.metadata diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 index 70b0eb0d719..8681265cd40 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt.201 @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.backend.jvm.lower.hasAssertionsDisabledField import org.jetbrains.kotlin.codegen.DescriptorAsmUtil import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.writeKotlinMetadata -import org.jetbrains.kotlin.config.JvmAbiStability import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -197,10 +196,7 @@ class ClassCodegen private constructor( private fun generateKotlinMetadataAnnotation() { // TODO: if `-Xmultifile-parts-inherit` is enabled, write the corresponding flag for parts and facades to [Metadata.extraInt]. - var extraFlags = JvmAnnotationNames.METADATA_JVM_IR_FLAG - if (state.abiStability != JvmAbiStability.UNSTABLE) { - extraFlags += JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG - } + val extraFlags = context.backendExtension.generateMetadataExtraFlags(state.abiStability) val facadeClassName = context.multifileFacadeForPart[irClass.attributeOwnerId] val metadata = irClass.metadata diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index fbd565b2b17..f5897f1ba1a 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -46,6 +46,7 @@ public final class JvmAnnotationNames { public static final int METADATA_STRICT_VERSION_SEMANTICS_FLAG = 1 << 3; public static final int METADATA_JVM_IR_FLAG = 1 << 4; public static final int METADATA_JVM_IR_STABLE_ABI_FLAG = 1 << 5; + public static final int METADATA_FIR_FLAG = 1 << 6; public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); diff --git a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt index f00c58b2d23..8b7773005cd 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt @@ -27,6 +27,9 @@ enum class DeserializedContainerAbiStability { // Either the container is stable, or this compiler is configured to ignore ABI stability of dependencies. STABLE, + // The container is unstable because it is compiled with FIR, and this compiler is _not_ configured to ignore that. + FIR_UNSTABLE, + // The container is unstable because it is compiled with unstable JVM IR backend, and this compiler is _not_ configured to ignore that. IR_UNSTABLE, } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt index 9a659433a4f..5195c89b22b 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/DeserializedDescriptorResolver.kt @@ -101,6 +101,7 @@ class DeserializedDescriptorResolver { private val KotlinJvmBinaryClass.abiStability: DeserializedContainerAbiStability get() = when { components.configuration.allowUnstableDependencies -> DeserializedContainerAbiStability.STABLE + classHeader.isUnstableFirBinary -> DeserializedContainerAbiStability.FIR_UNSTABLE classHeader.isUnstableJvmIrBinary -> DeserializedContainerAbiStability.IR_UNSTABLE else -> DeserializedContainerAbiStability.STABLE } diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt index 9bd443d5d69..6a8bc7a8eaf 100644 --- a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt +++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt @@ -5,7 +5,7 @@ package org.jetbrains.kotlin.load.kotlin.header -import org.jetbrains.kotlin.load.java.JvmAnnotationNames +import org.jetbrains.kotlin.load.java.JvmAnnotationNames.* import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.DELEGATING import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.INHERITING import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmBytecodeBinaryVersion @@ -54,21 +54,25 @@ class KotlinClassHeader( @Suppress("unused") val multifileClassKind: MultifileClassKind? get() = if (kind == Kind.MULTIFILE_CLASS || kind == Kind.MULTIFILE_CLASS_PART) { - if ((extraInt and JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG) != 0) + if (extraInt.has(METADATA_MULTIFILE_PARTS_INHERIT_FLAG)) INHERITING else DELEGATING } else null val isUnstableJvmIrBinary: Boolean - get() = (extraInt and JvmAnnotationNames.METADATA_JVM_IR_FLAG) != 0 && - (extraInt and JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG == 0) + get() = extraInt.has(METADATA_JVM_IR_FLAG) && !extraInt.has(METADATA_JVM_IR_STABLE_ABI_FLAG) + + val isUnstableFirBinary: Boolean + get() = extraInt.has(METADATA_FIR_FLAG) && !extraInt.has(METADATA_JVM_IR_STABLE_ABI_FLAG) val isPreRelease: Boolean - get() = (extraInt and JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG) != 0 + get() = extraInt.has(METADATA_PRE_RELEASE_FLAG) val isScript: Boolean - get() = (extraInt and JvmAnnotationNames.METADATA_SCRIPT_FLAG) != 0 + get() = extraInt.has(METADATA_SCRIPT_FLAG) override fun toString() = "$kind version=$metadataVersion" + + private fun Int.has(flag: Int): Boolean = (this and flag) != 0 } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt index 593008c7296..830bbabfbeb 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt @@ -192,7 +192,7 @@ private class ElementAnnotator( val factory = diagnostic.factory // hack till the root cause #KT-21246 is fixed - if (isIrCompileClassDiagnosticForModulesWithEnabledIR(diagnostic)) return + if (isUnstableAbiClassDiagnosticForModulesWithEnabledUnstableAbi(diagnostic)) return assert(diagnostics.all { it.psiElement == element && it.factory == factory }) @@ -272,16 +272,18 @@ private class ElementAnnotator( data.processDiagnostics(holder, diagnostics, fixesMap) } - private fun isIrCompileClassDiagnosticForModulesWithEnabledIR(diagnostic: Diagnostic): Boolean { - if (diagnostic.factory != Errors.IR_COMPILED_CLASS) return false + private fun isUnstableAbiClassDiagnosticForModulesWithEnabledUnstableAbi(diagnostic: Diagnostic): Boolean { + val setting = when (diagnostic.factory) { + Errors.IR_COMPILED_CLASS -> K2JVMCompilerArguments::useIR + Errors.FIR_COMPILED_CLASS -> K2JVMCompilerArguments::useFir + else -> return false + } val module = element.module ?: return false val moduleFacetSettings = KotlinFacetSettingsProvider.getInstance(element.project)?.getSettings(module) ?: return false - return moduleFacetSettings.isCompilerSettingPresent(K2JVMCompilerArguments::useIR) - || moduleFacetSettings.isCompilerSettingPresent(K2JVMCompilerArguments::allowJvmIrDependencies) + return moduleFacetSettings.isCompilerSettingPresent(setting) } companion object { val LOG = Logger.getInstance(ElementAnnotator::class.java) } } - diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt index 27e68cf27c1..921e915e31d 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt @@ -22,7 +22,6 @@ import com.intellij.debugger.engine.evaluation.EvaluateException import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil import com.intellij.debugger.engine.evaluation.EvaluationContextImpl import com.intellij.debugger.engine.evaluation.expression.* -import com.intellij.lang.java.JavaLanguage import com.intellij.openapi.diagnostic.Attachment import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.progress.ProcessCanceledException @@ -32,7 +31,6 @@ import com.intellij.testFramework.runInEdtAndWait import com.sun.jdi.* import com.sun.jdi.Value import org.jetbrains.eval4j.* -import org.jetbrains.eval4j.Value as Eval4JValue import org.jetbrains.eval4j.jdi.JDIEval import org.jetbrains.eval4j.jdi.asJdiValue import org.jetbrains.eval4j.jdi.asValue @@ -47,28 +45,32 @@ import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.core.util.attachmentByPsiFile import org.jetbrains.kotlin.idea.core.util.mergeAttachments import org.jetbrains.kotlin.idea.core.util.runInReadActionWithWriteActionPriorityWithPCE -import org.jetbrains.kotlin.idea.debugger.* +import org.jetbrains.kotlin.idea.debugger.DebuggerUtils +import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationStatus.EvaluationContextLanguage import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.Companion.compileCodeFragmentCacheAware import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.GENERATED_CLASS_NAME import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.GENERATED_FUNCTION_NAME import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.* +import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.ClassLoadingResult import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.loadClassesSafely import org.jetbrains.kotlin.idea.debugger.evaluate.variables.EvaluatorValueConverter import org.jetbrains.kotlin.idea.debugger.evaluate.variables.VariableFinder +import org.jetbrains.kotlin.idea.debugger.safeLocation +import org.jetbrains.kotlin.idea.debugger.safeMethod +import org.jetbrains.kotlin.idea.debugger.safeVisibleVariableByName +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.AnalyzingUtils import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.resolve.jvm.AsmTypes -import org.jetbrains.org.objectweb.asm.* +import org.jetbrains.org.objectweb.asm.ClassReader import org.jetbrains.org.objectweb.asm.tree.ClassNode -import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationStatus.EvaluationContextLanguage -import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.ClassLoadingResult -import org.jetbrains.kotlin.idea.resolve.ResolutionFacade -import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import java.util.* +import org.jetbrains.eval4j.Value as Eval4JValue internal val LOG = Logger.getInstance(KotlinEvaluator::class.java) @@ -446,7 +448,10 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi companion object { private val IGNORED_DIAGNOSTICS: Set> = Errors.INVISIBLE_REFERENCE_DIAGNOSTICS + - setOf(Errors.EXPERIMENTAL_API_USAGE_ERROR, Errors.MISSING_DEPENDENCY_SUPERCLASS, Errors.IR_COMPILED_CLASS) + setOf( + Errors.EXPERIMENTAL_API_USAGE_ERROR, Errors.MISSING_DEPENDENCY_SUPERCLASS, Errors.IR_COMPILED_CLASS, + Errors.FIR_COMPILED_CLASS + ) private val DEFAULT_METHOD_MARKERS = listOf(AsmTypes.OBJECT_TYPE, AsmTypes.DEFAULT_CONSTRUCTOR_MARKER) diff --git a/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt b/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt index c39338e5612..ad9c1cb49bd 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt +++ b/libraries/stdlib/jvm/runtime/kotlin/Metadata.kt @@ -66,11 +66,12 @@ public annotation class Metadata( * * 0 - this is a multi-file class facade or part, compiled with `-Xmultifile-parts-inherit`. * * 1 - this class file is compiled by a pre-release version of Kotlin and is not visible to release versions. * * 2 - this class file is a compiled Kotlin script source file (.kts). - * * 3 - the metadata of this class file is not supposed to be read by the compiler, whose major.minor version is less than - * the major.minor version of this metadata ([metadataVersion]). - * * 4 - this class file is compiled with the new Kotlin compiler backend introduced in Kotlin 1.4. - * * 5 - if the class file is compiled with the new Kotlin compiler backend, the metadata has been verified by the author and - * no metadata incompatibility diagnostic should be reported at the call site. + * * 3 - "strict metadata version semantics". The metadata of this class file is not supposed to be read by the compiler, + * whose major.minor version is less than the major.minor version of this metadata ([metadataVersion]). + * * 4 - this class file is compiled with the new Kotlin compiler backend (JVM IR) introduced in Kotlin 1.4. + * * 5 - this class file has stable metadata and ABI. This is used only for class files compiled with JVM IR (see flag #4) or FIR (#6), + * and prevents metadata incompatibility diagnostics from being reported where the class is used. + * * 6 - this class file is compiled with the new Kotlin compiler frontend (FIR). */ @SinceKotlin("1.1") @get:JvmName("xi") From 06805ffbaa6bb1a84bd42c23a545561f3cce914d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 7 Dec 2020 21:38:45 +0100 Subject: [PATCH 005/176] Change CLI flags for controlling diagnostics for ABI of FIR and JVM IR - Use a more generic `-Xallow-unstable-dependencies` instead of `-Xallow-jvm-ir-dependencies` - Change `-Xir-binary-with-stable-abi` to `-Xabi-stability=stable`, with an additional option to specify `unstable` after a subsequent commit where JVM IR becomes stable by default #KT-43592 --- .../common/arguments/K2JVMCompilerArguments.kt | 18 +++++++++--------- .../messages/AnalyzerWithCompilerReport.kt | 4 ++-- .../jetbrains/kotlin/cli/jvm/jvmArguments.kt | 12 +++++++++++- .../jetbrains/kotlin/config/JvmAbiStability.kt | 5 +++++ compiler/testData/cli/jvm/extraHelp.out | 8 +++++--- .../CompileKotlinAgainstCustomBinariesTest.kt | 4 ++-- 6 files changed, 34 insertions(+), 17 deletions(-) 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 0c217daed93..7379c779c1a 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 @@ -95,18 +95,18 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { var irCheckLocalNames: Boolean by FreezableVar(false) @Argument( - value = "-Xallow-jvm-ir-dependencies", - description = "When not using the IR backend, do not report errors on those classes in dependencies, " + - "which were compiled by the IR backend" + value = "-Xallow-unstable-dependencies", + description = "Do not report errors on classes in dependencies, which were compiled by an unstable version of the Kotlin compiler" ) - var allowJvmIrDependencies: Boolean by FreezableVar(false) + var allowUnstableDependencies: Boolean by FreezableVar(false) @Argument( - value = "-Xir-binary-with-stable-abi", - description = "When using the IR backend, produce binaries which can be read by non-IR backend.\n" + - "The author is responsible for verifying that the resulting binaries do indeed have the correct ABI" + value = "-Xabi-stability", + valueDescription = "{stable|unstable}", + description = "When using unstable compiler features such as FIR or JVM IR, use 'stable' to mark generated class files as stable\n" + + "to prevent diagnostics from stable compilers at the call site.\n" ) - var isIrWithStableAbi: Boolean by FreezableVar(false) + var abiStability: String? by FreezableVar(null) @Argument( value = "-Xir-do-not-clear-binding-context", @@ -446,7 +446,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview - result[AnalysisFlags.allowUnstableDependencies] = allowJvmIrDependencies || useIR || useFir + result[AnalysisFlags.allowUnstableDependencies] = allowUnstableDependencies || useIR || useFir result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses return result } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt index 50ce24605f3..eb2bfba7765 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt @@ -186,7 +186,7 @@ class AnalyzerWithCompilerReport( messageCollector.report( ERROR, "Classes compiled by a new Kotlin compiler backend were found in dependencies. " + - "Remove them from the classpath or use '-Xallow-jvm-ir-dependencies' to suppress errors" + "Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors" ) } @@ -194,7 +194,7 @@ class AnalyzerWithCompilerReport( messageCollector.report( ERROR, "Classes compiled by the new Kotlin compiler frontend were found in dependencies. " + - "Remove them from the classpath or use '-Xallow-jvm-ir-dependencies' to suppress errors" + "Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors" ) } 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 0df11b8c373..e3429a8fe25 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -173,7 +173,17 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.IR, arguments.useIR && !arguments.noUseIR) - put(JVMConfigurationKeys.ABI_STABILITY, if (arguments.isIrWithStableAbi) JvmAbiStability.STABLE else JvmAbiStability.UNSTABLE) + val abiStability = JvmAbiStability.fromStringOrNull(arguments.abiStability) + if (arguments.abiStability != null) { + if (abiStability == null) { + getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report( + ERROR, + "Unknown ABI stability mode: ${arguments.abiStability}, supported modes: ${JvmAbiStability.values().map { it.description }}" + ) + } else { + put(JVMConfigurationKeys.ABI_STABILITY, abiStability) + } + } put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, arguments.doNotClearBindingContext) put(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, arguments.noCallAssertions) diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt index 90fd1ca9d64..e40ecfae2c6 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JvmAbiStability.kt @@ -9,4 +9,9 @@ enum class JvmAbiStability(val description: String) { STABLE("stable"), UNSTABLE("unstable"), ; + + companion object { + fun fromStringOrNull(string: String?): JvmAbiStability? = + values().find { it.description == string } + } } diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 7d8bc2eaba4..2a2236368da 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -1,9 +1,13 @@ Usage: kotlinc-jvm where advanced options include: + -Xabi-stability={stable|unstable} + When using unstable compiler features such as FIR or JVM IR, use 'stable' to mark generated class files as stable + to prevent diagnostics from stable compilers at the call site. + -Xadd-modules= Root modules to resolve in addition to the initial modules, or all modules on the module path if is ALL-MODULE-PATH - -Xallow-jvm-ir-dependencies When not using the IR backend, do not report errors on those classes in dependencies, which were compiled by the IR backend -Xallow-no-source-files Allow no source files + -Xallow-unstable-dependencies Do not report errors on classes in dependencies, which were compiled by an unstable version of the Kotlin compiler -Xassertions={always-enable|always-disable|jvm|legacy} Assert calls behaviour -Xassertions=always-enable: enable, ignore jvm assertion settings; @@ -27,8 +31,6 @@ where advanced options include: -Xfriend-paths= Paths to output directories for friend modules (whose internals should be visible) -Xmultifile-parts-inherit Compile multifile classes as a hierarchy of parts and facade -Xir-check-local-names Check that names of local classes and anonymous objects are the same in the IR backend as in the old backend - -Xir-binary-with-stable-abi When using the IR backend, produce binaries which can be read by non-IR backend. - The author is responsible for verifying that the resulting binaries do indeed have the correct ABI -Xmodule-path= Paths where to find Java 9+ modules -Xjava-package-prefix Package prefix for Java files -Xjava-source-roots= Paths to directories with Java source files diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index 3b5c02d2a9b..402dbe9f360 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -685,13 +685,13 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration } fun testOldAgainstJvmIrWithStableAbi() { - val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir", "-Xir-binary-with-stable-abi")) + val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir", "-Xabi-stability=stable")) compileKotlin("source.kt", tmpdir, listOf(library)) } fun testOldAgainstJvmIrWithAllowIrDependencies() { val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir")) - compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xallow-jvm-ir-dependencies")) + compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xallow-unstable-dependencies")) } fun testSealedClassesAndInterfaces() { From 691b20a6852177ab8756b4249970037a0786ae0b Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 10 Dec 2020 13:15:42 +0100 Subject: [PATCH 006/176] JVM IR, FIR: set IR configuration key to true if FIR is enabled --- .../kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt | 5 +---- .../cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt | 2 +- .../scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt | 3 +-- 3 files changed, 3 insertions(+), 7 deletions(-) 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 eebb41609a1..6087fdd8f86 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 @@ -570,8 +570,6 @@ object KotlinToJVMBytecodeCompiler { sourceFiles: List, module: Module? ): GenerationState { - val isIR = (configuration.getBoolean(JVMConfigurationKeys.IR) || - configuration.getBoolean(CommonConfigurationKeys.USE_FIR)) val generationState = GenerationState.Builder( environment.project, ClassBuilderFactories.BINARIES, @@ -581,13 +579,12 @@ object KotlinToJVMBytecodeCompiler { configuration ) .codegenFactory( - if (isIR) JvmIrCodegenFactory( + if (configuration.getBoolean(JVMConfigurationKeys.IR)) JvmIrCodegenFactory( configuration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases) ) else DefaultCodegenFactory ) .withModule(module) .onIndependentPartCompilationEnd(createOutputFilesFlushingCallbackIfPossible(configuration)) - .isIrBackend(isIR) .build() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() 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 e3429a8fe25..ad9346fa9de 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -171,7 +171,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters) - put(JVMConfigurationKeys.IR, arguments.useIR && !arguments.noUseIR) + put(JVMConfigurationKeys.IR, (arguments.useIR && !arguments.noUseIR) || arguments.useFir) val abiStability = JvmAbiStability.fromStringOrNull(arguments.abiStability) if (arguments.abiStability != null) { diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt index e7c9210f1a2..2dd85ee1592 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.DefaultCodegenFactory import org.jetbrains.kotlin.codegen.KotlinCodegenFacade import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.languageVersionSettings @@ -235,7 +234,7 @@ private fun generate( sourceFiles, kotlinCompilerConfiguration ).codegenFactory( - if (kotlinCompilerConfiguration.getBoolean(JVMConfigurationKeys.IR) || kotlinCompilerConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR)) + if (kotlinCompilerConfiguration.getBoolean(JVMConfigurationKeys.IR)) JvmIrCodegenFactory( kotlinCompilerConfiguration.get(CLIConfigurationKeys.PHASE_CONFIG) ?: PhaseConfig(jvmPhases) ) else DefaultCodegenFactory From e0593ff70f5f8bd72eb9ff16dcad79c5d426bc88 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 10 Dec 2020 13:51:08 +0100 Subject: [PATCH 007/176] Minor, extract CompilerConfiguration.messageCollector to extension property --- .../jetbrains/kotlin/cli/jvm/jvmArguments.kt | 41 +++++++------------ 1 file changed, 14 insertions(+), 27 deletions(-) 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 ad9346fa9de..3f72c805e46 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.getLibraryFromHome import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* +import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot @@ -19,9 +20,6 @@ import org.jetbrains.kotlin.utils.PathUtil import java.io.File fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArguments) { - - val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) - put(JVMConfigurationKeys.INCLUDE_RUNTIME, arguments.includeRuntime) putIfNotNull(JVMConfigurationKeys.FRIEND_PATHS, arguments.friendPaths?.asList()) @@ -71,9 +69,6 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu } fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): Boolean { - - val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) - if (arguments.noJdk) { put(JVMConfigurationKeys.NO_JDK, true) @@ -84,7 +79,7 @@ fun CompilerConfiguration.configureJdkHome(arguments: K2JVMCompilerArguments): B } if (arguments.jdkHome != null) { - val jdkHome = File(arguments.jdkHome) + val jdkHome = File(arguments.jdkHome!!) if (!jdkHome.exists()) { messageCollector.report(ERROR, "JDK home directory does not exist: $jdkHome") return false @@ -114,7 +109,6 @@ fun CompilerConfiguration.configureExplicitContentRoots(arguments: K2JVMCompiler } fun CompilerConfiguration.configureStandardLibs(paths: KotlinPaths?, arguments: K2JVMCompilerArguments) { - val messageCollector = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val isModularJava = isModularJava() fun addRoot(moduleName: String, libraryName: String, getLibrary: (KotlinPaths) -> File, noLibraryArgument: String) { @@ -176,7 +170,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr val abiStability = JvmAbiStability.fromStringOrNull(arguments.abiStability) if (arguments.abiStability != null) { if (abiStability == null) { - getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report( + messageCollector.report( ERROR, "Unknown ABI stability mode: ${arguments.abiStability}, supported modes: ${JvmAbiStability.values().map { it.description }}" ) @@ -201,43 +195,34 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.NO_UNIFIED_NULL_CHECKS, arguments.noUnifiedNullChecks) if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) { - getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report( + messageCollector.report( ERROR, "Unknown constructor call normalization mode: ${arguments.constructorCallNormalizationMode}, " + "supported modes: ${JVMConstructorCallNormalizationMode.values().map { it.description }}" ) } - val constructorCallNormalizationMode = - JVMConstructorCallNormalizationMode.fromStringOrNull(arguments.constructorCallNormalizationMode) + val constructorCallNormalizationMode = JVMConstructorCallNormalizationMode.fromStringOrNull(arguments.constructorCallNormalizationMode) if (constructorCallNormalizationMode != null) { - put( - JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE, - constructorCallNormalizationMode - ) + put(JVMConfigurationKeys.CONSTRUCTOR_CALL_NORMALIZATION_MODE, constructorCallNormalizationMode) } val assertionsMode = JVMAssertionsMode.fromStringOrNull(arguments.assertionsMode) if (assertionsMode == null) { - getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report( + messageCollector.report( ERROR, - "Unknown assertions mode: ${arguments.assertionsMode}, " + - "supported modes: ${JVMAssertionsMode.values().map { it.description }}" + "Unknown assertions mode: ${arguments.assertionsMode}, supported modes: ${JVMAssertionsMode.values().map { it.description }}" ) } - put( - JVMConfigurationKeys.ASSERTIONS_MODE, - assertionsMode ?: JVMAssertionsMode.DEFAULT - ) + put(JVMConfigurationKeys.ASSERTIONS_MODE, assertionsMode ?: JVMAssertionsMode.DEFAULT) put(JVMConfigurationKeys.USE_TYPE_TABLE, arguments.useTypeTable) put(JVMConfigurationKeys.SKIP_RUNTIME_VERSION_CHECK, arguments.skipRuntimeVersionCheck) put(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING, arguments.useOldClassFilesReading) if (arguments.useOldClassFilesReading) { - getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) - .report(INFO, "Using the old java class files reading implementation") + messageCollector.report(INFO, "Using the old java class files reading implementation") } put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage) @@ -247,8 +232,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.ENABLE_JVM_PREVIEW, arguments.enableJvmPreview) if (arguments.enableJvmPreview) { - getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) - .report(INFO, "Using preview Java language features") + messageCollector.report(INFO, "Using preview Java language features") } arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) } @@ -261,3 +245,6 @@ fun CompilerConfiguration.configureKlibPaths(arguments: K2JVMCompilerArguments) ?.filterNot { it.isEmpty() } ?.let { put(JVMConfigurationKeys.KLIB_PATHS, it) } } + +private val CompilerConfiguration.messageCollector: MessageCollector + get() = getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) From eef06cded39b64bdf54561b4d9d5c1a3259e2098 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 1 Dec 2020 18:53:50 +0100 Subject: [PATCH 008/176] JVM IR: output stable ABI binaries by default #KT-43592 Fixed --- .../arguments/K2JVMCompilerArguments.kt | 8 +++-- .../messages/AnalyzerWithCompilerReport.kt | 4 +-- .../jetbrains/kotlin/cli/jvm/jvmArguments.kt | 5 ++- .../jetbrains/kotlin/diagnostics/Errors.java | 2 +- .../rendering/DefaultErrorMessages.java | 3 +- .../checkers/MissingDependencyClassChecker.kt | 2 +- .../kotlin/backend/jvm/JvmBackendExtension.kt | 2 +- .../cli/jvm/abiStabilityIncorrectValue.args | 5 +++ .../cli/jvm/abiStabilityIncorrectValue.out | 2 ++ .../abiStabilityUnstableWithOldBackend.args | 4 +++ .../abiStabilityUnstableWithOldBackend.out | 2 ++ compiler/testData/cli/jvm/extraHelp.out | 5 +-- .../library/a.kt | 0 .../output.txt | 0 .../source.kt | 0 .../library/a.kt | 0 .../output.txt | 0 .../source.kt | 0 .../oldAgainstJvmIr/output.txt | 8 ----- .../library/a.kt | 0 .../oldJvmAgainstFir/output.txt | 8 +++++ .../source.kt | 0 .../library/a.kt | 0 .../output.txt | 0 .../source.kt | 0 .../library/a.kt | 0 .../output.txt | 0 .../source.kt | 0 .../oldJvmAgainstJvmIr/library/a.kt | 5 +++ .../oldJvmAgainstJvmIr/output.txt | 1 + .../oldJvmAgainstJvmIr/source.kt | 5 +++ .../library/a.kt | 5 +++ .../output.txt | 8 +++++ .../source.kt | 5 +++ .../kotlin/cli/CliTestGenerated.java | 10 ++++++ .../CompileKotlinAgainstCustomBinariesTest.kt | 36 +++++++++++++------ .../DeserializedContainerSource.kt | 5 ++- .../idea/highlighter/KotlinPsiChecker.kt | 2 +- .../evaluate/KotlinEvaluatorBuilder.kt | 19 +++++----- 39 files changed, 117 insertions(+), 44 deletions(-) create mode 100644 compiler/testData/cli/jvm/abiStabilityIncorrectValue.args create mode 100644 compiler/testData/cli/jvm/abiStabilityIncorrectValue.out create mode 100644 compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.args create mode 100644 compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.out rename compiler/testData/compileKotlinAgainstCustomBinaries/{jvmIrAgainstJvmIr => firAgainstFir}/library/a.kt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{jvmIrAgainstJvmIr => firAgainstFir}/output.txt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{jvmIrAgainstJvmIr => firAgainstFir}/source.kt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{jvmIrAgainstOld => firAgainstOldJvm}/library/a.kt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{jvmIrAgainstOld => firAgainstOldJvm}/output.txt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{jvmIrAgainstOld => firAgainstOldJvm}/source.kt (100%) delete mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/output.txt rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIr => oldJvmAgainstFir}/library/a.kt (100%) create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/output.txt rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIr => oldJvmAgainstFir}/source.kt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIrWithAllowIrDependencies => oldJvmAgainstFirWithAllowUnstableDependencies}/library/a.kt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIrWithAllowIrDependencies => oldJvmAgainstFirWithAllowUnstableDependencies}/output.txt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIrWithAllowIrDependencies => oldJvmAgainstFirWithAllowUnstableDependencies}/source.kt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIrWithStableAbi => oldJvmAgainstFirWithStableAbi}/library/a.kt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIrWithStableAbi => oldJvmAgainstFirWithStableAbi}/output.txt (100%) rename compiler/testData/compileKotlinAgainstCustomBinaries/{oldAgainstJvmIrWithStableAbi => oldJvmAgainstFirWithStableAbi}/source.kt (100%) create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/library/a.kt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/output.txt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/source.kt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/library/a.kt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/output.txt create mode 100644 compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/source.kt 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 7379c779c1a..25ff966572d 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 @@ -103,8 +103,10 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { @Argument( value = "-Xabi-stability", valueDescription = "{stable|unstable}", - description = "When using unstable compiler features such as FIR or JVM IR, use 'stable' to mark generated class files as stable\n" + - "to prevent diagnostics from stable compilers at the call site.\n" + description = "When using unstable compiler features such as FIR, use 'stable' to mark generated class files as stable\n" + + "to prevent diagnostics from stable compilers at the call site.\n" + + "When using the JVM IR backend, conversely, use 'unstable' to mark generated class files as unstable\n" + + "to force diagnostics to be reported." ) var abiStability: String? by FreezableVar(null) @@ -446,7 +448,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() { result[JvmAnalysisFlags.suppressMissingBuiltinsError] = suppressMissingBuiltinsError result[JvmAnalysisFlags.irCheckLocalNames] = irCheckLocalNames result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview - result[AnalysisFlags.allowUnstableDependencies] = allowUnstableDependencies || useIR || useFir + result[AnalysisFlags.allowUnstableDependencies] = allowUnstableDependencies || useFir result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses return result } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt index eb2bfba7765..d5e0db6b644 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/AnalyzerWithCompilerReport.kt @@ -182,10 +182,10 @@ class AnalyzerWithCompilerReport( ) } - if (diagnostics.any { it.factory == Errors.IR_COMPILED_CLASS }) { + if (diagnostics.any { it.factory == Errors.IR_WITH_UNSTABLE_ABI_COMPILED_CLASS }) { messageCollector.report( ERROR, - "Classes compiled by a new Kotlin compiler backend were found in dependencies. " + + "Classes compiled by an unstable version of the Kotlin compiler were found in dependencies. " + "Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors" ) } 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 3f72c805e46..cbb8f6d9f58 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -165,7 +165,8 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.PARAMETERS_METADATA, arguments.javaParameters) - put(JVMConfigurationKeys.IR, (arguments.useIR && !arguments.noUseIR) || arguments.useFir) + val useIR = (arguments.useIR && !arguments.noUseIR) || arguments.useFir + put(JVMConfigurationKeys.IR, useIR) val abiStability = JvmAbiStability.fromStringOrNull(arguments.abiStability) if (arguments.abiStability != null) { @@ -174,6 +175,8 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr ERROR, "Unknown ABI stability mode: ${arguments.abiStability}, supported modes: ${JvmAbiStability.values().map { it.description }}" ) + } else if (!useIR && abiStability == JvmAbiStability.UNSTABLE) { + messageCollector.report(ERROR, "-Xabi-stability=unstable is not supported in the old JVM backend") } else { put(JVMConfigurationKeys.ABI_STABILITY, abiStability) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index ded6d7b0b80..9a935e80ece 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -118,7 +118,7 @@ public interface Errors { DiagnosticFactory1 MISSING_IMPORTED_SCRIPT_PSI = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 PRE_RELEASE_CLASS = DiagnosticFactory1.create(ERROR); - DiagnosticFactory1 IR_COMPILED_CLASS = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 IR_WITH_UNSTABLE_ABI_COMPILED_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 FIR_COMPILED_CLASS = DiagnosticFactory1.create(ERROR); DiagnosticFactory2> INCOMPATIBLE_CLASS = DiagnosticFactory2.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 3a06a25353e..214bd9ee0de 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -11,7 +11,6 @@ import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.config.LanguageVersion; -import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic; @@ -401,7 +400,7 @@ public class DefaultErrorMessages { MAP.put(MISSING_IMPORTED_SCRIPT_PSI, "Imported script file ''{0}'' is not loaded. Check your script imports", TO_STRING); MAP.put(MISSING_SCRIPT_PROVIDED_PROPERTY_CLASS, "Cannot access script provided property class ''{0}''. Check your module classpath for missing or conflicting dependencies", TO_STRING); MAP.put(PRE_RELEASE_CLASS, "{0} is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler", TO_STRING); - MAP.put(IR_COMPILED_CLASS, "{0} is compiled by a new Kotlin compiler backend and cannot be loaded by the old compiler", TO_STRING); + MAP.put(IR_WITH_UNSTABLE_ABI_COMPILED_CLASS, "{0} is compiled by an unstable version of the Kotlin compiler and cannot be loaded by this compiler", TO_STRING); MAP.put(FIR_COMPILED_CLASS, "{0} is compiled by the new Kotlin compiler frontend and cannot be loaded by the old compiler", TO_STRING); MAP.put(INCOMPATIBLE_CLASS, "{0} was compiled with an incompatible version of Kotlin. {1}", diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt index 400650958cd..2df4da03bc9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/MissingDependencyClassChecker.kt @@ -63,7 +63,7 @@ object MissingDependencyClassChecker : CallChecker { return FIR_COMPILED_CLASS.on(reportOn, source.presentableString) } if (source.abiStability == DeserializedContainerAbiStability.IR_UNSTABLE) { - return IR_COMPILED_CLASS.on(reportOn, source.presentableString) + return IR_WITH_UNSTABLE_ABI_COMPILED_CLASS.on(reportOn, source.presentableString) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt index a1f0e3cef0a..6f8185c9a9a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendExtension.kt @@ -33,6 +33,6 @@ interface JvmBackendExtension { override fun generateMetadataExtraFlags(abiStability: JvmAbiStability?): Int = JvmAnnotationNames.METADATA_JVM_IR_FLAG or - (if (abiStability == JvmAbiStability.STABLE) JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG else 0) + (if (abiStability != JvmAbiStability.UNSTABLE) JvmAnnotationNames.METADATA_JVM_IR_STABLE_ABI_FLAG else 0) } } diff --git a/compiler/testData/cli/jvm/abiStabilityIncorrectValue.args b/compiler/testData/cli/jvm/abiStabilityIncorrectValue.args new file mode 100644 index 00000000000..3bdd5af2b60 --- /dev/null +++ b/compiler/testData/cli/jvm/abiStabilityIncorrectValue.args @@ -0,0 +1,5 @@ +$TESTDATA_DIR$/simple.kt +-d +$TEMP_DIR$ +-Xuse-ir +-Xabi-stability=unknown diff --git a/compiler/testData/cli/jvm/abiStabilityIncorrectValue.out b/compiler/testData/cli/jvm/abiStabilityIncorrectValue.out new file mode 100644 index 00000000000..c132471a0c1 --- /dev/null +++ b/compiler/testData/cli/jvm/abiStabilityIncorrectValue.out @@ -0,0 +1,2 @@ +error: unknown ABI stability mode: unknown, supported modes: [stable, unstable] +COMPILATION_ERROR diff --git a/compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.args b/compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.args new file mode 100644 index 00000000000..3d0218fd1c3 --- /dev/null +++ b/compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/simple.kt +-d +$TEMP_DIR$ +-Xabi-stability=unstable diff --git a/compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.out b/compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.out new file mode 100644 index 00000000000..4383a3f6de4 --- /dev/null +++ b/compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.out @@ -0,0 +1,2 @@ +error: -Xabi-stability=unstable is not supported in the old JVM backend +COMPILATION_ERROR diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 2a2236368da..111025d9443 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -1,9 +1,10 @@ Usage: kotlinc-jvm where advanced options include: -Xabi-stability={stable|unstable} - When using unstable compiler features such as FIR or JVM IR, use 'stable' to mark generated class files as stable + When using unstable compiler features such as FIR, use 'stable' to mark generated class files as stable to prevent diagnostics from stable compilers at the call site. - + When using the JVM IR backend, conversely, use 'unstable' to mark generated class files as unstable + to force diagnostics to be reported. -Xadd-modules= Root modules to resolve in addition to the initial modules, or all modules on the module path if is ALL-MODULE-PATH -Xallow-no-source-files Allow no source files diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstJvmIr/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFir/library/a.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstJvmIr/library/a.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFir/library/a.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstJvmIr/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFir/output.txt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstJvmIr/output.txt rename to compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFir/output.txt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstJvmIr/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFir/source.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstJvmIr/source.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstFir/source.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstOld/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstOldJvm/library/a.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstOld/library/a.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstOldJvm/library/a.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstOld/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstOldJvm/output.txt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstOld/output.txt rename to compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstOldJvm/output.txt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstOld/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstOldJvm/source.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/jvmIrAgainstOld/source.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/firAgainstOldJvm/source.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/output.txt deleted file mode 100644 index 6bde2a37585..00000000000 --- a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/output.txt +++ /dev/null @@ -1,8 +0,0 @@ -error: classes compiled by a new Kotlin compiler backend were found in dependencies. Remove them from the classpath or use '-Xallow-jvm-ir-dependencies' to suppress errors -compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/source.kt:4:5: error: class 'lib.AKt' is compiled by a new Kotlin compiler backend and cannot be loaded by the old compiler - get { Box("OK").value } - ^ -compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/source.kt:4:11: error: class 'lib.Box' is compiled by a new Kotlin compiler backend and cannot be loaded by the old compiler - get { Box("OK").value } - ^ -COMPILATION_ERROR diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/library/a.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/library/a.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/library/a.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/output.txt new file mode 100644 index 00000000000..6fc8c06126f --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/output.txt @@ -0,0 +1,8 @@ +error: classes compiled by the new Kotlin compiler frontend were found in dependencies. Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors +compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/source.kt:4:5: error: class 'lib.AKt' is compiled by the new Kotlin compiler frontend and cannot be loaded by the old compiler + get { Box("OK").value } + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/source.kt:4:11: error: class 'lib.Box' is compiled by the new Kotlin compiler frontend and cannot be loaded by the old compiler + get { Box("OK").value } + ^ +COMPILATION_ERROR diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/source.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIr/source.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFir/source.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithAllowIrDependencies/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithAllowUnstableDependencies/library/a.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithAllowIrDependencies/library/a.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithAllowUnstableDependencies/library/a.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithAllowIrDependencies/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithAllowUnstableDependencies/output.txt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithAllowIrDependencies/output.txt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithAllowUnstableDependencies/output.txt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithAllowIrDependencies/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithAllowUnstableDependencies/source.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithAllowIrDependencies/source.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithAllowUnstableDependencies/source.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithStableAbi/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithStableAbi/library/a.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithStableAbi/library/a.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithStableAbi/library/a.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithStableAbi/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithStableAbi/output.txt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithStableAbi/output.txt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithStableAbi/output.txt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithStableAbi/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithStableAbi/source.kt similarity index 100% rename from compiler/testData/compileKotlinAgainstCustomBinaries/oldAgainstJvmIrWithStableAbi/source.kt rename to compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstFirWithStableAbi/source.kt diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/library/a.kt new file mode 100644 index 00000000000..71e3e5d293d --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/library/a.kt @@ -0,0 +1,5 @@ +package lib + +class Box(val value: String) + +inline fun get(block: () -> T): T = block() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/output.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/output.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/source.kt new file mode 100644 index 00000000000..ffadd735100 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIr/source.kt @@ -0,0 +1,5 @@ +import lib.* + +fun main() { + get { Box("OK").value } +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/library/a.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/library/a.kt new file mode 100644 index 00000000000..71e3e5d293d --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/library/a.kt @@ -0,0 +1,5 @@ +package lib + +class Box(val value: String) + +inline fun get(block: () -> T): T = block() diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/output.txt new file mode 100644 index 00000000000..6914512561d --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/output.txt @@ -0,0 +1,8 @@ +error: classes compiled by an unstable version of the Kotlin compiler were found in dependencies. Remove them from the classpath or use '-Xallow-unstable-dependencies' to suppress errors +compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/source.kt:4:5: error: class 'lib.AKt' is compiled by an unstable version of the Kotlin compiler and cannot be loaded by this compiler + get { Box("OK").value } + ^ +compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/source.kt:4:11: error: class 'lib.Box' is compiled by an unstable version of the Kotlin compiler and cannot be loaded by this compiler + get { Box("OK").value } + ^ +COMPILATION_ERROR diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/source.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/source.kt new file mode 100644 index 00000000000..ffadd735100 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/oldJvmAgainstJvmIrWithUnstableAbi/source.kt @@ -0,0 +1,5 @@ +import lib.* + +fun main() { + get { Box("OK").value } +} diff --git a/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java index 0811666f4d4..a9f999cda90 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/cli/CliTestGenerated.java @@ -27,6 +27,16 @@ public class CliTestGenerated extends AbstractCliTest { KotlinTestUtils.runTest(this::doJvmTest, this, testDataFilePath); } + @TestMetadata("abiStabilityIncorrectValue.args") + public void testAbiStabilityIncorrectValue() throws Exception { + runTest("compiler/testData/cli/jvm/abiStabilityIncorrectValue.args"); + } + + @TestMetadata("abiStabilityUnstableWithOldBackend.args") + public void testAbiStabilityUnstableWithOldBackend() throws Exception { + runTest("compiler/testData/cli/jvm/abiStabilityUnstableWithOldBackend.args"); + } + public void testAllFilesPresentInJvm() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/cli/jvm"), Pattern.compile("^(.+)\\.args$"), null, false); } diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index 402dbe9f360..f6c05bc2bea 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -669,28 +669,44 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration classLoader.loadClass("SourceKt").getDeclaredMethod("main").invoke(null) } - fun testJvmIrAgainstJvmIr() { - val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir")) - compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xuse-ir")) + fun testFirAgainstFir() { + val library = compileLibrary("library", additionalOptions = listOf("-Xuse-fir")) + compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xuse-fir")) } - fun testJvmIrAgainstOld() { + fun testFirAgainstOldJvm() { val library = compileLibrary("library") - compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xuse-ir")) + compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xuse-fir")) } - fun testOldAgainstJvmIr() { + fun testOldJvmAgainstJvmIr() { val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir")) compileKotlin("source.kt", tmpdir, listOf(library)) + + val library2 = compileLibrary("library", additionalOptions = listOf("-Xuse-ir", "-Xabi-stability=stable")) + compileKotlin("source.kt", tmpdir, listOf(library2)) + } + + fun testOldJvmAgainstFir() { + val library = compileLibrary("library", additionalOptions = listOf("-Xuse-fir")) + compileKotlin("source.kt", tmpdir, listOf(library)) + + val library2 = compileLibrary("library", additionalOptions = listOf("-Xuse-fir", "-Xabi-stability=unstable")) + compileKotlin("source.kt", tmpdir, listOf(library2)) + } + + fun testOldJvmAgainstJvmIrWithUnstableAbi() { + val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir", "-Xabi-stability=unstable")) + compileKotlin("source.kt", tmpdir, listOf(library)) } - fun testOldAgainstJvmIrWithStableAbi() { - val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir", "-Xabi-stability=stable")) + fun testOldJvmAgainstFirWithStableAbi() { + val library = compileLibrary("library", additionalOptions = listOf("-Xuse-fir", "-Xabi-stability=stable")) compileKotlin("source.kt", tmpdir, listOf(library)) } - fun testOldAgainstJvmIrWithAllowIrDependencies() { - val library = compileLibrary("library", additionalOptions = listOf("-Xuse-ir")) + fun testOldJvmAgainstFirWithAllowUnstableDependencies() { + val library = compileLibrary("library", additionalOptions = listOf("-Xuse-fir")) compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-Xallow-unstable-dependencies")) } diff --git a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt index 8b7773005cd..e3ee7f218df 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/DeserializedContainerSource.kt @@ -30,6 +30,9 @@ enum class DeserializedContainerAbiStability { // The container is unstable because it is compiled with FIR, and this compiler is _not_ configured to ignore that. FIR_UNSTABLE, - // The container is unstable because it is compiled with unstable JVM IR backend, and this compiler is _not_ configured to ignore that. + // The container is unstable because either: + // 1) it is compiled with JVM IR prior to 1.4.30, or + // 2) it is compiled with JVM IR >= 1.4.30 with the `-Xabi-stability=unstable` compiler option, + // and this compiler is _not_ configured to ignore that. IR_UNSTABLE, } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt index 830bbabfbeb..35506e98243 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/KotlinPsiChecker.kt @@ -274,7 +274,7 @@ private class ElementAnnotator( private fun isUnstableAbiClassDiagnosticForModulesWithEnabledUnstableAbi(diagnostic: Diagnostic): Boolean { val setting = when (diagnostic.factory) { - Errors.IR_COMPILED_CLASS -> K2JVMCompilerArguments::useIR + Errors.IR_WITH_UNSTABLE_ABI_COMPILED_CLASS -> K2JVMCompilerArguments::useIR Errors.FIR_COMPILED_CLASS -> K2JVMCompilerArguments::useFir else -> return false } diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt index 921e915e31d..e8bf4008634 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluatorBuilder.kt @@ -31,6 +31,7 @@ import com.intellij.testFramework.runInEdtAndWait import com.sun.jdi.* import com.sun.jdi.Value import org.jetbrains.eval4j.* +import org.jetbrains.eval4j.Value as Eval4JValue import org.jetbrains.eval4j.jdi.JDIEval import org.jetbrains.eval4j.jdi.asJdiValue import org.jetbrains.eval4j.jdi.asValue @@ -45,32 +46,28 @@ import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.core.util.attachmentByPsiFile import org.jetbrains.kotlin.idea.core.util.mergeAttachments import org.jetbrains.kotlin.idea.core.util.runInReadActionWithWriteActionPriorityWithPCE -import org.jetbrains.kotlin.idea.debugger.DebuggerUtils -import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationStatus.EvaluationContextLanguage +import org.jetbrains.kotlin.idea.debugger.* import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches.Companion.compileCodeFragmentCacheAware import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.GENERATED_CLASS_NAME import org.jetbrains.kotlin.idea.debugger.evaluate.classLoading.GENERATED_FUNCTION_NAME import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.* -import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.ClassLoadingResult import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.loadClassesSafely import org.jetbrains.kotlin.idea.debugger.evaluate.variables.EvaluatorValueConverter import org.jetbrains.kotlin.idea.debugger.evaluate.variables.VariableFinder -import org.jetbrains.kotlin.idea.debugger.safeLocation -import org.jetbrains.kotlin.idea.debugger.safeMethod -import org.jetbrains.kotlin.idea.debugger.safeVisibleVariableByName -import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.AnalyzingUtils import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.resolve.jvm.AsmTypes -import org.jetbrains.org.objectweb.asm.ClassReader +import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.tree.ClassNode +import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationStatus.EvaluationContextLanguage +import org.jetbrains.kotlin.idea.debugger.evaluate.compilingEvaluator.ClassLoadingResult +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import java.util.* -import org.jetbrains.eval4j.Value as Eval4JValue internal val LOG = Logger.getInstance(KotlinEvaluator::class.java) @@ -449,7 +446,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi companion object { private val IGNORED_DIAGNOSTICS: Set> = Errors.INVISIBLE_REFERENCE_DIAGNOSTICS + setOf( - Errors.EXPERIMENTAL_API_USAGE_ERROR, Errors.MISSING_DEPENDENCY_SUPERCLASS, Errors.IR_COMPILED_CLASS, + Errors.EXPERIMENTAL_API_USAGE_ERROR, Errors.MISSING_DEPENDENCY_SUPERCLASS, Errors.IR_WITH_UNSTABLE_ABI_COMPILED_CLASS, Errors.FIR_COMPILED_CLASS ) From 02c617468fa29c3e242ac0ba342cd1fafd0467ad Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Wed, 16 Dec 2020 19:37:00 +0100 Subject: [PATCH 009/176] Add support for a callback on recursion for memoized functions --- .../kotlin/storage/StorageManagerTest.java | 9 +-- .../storage/LockBasedStorageManager.java | 62 ++++++++++++++++--- .../storage/ObservableStorageManager.kt | 8 +++ .../kotlin/storage/StorageManager.kt | 4 ++ 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/compiler/tests/org/jetbrains/kotlin/storage/StorageManagerTest.java b/compiler/tests/org/jetbrains/kotlin/storage/StorageManagerTest.java index 5ef7efb779d..290aa357b42 100644 --- a/compiler/tests/org/jetbrains/kotlin/storage/StorageManagerTest.java +++ b/compiler/tests/org/jetbrains/kotlin/storage/StorageManagerTest.java @@ -163,7 +163,8 @@ public class StorageManagerTest extends TestCase { fail(); } catch (AssertionError e) { - assertTrue(e.getMessage().startsWith("Recursion detected on input: !!!")); + String message = e.getMessage(); + assertTrue("Expected message starting with \"Recursion detected\", got: " + message, message.startsWith("Recursion detected on input: !!!")); } } @@ -213,7 +214,7 @@ public class StorageManagerTest extends TestCase { new C().rec.invoke(); fail(); } - catch (IllegalStateException e) { + catch (AssertionError e) { // OK } } @@ -232,7 +233,7 @@ public class StorageManagerTest extends TestCase { new C().rec.invoke(); fail(); } - catch (IllegalStateException e) { + catch (AssertionError e) { // OK } } @@ -284,7 +285,7 @@ public class StorageManagerTest extends TestCase { new C().rec.invoke(); fail(); } - catch (IllegalStateException e) { + catch (AssertionError e) { // OK } } diff --git a/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java b/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java index 5ae93d8ca57..14aad06748c 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java +++ b/core/util.runtime/src/org/jetbrains/kotlin/storage/LockBasedStorageManager.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.storage; import kotlin.Unit; import kotlin.jvm.functions.Function0; import kotlin.jvm.functions.Function1; +import kotlin.jvm.functions.Function2; import kotlin.text.StringsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,7 +57,7 @@ public class LockBasedStorageManager implements StorageManager { public static final StorageManager NO_LOCKS = new LockBasedStorageManager("NO_LOCKS", ExceptionHandlingStrategy.THROW, EmptySimpleLock.INSTANCE) { @NotNull @Override - protected RecursionDetectedResult recursionDetectedDefault() { + protected RecursionDetectedResult recursionDetectedDefault(@NotNull String source, K input) { return RecursionDetectedResult.fallThrough(); } }; @@ -123,6 +124,15 @@ public class LockBasedStorageManager implements StorageManager { return createMemoizedFunction(compute, LockBasedStorageManager.createConcurrentHashMap()); } + @NotNull + @Override + public MemoizedFunctionToNotNull createMemoizedFunction( + @NotNull Function1 compute, + @NotNull Function2 onRecursiveCall + ) { + return createMemoizedFunction(compute, onRecursiveCall, LockBasedStorageManager.createConcurrentHashMap()); + } + @NotNull @Override public MemoizedFunctionToNotNull createMemoizedFunction( @@ -132,6 +142,22 @@ public class LockBasedStorageManager implements StorageManager { return new MapBasedMemoizedFunctionToNotNull(this, map, compute); } + @NotNull + @Override + public MemoizedFunctionToNotNull createMemoizedFunction( + @NotNull Function1 compute, + @NotNull final Function2 onRecursiveCall, + @NotNull ConcurrentMap map + ) { + return new MapBasedMemoizedFunctionToNotNull(this, map, compute) { + @NotNull + @Override + protected RecursionDetectedResult recursionDetected(K input, boolean firstTime) { + return RecursionDetectedResult.value(onRecursiveCall.invoke(input, firstTime)); + } + }; + } + @NotNull @Override public MemoizedFunctionToNullable createMemoizedFunctionWithNullableValues(@NotNull Function1 compute) { @@ -278,8 +304,15 @@ public class LockBasedStorageManager implements StorageManager { } @NotNull - protected RecursionDetectedResult recursionDetectedDefault() { - throw sanitizeStackTrace(new IllegalStateException("Recursive call in a lazy value under " + this)); + protected RecursionDetectedResult recursionDetectedDefault(@NotNull String source, K input) { + throw sanitizeStackTrace( + new AssertionError("Recursion detected " + source + + (input == null + ? "" + : "on input: " + input + ) + " under " + this + ) + ); } private static class RecursionDetectedResult { @@ -406,7 +439,7 @@ public class LockBasedStorageManager implements StorageManager { */ @NotNull protected RecursionDetectedResult recursionDetected(boolean firstTime) { - return storageManager.recursionDetectedDefault(); + return storageManager.recursionDetectedDefault("in a lazy value", null); } protected void postCompute(T value) { @@ -521,9 +554,22 @@ public class LockBasedStorageManager implements StorageManager { storageManager.lock.lock(); try { value = cache.get(input); + if (value == NotValue.COMPUTING) { - throw recursionDetected(input); + value = NotValue.RECURSION_WAS_DETECTED; + RecursionDetectedResult result = recursionDetected(input, /*firstTime = */ true); + if (!result.isFallThrough()) { + return result.getValue(); + } } + + if (value == NotValue.RECURSION_WAS_DETECTED) { + RecursionDetectedResult result = recursionDetected(input, /*firstTime = */ false); + if (!result.isFallThrough()) { + return result.getValue(); + } + } + if (value != null) return WrappedValues.unescapeExceptionOrNull(value); AssertionError error = null; @@ -567,10 +613,8 @@ public class LockBasedStorageManager implements StorageManager { } @NotNull - private AssertionError recursionDetected(K input) { - return sanitizeStackTrace( - new AssertionError("Recursion detected on input: " + input + " under " + storageManager) - ); + protected RecursionDetectedResult recursionDetected(K input, boolean firstTime) { + return storageManager.recursionDetectedDefault("", input); } @NotNull diff --git a/core/util.runtime/src/org/jetbrains/kotlin/storage/ObservableStorageManager.kt b/core/util.runtime/src/org/jetbrains/kotlin/storage/ObservableStorageManager.kt index 24cf4933923..141299df18d 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/storage/ObservableStorageManager.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/storage/ObservableStorageManager.kt @@ -26,6 +26,10 @@ abstract class ObservableStorageManager(private val delegate: StorageManager) : return delegate.createMemoizedFunction(compute.observable) } + override fun createMemoizedFunction(compute: (K) -> V, onRecursiveCall: (K, Boolean) -> V): MemoizedFunctionToNotNull { + return delegate.createMemoizedFunction(compute.observable, onRecursiveCall) + } + override fun createMemoizedFunctionWithNullableValues(compute: (K) -> V?): MemoizedFunctionToNullable { return delegate.createMemoizedFunctionWithNullableValues(compute.observable) } @@ -34,6 +38,10 @@ abstract class ObservableStorageManager(private val delegate: StorageManager) : return delegate.createMemoizedFunction(compute.observable, map) } + override fun createMemoizedFunction(compute: (K) -> V, onRecursiveCall: (K, Boolean) -> V, map: ConcurrentMap): MemoizedFunctionToNotNull { + return delegate.createMemoizedFunction(compute.observable, onRecursiveCall, map) + } + override fun createMemoizedFunctionWithNullableValues(compute: (K) -> V, map: ConcurrentMap): MemoizedFunctionToNullable { return delegate.createMemoizedFunctionWithNullableValues(compute.observable, map) } diff --git a/core/util.runtime/src/org/jetbrains/kotlin/storage/StorageManager.kt b/core/util.runtime/src/org/jetbrains/kotlin/storage/StorageManager.kt index 83e8f11d6eb..b517f0a5063 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/storage/StorageManager.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/storage/StorageManager.kt @@ -29,6 +29,8 @@ interface StorageManager { */ fun createMemoizedFunction(compute: (K) -> V): MemoizedFunctionToNotNull + fun createMemoizedFunction(compute: (K) -> V, onRecursiveCall: (K, Boolean) -> V): MemoizedFunctionToNotNull + fun createMemoizedFunctionWithNullableValues(compute: (K) -> V?): MemoizedFunctionToNullable fun createCacheWithNullableValues(): CacheWithNullableValues @@ -36,6 +38,8 @@ interface StorageManager { fun createMemoizedFunction(compute: (K) -> V, map: ConcurrentMap): MemoizedFunctionToNotNull + fun createMemoizedFunction(compute: (K) -> V, onRecursiveCall: (K, Boolean) -> V, map: ConcurrentMap): MemoizedFunctionToNotNull + fun createMemoizedFunctionWithNullableValues(compute: (K) -> V, map: ConcurrentMap): MemoizedFunctionToNullable fun createLazyValue(computable: () -> T): NotNullLazyValue From 9ee17cd610bf37cc396d4eea0fe23b863d565e47 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Wed, 16 Dec 2020 19:42:35 +0100 Subject: [PATCH 010/176] Do not throw assertion on recursion in typealias declaration, return empty list of descriptors instead, allowing for proper error reporting later. #KT-18344 fixed --- .../resolve/lazy/descriptors/AbstractLazyMemberScope.kt | 2 +- .../tests/typealias/boundsViolationRecursive.fir.kt | 3 +++ .../diagnostics/tests/typealias/boundsViolationRecursive.kt | 3 +++ .../tests/typealias/boundsViolationRecursive.txt | 3 +++ .../kotlin/test/runners/DiagnosticTestGenerated.java | 6 ++++++ .../runners/FirOldFrontendDiagnosticsTestGenerated.java | 6 ++++++ 6 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.fir.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt index 7bced7ad3e1..08310b5da60 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/AbstractLazyMemberScope.kt @@ -50,7 +50,7 @@ protected constructor( private val propertyDescriptors: MemoizedFunctionToNotNull> = storageManager.createMemoizedFunction { doGetProperties(it) } private val typeAliasDescriptors: MemoizedFunctionToNotNull> = - storageManager.createMemoizedFunction { doGetTypeAliases(it) } + storageManager.createMemoizedFunction( { doGetTypeAliases(it) }, onRecursiveCall = { _,_ -> emptyList() }) private val declaredFunctionDescriptors: MemoizedFunctionToNotNull> = storageManager.createMemoizedFunction { getDeclaredFunctions(it) } diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.fir.kt b/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.fir.kt new file mode 100644 index 00000000000..c2efd713d78 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.fir.kt @@ -0,0 +1,3 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER + +typealias R> = List diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.kt b/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.kt new file mode 100644 index 00000000000..1733bf2eb6a --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.kt @@ -0,0 +1,3 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER + +typealias RList<R>> = List diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.txt b/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.txt new file mode 100644 index 00000000000..c30a61d8f3f --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.txt @@ -0,0 +1,3 @@ +package + +public typealias R> = kotlin.collections.List diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index fbb0cacf8f4..1e91b1800d0 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -28653,6 +28653,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasRHS.kt"); } + @Test + @TestMetadata("boundsViolationRecursive.kt") + public void testBoundsViolationRecursive() throws Exception { + runTest("compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.kt"); + } + @Test @TestMetadata("capturingTypeParametersFromOuterClass.kt") public void testCapturingTypeParametersFromOuterClass() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 5e40236383c..ca3fc1a16c8 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -28557,6 +28557,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasRHS.kt"); } + @Test + @TestMetadata("boundsViolationRecursive.kt") + public void testBoundsViolationRecursive() throws Exception { + runTest("compiler/testData/diagnostics/tests/typealias/boundsViolationRecursive.kt"); + } + @Test @TestMetadata("capturingTypeParametersFromOuterClass.kt") public void testCapturingTypeParametersFromOuterClass() throws Exception { From 0671fd9aaa2c9fc9edd05c5639de0a117b6d3aad Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 17 Dec 2020 19:25:41 +0100 Subject: [PATCH 011/176] Support destructuring declarations in scratch files #KT-25038 fixed --- .../compile/KtScratchSourceFileProcessor.kt | 19 +++++++++++++++++++ .../ScratchRunActionTestGenerated.java | 10 ++++++++++ .../scratch/destructuringDecls.comp.after | 7 +++++++ .../testData/scratch/destructuringDecls.kts | 7 +++++++ .../scratch/destructuringDecls.repl.after | 7 +++++++ 5 files changed, 50 insertions(+) create mode 100644 idea/scripting-support/testData/scratch/destructuringDecls.comp.after create mode 100644 idea/scripting-support/testData/scratch/destructuringDecls.kts create mode 100644 idea/scripting-support/testData/scratch/destructuringDecls.repl.after diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchSourceFileProcessor.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchSourceFileProcessor.kt index df110183eef..8064f40fd3a 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchSourceFileProcessor.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/scratch/compile/KtScratchSourceFileProcessor.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.RenderingContext import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.scratch.ScratchExpression import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore class KtScratchSourceFileProcessor { companion object { @@ -71,6 +72,7 @@ class KtScratchSourceFileProcessor { fun process(expression: ScratchExpression) { val psiElement = expression.element when (psiElement) { + is KtDestructuringDeclaration -> processDestructuringDeclaration(expression, psiElement) is KtVariableDeclaration -> processDeclaration(expression, psiElement) is KtFunction -> processDeclaration(expression, psiElement) is KtClassOrObject -> processDeclaration(expression, psiElement) @@ -89,6 +91,23 @@ class KtScratchSourceFileProcessor { objectBuilder.appendLineInfo(e) } + private fun processDestructuringDeclaration(e: ScratchExpression, c: KtDestructuringDeclaration) { + val entries = c.entries.mapNotNull { if (it.isSingleUnderscore) null else it.resolveToDescriptorIfAny() } + entries.forEach { + val context = RenderingContext.of(it) + val rendered = Renderers.COMPACT.render(it, context) + classBuilder.append(rendered).newLine() + objectBuilder.println(rendered) + } + objectBuilder.appendLineInfo(e) + classBuilder.append("init {").newLine() + classBuilder.append(c.text).newLine() + entries.forEach { + classBuilder.append("this.${it.name} = ${it.name}").newLine() + } + classBuilder.append("}").newLine() + } + private fun processExpression(e: ScratchExpression, expr: KtExpression) { val resName = "$GET_RES_FUN_NAME_PREFIX$resCount" diff --git a/idea/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java b/idea/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java index 58a941e2496..383712fa1f7 100644 --- a/idea/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java +++ b/idea/scripting-support/test/org/jetbrains/kotlin/idea/scratch/ScratchRunActionTestGenerated.java @@ -31,6 +31,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/scripting-support/testData/scratch"), Pattern.compile("^(.+)\\.kts$"), null, false); } + @TestMetadata("destructuringDecls.kts") + public void testDestructuringDecls() throws Exception { + runTest("idea/scripting-support/testData/scratch/destructuringDecls.kts"); + } + @TestMetadata("for.kts") public void testFor() throws Exception { runTest("idea/scripting-support/testData/scratch/for.kts"); @@ -119,6 +124,11 @@ public class ScratchRunActionTestGenerated extends AbstractScratchRunActionTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/scripting-support/testData/scratch"), Pattern.compile("^(.+)\\.kts$"), null, false); } + @TestMetadata("destructuringDecls.kts") + public void testDestructuringDecls() throws Exception { + runTest("idea/scripting-support/testData/scratch/destructuringDecls.kts"); + } + @TestMetadata("for.kts") public void testFor() throws Exception { runTest("idea/scripting-support/testData/scratch/for.kts"); diff --git a/idea/scripting-support/testData/scratch/destructuringDecls.comp.after b/idea/scripting-support/testData/scratch/destructuringDecls.comp.after new file mode 100644 index 00000000000..e950d3bd456 --- /dev/null +++ b/idea/scripting-support/testData/scratch/destructuringDecls.comp.after @@ -0,0 +1,7 @@ +// REPL_MODE: false + +val (foo, bar) = 1 to "2" // RESULT: val foo: Int; val bar: String +foo // RESULT: 1 +bar // RESULT: 2 +val (_, baz) = 3 to "4" // RESULT: val baz: String +baz // RESULT: 4 \ No newline at end of file diff --git a/idea/scripting-support/testData/scratch/destructuringDecls.kts b/idea/scripting-support/testData/scratch/destructuringDecls.kts new file mode 100644 index 00000000000..e24c166f89f --- /dev/null +++ b/idea/scripting-support/testData/scratch/destructuringDecls.kts @@ -0,0 +1,7 @@ +// REPL_MODE: ~REPL_MODE~ + +val (foo, bar) = 1 to "2" +foo +bar +val (_, baz) = 3 to "4" +baz diff --git a/idea/scripting-support/testData/scratch/destructuringDecls.repl.after b/idea/scripting-support/testData/scratch/destructuringDecls.repl.after new file mode 100644 index 00000000000..531cdbbc5f5 --- /dev/null +++ b/idea/scripting-support/testData/scratch/destructuringDecls.repl.after @@ -0,0 +1,7 @@ +// REPL_MODE: true + +val (foo, bar) = 1 to "2" +foo // RESULT: res1: kotlin.Int = 1 +bar // RESULT: res2: kotlin.String = 2 +val (_, baz) = 3 to "4" +baz // RESULT: res4: kotlin.String = 4 From 65cf941b9beb62972cd12203ecd367d6bc21e30c Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Thu, 17 Dec 2020 19:27:38 +0100 Subject: [PATCH 012/176] Remove assertion about dispatch receiver in scripts #KT-42530 fixed --- .../jetbrains/kotlin/resolve/DescriptorResolver.java | 3 ++- .../scripting-compiler/testData/compiler/kt42530.kts | 5 +++++ .../kotlin/scripting/compiler/test/ScriptTest.kt | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 plugins/scripting/scripting-compiler/testData/compiler/kt42530.kts diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 2714eeef1ff..ac2ed637f87 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -328,7 +328,8 @@ public class DescriptorResolver { } destructuringVariables = () -> { - assert owner.getDispatchReceiverParameter() == null + ReceiverParameterDescriptor dispatchReceiver = owner.getDispatchReceiverParameter(); + assert dispatchReceiver == null || dispatchReceiver.getContainingDeclaration() instanceof ScriptDescriptor : "Destructuring declarations are only be parsed for lambdas, and they must not have a dispatch receiver"; LexicalScope scopeForDestructuring = ScopeUtilsKt.createScopeForDestructuring(scope, owner.getExtensionReceiverParameter()); diff --git a/plugins/scripting/scripting-compiler/testData/compiler/kt42530.kts b/plugins/scripting/scripting-compiler/testData/compiler/kt42530.kts new file mode 100644 index 00000000000..dcde2199a13 --- /dev/null +++ b/plugins/scripting/scripting-compiler/testData/compiler/kt42530.kts @@ -0,0 +1,5 @@ + +fun Int.isOdd() = (this % 2) == 1 +val list: List> = listOf(1 to "a", 2 to "b") +val (odds, evens) = list.partition { (i, _) -> i.isOdd() } +odds diff --git a/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/test/ScriptTest.kt b/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/test/ScriptTest.kt index 174579f0f3e..73e4f3c8ec4 100644 --- a/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/test/ScriptTest.kt +++ b/plugins/scripting/scripting-compiler/tests/org/jetbrains/kotlin/scripting/compiler/test/ScriptTest.kt @@ -76,6 +76,16 @@ class ScriptTest : TestCase() { }) } + fun testKt42530() { + val aClass = compileScript("kt42530.kts", StandardScriptDefinition) + Assert.assertNotNull(aClass) + val out = captureOut { + val anObj = tryConstructClassFromStringArgs(aClass!!, emptyList()) + Assert.assertNotNull(anObj) + } + assertEqualsTrimmed("[(1, a)]", out) + } + private fun compileScript( scriptPath: String, scriptDefinition: KotlinScriptDefinition, From 3e8016ed25cf5e7259dcc13e0468d2bf72acfcc9 Mon Sep 17 00:00:00 2001 From: Andrei Klunnyi Date: Mon, 14 Dec 2020 18:32:23 +0100 Subject: [PATCH 013/176] KTIJ-717 [Java side inspection]: "implementation of Kotlin sealed" --- .../KotlinSealedInheritorsInJava.html | 5 ++ .../messages/KotlinBundle.properties | 2 + idea/resources/META-INF/inspections.xml | 8 +++ .../KotlinSealedInheritorsInJavaInspection.kt | 57 +++++++++++++++ .../before/JavaTriesToExtendKotlinSealed.java | 18 +++++ .../before/KotlinSealedDeclarations.kt | 5 ++ .../kotlinSealedInJavaTest/expected.xml | 72 +++++++++++++++++++ .../kotlinSealedInJavaTest.test | 3 + .../MultiFileInspectionTestGenerated.java | 5 ++ 9 files changed, 175 insertions(+) create mode 100644 idea/resources-en/inspectionDescriptions/KotlinSealedInheritorsInJava.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/KotlinSealedInheritorsInJavaInspection.kt create mode 100644 idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/JavaTriesToExtendKotlinSealed.java create mode 100644 idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/KotlinSealedDeclarations.kt create mode 100644 idea/testData/multiFileInspections/kotlinSealedInJavaTest/expected.xml create mode 100644 idea/testData/multiFileInspections/kotlinSealedInJavaTest/kotlinSealedInJavaTest.test diff --git a/idea/resources-en/inspectionDescriptions/KotlinSealedInheritorsInJava.html b/idea/resources-en/inspectionDescriptions/KotlinSealedInheritorsInJava.html new file mode 100644 index 00000000000..a81e027b794 --- /dev/null +++ b/idea/resources-en/inspectionDescriptions/KotlinSealedInheritorsInJava.html @@ -0,0 +1,5 @@ + + +This inspection reports attempt to inherit Kotlin sealed interface/class in Java code. + + \ No newline at end of file diff --git a/idea/resources-en/messages/KotlinBundle.properties b/idea/resources-en/messages/KotlinBundle.properties index 8503a39be15..a5b57965757 100644 --- a/idea/resources-en/messages/KotlinBundle.properties +++ b/idea/resources-en/messages/KotlinBundle.properties @@ -1343,6 +1343,7 @@ double.negation.fix.text=Remove redundant negations redundant.double.negation=Redundant double negation equals.between.objects.of.inconvertible.types='equals()' between objects of inconvertible types usage.of.kotlin.internal.declaration.from.different.module=Usage of Kotlin internal declaration from different module +inheritance.of.kotlin.sealed=Java {0,choice,0#interface|1#class} cannot be a part of Kotlin sealed hierarchy junit.static.methods=JUnit static methods redundant.override.fix.text=Remove redundant overriding method redundant.overriding.method=Redundant overriding method @@ -2064,6 +2065,7 @@ inspection.replace.array.of.with.literal.display.name='arrayOf' call can be repl inspection.copy.without.named.arguments.display.name='copy' method of data class is called without named arguments inspection.move.suspicious.callable.reference.into.parentheses.display.name=Suspicious callable reference used as lambda result inspection.kotlin.internal.in.java.display.name=Usage of Kotlin internal declarations from Java +inspection.kotlin.sealed.in.java.display.name=Inheritance of Kotlin sealed interface/class from Java inspection.unused.lambda.expression.body.display.name=Unused return value of a function with lambda expression body inspection.destructuring.wrong.name.display.name=Variable in destructuring declaration uses name of a wrong data class property inspection.data.class.private.constructor.display.name=Private data class constructor is exposed via the 'copy' method diff --git a/idea/resources/META-INF/inspections.xml b/idea/resources/META-INF/inspections.xml index eb699fcedf2..4717ddc6426 100644 --- a/idea/resources/META-INF/inspections.xml +++ b/idea/resources/META-INF/inspections.xml @@ -1504,6 +1504,14 @@ language="JAVA" key="inspection.kotlin.internal.in.java.display.name" bundle="messages.KotlinBundle"/> + + { + if (this is PsiAnonymousClass && baseClassType.isKotlinSealed()) + return listOf(baseClassReference) + + val sealedBaseClasses = extendsList?.listSealedMembers() + val sealedBaseInterfaces = implementsList?.listSealedMembers() + + return sealedBaseClasses.orEmpty() + sealedBaseInterfaces.orEmpty() + } + + private fun PsiReferenceList.listSealedMembers(): List? = referencedTypes + ?.filter { it.isKotlinSealed() } + ?.mapNotNull { it as? PsiClassReferenceType } + ?.map { it.reference } + + private fun PsiClassType.isKotlinSealed(): Boolean = resolve()?.isKotlinSealed() == true + + private fun PsiClass.isKotlinSealed(): Boolean = this is KtUltraLightClass && getDescriptor()?.isSealed() == true + + private val PsiClass.abstractionTypeName: String + get() = if (isInterface) "interface" else "class" + } + + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor { + return object : JavaElementVisitor() { + override fun visitClass(aClass: PsiClass?) { + aClass?.listSealedParentReferences()?.forEach { + holder.registerProblem( + it, KotlinBundle.message("inheritance.of.kotlin.sealed", 0.takeIf { aClass.isInterface } ?: 1), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING + ) + } + } + + override fun visitAnonymousClass(aClass: PsiAnonymousClass?) = visitClass(aClass) + } + } +} \ No newline at end of file diff --git a/idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/JavaTriesToExtendKotlinSealed.java b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/JavaTriesToExtendKotlinSealed.java new file mode 100644 index 00000000000..2ab7d257214 --- /dev/null +++ b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/JavaTriesToExtendKotlinSealed.java @@ -0,0 +1,18 @@ +public class JavaTriesToExtendKotlinSealed { + + private static class TryToImplement implements KotlinSealedInterface {} + private static interface TryToExtend extends KotlinSealedInterface {} + private static class TryToExtendClass extends KotlinSealedClass {} + + class OkToImplement implements KotlinInterface {} + interface OkToExtend extends KotlinInterface {} + class OkToExtendClass extends KotlinClass{} + + public static void main(String[] args) { + KotlinSealedInterface sealedInterface = new KotlinSealedInterface() {}; // anonymouns class implements interface + KotlinSealedClass sealedClass = new KotlinSealedClass() {}; + + new KotlinInterface() {}; + new KotlinClass() {}; + } +} \ No newline at end of file diff --git a/idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/KotlinSealedDeclarations.kt b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/KotlinSealedDeclarations.kt new file mode 100644 index 00000000000..7e9097cee71 --- /dev/null +++ b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/before/KotlinSealedDeclarations.kt @@ -0,0 +1,5 @@ +sealed interface KotlinSealedInterface +sealed class KotlinSealedClass + +interface KotlinInterface: KotlinSealedInterface +class KotlinClass: KotlinSealedClass() \ No newline at end of file diff --git a/idea/testData/multiFileInspections/kotlinSealedInJavaTest/expected.xml b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/expected.xml new file mode 100644 index 00000000000..585da3710b0 --- /dev/null +++ b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/expected.xml @@ -0,0 +1,72 @@ + + + JavaTriesToExtendKotlinSealed.java + 3 + testKotlinSealedInJavaTest_KotlinSealedInJavaTest + <default> + + Inheritance of Kotlin sealed + interface/class from Java + + Java class cannot be a part of Kotlin sealed hierarchy + KotlinSealedInterface + 4 + 71 + + + + JavaTriesToExtendKotlinSealed.java + 4 + testKotlinSealedInJavaTest_KotlinSealedInJavaTest + <default> + + Inheritance of Kotlin sealed + interface/class from Java + + Java interface cannot be a part of Kotlin sealed hierarchy + KotlinSealedInterface + 4 + 69 + + + + JavaTriesToExtendKotlinSealed.java + 5 + testKotlinSealedInJavaTest_KotlinSealedInJavaTest + <default> + + Inheritance of Kotlin sealed + interface/class from Java + + Java class cannot be a part of Kotlin sealed hierarchy + KotlinSealedClass + 4 + 66 + + + + JavaTriesToExtendKotlinSealed.java + 12 + testKotlinSealedInJavaTest_KotlinSealedInJavaTest + <default> + + Inheritance of Kotlin sealed interface/class from Java + Java class cannot be a part of Kotlin sealed hierarchy + KotlinSealedInterface + 52 + 26 + + + + JavaTriesToExtendKotlinSealed.java + 13 + testKotlinSealedInJavaTest_KotlinSealedInJavaTest + <default> + + Inheritance of Kotlin sealed interface/class from Java + Java class cannot be a part of Kotlin sealed hierarchy + KotlinSealedClass() + 44 + 22 + + \ No newline at end of file diff --git a/idea/testData/multiFileInspections/kotlinSealedInJavaTest/kotlinSealedInJavaTest.test b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/kotlinSealedInJavaTest.test new file mode 100644 index 00000000000..ef7ba9896b7 --- /dev/null +++ b/idea/testData/multiFileInspections/kotlinSealedInJavaTest/kotlinSealedInJavaTest.test @@ -0,0 +1,3 @@ +{ + "inspectionClass": "org.jetbrains.kotlin.idea.inspections.KotlinSealedInheritorsInJavaInspection" +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/MultiFileInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/MultiFileInspectionTestGenerated.java index 8c893b2d52e..edc26e85601 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/MultiFileInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/MultiFileInspectionTestGenerated.java @@ -49,6 +49,11 @@ public class MultiFileInspectionTestGenerated extends AbstractMultiFileInspectio runTest("idea/testData/multiFileInspections/kotlinInternalInJavaTest/kotlinInternalInJavaTest.test"); } + @TestMetadata("kotlinSealedInJavaTest/kotlinSealedInJavaTest.test") + public void testKotlinSealedInJavaTest_KotlinSealedInJavaTest() throws Exception { + runTest("idea/testData/multiFileInspections/kotlinSealedInJavaTest/kotlinSealedInJavaTest.test"); + } + @TestMetadata("mainInTwoModules/mainInTwoModules.test") public void testMainInTwoModules_MainInTwoModules() throws Exception { runTest("idea/testData/multiFileInspections/mainInTwoModules/mainInTwoModules.test"); From 7add18661684dba4aabcf7759f74eb3287fd539d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 7 Dec 2020 13:01:12 +0300 Subject: [PATCH 014/176] Optimize/simplify FirClass<*>.findNonInterfaceSupertype --- .../jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 7ce2f17043d..2b5a7f6f0d4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -288,12 +288,12 @@ private fun FirDeclaration.hasBody(): Boolean = when (this) { */ fun FirClass<*>.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef? { for (it in superTypeRefs) { - val classId = it.safeAs() + val lookupTag = it.safeAs() ?.type.safeAs() - ?.lookupTag?.classId + ?.lookupTag ?: continue - val fir = context.session.firSymbolProvider.getClassLikeSymbolByFqName(classId) + val fir = lookupTag.toSymbol(context.session) ?.fir.safeAs>() ?: continue From c94c71cc503d9793e1b4e420139adda493a52f5f Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 7 Dec 2020 12:50:48 +0300 Subject: [PATCH 015/176] Optimize/simplify ConeClassLikeLookupTag.getNestedClassifierScope --- .../src/org/jetbrains/kotlin/fir/scopes/Scopes.kt | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt index 37f4fdc2828..74af476098c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt @@ -8,13 +8,9 @@ package org.jetbrains.kotlin.fir.scopes import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.ScopeSessionKey -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider -import org.jetbrains.kotlin.fir.resolve.scopeSessionKey +import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.scopes.impl.* import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag -import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol import org.jetbrains.kotlin.name.FqName private object FirDefaultStarImportingScopeKey : ScopeSessionKey() @@ -67,9 +63,6 @@ private fun doCreateImportingScopes( private val PACKAGE_MEMBER = scopeSessionKey() fun ConeClassLikeLookupTag.getNestedClassifierScope(session: FirSession, scopeSession: ScopeSession): FirScope? { - val klass = when (this) { - is ConeClassLookupTagWithFixedSymbol -> symbol.fir - else -> session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir as? FirRegularClass ?: return null - } + val klass = toSymbol(session)?.fir as? FirRegularClass ?: return null return klass.scopeProvider.getNestedClassifierScope(klass, session, scopeSession) } From 42b590d07cabed8616d9ff3487d6fa9b0d66eec5 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 7 Dec 2020 11:30:54 +0300 Subject: [PATCH 016/176] Optimize/simplify FirSealedClassConstructorCallChecker --- .../FirSealedClassConstructorCallChecker.kt | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedClassConstructorCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedClassConstructorCallChecker.kt index d6610c355e0..1a014103fec 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedClassConstructorCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirSealedClassConstructorCallChecker.kt @@ -13,13 +13,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirRegularClass -import org.jetbrains.kotlin.fir.declarations.classId import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference -import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.utils.addToStdlib.safeAs object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() { @@ -29,13 +27,10 @@ object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() { ?.fir.safeAs() ?: return - val typeClassId = constructorFir.returnTypeRef.safeAs() + val typeFir = constructorFir.returnTypeRef.safeAs() ?.type.safeAs() - ?.lookupTag - ?.classId - ?: return - - val typeFir = typeClassId.toRegularClass(context) + ?.lookupTag?.toSymbol(context.session) + ?.fir as? FirRegularClass ?: return if (typeFir.status.modality == Modality.SEALED) { @@ -43,15 +38,6 @@ object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() { } } - private fun ClassId.toRegularClass(context: CheckerContext): FirRegularClass? = if (!isLocal) { - context.session.firSymbolProvider.getClassLikeSymbolByFqName(this) - ?.fir.safeAs() - } else { - context.containingDeclarations - .lastOrNull { it.safeAs()?.classId == this } - .safeAs() - } - private fun DiagnosticReporter.report(source: FirSourceElement?) { source?.let { report(FirErrors.SEALED_CLASS_CONSTRUCTOR_CALL.on(it)) } } From 3ab5b57594189134674ada402515e39a570d08c9 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 7 Dec 2020 12:00:56 +0300 Subject: [PATCH 017/176] Optimize/simplify FirJvmTypeMapper.representativeUpperBound --- .../kotlin/fir/backend/jvm/FirJvmTypeMapper.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt index 689fcfc4309..9bab68f2372 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.types.model.SimpleTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker import org.jetbrains.kotlin.types.model.TypeParameterMarker import org.jetbrains.kotlin.utils.addToStdlib.runIf +import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.Type class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext, FirSessionComponent { @@ -189,7 +190,8 @@ val FirSession.jvmTypeMapper: FirJvmTypeMapper by FirSession.sessionComponentAcc class ConeTypeSystemCommonBackendContextForTypeMapping( val context: ConeTypeContext ) : TypeSystemCommonBackendContext by context, TypeSystemCommonBackendContextForTypeMapping { - private val symbolProvider = context.session.firSymbolProvider + private val session = context.session + private val symbolProvider = session.firSymbolProvider override fun TypeConstructorMarker.isTypeParameter(): Boolean { return this is ConeTypeParameterLookupTag @@ -210,7 +212,7 @@ class ConeTypeSystemCommonBackendContextForTypeMapping( override fun SimpleTypeMarker.isSuspendFunction(): Boolean { require(this is ConeSimpleKotlinType) - return isSuspendFunctionType(context.session) + return isSuspendFunctionType(session) } override fun SimpleTypeMarker.isKClass(): Boolean { @@ -234,8 +236,8 @@ class ConeTypeSystemCommonBackendContextForTypeMapping( require(this is ConeTypeParameterLookupTag) val bounds = this.typeParameterSymbol.fir.bounds.map { it.coneType } return bounds.firstOrNull { - val classId = it.classId ?: return@firstOrNull false - val classSymbol = symbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol ?: return@firstOrNull false + val classSymbol = it.safeAs()?.fullyExpandedType(session) + ?.lookupTag?.toSymbol(session) as? FirRegularClassSymbol ?: return@firstOrNull false val kind = classSymbol.fir.classKind kind != ClassKind.INTERFACE && kind != ClassKind.ANNOTATION_CLASS } ?: bounds.first() From c6a40b232204c12bd3bf58de8c69debdae079e9c Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 7 Dec 2020 12:54:53 +0300 Subject: [PATCH 018/176] Optimize/simplify FirJvmTypeMapper.defaultType --- .../org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt index 9bab68f2372..ab8b39b178f 100644 --- a/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt @@ -202,7 +202,7 @@ class ConeTypeSystemCommonBackendContextForTypeMapping( return when (this) { is ConeTypeParameterLookupTag -> ConeTypeParameterTypeImpl(this, isNullable = false) is ConeClassLikeLookupTag -> { - val symbol = symbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol + val symbol = toSymbol(session) as? FirRegularClassSymbol ?: error("Class for $this not found") symbol.fir.defaultType() } From d5a6991b2dc01f0e2adea1e6b06657d6eee393d8 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 10 Dec 2020 00:32:39 -0800 Subject: [PATCH 019/176] FIR: extend SAM conversion to subtype of functional type --- .../generators/CallAndReferenceGenerator.kt | 10 ++++- .../kotlin/fir/resolve/LookupTagUtils.kt | 4 ++ .../kotlin/fir/resolve/SamResolution.kt | 23 +++++----- .../kotlin/fir/resolve/calls/Arguments.kt | 45 ++++++++++++++----- ...ntersectionTypeToFunInterfaceConversion.kt | 1 - ...fFunctionalTypeToFunInterfaceConversion.kt | 1 - .../caoWithAdaptationForSam.fir.kt.txt | 4 +- .../caoWithAdaptationForSam.fir.txt | 12 +++-- .../samConversionsWithSmartCasts.fir.kt.txt | 12 ++--- .../samConversionsWithSmartCasts.fir.txt | 33 ++++++++------ 10 files changed, 96 insertions(+), 49 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 35353eda734..df570b58712 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -22,6 +22,8 @@ import org.jetbrains.kotlin.fir.resolve.calls.isFunctional import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isKMutableProperty +import org.jetbrains.kotlin.fir.resolve.resolveFunctionTypeIfSamInterface +import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.* @@ -618,8 +620,12 @@ class CallAndReferenceGenerator( if (expectedType is ConeTypeParameterType || expectedType.isBuiltinFunctionalType(session)) { return false } - // On the other hand, the actual type should be a functional type. - return argument.isFunctional(session) + // On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`. + val lookupTag = parameter.returnTypeRef.coneTypeSafe()?.lookupTag + val firRegularClass = lookupTag?.toFirRegularClass(session) + // TODO: cache SAM interface to resolved function type, as [SamResolution] does? + val expectedFunctionType = firRegularClass?.resolveFunctionTypeIfSamInterface(session, scopeSession) + return argument.isFunctional(session, scopeSession, expectedFunctionType) } private fun IrExpression.applyAssigningArrayElementsToVarargInNamedForm( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt index 3ed79836a58..14f6da469f7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/LookupTagUtils.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.resolve import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag @@ -32,6 +33,9 @@ fun ConeClassLikeLookupTag.toSymbol(useSiteSession: FirSession): FirClassLikeSym } } +fun ConeClassLikeLookupTag.toFirRegularClass(session: FirSession): FirRegularClass? = + session.firSymbolProvider.getSymbolByLookupTag(this)?.fir as? FirRegularClass + @OptIn(LookupTagInternals::class) fun ConeClassLikeLookupTagImpl.bindSymbolToLookupTag(session: FirSession, symbol: FirClassLikeSymbol<*>?) { boundSymbol = OneElementWeakMap(session, symbol) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt index 0b8947f2440..86ec79b1a28 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt @@ -70,11 +70,7 @@ class FirSamResolverImpl( } private fun getFunctionTypeForPossibleSamType(type: ConeClassLikeType): ConeLookupTagBasedType? { - val firRegularClass = - firSession.firSymbolProvider - .getSymbolByLookupTag(type.lookupTag) - ?.fir as? FirRegularClass - ?: return null + val firRegularClass = type.lookupTag.toFirRegularClass(firSession) ?: return null val unsubstitutedFunctionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null @@ -216,11 +212,7 @@ class FirSamResolverImpl( private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): ConeLookupTagBasedType? { return resolvedFunctionType.getOrPut(firRegularClass) { - if (!firRegularClass.status.isFun) return@getOrPut NULL_STUB - val abstractMethod = firRegularClass.getSingleAbstractMethodOrNull(firSession, scopeSession) ?: return@getOrPut NULL_STUB - // TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) } - - abstractMethod.getFunctionTypeForAbstractMethod() + firRegularClass.resolveFunctionTypeIfSamInterface(firSession, scopeSession) ?: NULL_STUB } as? ConeLookupTagBasedType } @@ -230,6 +222,17 @@ class FirSamResolverImpl( } } +fun FirRegularClass.resolveFunctionTypeIfSamInterface( + session: FirSession, + scopeSession: ScopeSession +): ConeLookupTagBasedType? { + if (!this.status.isFun) return null + val abstractMethod = getSingleAbstractMethodOrNull(session, scopeSession) ?: return null + // TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) } + + return abstractMethod.getFunctionTypeForAbstractMethod() +} + private fun FirRegularClass.getSingleAbstractMethodOrNull( session: FirSession, scopeSession: ScopeSession, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index 25593e0f709..9c62316d0e6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition import org.jetbrains.kotlin.types.model.CaptureStatus +import org.jetbrains.kotlin.utils.addToStdlib.runIf fun Candidate.resolveArgumentExpression( csBuilder: ConstraintSystemBuilder, @@ -336,10 +337,9 @@ internal fun Candidate.resolveArgument( sink: CheckerSink, context: ResolutionContext ) { - argument.resultType.ensureResolvedTypeDeclaration(context.session) - val expectedType = prepareExpectedType(context.session, argument, parameter, context) + val expectedType = prepareExpectedType(context.session, context.bodyResolveComponents.scopeSession, argument, parameter, context) resolveArgumentExpression( this.system.getBuilder(), argument, @@ -354,18 +354,20 @@ internal fun Candidate.resolveArgument( private fun Candidate.prepareExpectedType( session: FirSession, + scopeSession: ScopeSession, argument: FirExpression, parameter: FirValueParameter?, context: ResolutionContext ): ConeKotlinType? { if (parameter == null) return null val basicExpectedType = argument.getExpectedTypeForSAMConversion(parameter/*, LanguageVersionSettings*/) - val expectedType = getExpectedTypeWithSAMConversion(session, argument, basicExpectedType, context) ?: basicExpectedType + val expectedType = getExpectedTypeWithSAMConversion(session, scopeSession, argument, basicExpectedType, context) ?: basicExpectedType return this.substitutor.substituteOrSelf(expectedType) } private fun Candidate.getExpectedTypeWithSAMConversion( session: FirSession, + scopeSession: ScopeSession, argument: FirExpression, candidateExpectedType: ConeKotlinType, context: ResolutionContext @@ -375,20 +377,43 @@ private fun Candidate.getExpectedTypeWithSAMConversion( val firFunction = symbol.fir as? FirFunction<*> ?: return null if (!context.bodyResolveComponents.samResolver.shouldRunSamConversionForFunction(firFunction)) return null - if (!argument.isFunctional(session)) return null - // TODO: resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!)) - return context.bodyResolveComponents.samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType).apply { - usesSAM = true + val expectedFunctionType = context.bodyResolveComponents.samResolver.getFunctionTypeForPossibleSamType(candidateExpectedType) + return runIf(argument.isFunctional(session, scopeSession, expectedFunctionType)) { + expectedFunctionType.apply { + // Even though the `expectedFunctionalType` could be `null`, we should mark the flag to indicate that the argument is a + // functional type. That will help avoid ambiguous `invoke` resolutions. See KT-39824 + usesSAM = true + } } } -fun FirExpression.isFunctional(session: FirSession): Boolean = +fun FirExpression.isFunctional( + session: FirSession, + scopeSession: ScopeSession, + expectedFunctionType: ConeKotlinType?, +): Boolean { when ((this as? FirWrappedArgumentExpression)?.expression ?: this) { - is FirAnonymousFunction, is FirCallableReferenceAccess -> true - else -> typeRef.coneTypeSafe()?.isBuiltinFunctionalType(session) == true + is FirAnonymousFunction, is FirCallableReferenceAccess -> return true + else -> { + // Either a functional type or a subtype of a class that has a contributed `invoke`. + val coneType = typeRef.coneTypeSafe() ?: return false + if (coneType.isBuiltinFunctionalType(session)) { + return true + } + val classLikeExpectedFunctionType = expectedFunctionType as? ConeClassLikeType + if (classLikeExpectedFunctionType == null || coneType is ConeIntegerLiteralType) { + return false + } + val invokeSymbol = + coneType.findContributedInvokeSymbol( + session, scopeSession, classLikeExpectedFunctionType, shouldCalculateReturnTypesOfFakeOverrides = false + ) + return invokeSymbol != null + } } +} fun FirExpression.getExpectedTypeForSAMConversion( parameter: FirValueParameter/*, languageVersionSettings: LanguageVersionSettings*/ diff --git a/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt b/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt index 4d517beeff1..559237c5ce5 100644 --- a/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt +++ b/compiler/testData/codegen/box/funInterface/intersectionTypeToFunInterfaceConversion.kt @@ -1,6 +1,5 @@ // DONT_TARGET_EXACT_BACKEND: WASM // WASM_MUTE_REASON: SAM_CONVERSIONS -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS, JS_IR // IGNORE_BACKEND: JS_IR_ES6 diff --git a/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt b/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt index ab655dd96a2..514727ebe19 100644 --- a/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt +++ b/compiler/testData/codegen/box/funInterface/subtypeOfFunctionalTypeToFunInterfaceConversion.kt @@ -1,6 +1,5 @@ // DONT_TARGET_EXACT_BACKEND: WASM // WASM_MUTE_REASON: SAM_CONVERSIONS -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS, JS_IR // IGNORE_BACKEND: JS_IR_ES6 diff --git a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt index 16b3427c296..2598c69ea47 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt @@ -64,7 +64,7 @@ fun test4(fn: Function1) { fn is IFoo -> { // BLOCK val <>: A = A val <>: IFoo = fn /*as IFoo */ - <>.set(i = <>, newValue = <>.get(i = <>).plus(other = 1)) + <>.set(i = <> /*-> IFoo */, newValue = <>.get(i = <> /*-> IFoo */).plus(other = 1)) } } } @@ -84,7 +84,7 @@ fun test6(a: Any) { { // BLOCK val <>: A = A val <>: Function1 = a /*as Function1 */ - <>.set(i = <>, newValue = <>.get(i = <>).plus(other = 1)) + <>.set(i = <> /*-> IFoo */, newValue = <>.get(i = <> /*-> IFoo */).plus(other = 1)) } } diff --git a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt index d1943517037..b74efa16760 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt @@ -141,11 +141,13 @@ FILE fqName: fileName:/caoWithAdaptationForSam.kt GET_VAR 'fn: kotlin.Function1 declared in .test4' type=kotlin.Function1 origin=null CALL 'public final fun set (i: .IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=null $receiver: GET_VAR 'val tmp_2: .A [val] declared in .test4' type=.A origin=null - i: GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null + i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo + GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null $this: CALL 'public final fun get (i: .IFoo): kotlin.Int [operator] declared in ' type=kotlin.Int origin=null $receiver: GET_VAR 'val tmp_2: .A [val] declared in .test4' type=.A origin=null - i: GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null + i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo + GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null other: CONST Int type=kotlin.Int value=1 FUN name:test5 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Any @@ -187,9 +189,11 @@ FILE fqName: fileName:/caoWithAdaptationForSam.kt GET_VAR 'a: kotlin.Any declared in .test6' type=kotlin.Any origin=null CALL 'public final fun set (i: .IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=null $receiver: GET_VAR 'val tmp_6: .A [val] declared in .test6' type=.A origin=null - i: GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null + i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo + GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null $this: CALL 'public final fun get (i: .IFoo): kotlin.Int [operator] declared in ' type=kotlin.Int origin=null $receiver: GET_VAR 'val tmp_6: .A [val] declared in .test6' type=.A origin=null - i: GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null + i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo + GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null other: CONST Int type=kotlin.Int value=1 diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt index b769f5e4a61..91c55e89d1e 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt @@ -14,29 +14,29 @@ fun run2(r1: KRunnable, r2: KRunnable) { } fun test0(a: T) where T : KRunnable, T : Function0 { - run1(r = a) + run1(r = a /*-> KRunnable */) } fun test1(a: Function0) { when { - a is KRunnable -> run1(r = a /*as KRunnable */) + a is KRunnable -> run1(r = a /*as KRunnable */ /*-> KRunnable */) } } fun test2(a: KRunnable) { a as Function0 /*~> Unit */ - run1(r = a /*as Function0 */) + run1(r = a /*as Function0 */ /*-> KRunnable */) } fun test3(a: Function0) { when { - a is KRunnable -> run2(r1 = a /*as KRunnable */, r2 = a /*as KRunnable */) + a is KRunnable -> run2(r1 = a /*as KRunnable */ /*-> KRunnable */, r2 = a /*as KRunnable */ /*-> KRunnable */) } } fun test4(a: Function0, b: Function0) { when { - a is KRunnable -> run2(r1 = a /*as KRunnable */, r2 = b /*-> KRunnable */) + a is KRunnable -> run2(r1 = a /*as KRunnable */ /*-> KRunnable */, r2 = b /*-> KRunnable */) } } @@ -50,7 +50,7 @@ fun test5x(a: Any) { when { a is KRunnable -> { // BLOCK a /*as KRunnable */ as Function0 /*~> Unit */ - run1(r = a /*as KRunnable */) + run1(r = a /*as KRunnable */ /*-> KRunnable */) } } } diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt index 86e5d5b4cdb..d89270747af 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt @@ -34,7 +34,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt VALUE_PARAMETER name:a index:0 type:T of .test0 BLOCK_BODY CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: GET_VAR 'a: T of .test0 declared in .test0' type=T of .test0 origin=null + r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + GET_VAR 'a: T of .test0 declared in .test0' type=T of .test0 origin=null FUN name:test1 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -43,8 +44,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.KRunnable GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null then: CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null + r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null FUN name:test2 visibility:public modality:FINAL <> (a:.KRunnable) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:.KRunnable BLOCK_BODY @@ -52,8 +54,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt TYPE_OP type=kotlin.Function0 origin=CAST typeOperand=kotlin.Function0 GET_VAR 'a: .KRunnable declared in .test2' type=.KRunnable origin=null CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 - GET_VAR 'a: .KRunnable declared in .test2' type=.KRunnable origin=null + r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'a: .KRunnable declared in .test2' type=.KRunnable origin=null FUN name:test3 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -62,10 +65,12 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.KRunnable GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null then: CALL 'public final fun run2 (r1: .KRunnable, r2: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r1: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null - r2: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r1: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r2: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null FUN name:test4 visibility:public modality:FINAL <> (a:kotlin.Function0, b:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 VALUE_PARAMETER name:b index:1 type:kotlin.Function0 @@ -75,8 +80,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.KRunnable GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null then: CALL 'public final fun run2 (r1: .KRunnable, r2: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r1: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null + r1: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null r2: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable GET_VAR 'b: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null FUN name:test5 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit @@ -102,8 +108,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null + r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable + TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null FUN name:test6 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Any BLOCK_BODY From 4a24f0fab3fb66d95436c45dfbe73f3f1720097c Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 10 Dec 2020 12:28:50 -0800 Subject: [PATCH 020/176] FIR2IR: use FirSamResolverImpl to get function type for possible SAM type --- .../generators/CallAndReferenceGenerator.kt | 9 +++----- .../kotlin/fir/resolve/SamResolution.kt | 21 +++++++------------ 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index df570b58712..fb94f001664 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -17,13 +17,12 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.references.impl.FirReferencePlaceholderForResolvedAnnotations import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.fir.resolve.FirSamResolverImpl import org.jetbrains.kotlin.fir.resolve.calls.getExpectedTypeForSAMConversion import org.jetbrains.kotlin.fir.resolve.calls.isFunctional import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isKMutableProperty -import org.jetbrains.kotlin.fir.resolve.resolveFunctionTypeIfSamInterface -import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.* @@ -48,6 +47,7 @@ class CallAndReferenceGenerator( private val approximator = object : AbstractTypeApproximator(session.typeContext) {} private val adapterGenerator = AdapterGenerator(components, conversionScope) + private val samResolver = FirSamResolverImpl(session, scopeSession) private fun FirTypeRef.toIrType(): IrType = with(typeConverter) { toIrType() } @@ -621,10 +621,7 @@ class CallAndReferenceGenerator( return false } // On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`. - val lookupTag = parameter.returnTypeRef.coneTypeSafe()?.lookupTag - val firRegularClass = lookupTag?.toFirRegularClass(session) - // TODO: cache SAM interface to resolved function type, as [SamResolution] does? - val expectedFunctionType = firRegularClass?.resolveFunctionTypeIfSamInterface(session, scopeSession) + val expectedFunctionType = samResolver.getFunctionTypeForPossibleSamType(parameter.returnTypeRef.coneType) return argument.isFunctional(session, scopeSession, expectedFunctionType) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt index 86ec79b1a28..ed9ea28cca3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/SamResolution.kt @@ -45,7 +45,7 @@ val SAM_PARAMETER_NAME = Name.identifier("block") class FirSamResolverImpl( private val firSession: FirSession, private val scopeSession: ScopeSession, - private val outerClassManager: FirOuterClassManager, + private val outerClassManager: FirOuterClassManager? = null, ) : FirSamResolver() { private val resolvedFunctionType: MutableMap = mutableMapOf() @@ -206,13 +206,17 @@ class FirSamResolverImpl( resolvePhase = FirResolvePhase.BODY_RESOLVE }.apply { - containingClassAttr = outerClassManager.outerClass(firRegularClass.symbol)?.toLookupTag() + containingClassAttr = outerClassManager?.outerClass(firRegularClass.symbol)?.toLookupTag() } } private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): ConeLookupTagBasedType? { return resolvedFunctionType.getOrPut(firRegularClass) { - firRegularClass.resolveFunctionTypeIfSamInterface(firSession, scopeSession) ?: NULL_STUB + if (!firRegularClass.status.isFun) return@getOrPut NULL_STUB + val abstractMethod = firRegularClass.getSingleAbstractMethodOrNull(firSession, scopeSession) ?: return@getOrPut NULL_STUB + // TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) } + + abstractMethod.getFunctionTypeForAbstractMethod() } as? ConeLookupTagBasedType } @@ -222,17 +226,6 @@ class FirSamResolverImpl( } } -fun FirRegularClass.resolveFunctionTypeIfSamInterface( - session: FirSession, - scopeSession: ScopeSession -): ConeLookupTagBasedType? { - if (!this.status.isFun) return null - val abstractMethod = getSingleAbstractMethodOrNull(session, scopeSession) ?: return null - // TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) } - - return abstractMethod.getFunctionTypeForAbstractMethod() -} - private fun FirRegularClass.getSingleAbstractMethodOrNull( session: FirSession, scopeSession: ScopeSession, From 3bca6ae8937bfbfdfd2e449e663cdcdd8b706ba6 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 10 Dec 2020 14:20:01 -0800 Subject: [PATCH 021/176] FIR: allow lower bound of flexible type when finding contributed invoke --- .../kotlin/fir/resolve/calls/Arguments.kt | 2 +- .../sam/passSubtypeOfFunctionSamConversion.kt | 1 - .../tests/j+k/sam/recursiveSamsAndInvoke.kt | 2 +- .../samConversionsWithSmartCasts.fir.kt | 4 +- .../samConversionsWithSmartCasts.fir.kt.txt | 14 +++--- .../sam/samConversionsWithSmartCasts.fir.txt | 48 +++++++++++-------- 6 files changed, 40 insertions(+), 31 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index 9c62316d0e6..adcb10f28d2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -402,7 +402,7 @@ fun FirExpression.isFunctional( if (coneType.isBuiltinFunctionalType(session)) { return true } - val classLikeExpectedFunctionType = expectedFunctionType as? ConeClassLikeType + val classLikeExpectedFunctionType = expectedFunctionType?.lowerBoundIfFlexible() as? ConeClassLikeType if (classLikeExpectedFunctionType == null || coneType is ConeIntegerLiteralType) { return false } diff --git a/compiler/testData/codegen/box/sam/passSubtypeOfFunctionSamConversion.kt b/compiler/testData/codegen/box/sam/passSubtypeOfFunctionSamConversion.kt index d2b87472604..11948e9ce26 100644 --- a/compiler/testData/codegen/box/sam/passSubtypeOfFunctionSamConversion.kt +++ b/compiler/testData/codegen/box/sam/passSubtypeOfFunctionSamConversion.kt @@ -1,5 +1,4 @@ // TARGET_BACKEND: JVM -// IGNORE_BACKEND_FIR: JVM_IR // FILE: a.kt diff --git a/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt b/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt index f4d975f42ef..37fcf10fcc9 100644 --- a/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt +++ b/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt @@ -16,7 +16,7 @@ public interface MyListener> { typealias Handler = (cause: Throwable?) -> Unit fun MyFuture.setup() { - addListener(ListenerImpl>()) + addListener(ListenerImpl>()) addListener { } } diff --git a/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.fir.kt b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.fir.kt index a95ff868f00..329a29f52dd 100644 --- a/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.fir.kt +++ b/compiler/testData/diagnostics/tests/samConversions/samConversionsWithSmartCasts.fir.kt @@ -49,11 +49,11 @@ fun test6(a: Any) { fun test7(a: (Int) -> Int) { a as () -> Unit - J().run1(a) + J().run1(a) } fun test8(a: () -> Unit) { - J().run1(J.id(a)) + J().run1(J.id(a)) } fun test9() { diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt index ee1b3d61c77..85ebe18232e 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt @@ -1,24 +1,24 @@ fun test1(a: Function0) { when { - a is Runnable -> runStatic(r = a /*as Runnable */) + a is Runnable -> runStatic(r = a /*as Runnable */ /*-> Runnable? */) } } fun test2(a: Function0) { when { - a is Runnable -> J().run1(r = a /*as Runnable */) + a is Runnable -> J().run1(r = a /*as Runnable */ /*-> Runnable? */) } } fun test3(a: Function0) { when { - a is Runnable -> J().run2(r1 = a /*as Runnable */, r2 = a /*as Runnable */) + a is Runnable -> J().run2(r1 = a /*as Runnable */ /*-> Runnable? */, r2 = a /*as Runnable */ /*-> Runnable? */) } } fun test4(a: Function0, b: Function0) { when { - a is Runnable -> J().run2(r1 = a /*as Runnable */, r2 = b /*-> Runnable? */) + a is Runnable -> J().run2(r1 = a /*as Runnable */ /*-> Runnable? */, r2 = b /*-> Runnable? */) } } @@ -32,7 +32,7 @@ fun test5x(a: Any) { when { a is Runnable -> { // BLOCK a /*as Runnable */ as Function0 /*~> Unit */ - J().run1(r = a /*as Runnable */) + J().run1(r = a /*as Runnable */ /*-> Runnable? */) } } } @@ -44,11 +44,11 @@ fun test6(a: Any) { fun test7(a: Function1) { a as Function0 /*~> Unit */ - error("") /* ErrorCallExpression */a /*as Function0 */; + J().run1(r = a /*as Function0 */ /*-> Runnable? */) } fun test8(a: Function0) { - error("") /* ErrorCallExpression */id?>(x = a); + J().run1(r = id?>(x = a) /*-> Runnable? */) } fun test9() { diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt index 40cc1ac952e..5a22093c4e2 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt @@ -7,8 +7,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=java.lang.Runnable GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null then: CALL 'public open fun runStatic (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null - r: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null + r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -18,8 +19,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null then: CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null + r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null FUN name:test3 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -29,10 +31,12 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null then: CALL 'public open fun run2 (r1: java.lang.Runnable?, r2: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r1: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null - r2: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r1: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r2: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null FUN name:test4 visibility:public modality:FINAL <> (a:kotlin.Function0, b:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 VALUE_PARAMETER name:b index:1 type:kotlin.Function0 @@ -43,8 +47,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null then: CALL 'public open fun run2 (r1: java.lang.Runnable?, r2: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r1: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null + r1: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null r2: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? GET_VAR 'b: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null FUN name:test5 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit @@ -72,8 +77,9 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null + r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null FUN name:test6 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Any BLOCK_BODY @@ -91,16 +97,20 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit TYPE_OP type=kotlin.Function0 origin=CAST typeOperand=kotlin.Function0 GET_VAR 'a: kotlin.Function1 declared in .test7' type=kotlin.Function1 origin=null - ERROR_CALL 'Unresolved reference: #' type=kotlin.Unit - TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 - GET_VAR 'a: kotlin.Function1 declared in .test7' type=kotlin.Function1 origin=null + CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null + $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null + r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'a: kotlin.Function1 declared in .test7' type=kotlin.Function1 origin=null FUN name:test8 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY - ERROR_CALL 'Unresolved reference: #' type=kotlin.Unit - CALL 'public open fun id (x: T of .J.id?): T of .J.id? declared in .J' type=kotlin.Function0? origin=null - : kotlin.Function0? - x: GET_VAR 'a: kotlin.Function0 declared in .test8' type=kotlin.Function0 origin=null + CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null + $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null + r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? + CALL 'public open fun id (x: T of .J.id?): T of .J.id? declared in .J' type=kotlin.Function0? origin=null + : kotlin.Function0? + x: GET_VAR 'a: kotlin.Function0 declared in .test8' type=kotlin.Function0 origin=null FUN name:test9 visibility:public modality:FINAL <> () returnType:kotlin.Unit BLOCK_BODY CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null From 7df289746c78f50f4ab29d10153d318cc0c6323d Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 10 Dec 2020 15:05:47 -0800 Subject: [PATCH 022/176] FIR: fix invoke lookup for SAM resolution --- .../kotlin/fir/resolve/calls/Arguments.kt | 32 +++++++++++++++++-- .../tests/j+k/sam/recursiveSamsAndInvoke.kt | 2 +- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index adcb10f28d2..511470096ca 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition +import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.model.CaptureStatus import org.jetbrains.kotlin.utils.addToStdlib.runIf @@ -409,8 +410,35 @@ fun FirExpression.isFunctional( val invokeSymbol = coneType.findContributedInvokeSymbol( session, scopeSession, classLikeExpectedFunctionType, shouldCalculateReturnTypesOfFakeOverrides = false - ) - return invokeSymbol != null + ) ?: return false + // Make sure the contributed `invoke` is indeed a wanted functional type by checking if types are compatible. + val expectedReturnType = classLikeExpectedFunctionType.returnType(session)!!.lowerBoundIfFlexible() + val returnTypeCompatible = + expectedReturnType is ConeTypeParameterType || + AbstractTypeChecker.isSubtypeOf( + session.inferenceComponents.ctx, + invokeSymbol.fir.returnTypeRef.coneType, + expectedReturnType, + isFromNullabilityConstraint = false + ) + if (!returnTypeCompatible) { + return false + } + if (invokeSymbol.fir.valueParameters.size != classLikeExpectedFunctionType.typeArguments.size - 1) { + return false + } + val parameterPairs = + invokeSymbol.fir.valueParameters.zip(classLikeExpectedFunctionType.valueParameterTypesIncludingReceiver(session)) + return parameterPairs.all { (invokeParameter, expectedParameter) -> + val expectedParameterType = expectedParameter!!.lowerBoundIfFlexible() + expectedParameterType is ConeTypeParameterType || + AbstractTypeChecker.isSubtypeOf( + session.inferenceComponents.ctx, + invokeParameter.returnTypeRef.coneType, + expectedParameterType, + isFromNullabilityConstraint = false + ) + } } } } diff --git a/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt b/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt index 37fcf10fcc9..f4d975f42ef 100644 --- a/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt +++ b/compiler/testData/diagnostics/tests/j+k/sam/recursiveSamsAndInvoke.kt @@ -16,7 +16,7 @@ public interface MyListener> { typealias Handler = (cause: Throwable?) -> Unit fun MyFuture.setup() { - addListener(ListenerImpl>()) + addListener(ListenerImpl>()) addListener { } } From d753d21dee4c1b282423ea43db2f90e2b651f5eb Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Sun, 20 Dec 2020 23:01:55 -0800 Subject: [PATCH 023/176] FIR2IR: don't add SAM conversion for explicit subtype cases --- .../generators/CallAndReferenceGenerator.kt | 13 ++++++++ .../caoWithAdaptationForSam.fir.kt.txt | 4 +-- .../caoWithAdaptationForSam.fir.txt | 12 +++---- .../samConversionsWithSmartCasts.fir.kt.txt | 12 +++---- .../samConversionsWithSmartCasts.fir.txt | 33 ++++++++----------- .../samConversionsWithSmartCasts.fir.kt.txt | 10 +++--- .../sam/samConversionsWithSmartCasts.fir.txt | 30 +++++++---------- 7 files changed, 55 insertions(+), 59 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index fb94f001664..b8accddf4cf 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.resolve.FirSamResolverImpl import org.jetbrains.kotlin.fir.resolve.calls.getExpectedTypeForSAMConversion import org.jetbrains.kotlin.fir.resolve.calls.isFunctional import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType import org.jetbrains.kotlin.fir.resolve.inference.isKMutableProperty import org.jetbrains.kotlin.fir.resolve.toSymbol @@ -38,6 +39,7 @@ import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.psi2ir.generators.hasNoSideEffects import org.jetbrains.kotlin.types.AbstractTypeApproximator +import org.jetbrains.kotlin.types.AbstractTypeChecker class CallAndReferenceGenerator( private val components: Fir2IrComponents, @@ -615,6 +617,17 @@ class CallAndReferenceGenerator( } private fun needSamConversion(argument: FirExpression, parameter: FirValueParameter): Boolean { + // If the type of the argument is already an explicitly subtype of the type of the parameter, we don't need SAM conversion. + if (argument.typeRef !is FirResolvedTypeRef || + AbstractTypeChecker.isSubtypeOf( + session.inferenceComponents.ctx, + argument.typeRef.coneType, + parameter.returnTypeRef.coneType, + isFromNullabilityConstraint = true + ) + ) { + return false + } // If the expected type is a built-in functional type, we don't need SAM conversion. val expectedType = argument.getExpectedTypeForSAMConversion(parameter) if (expectedType is ConeTypeParameterType || expectedType.isBuiltinFunctionalType(session)) { diff --git a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt index 2598c69ea47..16b3427c296 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.kt.txt @@ -64,7 +64,7 @@ fun test4(fn: Function1) { fn is IFoo -> { // BLOCK val <>: A = A val <>: IFoo = fn /*as IFoo */ - <>.set(i = <> /*-> IFoo */, newValue = <>.get(i = <> /*-> IFoo */).plus(other = 1)) + <>.set(i = <>, newValue = <>.get(i = <>).plus(other = 1)) } } } @@ -84,7 +84,7 @@ fun test6(a: Any) { { // BLOCK val <>: A = A val <>: Function1 = a /*as Function1 */ - <>.set(i = <> /*-> IFoo */, newValue = <>.get(i = <> /*-> IFoo */).plus(other = 1)) + <>.set(i = <>, newValue = <>.get(i = <>).plus(other = 1)) } } diff --git a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt index b74efa16760..d1943517037 100644 --- a/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt +++ b/compiler/testData/ir/irText/expressions/callableReferences/caoWithAdaptationForSam.fir.txt @@ -141,13 +141,11 @@ FILE fqName: fileName:/caoWithAdaptationForSam.kt GET_VAR 'fn: kotlin.Function1 declared in .test4' type=kotlin.Function1 origin=null CALL 'public final fun set (i: .IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=null $receiver: GET_VAR 'val tmp_2: .A [val] declared in .test4' type=.A origin=null - i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo - GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null + i: GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null $this: CALL 'public final fun get (i: .IFoo): kotlin.Int [operator] declared in ' type=kotlin.Int origin=null $receiver: GET_VAR 'val tmp_2: .A [val] declared in .test4' type=.A origin=null - i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo - GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null + i: GET_VAR 'val tmp_3: .IFoo [val] declared in .test4' type=.IFoo origin=null other: CONST Int type=kotlin.Int value=1 FUN name:test5 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Any @@ -189,11 +187,9 @@ FILE fqName: fileName:/caoWithAdaptationForSam.kt GET_VAR 'a: kotlin.Any declared in .test6' type=kotlin.Any origin=null CALL 'public final fun set (i: .IFoo, newValue: kotlin.Int): kotlin.Unit [operator] declared in ' type=kotlin.Unit origin=null $receiver: GET_VAR 'val tmp_6: .A [val] declared in .test6' type=.A origin=null - i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo - GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null + i: GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null newValue: CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null $this: CALL 'public final fun get (i: .IFoo): kotlin.Int [operator] declared in ' type=kotlin.Int origin=null $receiver: GET_VAR 'val tmp_6: .A [val] declared in .test6' type=.A origin=null - i: TYPE_OP type=.IFoo origin=SAM_CONVERSION typeOperand=.IFoo - GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null + i: GET_VAR 'val tmp_7: kotlin.Function1 [val] declared in .test6' type=kotlin.Function1 origin=null other: CONST Int type=kotlin.Int value=1 diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt index 91c55e89d1e..b769f5e4a61 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.kt.txt @@ -14,29 +14,29 @@ fun run2(r1: KRunnable, r2: KRunnable) { } fun test0(a: T) where T : KRunnable, T : Function0 { - run1(r = a /*-> KRunnable */) + run1(r = a) } fun test1(a: Function0) { when { - a is KRunnable -> run1(r = a /*as KRunnable */ /*-> KRunnable */) + a is KRunnable -> run1(r = a /*as KRunnable */) } } fun test2(a: KRunnable) { a as Function0 /*~> Unit */ - run1(r = a /*as Function0 */ /*-> KRunnable */) + run1(r = a /*as Function0 */) } fun test3(a: Function0) { when { - a is KRunnable -> run2(r1 = a /*as KRunnable */ /*-> KRunnable */, r2 = a /*as KRunnable */ /*-> KRunnable */) + a is KRunnable -> run2(r1 = a /*as KRunnable */, r2 = a /*as KRunnable */) } } fun test4(a: Function0, b: Function0) { when { - a is KRunnable -> run2(r1 = a /*as KRunnable */ /*-> KRunnable */, r2 = b /*-> KRunnable */) + a is KRunnable -> run2(r1 = a /*as KRunnable */, r2 = b /*-> KRunnable */) } } @@ -50,7 +50,7 @@ fun test5x(a: Any) { when { a is KRunnable -> { // BLOCK a /*as KRunnable */ as Function0 /*~> Unit */ - run1(r = a /*as KRunnable */ /*-> KRunnable */) + run1(r = a /*as KRunnable */) } } } diff --git a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt index d89270747af..86e5d5b4cdb 100644 --- a/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt +++ b/compiler/testData/ir/irText/expressions/funInterface/samConversionsWithSmartCasts.fir.txt @@ -34,8 +34,7 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt VALUE_PARAMETER name:a index:0 type:T of .test0 BLOCK_BODY CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - GET_VAR 'a: T of .test0 declared in .test0' type=T of .test0 origin=null + r: GET_VAR 'a: T of .test0 declared in .test0' type=T of .test0 origin=null FUN name:test1 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -44,9 +43,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.KRunnable GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null then: CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null + r: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null FUN name:test2 visibility:public modality:FINAL <> (a:.KRunnable) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:.KRunnable BLOCK_BODY @@ -54,9 +52,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt TYPE_OP type=kotlin.Function0 origin=CAST typeOperand=kotlin.Function0 GET_VAR 'a: .KRunnable declared in .test2' type=.KRunnable origin=null CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 - GET_VAR 'a: .KRunnable declared in .test2' type=.KRunnable origin=null + r: TYPE_OP type=kotlin.Function0 origin=IMPLICIT_CAST typeOperand=kotlin.Function0 + GET_VAR 'a: .KRunnable declared in .test2' type=.KRunnable origin=null FUN name:test3 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -65,12 +62,10 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.KRunnable GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null then: CALL 'public final fun run2 (r1: .KRunnable, r2: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r1: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null - r2: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r1: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r2: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null FUN name:test4 visibility:public modality:FINAL <> (a:kotlin.Function0, b:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 VALUE_PARAMETER name:b index:1 type:kotlin.Function0 @@ -80,9 +75,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=.KRunnable GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null then: CALL 'public final fun run2 (r1: .KRunnable, r2: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r1: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null + r1: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null r2: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable GET_VAR 'b: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null FUN name:test5 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit @@ -108,9 +102,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null CALL 'public final fun run1 (r: .KRunnable): kotlin.Unit declared in ' type=kotlin.Unit origin=null - r: TYPE_OP type=.KRunnable origin=SAM_CONVERSION typeOperand=.KRunnable - TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable - GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null + r: TYPE_OP type=.KRunnable origin=IMPLICIT_CAST typeOperand=.KRunnable + GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null FUN name:test6 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Any BLOCK_BODY diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt index 85ebe18232e..8a6af5e2cfa 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.kt.txt @@ -1,24 +1,24 @@ fun test1(a: Function0) { when { - a is Runnable -> runStatic(r = a /*as Runnable */ /*-> Runnable? */) + a is Runnable -> runStatic(r = a /*as Runnable */) } } fun test2(a: Function0) { when { - a is Runnable -> J().run1(r = a /*as Runnable */ /*-> Runnable? */) + a is Runnable -> J().run1(r = a /*as Runnable */) } } fun test3(a: Function0) { when { - a is Runnable -> J().run2(r1 = a /*as Runnable */ /*-> Runnable? */, r2 = a /*as Runnable */ /*-> Runnable? */) + a is Runnable -> J().run2(r1 = a /*as Runnable */, r2 = a /*as Runnable */) } } fun test4(a: Function0, b: Function0) { when { - a is Runnable -> J().run2(r1 = a /*as Runnable */ /*-> Runnable? */, r2 = b /*-> Runnable? */) + a is Runnable -> J().run2(r1 = a /*as Runnable */, r2 = b /*-> Runnable? */) } } @@ -32,7 +32,7 @@ fun test5x(a: Any) { when { a is Runnable -> { // BLOCK a /*as Runnable */ as Function0 /*~> Unit */ - J().run1(r = a /*as Runnable */ /*-> Runnable? */) + J().run1(r = a /*as Runnable */) } } } diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt index 5a22093c4e2..720cf65c0da 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionsWithSmartCasts.fir.txt @@ -7,9 +7,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=java.lang.Runnable GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null then: CALL 'public open fun runStatic (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null - r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? - TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null + r: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test1' type=kotlin.Function0 origin=null FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -19,9 +18,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null then: CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? - TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null + r: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test2' type=kotlin.Function0 origin=null FUN name:test3 visibility:public modality:FINAL <> (a:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 BLOCK_BODY @@ -31,12 +29,10 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null then: CALL 'public open fun run2 (r1: java.lang.Runnable?, r2: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r1: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? - TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null - r2: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? - TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r1: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null + r2: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test3' type=kotlin.Function0 origin=null FUN name:test4 visibility:public modality:FINAL <> (a:kotlin.Function0, b:kotlin.Function0) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Function0 VALUE_PARAMETER name:b index:1 type:kotlin.Function0 @@ -47,9 +43,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null then: CALL 'public open fun run2 (r1: java.lang.Runnable?, r2: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r1: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? - TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null + r1: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null r2: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? GET_VAR 'b: kotlin.Function0 declared in .test4' type=kotlin.Function0 origin=null FUN name:test5 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit @@ -77,9 +72,8 @@ FILE fqName: fileName:/samConversionsWithSmartCasts.kt GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null CALL 'public open fun run1 (r: java.lang.Runnable?): kotlin.Unit declared in .J' type=kotlin.Unit origin=null $this: CONSTRUCTOR_CALL 'public constructor () [primary] declared in .J' type=.J origin=null - r: TYPE_OP type=java.lang.Runnable? origin=SAM_CONVERSION typeOperand=java.lang.Runnable? - TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable - GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null + r: TYPE_OP type=java.lang.Runnable origin=IMPLICIT_CAST typeOperand=java.lang.Runnable + GET_VAR 'a: kotlin.Any declared in .test5x' type=kotlin.Any origin=null FUN name:test6 visibility:public modality:FINAL <> (a:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:a index:0 type:kotlin.Any BLOCK_BODY From 1f258c28fc64adb62a9f45ce479ac3a1e054a6db Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 18 Dec 2020 12:33:40 +0300 Subject: [PATCH 024/176] [Test] Extract main compiler test generator to separate project This is needed because now we have different tests modules with different test frameworks (JUnit3 and JUnit5) which has no dependencies between each other. So for keeping all test generation config in one place we need module which may rely on all independent test modules --- .../Generate_Compiler_Tests.xml | 3 +- compiler/build.gradle.kts | 3 -- compiler/tests-common-new/build.gradle.kts | 8 ++--- .../test/generators/NewTestGenerationDSL.kt | 6 ++-- .../test/generators/NewTestGeneratorImpl.kt | 2 ++ .../build.gradle.kts | 35 +++++++++++++++++++ .../test/generators/GenerateCompilerTests.kt | 13 +++++++ .../GenerateJUnit3CompilerTests.kt} | 8 ++--- .../GenerateJUnit5CompilerTests.kt} | 15 ++++---- .../pill/generate-all-tests/build.gradle.kts | 2 +- .../kotlin/pill/generateAllTests/Main.java | 3 +- settings.gradle | 1 + 12 files changed, 70 insertions(+), 29 deletions(-) create mode 100644 compiler/tests-for-compiler-generator/build.gradle.kts create mode 100644 compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateCompilerTests.kt rename compiler/{tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt => tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt} (99%) rename compiler/{tests-common-new/tests/org/jetbrains/kotlin/test/generators/GenerateNewCompilerTests.kt => tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit5CompilerTests.kt} (83%) diff --git a/.idea/runConfigurations/Generate_Compiler_Tests.xml b/.idea/runConfigurations/Generate_Compiler_Tests.xml index 44a573c3fb5..621873a8928 100644 --- a/.idea/runConfigurations/Generate_Compiler_Tests.xml +++ b/.idea/runConfigurations/Generate_Compiler_Tests.xml @@ -10,12 +10,11 @@ + + - -