Fix UnsafeNumber being applied incorrectly in hierarchical commonization

^KT-64376
This commit is contained in:
Timofey Solonin
2023-12-21 21:25:57 +01:00
committed by Space Team
parent 3c03e388d2
commit 0aa7b6f6ad
3 changed files with 26 additions and 17 deletions
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.commonizer.utils.*
private typealias BitWidth = Int private typealias BitWidth = Int
private class SubstitutableNumbers(private val numbers: Map<CirEntityId, BitWidth>) { private class SubstitutableNumbers(val numbers: Map<CirEntityId, BitWidth>) {
operator fun contains(id: CirEntityId) = id in numbers operator fun contains(id: CirEntityId) = id in numbers
fun choose(first: CirClassType, second: CirClassType): CirClassType? { fun choose(first: CirClassType, second: CirClassType): CirClassType? {
val firstBitWidth = numbers[first.classifierId] ?: return null val firstBitWidth = numbers[first.classifierId] ?: return null
@@ -71,14 +71,21 @@ private val floatingPointVars = SubstitutableNumbers(
) )
internal object OptimisticNumbersTypeCommonizer : AssociativeCommonizer<CirClassType> { internal object OptimisticNumbersTypeCommonizer : AssociativeCommonizer<CirClassType> {
override fun commonize(first: CirClassType, second: CirClassType): CirClassType? { private val commonizableNumberTypes = listOf(
val result = signedIntegers.choose(first, second) signedIntegers,
?: unsignedIntegers.choose(first, second) unsignedIntegers,
?: floatingPoints.choose(first, second) floatingPoints,
?: signedVarIntegers.choose(first, second) signedVarIntegers,
?: unsignedVarIntegers.choose(first, second) unsignedVarIntegers,
?: floatingPointVars.choose(first, second) floatingPointVars,
)
private val commonizableNumberIdentifiers = commonizableNumberTypes.flatMap { it.numbers.keys }.toSet()
fun isOptimisticallyCommonizableNumber(identifier: CirEntityId): Boolean = identifier in commonizableNumberIdentifiers
override fun commonize(first: CirClassType, second: CirClassType): CirClassType? {
val result = commonizableNumberTypes.firstNotNullOfOrNull { it.choose(first, second) }
return result?.withMarker() return result?.withMarker()
} }
@@ -52,23 +52,26 @@ private fun shouldCreateAnnotation(
if (!settings.getSetting(OptimisticNumberCommonizationEnabledKey)) if (!settings.getSetting(OptimisticNumberCommonizationEnabledKey))
return false return false
val annotatedInputDeclarationPresent = inputDeclarations.any { declaration -> val isDerivedFromOptimisticallyCommonizedType = inputDeclarations.any { declaration ->
declaration.annotations.any { annotation -> annotation is UnsafeNumberAnnotation } declaration.annotations.any { annotation -> annotation is UnsafeNumberAnnotation }
} }
if (annotatedInputDeclarationPresent) var isOptimisticallyCommonizedType = false
return true var isOptimisticallyCommonizableNumberType = false
var isMarkedTypeFound = false
commonizedType.accept(object : BasicCirTypeVisitor() { commonizedType.accept(object : BasicCirTypeVisitor() {
override fun visit(classType: CirClassType) { override fun visit(classType: CirClassType) {
classType.getAttachment<OptimisticNumbersTypeCommonizer.OptimisticCommonizationMarker>()?.let { isMarkedTypeFound = true } if (classType.getAttachment<OptimisticNumbersTypeCommonizer.OptimisticCommonizationMarker>() != null) {
?: super.visit(classType) isOptimisticallyCommonizedType = true
}
if (OptimisticNumbersTypeCommonizer.isOptimisticallyCommonizableNumber(classType.classifierId)) {
isOptimisticallyCommonizableNumberType = true
}
super.visit(classType)
} }
}) })
return isMarkedTypeFound return isOptimisticallyCommonizedType || (isDerivedFromOptimisticallyCommonizedType && isOptimisticallyCommonizableNumberType)
} }
private typealias RenderedType = String private typealias RenderedType = String
@@ -972,7 +972,6 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
result.assertCommonized( result.assertCommonized(
"(a, b, c)", """ "(a, b, c)", """
expect class X expect class X
@UnsafeNumber(["a: kotlin.Short", "b: kotlin.Int", "c: kotlin.Any"])
expect fun foo(x: X): X expect fun foo(x: X): X
""".trimIndent() """.trimIndent()
) )