From da1eb5d96e32344932f055980b1eee9c0306c462 Mon Sep 17 00:00:00 2001 From: "sebastian.sellmair" Date: Thu, 16 Sep 2021 12:50:37 +0200 Subject: [PATCH] [Commonizer] Implement CirTypeDistance.penalty ^KT-48288 --- .../core/ClassOrTypeAliasTypeCommonizer.kt | 21 ++++--------------- .../commonizer/mergedtree/CirTypeDistance.kt | 21 +++++++++++++++++-- .../kotlin/commonizer/CirTypeDistanceTest.kt | 16 +++++++++++++- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt index ec750342c02..fa2d01210c2 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt @@ -114,7 +114,7 @@ internal class ClassOrTypeAliasTypeCommonizer( } val resolvedClassifierFromDependencies = classifiers.commonDependencies.classifier(destinationClassifierId) - ?: classifiers.targetDependencies[targetIndex].classifier(destinationClassifierId) + ?: classifiers.targetDependencies[targetIndex].classifier(destinationClassifierId) // necessary? if (resolvedClassifierFromDependencies != null && resolvedClassifierFromDependencies is CirProvided.TypeAlias) { return backwardsSubstitute(targetIndex, sourceType, destinationClassifierId, resolvedClassifierFromDependencies) @@ -201,20 +201,14 @@ internal class ClassOrTypeAliasTypeCommonizer( val typeSubstitutionCandidates = resolveTypeSubstitutionCandidates(classifiers, commonId, types) .filter { typeSubstitutionCandidate -> + assert(typeSubstitutionCandidate.typeDistance.isZero.not()) { "Expected no zero typeDistance" } if (typeSubstitutionCandidate.typeDistance.isNotReachable) return@filter false if (typeSubstitutionCandidate.typeDistance.isNegative && !backwardsSubstitutionAllowed) return@filter false if (typeSubstitutionCandidate.typeDistance.isPositive && !forwardSubstitutionAllowed) return@filter false true } - if (typeSubstitutionCandidates.isEmpty()) return null - if (typeSubstitutionCandidates.size == 1) return typeSubstitutionCandidates.first().id - - val forwardSubstitutionCandidates = typeSubstitutionCandidates.filter { it.typeDistance.isPositive } - val backwardsSubstitutionCandidates = typeSubstitutionCandidates.filter { it.typeDistance.isNegative } - - return forwardSubstitutionCandidates.minByOrNull { it.typeDistance }?.id - ?: backwardsSubstitutionCandidates.maxByOrNull { it.typeDistance }?.id + return typeSubstitutionCandidates.minByOrNull { it.typeDistance.penalty }?.id } } @@ -231,14 +225,7 @@ private fun resolveTypeSubstitutionCandidates( if (typeDistances.any { it.isNotReachable }) return@mapCandidateId null TypeSubstitutionCandidate( id = candidateId, - typeDistance = checkNotNull(typeDistances.worstOrNull()) + typeDistance = checkNotNull(typeDistances.maxByOrNull { it.penalty }) ) } } - -private fun List.worstOrNull(): CirTypeDistance? { - if (this.isEmpty()) return null - // Negative Type Distances are considered 'worse' - filter { it.isNegative }.minOrNull()?.let { return it } - return maxOrNull() -} \ No newline at end of file diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeDistance.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeDistance.kt index 09af4a6ead5..0ac5e1c7c02 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeDistance.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/mergedtree/CirTypeDistance.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.commonizer.mergedtree import org.jetbrains.kotlin.commonizer.CommonizerTarget import org.jetbrains.kotlin.commonizer.cir.* import org.jetbrains.kotlin.commonizer.mergedtree.CirTypeDistance.Companion.unreachable -import kotlin.math.absoluteValue @JvmInline value class CirTypeDistance(private val value: Int) : Comparable { @@ -23,7 +22,25 @@ value class CirTypeDistance(private val value: Int) : Comparable Int.MAX_VALUE + isNegative -> -value + isZero -> Int.MIN_VALUE + isPositive -> Int.MIN_VALUE + value + else -> throw IllegalStateException("Unable to calculate penalty for $this") + } operator fun plus(value: Int) = if (isReachable) CirTypeDistance(this.value + value) else this diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CirTypeDistanceTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CirTypeDistanceTest.kt index 83e1970ce30..99943a435c5 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CirTypeDistanceTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/CirTypeDistanceTest.kt @@ -308,9 +308,23 @@ class CirTypeDistanceTest : KtInlineSourceCommonizerTestCase() { assertUnreachable(CirTypeDistance.unreachable.dec()) assertUnreachable(CirTypeDistance.unreachable - CirTypeDistance(1)) assertUnreachable(CirTypeDistance(1) - CirTypeDistance.unreachable) - assertUnreachable(CirTypeDistance.unreachable.absoluteValue) assertEquals(CirTypeDistance(Int.MAX_VALUE), CirTypeDistance.unreachable) } + + fun `test penalty`() { + assertEquals(1, CirTypeDistance(-1).penalty) + assertEquals(2, CirTypeDistance(-2).penalty) + assertEquals(Int.MIN_VALUE, CirTypeDistance(0).penalty) + assertEquals(Int.MAX_VALUE, CirTypeDistance.unreachable.penalty) + assertEquals(Int.MIN_VALUE + 1, CirTypeDistance(1).penalty) + assertEquals(Int.MIN_VALUE + 2, CirTypeDistance(2).penalty) + assertTrue(CirTypeDistance(-1).penalty > CirTypeDistance(1).penalty) + assertTrue(CirTypeDistance(-1).penalty > CirTypeDistance(10).penalty) + assertTrue(CirTypeDistance(2).penalty > CirTypeDistance(1).penalty) + assertTrue(CirTypeDistance(-2).penalty > CirTypeDistance(-1).penalty) + assertTrue(CirTypeDistance(1).penalty > CirTypeDistance(0).penalty) + assertTrue(CirTypeDistance(-1).penalty > CirTypeDistance(0).penalty) + } } private fun assertUnreachable(typeDistance: CirTypeDistance) {