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 class SubstitutableNumbers(private val numbers: Map<CirEntityId, BitWidth>) {
private class SubstitutableNumbers(val numbers: Map<CirEntityId, BitWidth>) {
operator fun contains(id: CirEntityId) = id in numbers
fun choose(first: CirClassType, second: CirClassType): CirClassType? {
val firstBitWidth = numbers[first.classifierId] ?: return null
@@ -71,14 +71,21 @@ private val floatingPointVars = SubstitutableNumbers(
)
internal object OptimisticNumbersTypeCommonizer : AssociativeCommonizer<CirClassType> {
override fun commonize(first: CirClassType, second: CirClassType): CirClassType? {
val result = signedIntegers.choose(first, second)
?: unsignedIntegers.choose(first, second)
?: floatingPoints.choose(first, second)
?: signedVarIntegers.choose(first, second)
?: unsignedVarIntegers.choose(first, second)
?: floatingPointVars.choose(first, second)
private val commonizableNumberTypes = listOf(
signedIntegers,
unsignedIntegers,
floatingPoints,
signedVarIntegers,
unsignedVarIntegers,
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()
}
@@ -52,23 +52,26 @@ private fun shouldCreateAnnotation(
if (!settings.getSetting(OptimisticNumberCommonizationEnabledKey))
return false
val annotatedInputDeclarationPresent = inputDeclarations.any { declaration ->
val isDerivedFromOptimisticallyCommonizedType = inputDeclarations.any { declaration ->
declaration.annotations.any { annotation -> annotation is UnsafeNumberAnnotation }
}
if (annotatedInputDeclarationPresent)
return true
var isMarkedTypeFound = false
var isOptimisticallyCommonizedType = false
var isOptimisticallyCommonizableNumberType = false
commonizedType.accept(object : BasicCirTypeVisitor() {
override fun visit(classType: CirClassType) {
classType.getAttachment<OptimisticNumbersTypeCommonizer.OptimisticCommonizationMarker>()?.let { isMarkedTypeFound = true }
?: super.visit(classType)
if (classType.getAttachment<OptimisticNumbersTypeCommonizer.OptimisticCommonizationMarker>() != null) {
isOptimisticallyCommonizedType = true
}
if (OptimisticNumbersTypeCommonizer.isOptimisticallyCommonizableNumber(classType.classifierId)) {
isOptimisticallyCommonizableNumberType = true
}
super.visit(classType)
}
})
return isMarkedTypeFound
return isOptimisticallyCommonizedType || (isDerivedFromOptimisticallyCommonizedType && isOptimisticallyCommonizableNumberType)
}
private typealias RenderedType = String
@@ -972,7 +972,6 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
result.assertCommonized(
"(a, b, c)", """
expect class X
@UnsafeNumber(["a: kotlin.Short", "b: kotlin.Int", "c: kotlin.Any"])
expect fun foo(x: X): X
""".trimIndent()
)