From a2c24e696f355e2fcbf62b84b26b2704988053e7 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Wed, 4 Mar 2020 16:55:15 +0300 Subject: [PATCH] Leverage existing psi2ir function declaration generator in plugin This seems to be the only reasonable way to provide function declarations with _correctly_ substituted type parameters without rewriting logic from scratch; correctly scoped type parameters in IR are now required in serialization plugin by all backends. Also fix some missing upper bounds. --- .../kotlin/psi2ir/Psi2IrTranslator.kt | 2 +- .../psi2ir/generators/GeneratorContext.kt | 59 +++++++++++-------- .../jetbrains/kotlin/ir/backend/js/klib.kt | 3 +- .../build.gradle.kts | 1 + .../compiler/backend/ir/GeneratorHelpers.kt | 41 +++++++++++-- .../ir/SerializableCompanionIrGenerator.kt | 17 ++++-- .../backend/ir/SerializerForEnumsGenerator.kt | 11 +++- .../resolve/KSerializerDescriptorResolver.kt | 17 +----- 8 files changed, 98 insertions(+), 53 deletions(-) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt index 6b283045a8f..09caccc93f6 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/Psi2IrTranslator.kt @@ -62,7 +62,7 @@ class Psi2IrTranslator( symbolTable: SymbolTable = SymbolTable(signaturer), extensions: GeneratorExtensions = GeneratorExtensions() ): GeneratorContext = - GeneratorContext(configuration, moduleDescriptor, bindingContext, languageVersionSettings, symbolTable, extensions, signaturer) + createGeneratorContext(configuration, moduleDescriptor, bindingContext, languageVersionSettings, symbolTable, extensions, signaturer) fun generateModuleFragment( context: GeneratorContext, diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt index 698cd4d5d70..9fff8b18d3f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/GeneratorContext.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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.psi2ir.generators @@ -24,12 +13,41 @@ import org.jetbrains.kotlin.descriptors.NotFoundClasses import org.jetbrains.kotlin.ir.builders.IrGeneratorContext import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.ConstantValueGenerator +import org.jetbrains.kotlin.ir.util.IdSignatureComposer +import org.jetbrains.kotlin.ir.util.SymbolTable +import org.jetbrains.kotlin.ir.util.TypeTranslator import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.storage.LockBasedStorageManager +fun createGeneratorContext( + configuration: Psi2IrConfiguration, + moduleDescriptor: ModuleDescriptor, + bindingContext: BindingContext, + languageVersionSettings: LanguageVersionSettings, + symbolTable: SymbolTable, + extensions: GeneratorExtensions, + signaturer: IdSignatureComposer +): GeneratorContext { + val typeTranslator = TypeTranslator(symbolTable, languageVersionSettings, builtIns = moduleDescriptor.builtIns) + val constantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable) + typeTranslator.constantValueGenerator = constantValueGenerator + constantValueGenerator.typeTranslator = typeTranslator + return GeneratorContext( + configuration, + moduleDescriptor, + bindingContext, + languageVersionSettings, + symbolTable, + extensions, + typeTranslator, + constantValueGenerator, + IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable) + ) +} + class GeneratorContext( val configuration: Psi2IrConfiguration, val moduleDescriptor: ModuleDescriptor, @@ -37,20 +55,13 @@ class GeneratorContext( val languageVersionSettings: LanguageVersionSettings, val symbolTable: SymbolTable, val extensions: GeneratorExtensions, - signaturer: IdSignatureComposer + val typeTranslator: TypeTranslator, + val constantValueGenerator: ConstantValueGenerator, + override val irBuiltIns: IrBuiltIns ) : IrGeneratorContext() { - val constantValueGenerator: ConstantValueGenerator = ConstantValueGenerator(moduleDescriptor, symbolTable) - val typeTranslator: TypeTranslator = TypeTranslator(symbolTable, languageVersionSettings, builtIns = moduleDescriptor.builtIns) val callToSubstitutedDescriptorMap = mutableMapOf() - init { - typeTranslator.constantValueGenerator = constantValueGenerator - constantValueGenerator.typeTranslator = typeTranslator - } - - override val irBuiltIns: IrBuiltIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable) - val sourceManager = PsiSourceManager() // TODO: inject a correct StorageManager instance, or store NotFoundClasses inside ModuleDescriptor diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 9e297e72c04..80c59c3d502 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -47,6 +47,7 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.psi2ir.generators.createGeneratorContext import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContextUtils @@ -241,7 +242,7 @@ private fun runAnalysisAndPreparePsi2Ir(depsDescriptors: ModulesStructure): Gene val mangler = JsManglerDesc val signaturer = IdSignatureDescriptor(mangler) - return GeneratorContext( + return createGeneratorContext( Psi2IrConfiguration(), analysisResult.moduleDescriptor, analysisResult.bindingContext, diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts b/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts index 3970631d53e..308ad585167 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { compileOnly(project(":compiler:frontend")) compileOnly(project(":compiler:backend")) compileOnly(project(":compiler:ir.backend.common")) + compileOnly(project(":compiler:ir.psi2ir")) compileOnly(project(":js:js.frontend")) compileOnly(project(":js:js.translator")) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index a3490496cd5..5c11bcba3b2 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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. */ @@ -26,6 +26,11 @@ import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi2ir.Psi2IrConfiguration +import org.jetbrains.kotlin.psi2ir.generators.DeclarationGenerator +import org.jetbrains.kotlin.psi2ir.generators.FunctionGenerator +import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext +import org.jetbrains.kotlin.psi2ir.generators.GeneratorExtensions import org.jetbrains.kotlin.resolve.descriptorUtil.classId import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.isTypeParameter @@ -50,6 +55,24 @@ interface IrBuilderExtension { } } + private fun createFunctionGenerator(): FunctionGenerator = with(compilerContext) { + return FunctionGenerator( + DeclarationGenerator( + GeneratorContext( + Psi2IrConfiguration(), + moduleDescriptor, + bindingContext, + languageVersionSettings, + symbolTable, + GeneratorExtensions(), + typeTranslator, + typeTranslator.constantValueGenerator, + irBuiltIns + ) + ) + ) + } + fun IrClass.contributeFunction( descriptor: FunctionDescriptor, declareNew: Boolean = true, @@ -59,9 +82,16 @@ interface IrBuilderExtension { descriptor ) else compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner f.parent = this - f.returnType = descriptor.returnType!!.toIrType() - if (declareNew) f.createParameterDeclarations(this.thisReceiver!!) - f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody(this.startOffset, this.endOffset) { bodyGen(f) } + if (declareNew) { + f.buildWithScope { + createFunctionGenerator().generateFunctionParameterDeclarationsAndReturnType(f, null, null) + } + } + + f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody( + this.startOffset, + this.endOffset + ) { bodyGen(f) } this.addMember(f) } @@ -347,7 +377,7 @@ interface IrBuilderExtension { SERIALIZABLE_PLUGIN_ORIGIN, this, type.toIrType(), - null + (this as? ValueParameterDescriptor)?.varargElementType?.toIrType() ).also { it.parent = this@createParameterDeclarations } @@ -372,6 +402,7 @@ interface IrBuilderExtension { it ).also { typeParameter -> typeParameter.parent = this + typeParameter.superTypes.addAll(it.upperBounds.map { it.toIrType() }) } } } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt index aa0038fb358..f7cdc61c873 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableCompanionIrGenerator.kt @@ -1,3 +1,8 @@ +/* + * 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.kotlinx.serialization.compiler.backend.ir import org.jetbrains.kotlin.descriptors.* @@ -111,21 +116,23 @@ class SerializableCompanionIrGenerator( && it.returnType != null && isKSerializer(it.returnType) } ?: return irClass.contributeFunction(serialFactoryDescriptor) { factory -> + val kSerializerStarType = factory.returnType val array = factory.valueParameters.first() val argsSize = serializableDescriptor.declaredTypeParameters.size val arrayGet = compilerContext.builtIns.array.getFuncDesc("get").single() val arrayGetSymbol = compilerContext.symbolTable.referenceFunction(arrayGet) - val outAnyNullable = makeTypeProjection(compilerContext.irBuiltIns.anyNType, Variance.OUT_VARIANCE).type - - val serializers: List = (0 until argsSize).map { irInvoke(irGet(array), arrayGetSymbol, irInt(it)) } + val serializers: List = (0 until argsSize).map { + irInvoke(irGet(array), arrayGetSymbol, irInt(it), typeHint = kSerializerStarType) + } val serializerCall = compilerContext.symbolTable.referenceSimpleFunction(getterDescriptor) val call = irInvoke( IrGetValueImpl(startOffset, endOffset, factory.dispatchReceiverParameter!!.symbol), serializerCall, - List(argsSize) { outAnyNullable }, - serializers + List(argsSize) { compilerContext.irBuiltIns.anyNType }, + serializers, + returnTypeHint = kSerializerStarType ) +irReturn(call) patchSerializableClassWithMarkerAnnotation(companionDescriptor) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt index ccfcd93a394..6fcd2e9d7e2 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerForEnumsGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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. */ @@ -7,13 +7,13 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.properties import org.jetbrains.kotlin.ir.util.referenceFunction @@ -61,7 +61,12 @@ class SerializerForEnumsGenerator( compilerContext.builtIns.array.getFuncDesc("get").single() val arrayGetSymbol = compilerContext.symbolTable.referenceFunction(arrayGet) val getValueByOrdinal = - irInvoke(getValues, arrayGetSymbol, irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter)) + irInvoke( + getValues, + arrayGetSymbol, + irInvoke(irGet(loadFunc.valueParameters[0]), decode, serialDescGetter), + typeHint = serializableIrClass.defaultType + ) +irReturn(getValueByOrdinal) } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt index 0bc31675b79..e035c8c6bd5 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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.kotlinx.serialization.compiler.resolve @@ -460,7 +449,7 @@ object KSerializerDescriptorResolver { declaresDefaultValue = false, isCrossinline = false, isNoinline = false, - varargElementType = serializerClass.defaultType, + varargElementType = kSerializerStarType, source = f.source )