From a3e3b43aed71fb83da9fd90e788f711d51e04783 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Thu, 10 Oct 2019 16:10:48 +0700 Subject: [PATCH] [Commonizer] Fix: approximate signatures with type parameter upper bounds --- .../commonizer/mergedtree/ir/CirType.kt | 4 +- .../kotlin/descriptors/commonizer/utils.kt | 55 +++++++++++++------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt index e51430c56ed..84709438904 100644 --- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt +++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CirType.kt @@ -47,8 +47,8 @@ class CirSimpleType(private val wrapped: SimpleType) : CirType() { val isDefinitelyNotNullType get() = abbreviation.isDefinitelyNotNullType val expandedTypeConstructorId by lazy(PUBLICATION) { CirTypeConstructorId(expanded) } - inline val isClassOrTypeAlias: Boolean get() = (kind == CLASS || kind == TYPE_ALIAS) - val fqNameWithTypeParameters: String get() = wrapped.fqNameWithTypeParameters + inline val isClassOrTypeAlias get() = (kind == CLASS || kind == TYPE_ALIAS) + val fqNameWithTypeParameters by lazy(PUBLICATION) { wrapped.fqNameWithTypeParameters } override fun equals(other: Any?) = wrapped == (other as? CirSimpleType)?.wrapped override fun hashCode() = wrapped.hashCode() diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt index 6db17a45bde..e0628149290 100644 --- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt +++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt @@ -11,7 +11,10 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeUtils.getTypeParameterDescriptorOrNull import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.types.isNullable +import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance internal fun Sequence.toList(expectedCapacity: Int): List { @@ -29,29 +32,49 @@ internal inline val KotlinType.fqName: FqName get() = declarationDescriptor.fqNameSafe internal val KotlinType.fqNameWithTypeParameters: String - get() = buildString { buildFqNameWithTypeParameters(this@fqNameWithTypeParameters) } + get() = buildString { buildFqNameWithTypeParameters(this@fqNameWithTypeParameters, HashSet()) } -private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType) { +private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType, exploredTypeParameters: MutableSet) { append(type.fqName) - val arguments = type.arguments - if (arguments.isNotEmpty()) { - append("<") - arguments.forEachIndexed { index, argument -> - if (index > 0) - append(",") + val typeParameterDescriptor = getTypeParameterDescriptorOrNull(type) + if (typeParameterDescriptor != null) { + // N.B this is type parameter type - if (argument.isStarProjection) - append("*") - else { - val variance = argument.projectionKind - if (variance != Variance.INVARIANT) - append(variance).append(" ") - buildFqNameWithTypeParameters(argument.type) + if (exploredTypeParameters.add(type.makeNotNullable())) { // print upper bounds once the first time when type parameter type is met + append(":[") + typeParameterDescriptor.upperBounds.forEachIndexed { index, upperBound -> + if (index > 0) + append(",") + buildFqNameWithTypeParameters(upperBound, exploredTypeParameters) } + append("]") + } + } else { + // N.B. this is classifier type + + val arguments = type.arguments + if (arguments.isNotEmpty()) { + append("<") + arguments.forEachIndexed { index, argument -> + if (index > 0) + append(",") + + if (argument.isStarProjection) + append("*") + else { + val variance = argument.projectionKind + if (variance != Variance.INVARIANT) + append(variance).append(" ") + buildFqNameWithTypeParameters(argument.type, exploredTypeParameters) + } + } + append(">") } - append(">") } + + if (type.isMarkedNullable) + append("?") } internal fun Any?.isNull(): Boolean = this == null