diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt index 522f9f4a2e8..d413f600294 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -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, 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: - // 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: + // 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() + } + } + } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt index 5a068d98c88..891acadd45e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/IrTypeMapper.kt @@ -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, sw: JvmSignatureWriter) = - kotlinTypeMapper.writeFormalTypeParameters(irParameters.map { it.descriptor }, sw) + fun writeFormalTypeParameters(irParameters: List, 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) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt index eb37436c026..dac3ac9e7a7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/IrTypeSystemContext.kt @@ -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 { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt index 60b8b6301bf..128d8d5d7f8 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeSystemCommonBackendContext.kt @@ -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 } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt index 0fea35e7755..055441d7bde 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/checker/ClassicTypeSystemContext.kt @@ -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 {