From ab550196e9cdc9ed6d21dc0f476f63c4f1c8a2e3 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 2 Oct 2018 16:51:09 +0200 Subject: [PATCH] Do not depend on ReflectionTypes from upstream Kotlin ReflectionTypes was incorrectly copied to common backend in https://github.com/JetBrains/kotlin/commit/27365dc4bed8833880dc7bd0fc0189fed5ff6fed. In fact, the copied class references `kProperty*Impl` types which are only available in kotlin-native's runtime [1], thus using them in the common Kotlin would lead to all kinds of confusion. The next step is to remove ReflectionTypes in the main Kotlin project (will be done later), remove the unneeded override Context.reflectionTypes, and rename reflectionTypes0 -> reflectionTypes. [1] Types with the same name are also declared in kotlin-reflect, but the JVM backend still can't reference them because generated JVM bytecode can only depend on kotlin-stdlib --- .../jetbrains/kotlin/backend/konan/Context.kt | 12 +++-- .../backend/konan/KonanReflectionTypes.kt | 50 +++++++++++++++++++ .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 22 ++++---- .../backend/konan/lower/DelegationLowering.kt | 7 ++- 4 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanReflectionTypes.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 5db029669de..22d428755cb 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.konan import llvm.LLVMDumpModule import llvm.LLVMModuleRef import org.jetbrains.kotlin.backend.common.DumpIrTreeWithDescriptorsVisitor -import org.jetbrains.kotlin.backend.common.ReflectionTypes import org.jetbrains.kotlin.backend.common.validateIrModule import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.ir.KonanIr @@ -49,7 +48,6 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.serialization.deserialization.getName -import org.jetbrains.kotlin.types.KotlinType import java.lang.System.out import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.reflect.KProperty @@ -309,9 +307,15 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { fun getValue(member: LazyMember): T = @Suppress("UNCHECKED_CAST") (lazyValues.getOrPut(member, { member.initializer(this) }) as T) - override val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) { - ReflectionTypes(moduleDescriptor, KonanFqNames.internalPackageName) + @Deprecated("Use reflectionTypes0 instead.", ReplaceWith("this.reflectionTypes0")) + override val reflectionTypes: org.jetbrains.kotlin.backend.common.ReflectionTypes + get() = throw UnsupportedOperationException("This method will be removed soon") + + // TODO: rename to reflectionTypes after updating the Kotlin compiler + val reflectionTypes0: KonanReflectionTypes by lazy(PUBLICATION) { + KonanReflectionTypes(moduleDescriptor, KonanFqNames.internalPackageName) } + private val vtableBuilders = mutableMapOf() fun getVtableBuilder(classDescriptor: IrClass) = vtableBuilders.getOrPut(classDescriptor) { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanReflectionTypes.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanReflectionTypes.kt new file mode 100644 index 00000000000..9ae2584ac4a --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/KonanReflectionTypes.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package org.jetbrains.kotlin.backend.konan + +import org.jetbrains.kotlin.builtins.KOTLIN_REFLECT_FQ_NAME +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import kotlin.reflect.KProperty + +class KonanReflectionTypes(module: ModuleDescriptor, internalPackage: FqName) { + + private val kotlinReflectScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { + module.getPackage(KOTLIN_REFLECT_FQ_NAME).memberScope + } + + private val internalScope: MemberScope by lazy(LazyThreadSafetyMode.PUBLICATION) { + module.getPackage(internalPackage).memberScope + } + + private fun find(memberScope: MemberScope, className: String): ClassDescriptor { + val name = Name.identifier(className) + return memberScope.getContributedClassifier(name, NoLookupLocation.FROM_REFLECTION) as ClassDescriptor + } + + private class ClassLookup(val memberScope: MemberScope) { + operator fun getValue(types: KonanReflectionTypes, property: KProperty<*>): ClassDescriptor { + return types.find(memberScope, property.name.capitalize()) + } + } + + fun getKFunction(n: Int): ClassDescriptor = find(kotlinReflectScope, "KFunction$n") + + val kProperty0: ClassDescriptor by ClassLookup(kotlinReflectScope) + val kFunctionImpl: ClassDescriptor by ClassLookup(internalScope) + val kProperty0Impl: ClassDescriptor by ClassLookup(internalScope) + val kProperty1Impl: ClassDescriptor by ClassLookup(internalScope) + val kProperty2Impl: ClassDescriptor by ClassLookup(internalScope) + val kMutableProperty0Impl: ClassDescriptor by ClassLookup(internalScope) + val kMutableProperty1Impl: ClassDescriptor by ClassLookup(internalScope) + val kMutableProperty2Impl: ClassDescriptor by ClassLookup(internalScope) + val kLocalDelegatedPropertyImpl: ClassDescriptor by ClassLookup(internalScope) + val kLocalDelegatedMutablePropertyImpl: ClassDescriptor by ClassLookup(internalScope) +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 0aac107c07c..77b27eebc9e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -414,23 +414,23 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val val isInitializedPropertyDescriptor = builtInsPackage("kotlin") .getContributedVariables(Name.identifier("isInitialized"), NoLookupLocation.FROM_BACKEND).single { it.extensionReceiverParameter.let { - it != null && TypeUtils.getClassDescriptor(it.type) == context.reflectionTypes.kProperty0 + it != null && TypeUtils.getClassDescriptor(it.type) == context.reflectionTypes0.kProperty0 } && !it.isExpect } val isInitializedGetterDescriptor = isInitializedPropertyDescriptor.getter!! - val kFunctionImpl = symbolTable.referenceClass(context.reflectionTypes.kFunctionImpl) + val kFunctionImpl = symbolTable.referenceClass(context.reflectionTypes0.kFunctionImpl) - val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl) - val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl) - val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl) - val kMutableProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0Impl) - val kMutableProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1Impl) - val kMutableProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty2Impl) + val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes0.kProperty0Impl) + val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes0.kProperty1Impl) + val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes0.kProperty2Impl) + val kMutableProperty0Impl = symbolTable.referenceClass(context.reflectionTypes0.kMutableProperty0Impl) + val kMutableProperty1Impl = symbolTable.referenceClass(context.reflectionTypes0.kMutableProperty1Impl) + val kMutableProperty2Impl = symbolTable.referenceClass(context.reflectionTypes0.kMutableProperty2Impl) - val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl) - val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl) + val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes0.kLocalDelegatedPropertyImpl) + val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes0.kLocalDelegatedMutablePropertyImpl) val getClassTypeInfo = internalFunction("getClassTypeInfo") val getObjectTypeInfo = internalFunction("getObjectTypeInfo") @@ -471,7 +471,7 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val .map { symbolTable.referenceClass(builtIns.getFunction(it)) } val kFunctions = (0 .. KONAN_FUNCTION_INTERFACES_MAX_PARAMETERS) - .map { symbolTable.referenceClass(context.reflectionTypes.getKFunction(it)) } + .map { symbolTable.referenceClass(context.reflectionTypes0.getKFunction(it)) } fun getKFunctionType(returnType: IrType, parameterTypes: List): IrType { val kFunctionClassSymbol = kFunctions[parameterTypes.size] diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt index 1f153e07139..9d64a524fbc 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DelegationLowering.kt @@ -47,7 +47,6 @@ import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.replace internal class PropertyDelegationLowering(val context: KonanBackendContext) : FileLoweringPass { - private val reflectionTypes = context.reflectionTypes private var tempIndex = 0 private fun getKPropertyImplConstructor(receiverTypes: List, @@ -300,9 +299,9 @@ internal class PropertyDelegationLowering(val context: KonanBackendContext) : Fi val arguments = type.arguments val expectedClassDescriptor = when (arguments.size) { 0 -> return false - 1 -> reflectionTypes.kMutableProperty0 - 2 -> reflectionTypes.kMutableProperty1 - 3 -> reflectionTypes.kMutableProperty2 + 1 -> context.reflectionTypes0.kMutableProperty0 + 2 -> context.reflectionTypes0.kMutableProperty1 + 3 -> context.reflectionTypes0.kMutableProperty2 else -> throw AssertionError("More than 2 receivers is not allowed") } return type == expectedClassDescriptor.defaultType.replace(arguments)