From b343d05e14985539c9794be3d123348d0224f032 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 23 Sep 2020 17:07:55 +0300 Subject: [PATCH] [FIR] Implement JvmTypeMapper based on cone types --- .../kotlin/fir/symbols/StandardClassIds.kt | 9 ++ .../fir/fir2ir/jvm-backend/build.gradle.kts | 1 + .../fir/backend/jvm/FirJvmTypeMapper.kt | 118 ++++++++++++++++++ .../fir/resolve/inference/InferenceUtils.kt | 6 + 4 files changed, 134 insertions(+) create mode 100644 compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt index e0a900d4ef7..0ea08f5a9c6 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.symbols +import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -74,6 +75,14 @@ object StandardClassIds { val unsignedTypes = listOf(UByte, UShort, UInt, ULong) val unsignedArrayTypeByElementType = unsignedTypes.associate { id -> id to id.shortClassName.primitiveArrayId() } val elementTypeByUnsignedArrayType = unsignedArrayTypeByElementType.inverseMap() + + val Continuation = + ClassId(StandardNames.COROUTINES_PACKAGE_FQ_NAME_RELEASE, StandardNames.CONTINUATION_INTERFACE_FQ_NAME_RELEASE.shortName()) + + @Suppress("FunctionName") + fun FunctionN(n: Int): ClassId { + return "Function$n".baseId() + } } private fun Map.inverseMap() = entries.associate { (k, v) -> v to k } diff --git a/compiler/fir/fir2ir/jvm-backend/build.gradle.kts b/compiler/fir/fir2ir/jvm-backend/build.gradle.kts index 851eafc6a25..a3235acadec 100644 --- a/compiler/fir/fir2ir/jvm-backend/build.gradle.kts +++ b/compiler/fir/fir2ir/jvm-backend/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { compileOnly(project(":core:descriptors")) + compileOnly(project(":core:compiler.backend.common.jvm")) compileOnly(project(":compiler:fir:cones")) compileOnly(project(":compiler:fir:resolve")) compileOnly(project(":compiler:fir:jvm")) 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 new file mode 100644 index 00000000000..c1690f7fdec --- /dev/null +++ b/compiler/fir/fir2ir/jvm-backend/src/org/jetbrains/kotlin/fir/backend/jvm/FirJvmTypeMapper.kt @@ -0,0 +1,118 @@ +/* + * 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.descriptors.ClassKind +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSessionComponent +import org.jetbrains.kotlin.fir.resolve.defaultType +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.resolve.inference.isKClassType +import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType +import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag +import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag +import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag +import org.jetbrains.kotlin.fir.symbols.StandardClassIds +import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl +import org.jetbrains.kotlin.load.kotlin.JvmDescriptorTypeWriter +import org.jetbrains.kotlin.load.kotlin.TypeMappingMode +import org.jetbrains.kotlin.types.AbstractTypeMapper +import org.jetbrains.kotlin.types.TypeMappingContext +import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext +import org.jetbrains.kotlin.types.TypeSystemCommonBackendContextForTypeMapping +import org.jetbrains.kotlin.types.model.KotlinTypeMarker +import org.jetbrains.kotlin.types.model.SimpleTypeMarker +import org.jetbrains.kotlin.types.model.TypeConstructorMarker +import org.jetbrains.kotlin.types.model.TypeParameterMarker +import org.jetbrains.org.objectweb.asm.Type + +class FirJvmTypeMapper(val session: FirSession) : TypeMappingContext>, FirSessionComponent { + override val typeContext = ConeTypeSystemCommonBackendContextForTypeMapping(session.typeContext) + + fun mapType(type: ConeKotlinType, mode: TypeMappingMode = TypeMappingMode.DEFAULT): Type { + return AbstractTypeMapper.mapType(this, type, mode) + } + + override fun getClassInternalName(typeConstructor: TypeConstructorMarker): String { + require(typeConstructor is ConeClassLikeLookupTag) + return typeConstructor.classId.asString().replace(".", "$").replace("/", ".") + } + + override fun JvmDescriptorTypeWriter.writeGenericType(type: SimpleTypeMarker, asmType: Type, mode: TypeMappingMode) { + error("Should not be called") + } +} + +val FirSession.jvmTypeMapper: FirJvmTypeMapper by FirSession.sessionComponentAccessor() + +class ConeTypeSystemCommonBackendContextForTypeMapping( + val context: ConeTypeContext +) : TypeSystemCommonBackendContext by context, TypeSystemCommonBackendContextForTypeMapping { + private val symbolProvider = context.session.firSymbolProvider + + override fun TypeConstructorMarker.isTypeParameter(): Boolean { + return this is ConeTypeParameterLookupTag + } + + override fun TypeConstructorMarker.defaultType(): ConeSimpleKotlinType { + require(this is ConeClassifierLookupTag) + return when (this) { + is ConeTypeParameterLookupTag -> ConeTypeParameterTypeImpl(this, isNullable = false) + is ConeClassLikeLookupTag -> { + val symbol = symbolProvider.getClassLikeSymbolByFqName(classId) as? FirRegularClassSymbol + ?: error("Class for $this not found") + symbol.fir.defaultType() + } + else -> error("Unsupported type constructor: $this") + } + } + + override fun SimpleTypeMarker.isSuspendFunction(): Boolean { + require(this is ConeSimpleKotlinType) + return isSuspendFunctionType(context.session) + } + + override fun SimpleTypeMarker.isKClass(): Boolean { + require(this is ConeSimpleKotlinType) + return isKClassType() + } + + override fun KotlinTypeMarker.isRawType(): Boolean { + return this is ConeRawType + } + + override fun TypeConstructorMarker.typeWithArguments(arguments: List): ConeSimpleKotlinType { + arguments.forEach { + require(it is ConeKotlinType) + } + @Suppress("UNCHECKED_CAST") + return defaultType().withArguments((arguments as List).toTypedArray()) + } + + override fun TypeParameterMarker.representativeUpperBound(): ConeKotlinType { + 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 kind = classSymbol.fir.classKind + kind != ClassKind.INTERFACE && kind != ClassKind.ANNOTATION_CLASS + } ?: bounds.first() + } + + override fun continuationTypeConstructor(): ConeClassLikeLookupTag { + return symbolProvider.getClassLikeSymbolByFqName(StandardClassIds.Continuation)?.toLookupTag() + ?: error("Continuation class not found") + } + + override fun functionNTypeConstructor(n: Int): TypeConstructorMarker { + return symbolProvider.getClassLikeSymbolByFqName(StandardClassIds.FunctionN(n))?.toLookupTag() + ?: error("Function$n class not found") + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt index 4c0375a37b9..49a045efae4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceUtils.kt @@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.typeContext +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.name.ClassId @@ -121,6 +123,10 @@ fun ConeKotlinType.findContributedInvokeSymbol( return if (overriddenInvoke != null) declaredInvoke else null } +fun ConeKotlinType.isKClassType(): Boolean { + return classId == StandardClassIds.KClass +} + fun ConeKotlinType.receiverType(expectedTypeRef: FirTypeRef?, session: FirSession): ConeKotlinType? { if (isBuiltinFunctionalType(session) && isExtensionFunctionType(session)) { return (this.fullyExpandedType(session).typeArguments.first() as ConeKotlinTypeProjection).type