JVM IR: do not use descriptors in IrTypeMapper.writeFormalTypeParameters

This commit is contained in:
Alexander Udalov
2019-08-06 06:00:15 +02:00
parent 598c6009f2
commit 0c6ab69b52
5 changed files with 80 additions and 43 deletions
@@ -55,7 +55,10 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -967,47 +970,13 @@ class KotlinTypeMapper @JvmOverloads constructor(
fun writeFormalTypeParameters(typeParameters: List<TypeParameterDescriptor>, sw: JvmSignatureWriter) {
if (sw.skipGenericSignature()) return
for (typeParameter in typeParameters) {
writeFormalTypeParameter(typeParameter, sw)
}
}
private fun writeFormalTypeParameter(typeParameterDescriptor: TypeParameterDescriptor, sw: JvmSignatureWriter) {
if (!classBuilderMode.generateBodies && typeParameterDescriptor.name.isSpecial) {
// If a type parameter has no name, the code below fails, but it should recover in case of light classes
return
}
sw.writeFormalTypeParameter(typeParameterDescriptor.name.asString())
sw.writeClassBound()
for (type in typeParameterDescriptor.upperBounds) {
if (type.constructor.declarationDescriptor is ClassDescriptor && !isJvmInterface(type)) {
mapType(type, sw, TypeMappingMode.GENERIC_ARGUMENT)
break
if (!classBuilderMode.generateBodies && typeParameter.name.isSpecial) {
// If a type parameter has no name, the code below fails, but it should recover in case of light classes
continue
}
}
// "extends Object" is optional according to ClassFileFormat-Java5.pdf
// but javac complaints to signature:
// <P:>Ljava/lang/Object;
// TODO: avoid writing java/lang/Object if interface list is not empty
sw.writeClassBoundEnd()
for (type in typeParameterDescriptor.upperBounds) {
when (val classifier = type.constructor.declarationDescriptor) {
is ClassDescriptor -> if (isJvmInterface(type)) {
sw.writeInterfaceBound()
mapType(type, sw, TypeMappingMode.GENERIC_ARGUMENT)
sw.writeInterfaceBoundEnd()
}
is TypeParameterDescriptor -> {
sw.writeInterfaceBound()
mapType(type, sw, TypeMappingMode.GENERIC_ARGUMENT)
sw.writeInterfaceBoundEnd()
}
else -> throw UnsupportedOperationException("Unknown classifier: $classifier")
SimpleClassicTypeSystemContext.writeFormalTypeParameter(typeParameter, sw) { type, mode ->
mapType(type as KotlinType, sw, mode)
}
}
}
@@ -1661,5 +1630,40 @@ class KotlinTypeMapper @JvmOverloads constructor(
sw.writeAsmType(type)
sw.writeParameterTypeEnd()
}
@JvmStatic
fun TypeSystemCommonBackendContext.writeFormalTypeParameter(
typeParameter: TypeParameterMarker,
sw: JvmSignatureWriter,
mapType: (KotlinTypeMarker, TypeMappingMode) -> Type
) {
sw.writeFormalTypeParameter(typeParameter.getName().asString())
sw.writeClassBound()
for (i in 0 until typeParameter.upperBoundCount()) {
val type = typeParameter.getUpperBound(i)
if (type.typeConstructor().getTypeParameterClassifier() == null && !type.isInterfaceOrAnnotationClass()) {
mapType(type, TypeMappingMode.GENERIC_ARGUMENT)
break
}
}
// "extends Object" is optional according to ClassFileFormat-Java5.pdf
// but javac complaints to signature:
// <P:>Ljava/lang/Object;
// TODO: avoid writing java/lang/Object if interface list is not empty
sw.writeClassBoundEnd()
for (i in 0 until typeParameter.upperBoundCount()) {
val type = typeParameter.getUpperBound(i)
if (type.typeConstructor().getTypeParameterClassifier() != null || type.isInterfaceOrAnnotationClass()) {
sw.writeInterfaceBound()
mapType(type, TypeMappingMode.GENERIC_ARGUMENT)
sw.writeInterfaceBoundEnd()
}
}
}
}
}
@@ -42,8 +42,16 @@ class IrTypeMapper(private val context: JvmBackendContext) {
context.getLocalClassInfo(irClass)?.internalName
?: JvmCodegenUtil.sanitizeNameIfNeeded(computeInternalName(irClass), context.state.languageVersionSettings)
fun writeFormalTypeParameters(irParameters: List<IrTypeParameter>, sw: JvmSignatureWriter) =
kotlinTypeMapper.writeFormalTypeParameters(irParameters.map { it.descriptor }, sw)
fun writeFormalTypeParameters(irParameters: List<IrTypeParameter>, sw: JvmSignatureWriter) {
if (sw.skipGenericSignature()) return
with(KotlinTypeMapper) {
for (typeParameter in irParameters) {
typeSystem.writeFormalTypeParameter(typeParameter.symbol, sw) { type, mode ->
mapType(type as IrType, mode, sw)
}
}
}
}
fun boxType(irType: IrType): Type =
AsmUtil.boxType(mapType(irType), irType.toKotlinType(), kotlinTypeMapper)
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.Variance
@@ -325,6 +326,14 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
override fun TypeConstructorMarker.getClassFqNameUnsafe(): FqNameUnsafe? =
(this as IrClassSymbol).owner.fqNameWhenAvailable?.toUnsafe()
override fun TypeParameterMarker.getName(): Name =
(this as IrTypeParameterSymbol).owner.name
override fun KotlinTypeMarker.isInterfaceOrAnnotationClass(): Boolean {
val irClass = (this as IrType).classOrNull?.owner
return irClass != null && (irClass.isInterface || irClass.isAnnotationClass)
}
}
fun extractTypeParameters(klass: IrDeclarationParent): List<IrTypeParameter> {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.types
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.model.*
interface TypeSystemCommonBackendContext : TypeSystemContext {
@@ -41,4 +42,8 @@ interface TypeSystemCommonBackendContext : TypeSystemContext {
fun TypeConstructorMarker.isUnderKotlinPackage(): Boolean
fun TypeConstructorMarker.getClassFqNameUnsafe(): FqNameUnsafe?
fun TypeParameterMarker.getName(): Name
fun KotlinTypeMarker.isInterfaceOrAnnotationClass(): Boolean
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
@@ -27,7 +28,6 @@ import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.math.max
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
override fun TypeConstructorMarker.isDenotable(): Boolean {
@@ -541,6 +541,17 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
require(this is TypeConstructor, this::errorMessage)
return (declarationDescriptor as ClassDescriptor).fqNameUnsafe
}
override fun TypeParameterMarker.getName(): Name {
require(this is TypeParameterDescriptor, this::errorMessage)
return name
}
override fun KotlinTypeMarker.isInterfaceOrAnnotationClass(): Boolean {
require(this is KotlinType, this::errorMessage)
val descriptor = constructor.declarationDescriptor
return descriptor is ClassDescriptor && (descriptor.kind == ClassKind.INTERFACE || descriptor.kind == ClassKind.ANNOTATION_CLASS)
}
}
fun TypeVariance.convertVariance(): Variance {