From 6793b27330e1ebdeb348d209347becef1c8a2416 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 19 Feb 2020 11:13:06 +0300 Subject: [PATCH] FIR: Optimize Java types mapping - Avoid duplicated computations for arguments - Do not recreate types if they weren't enhanced --- .../jetbrains/kotlin/fir/java/JavaUtils.kt | 28 ++++++++++++------- .../fir/java/enhancement/javaTypeUtils.kt | 15 ++++++++-- .../jetbrains/kotlin/fir/types/TypeUtils.kt | 2 +- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt index 275367b3e12..3d32cd0244b 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt @@ -96,12 +96,11 @@ internal fun JavaClassifierType.toFirResolvedTypeRef( forTypeParameterBounds: Boolean ): FirResolvedTypeRef { val coneType = - this.toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forTypeParameterBounds).run { - if (isForSupertypes) - this.lowerBoundIfFlexible() - else - this - } + if (isForSupertypes) + toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, isLowerBound = true, forTypeParameterBounds) + else + toConeKotlinTypeWithoutEnhancement(session, javaTypeParameterStack, forTypeParameterBounds) + return buildResolvedTypeRef { type = coneType this@toFirResolvedTypeRef.annotations.mapTo(annotations) { it.toFirAnnotationCall(session, javaTypeParameterStack) } @@ -166,7 +165,10 @@ private fun JavaClassifierType.toConeKotlinTypeWithoutEnhancement( forTypeParameterBounds: Boolean = false ): ConeKotlinType { val lowerBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, isLowerBound = true, forTypeParameterBounds) - val upperBound = toConeKotlinTypeForFlexibleBound(session, javaTypeParameterStack, isLowerBound = false, forTypeParameterBounds) + val upperBound = + toConeKotlinTypeForFlexibleBound( + session, javaTypeParameterStack, isLowerBound = false, forTypeParameterBounds, lowerBound + ) return if (isRaw) ConeRawType(lowerBound, upperBound) else ConeFlexibleType(lowerBound, upperBound) } @@ -263,8 +265,9 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound( session: FirSession, javaTypeParameterStack: JavaTypeParameterStack, isLowerBound: Boolean, - forTypeParameterBounds: Boolean -): ConeKotlinType { + forTypeParameterBounds: Boolean, + lowerBound: ConeLookupTagBasedType? = null +): ConeLookupTagBasedType { return when (val classifier = classifier) { is JavaClass -> { //val classId = classifier.classId!! @@ -275,6 +278,11 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound( } val lookupTag = ConeClassLikeLookupTagImpl(classId) + if (!isLowerBound && !isRaw && lookupTag == lowerBound?.lookupTag) { + return lookupTag.constructClassType( + lowerBound.typeArguments, isNullable = true + ) + } val mappedTypeArguments = if (isRaw) { @@ -306,7 +314,7 @@ private fun JavaClassifierType.toConeKotlinTypeForFlexibleBound( val symbol = javaTypeParameterStack[classifier] ConeTypeParameterTypeImpl(symbol.toLookupTag(), isNullable = !isLowerBound) } - else -> ConeClassErrorType(reason = "Unexpected classifier: $classifier") + else -> ConeKotlinErrorType("Unexpected classifier: $classifier") } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt index 44772fed3fd..64320075053 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/enhancement/javaTypeUtils.kt @@ -91,8 +91,9 @@ private fun ConeKotlinType.enhanceConeKotlinType( session, TypeComponentPosition.FLEXIBLE_UPPER, qualifiers, index ) - when (this) { - is ConeRawType -> ConeRawType(lowerResult, upperResult) + when { + lowerResult === lowerBound && upperResult === upperBound -> this + this is ConeRawType -> ConeRawType(lowerResult, upperResult) else -> coneFlexibleOrSimpleType( session, lowerResult, upperResult, isNotNullTypeParameter = qualifiers(index).isNotNullTypeParameter ) @@ -165,6 +166,8 @@ private fun ConeKotlinType.enhanceInflexibleType( val effectiveQualifiers = qualifiers(index) val enhancedTag = originalTag.enhanceMutability(effectiveQualifiers, position) + var wereChangesInArgs = false + val enhancedArguments = if (this is RawType) { // TODO: Support enhancing for raw types typeArguments @@ -178,13 +181,19 @@ private fun ConeKotlinType.enhanceInflexibleType( require(arg is ConeKotlinType) { "Should be invariant type: $arg" } globalArgIndex += arg.subtreeSize() - arg.enhanceConeKotlinType(session, qualifiers, globalArgIndex) + arg.enhanceConeKotlinType(session, qualifiers, globalArgIndex).also { + if (it !== arg) { + wereChangesInArgs = true + } + } } }.toTypedArray() } val enhancedNullability = getEnhancedNullability(effectiveQualifiers, position) + if (!wereChangesInArgs && originalTag == enhancedTag && enhancedNullability == isNullable) return this + val enhancedType = enhancedTag.constructType(enhancedArguments, enhancedNullability) // TODO: why all of these is needed diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 1c6d8c4910c..7ced10bbfd7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -185,7 +185,7 @@ fun ConeKotlinType.toTypeProjection(variance: Variance): ConeKotlinTypeProjectio fun ConeClassLikeLookupTag.constructClassType( typeArguments: Array, isNullable: Boolean, -): ConeLookupTagBasedType { +): ConeClassLikeType { return ConeClassLikeTypeImpl(this, typeArguments, isNullable) }