diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt index bd613974a35..3b93c62809d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinProperties.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.Companion.jsCompi import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_CINTEROP_COMMONIZATION import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_GRANULAR_SOURCE_SETS_METADATA import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION +import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_BY_DEFAULT import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_MPP_HIERARCHICAL_STRUCTURE_SUPPORT import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.PropertyNames.KOTLIN_NATIVE_DEPENDENCY_PROPAGATION @@ -221,6 +222,9 @@ internal class PropertiesProvider private constructor(private val project: Proje val mppEnableOptimisticNumberCommonization: Boolean get() = booleanProperty(KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION) ?: true + val mppEnablePlatformIntegerCommonization: Boolean + get() = booleanProperty(KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION) ?: false + val wasmStabilityNoWarn: Boolean get() = booleanProperty("kotlin.wasm.stability.nowarn") ?: false @@ -498,6 +502,7 @@ internal class PropertiesProvider private constructor(private val project: Proje const val KOTLIN_NATIVE_DEPENDENCY_PROPAGATION = "kotlin.native.enableDependencyPropagation" const val KOTLIN_MPP_ENABLE_OPTIMISTIC_NUMBER_COMMONIZATION = "kotlin.mpp.enableOptimisticNumberCommonization" const val KOTLIN_KPM_EXPERIMENTAL_MODEL_MAPPING = "kotlin.kpm.experimentalModelMapping" + const val KOTLIN_MPP_ENABLE_PLATFORM_INTEGER_COMMONIZATION = "kotlin.mpp.enablePlatformIntegerCommonization" } companion object { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerProjectExtensions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerProjectExtensions.kt index 0c42c4ac964..09ae76c65cf 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerProjectExtensions.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerProjectExtensions.kt @@ -6,10 +6,7 @@ package org.jetbrains.kotlin.gradle.targets.native.internal import org.gradle.api.Project -import org.jetbrains.kotlin.commonizer.AdditionalCommonizerSetting -import org.jetbrains.kotlin.commonizer.CommonizerLogLevel -import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey -import org.jetbrains.kotlin.commonizer.setTo +import org.jetbrains.kotlin.commonizer.* import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider internal val Project.commonizerLogLevel: CommonizerLogLevel @@ -24,5 +21,6 @@ internal val Project.commonizerLogLevel: CommonizerLogLevel internal val Project.additionalCommonizerSettings: List> get() = listOf( - OptimisticNumberCommonizationEnabledKey setTo isOptimisticNumberCommonizationEnabled + OptimisticNumberCommonizationEnabledKey setTo isOptimisticNumberCommonizationEnabled, + PlatformIntegerCommonizationEnabledKey setTo isPlatformIntegerCommonizationEnabled, ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt index 0f97176a486..3ee60561b51 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/native/internal/CommonizerTasks.kt @@ -25,6 +25,9 @@ internal val Project.isIntransitiveMetadataConfigurationEnabled: Boolean internal val Project.isOptimisticNumberCommonizationEnabled: Boolean get() = PropertiesProvider(this).mppEnableOptimisticNumberCommonization +internal val Project.isPlatformIntegerCommonizationEnabled: Boolean + get() = PropertiesProvider(this).mppEnablePlatformIntegerCommonization + internal val Project.commonizeTask: TaskProvider get() = locateOrRegisterTask( "commonize", diff --git a/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/CommonizerSettings.kt b/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/CommonizerSettings.kt index 92f6b87c742..1a878364e89 100644 --- a/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/CommonizerSettings.kt +++ b/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/CommonizerSettings.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.commonizer import org.jetbrains.kotlin.commonizer.cli.OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_ALIAS +import org.jetbrains.kotlin.commonizer.cli.PLATFORM_INTEGER_COMMONIZATION_ENABLED_ALIAS public interface CommonizerSettings { @@ -22,3 +23,9 @@ public object OptimisticNumberCommonizationEnabledKey : CommonizerSettings.Key() { + override val defaultValue: Boolean = false + override val alias: String + get() = PLATFORM_INTEGER_COMMONIZATION_ENABLED_ALIAS +} \ No newline at end of file diff --git a/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/cli/CommonizerArguments.kt b/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/cli/CommonizerArguments.kt index e2b897357e8..66b11ec14a1 100644 --- a/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/cli/CommonizerArguments.kt +++ b/native/commonizer-api/src/org/jetbrains/kotlin/commonizer/cli/CommonizerArguments.kt @@ -20,3 +20,4 @@ public const val COPY_ENDORSED_LIBS_ALIAS: String = "copy-endorsed-libs" // Commonizer settings public const val OPTIMISTIC_NUMBER_COMMONIZATION_ENABLED_ALIAS: String = "optimistic-numbers" +public const val PLATFORM_INTEGER_COMMONIZATION_ENABLED_ALIAS: String = "platform-integers" diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/CommonizerSettingOptionType.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/CommonizerSettingOptionType.kt index 7507a6f2a36..d40b2f57b0d 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/CommonizerSettingOptionType.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/CommonizerSettingOptionType.kt @@ -15,7 +15,3 @@ internal sealed class CommonizerSettingOptionType( description, mandatory = false, ) - -internal val ADDITIONAL_COMMONIZER_SETTINGS: List> = listOf( - OptimisticNumberCommonizationOptionType, -) diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/OptimisticNumberCommonizationOptionType.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/SettingOptionTypes.kt similarity index 51% rename from native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/OptimisticNumberCommonizationOptionType.kt rename to native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/SettingOptionTypes.kt index a52b5fa5af5..63ec375ec1f 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/OptimisticNumberCommonizationOptionType.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/cli/SettingOptionTypes.kt @@ -6,6 +6,12 @@ package org.jetbrains.kotlin.commonizer.cli import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey +import org.jetbrains.kotlin.commonizer.PlatformIntegerCommonizationEnabledKey + +internal val ADDITIONAL_COMMONIZER_SETTINGS: List> = listOf( + OptimisticNumberCommonizationOptionType, + PlatformIntegerCommonizationOptionType, +) internal object OptimisticNumberCommonizationOptionType : CommonizerSettingOptionType( OptimisticNumberCommonizationEnabledKey, @@ -14,3 +20,12 @@ internal object OptimisticNumberCommonizationOptionType : CommonizerSettingOptio override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option = Option(this, parseBoolean(rawValue, onError)) } + +internal object PlatformIntegerCommonizationOptionType : CommonizerSettingOptionType( + PlatformIntegerCommonizationEnabledKey, + "Boolean (default false)\n" + + "Enable support of experimental commonization of integers with different bit width to a platform-dependent type", +) { + override fun parse(rawValue: String, onError: (reason: String) -> Nothing): Option = + Option(this, parseBoolean(rawValue, onError)) +} 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 fa8db2be57d..822a3ec5db7 100644 --- a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/ClassOrTypeAliasTypeCommonizer.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.commonizer.core import org.jetbrains.kotlin.commonizer.CommonizerSettings import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey +import org.jetbrains.kotlin.commonizer.PlatformIntegerCommonizationEnabledKey import org.jetbrains.kotlin.commonizer.cir.* import org.jetbrains.kotlin.commonizer.mergedtree.* import org.jetbrains.kotlin.commonizer.utils.isUnderKotlinNativeSyntheticPackages @@ -18,14 +19,18 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs internal class ClassOrTypeAliasTypeCommonizer( private val typeCommonizer: TypeCommonizer, private val classifiers: CirKnownClassifiers, - private val isOptimisticNumberTypeCommonizationEnabled: Boolean + private val isOptimisticNumberTypeCommonizationEnabled: Boolean, + private val isPlatformIntegerCommonizationEnabled: Boolean, ) : NullableSingleInvocationCommonizer { constructor(typeCommonizer: TypeCommonizer, classifiers: CirKnownClassifiers, settings: CommonizerSettings) : this( - typeCommonizer, classifiers, settings.getSetting(OptimisticNumberCommonizationEnabledKey) + typeCommonizer, classifiers, + settings.getSetting(OptimisticNumberCommonizationEnabledKey), + settings.getSetting(PlatformIntegerCommonizationEnabledKey), ) private val isMarkedNullableCommonizer = TypeNullabilityCommonizer(typeCommonizer.context) + private val platformIntegerCommonizer = PlatformIntegerCommonizer(typeCommonizer) private val typeDistanceMeasurement = TypeDistanceMeasurement(typeCommonizer.context) override fun invoke(values: List): CirClassOrTypeAliasType? { @@ -34,7 +39,9 @@ internal class ClassOrTypeAliasTypeCommonizer( val isMarkedNullable = isMarkedNullableCommonizer.commonize(expansions.map { it.isMarkedNullable }) ?: return null val substitutedTypes = substituteTypesIfNecessary(values) - ?: isOptimisticNumberTypeCommonizationEnabled.ifTrue { + ?: isPlatformIntegerCommonizationEnabled.ifTrue { + return platformIntegerCommonizer.commonize(expansions)?.makeNullableIfNecessary(isMarkedNullable) + } ?: isOptimisticNumberTypeCommonizationEnabled.ifTrue { return OptimisticNumbersTypeCommonizer.commonize(expansions)?.makeNullableIfNecessary(isMarkedNullable) } ?: return null diff --git a/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/PlatformIntegerCommonizer.kt b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/PlatformIntegerCommonizer.kt new file mode 100644 index 00000000000..d2a95baa5d9 --- /dev/null +++ b/native/commonizer/src/org/jetbrains/kotlin/commonizer/core/PlatformIntegerCommonizer.kt @@ -0,0 +1,129 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.commonizer.core + +import org.jetbrains.kotlin.commonizer.cir.* +import org.jetbrains.kotlin.descriptors.konan.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.utils.SmartList + +class PlatformIntegerCommonizer( + private val typeArgumentListCommonizer: TypeArgumentListCommonizer +) : AssociativeCommonizer { + constructor(typeCommonizer: TypeCommonizer) : this(TypeArgumentListCommonizer(typeCommonizer)) + + override fun commonize(first: CirClassOrTypeAliasType, second: CirClassOrTypeAliasType): CirClassOrTypeAliasType? { + return when { + both(first, second) { it.classifierId in commonizableSignedIntegerIds } -> platformIntType + both(first, second) { it.classifierId in commonizableUnsignedIntegerIds } -> platformUIntType + both(first, second) { it.classifierId in commonizableSignedVarIds } -> commonizeVarOf(first, second, isSigned = true) + both(first, second) { it.classifierId in commonizableUnsignedVarIds } -> commonizeVarOf(first, second, isSigned = false) + both(first, second) { it.classifierId in commonizableSignedArrayIds } -> platformIntArrayType + both(first, second) { it.classifierId in commonizableUnsignedArrayIds } -> platformUIntArrayType + both(first, second) { it.classifierId in commonizableSignedRangeIds } -> platformIntRangeType + both(first, second) { it.classifierId in commonizableUnsignedRangeIds } -> platformUIntRangeType + both(first, second) { it.classifierId in commonizableSignedProgressionIds } -> platformIntProgressionType + both(first, second) { it.classifierId in commonizableUnsignedProgressionIds } -> platformUIntProgressionType + else -> null + } + } + + private inline fun both(first: T, second: T, predicate: (T) -> Boolean) = + predicate(first) && predicate(second) + + private fun commonizeVarOf( + first: CirClassOrTypeAliasType, + second: CirClassOrTypeAliasType, + isSigned: Boolean + ): CirClassOrTypeAliasType? { + if (first !is CirClassType || second !is CirClassType) return null + + val argument = typeArgumentListCommonizer.commonize(listOf(first.arguments, second.arguments))?.singleOrNull() + ?: return null + + return createCommonVarOfType(isSigned = isSigned, argument = argument) + } +} + +// commonizable groups +private val commonizableSignedIntegerIds: Set = listOf( + KOTLIN_INT_ID, KOTLIN_LONG_ID, PLATFORM_INT_ID +).toCirEntityIds() + +private val commonizableUnsignedIntegerIds: Set = listOf( + KOTLIN_UINT_ID, KOTLIN_ULONG_ID, PLATFORM_UINT_ID +).toCirEntityIds() + +private val commonizableSignedVarIds: Set = listOf( + INT_VAR_OF_ID, LONG_VAR_OF_ID, PLATFORM_INT_VAR_OF_ID +).toCirEntityIds() + +private val commonizableUnsignedVarIds: Set = listOf( + UINT_VAR_OF_ID, ULONG_VAR_OF_ID, PLATFORM_UINT_VAR_OF_ID +).toCirEntityIds() + +private val commonizableSignedArrayIds: Set = listOf( + INT_ARRAY_ID, LONG_ARRAY_ID, PLATFORM_INT_ARRAY_ID +).toCirEntityIds() + +private val commonizableUnsignedArrayIds: Set = listOf( + UINT_ARRAY_ID, ULONG_ARRAY_ID, PLATFORM_UINT_ARRAY_ID +).toCirEntityIds() + +private val commonizableSignedRangeIds: Set = listOf( + INT_RANGE_ID, LONG_RANGE_ID, PLATFORM_INT_RANGE_ID +).toCirEntityIds() + +private val commonizableUnsignedRangeIds: Set = listOf( + UINT_RANGE_ID, ULONG_RANGE_ID, PLATFORM_UINT_RANGE_ID +).toCirEntityIds() + +private val commonizableSignedProgressionIds: Set = listOf( + INT_PROGRESSION_ID, LONG_PROGRESSION_ID, PLATFORM_INT_PROGRESSION_ID +).toCirEntityIds() + +private val commonizableUnsignedProgressionIds: Set = listOf( + UINT_PROGRESSION, ULONG_PROGRESSION, PLATFORM_UINT_PROGRESSION_ID +).toCirEntityIds() + +private fun ClassId.toCirEntityId(): CirEntityId = + CirEntityId.create(this) + +private fun Collection.toCirEntityIds(): Set = + map { it.toCirEntityId()}.toSet() + +// plain integers +private val platformIntType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_INT_ID.toCirEntityId()) +private val platformUIntType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_UINT_ID.toCirEntityId()) + +// arrays +private val platformIntArrayType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_INT_ARRAY_ID.toCirEntityId()) +private val platformUIntArrayType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_UINT_ARRAY_ID.toCirEntityId()) + +// ranges +private val platformIntRangeType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_INT_RANGE_ID.toCirEntityId()) +private val platformUIntRangeType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_UINT_RANGE_ID.toCirEntityId()) + +// progressions +private val platformIntProgressionType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_INT_PROGRESSION_ID.toCirEntityId()) +private val platformUIntProgressionType: CirClassType = createSimpleCirTypeWithoutArguments(PLATFORM_UINT_PROGRESSION_ID.toCirEntityId()) + +private fun createSimpleCirTypeWithoutArguments(id: CirEntityId): CirClassType = + CirClassType.createInterned( + classId = id, + outerType = null, + arguments = emptyList(), + isMarkedNullable = false, + ) + +private fun createCommonVarOfType(isSigned: Boolean, argument: CirTypeProjection): CirClassType { + return CirClassType.createInterned( + classId = if (isSigned) PLATFORM_INT_VAR_OF_ID.toCirEntityId() else PLATFORM_UINT_VAR_OF_ID.toCirEntityId(), + outerType = null, + arguments = SmartList(argument), + isMarkedNullable = false, + ) +} diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/HierarchicalOptimisticNumbersTypeCommonizerTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/HierarchicalOptimisticNumbersTypeCommonizerTest.kt index 53ac6735456..2319a0eb653 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/HierarchicalOptimisticNumbersTypeCommonizerTest.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/HierarchicalOptimisticNumbersTypeCommonizerTest.kt @@ -589,14 +589,14 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom outputTarget("(a, b)") setting(OptimisticNumberCommonizationEnabledKey, true) registerFakeStdlibIntegersDependency("(a, b)") - simpleSingleSourceTarget("a", "typealias X = kotlinx.cinterop.UIntVarOf") - simpleSingleSourceTarget("b", "typealias X = kotlinx.cinterop.ULongVarOf") + simpleSingleSourceTarget("a", "typealias X = kotlinx.cinterop.UIntVarOf") + simpleSingleSourceTarget("b", "typealias X = kotlinx.cinterop.ULongVarOf") } result.assertCommonized( "(a, b)", """ @UnsafeNumber(["a: kotlinx.cinterop.UIntVarOf", "b: kotlinx.cinterop.ULongVarOf"]) - typealias X = kotlinx.cinterop.UIntVarOf + typealias X = kotlinx.cinterop.UIntVarOf """.trimIndent() ) } @@ -606,14 +606,14 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom outputTarget("(a, b)") setting(OptimisticNumberCommonizationEnabledKey, true) registerFakeStdlibIntegersDependency("(a, b)") - simpleSingleSourceTarget("a", "typealias X = kotlinx.cinterop.IntVarOf") - simpleSingleSourceTarget("b", "typealias X = kotlinx.cinterop.LongVarOf") + simpleSingleSourceTarget("a", "typealias X = kotlinx.cinterop.IntVarOf") + simpleSingleSourceTarget("b", "typealias X = kotlinx.cinterop.LongVarOf") } result.assertCommonized( "(a, b)", """ @UnsafeNumber(["a: kotlinx.cinterop.IntVarOf", "b: kotlinx.cinterop.LongVarOf"]) - typealias X = kotlinx.cinterop.IntVarOf + typealias X = kotlinx.cinterop.IntVarOf """.trimIndent() ) } diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/HierarchicalPlatformIntegerCommonizationTest.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/HierarchicalPlatformIntegerCommonizationTest.kt new file mode 100644 index 00000000000..b1ac6c18acd --- /dev/null +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/HierarchicalPlatformIntegerCommonizationTest.kt @@ -0,0 +1,416 @@ +/* + * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.commonizer.hierarchical + +import org.jetbrains.kotlin.commonizer.AbstractInlineSourcesCommonizationTest +import org.jetbrains.kotlin.commonizer.PlatformIntegerCommonizationEnabledKey +import org.jetbrains.kotlin.commonizer.assertCommonized + +class HierarchicalPlatformIntegerCommonizationTest : AbstractInlineSourcesCommonizationTest() { + fun `test signed ints`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + typealias X = Int + typealias Y = Long + """.trimIndent() + + "b" withSource """ + typealias X = Long + typealias Y = Int + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + @UnsafeNumber(["a: kotlin.Int", "b: kotlin.Long"]) + typealias X = PlatformInt + @UnsafeNumber(["a: kotlin.Long", "b: kotlin.Int"]) + typealias Y = PlatformInt + """.trimIndent() + ) + } + + fun `test unsigned ints`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + typealias X = UInt + typealias Y = ULong + """.trimIndent() + + "b" withSource """ + typealias X = ULong + typealias Y = UInt + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + @UnsafeNumber(["a: kotlin.UInt", "b: kotlin.ULong"]) + typealias X = PlatformUInt + @UnsafeNumber(["a: kotlin.ULong", "b: kotlin.UInt"]) + typealias Y = PlatformUInt + """.trimIndent() + ) + } + + fun `test signed vars`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlinx.cinterop.* + + typealias AX = Int + typealias AY = Long + typealias X = IntVarOf + typealias Y = LongVarOf + """.trimIndent() + + "b" withSource """ + import kotlinx.cinterop.* + + typealias AX = Long + typealias AY = Int + typealias X = LongVarOf + typealias Y = IntVarOf + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlinx.cinterop.* + + @UnsafeNumber(["a: kotlin.Int", "b: kotlin.Long"]) + typealias AX = PlatformInt + @UnsafeNumber(["a: kotlin.Long", "b: kotlin.Int"]) + typealias AY = PlatformInt + @UnsafeNumber(["a: kotlinx.cinterop.IntVarOf", "b: kotlinx.cinterop.LongVarOf"]) + typealias X = PlatformIntVarOf + @UnsafeNumber(["a: kotlinx.cinterop.LongVarOf", "b: kotlinx.cinterop.IntVarOf"]) + typealias Y = PlatformIntVarOf + """.trimIndent() + ) + } + + fun `test unsigned vars`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlinx.cinterop.* + + typealias AX = UInt + typealias AY = ULong + typealias X = UIntVarOf + typealias Y = ULongVarOf + """.trimIndent() + + "b" withSource """ + import kotlinx.cinterop.* + + typealias AX = ULong + typealias AY = UInt + typealias X = ULongVarOf + typealias Y = UIntVarOf + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlinx.cinterop.* + + @UnsafeNumber(["a: kotlin.UInt", "b: kotlin.ULong"]) + typealias AX = PlatformUInt + @UnsafeNumber(["a: kotlin.ULong", "b: kotlin.UInt"]) + typealias AY = PlatformUInt + @UnsafeNumber(["a: kotlinx.cinterop.UIntVarOf", "b: kotlinx.cinterop.ULongVarOf"]) + typealias X = PlatformUIntVarOf + @UnsafeNumber(["a: kotlinx.cinterop.ULongVarOf", "b: kotlinx.cinterop.UIntVarOf"]) + typealias Y = PlatformUIntVarOf + """.trimIndent() + ) + } + + fun `test signed arrays`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + typealias X = IntArray + typealias Y = LongArray + """.trimIndent() + + "b" withSource """ + typealias X = LongArray + typealias Y = IntArray + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlinx.cinterop.* + + typealias X = PlatformIntArray + typealias Y = PlatformIntArray + """.trimIndent() + ) + } + + fun `test unsigned arrays`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + typealias X = UIntArray + typealias Y = ULongArray + """.trimIndent() + + "b" withSource """ + typealias X = ULongArray + typealias Y = UIntArray + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlinx.cinterop.* + + typealias X = PlatformUIntArray + typealias Y = PlatformUIntArray + """.trimIndent() + ) + } + + fun `test signed ranges`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlin.ranges.* + + typealias X = IntRange + typealias Y = LongRange + """.trimIndent() + + "b" withSource """ + typealias X = LongRange + typealias Y = IntRange + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlin.ranges.* + + typealias X = PlatformIntRange + typealias Y = PlatformIntRange + """.trimIndent() + ) + } + + fun `test unsigned ranges`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlin.ranges.* + + typealias X = UIntRange + typealias Y = ULongRange + """.trimIndent() + + "b" withSource """ + typealias X = ULongRange + typealias Y = UIntRange + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlin.ranges.* + + typealias X = PlatformUIntRange + typealias Y = PlatformUIntRange + """.trimIndent() + ) + } + + fun `test signed progressions`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlin.ranges.* + + typealias X = IntProgression + typealias Y = LongProgression + """.trimIndent() + + "b" withSource """ + typealias X = LongProgression + typealias Y = IntProgression + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlin.ranges.* + + typealias X = PlatformIntProgression + typealias Y = PlatformIntProgression + """.trimIndent() + ) + } + + fun `test unsigned progressions`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlin.ranges.* + + typealias X = UIntProgression + typealias Y = ULongProgression + """.trimIndent() + + "b" withSource """ + typealias X = ULongProgression + typealias Y = UIntProgression + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlin.ranges.* + + typealias X = PlatformUIntProgression + typealias Y = PlatformUIntProgression + """.trimIndent() + ) + } + + fun `test platform types in return positions`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlin.ranges.* + import kotlinx.cinterop.* + + class C { + val i: Int = null!! + fun v(): IntVarOf = null!! + fun r(): IntRange = null!! + } + + val a: IntArray = null!! + fun p(): IntProgression = null!! + """.trimIndent() + + "b" withSource """ + import kotlin.ranges.* + import kotlinx.cinterop.* + + class C { + val i: Long = null!! + fun v(): LongVarOf = null!! + fun r(): LongRange = null!! + } + + val a: LongArray = null!! + fun p(): LongProgression = null!! + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlin.ranges.* + import kotlinx.cinterop.* + + expect class C() { + val i: PlatformInt + fun v(): PlatformIntVarOf + fun r(): PlatformIntRange + } + + expect val a: PlatformIntArray + expect fun p(): PlatformIntProgression + """.trimIndent() + ) + } + + fun `test platform types in signatures`() { + val result = commonize { + outputTarget("(a, b)") + setting(PlatformIntegerCommonizationEnabledKey, true) + registerFakeStdlibIntegersDependency("(a, b)") + + "a" withSource """ + import kotlin.ranges.* + import kotlinx.cinterop.* + + class C { + fun i(arg: Int) {} + fun v(arg: IntVarOf) {} + fun r(arg: IntRange) {} + } + + fun a(arg: IntArray) {} + fun p(arg: IntProgression) {} + """.trimIndent() + + "b" withSource """ + import kotlin.ranges.* + import kotlinx.cinterop.* + + class C { + fun i(arg: Long) {} + fun v(arg: LongVarOf) {} + fun r(arg: LongRange) {} + } + + fun a(arg: LongArray) {} + fun p(arg: LongProgression) {} + """.trimIndent() + } + + result.assertCommonized( + "(a, b)", """ + import kotlin.ranges.* + import kotlinx.cinterop.* + + expect class C() { + } + """.trimIndent() + ) + } +} diff --git a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/InlineSourceCommonizationTestDependencyUtils.kt b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/InlineSourceCommonizationTestDependencyUtils.kt index 5653aceb69e..cc5b60e2cf9 100644 --- a/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/InlineSourceCommonizationTestDependencyUtils.kt +++ b/native/commonizer/tests/org/jetbrains/kotlin/commonizer/hierarchical/InlineSourceCommonizationTestDependencyUtils.kt @@ -17,6 +17,8 @@ internal fun AbstractInlineSourcesCommonizationTest.ParametersBuilder.registerFa unsingedVarIntegers() singedVarIntegers() unsafeNumberAnnotationSource() + ranges() + platformIntegers() } } @@ -24,10 +26,16 @@ internal fun InlineSourceBuilder.ModuleBuilder.unsignedIntegers() { source( """ package kotlin - class UByte - class UShort - class UInt - class ULong + + class UByte : Comparable { override fun compareTo(other: UByte): Int = null!! } + class UShort : Comparable { override fun compareTo(other: UShort): Int = null!! } + class UInt : Comparable { override fun compareTo(other: UInt): Int = null!! } + class ULong : Comparable { override fun compareTo(other: ULong): Int = null!! } + + class UByteArray + class UShortArray + class UIntArray + class ULongArray """.trimIndent(), "unsigned.kt" ) } @@ -36,10 +44,10 @@ private fun InlineSourceBuilder.ModuleBuilder.unsingedVarIntegers() { source( """ package kotlinx.cinterop - class UByteVarOf - class UShortVarOf - class UIntVarOf - class ULongVarOf + class UByteVarOf + class UShortVarOf + class UIntVarOf + class ULongVarOf """.trimIndent(), "UnsignedVarOf.kt" ) } @@ -48,10 +56,10 @@ private fun InlineSourceBuilder.ModuleBuilder.singedVarIntegers() { source( """ package kotlinx.cinterop - class ByteVarOf - class ShortVarOf - class IntVarOf - class LongVarOf + class ByteVarOf + class ShortVarOf + class IntVarOf + class LongVarOf """.trimIndent(), "SignedVarOf.kt" ) } @@ -74,3 +82,61 @@ internal fun InlineSourceBuilder.ModuleBuilder.unsafeNumberAnnotationSource() { "UnsafeNumberTypeAlias.kt" ) } + +internal fun InlineSourceBuilder.ModuleBuilder.ranges() { + source( + """ + package kotlin.ranges + + interface ClosedRange> + + open class IntProgression + open class UIntProgression + open class LongProgression + open class ULongProgression + + class IntRange : IntProgression(), ClosedRange + class UIntRange : UIntProgression(), ClosedRange + class LongRange : LongProgression(), ClosedRange + class ULongRange : ULongProgression(), ClosedRange + """.trimIndent(), + "Ranges.kt" + ) +} + +private fun InlineSourceBuilder.ModuleBuilder.platformIntegers() { + source( + """ + package kotlin + + expect class PlatformInt : Number, Comparable + expect class PlatformUInt : Comparable + expect class PlatformIntArray + expect class PlatformUIntArray + """.trimIndent(), + "PlatformInts.kt" + ) + + source( + """ + package kotlinx.cinterop + + abstract class CVariable + + expect class PlatformIntVarOf : CVariable + expect class PlatformUIntVarOf : CVariable + """.trimIndent(), + "PlatformVars.kt" + ) + + source( + """ + package kotlin.ranges + + expect open class PlatformIntProgression + expect open class PlatformUIntProgression + expect class PlatformIntRange : PlatformIntProgression, ClosedRange + expect class PlatformUIntRange : PlatformUIntProgression, ClosedRange + """.trimIndent() + ) +} diff --git a/native/frontend/src/org/jetbrains/kotlin/descriptors/konan/PlatformIntegerClassIds.kt b/native/frontend/src/org/jetbrains/kotlin/descriptors/konan/PlatformIntegerClassIds.kt new file mode 100644 index 00000000000..53d8ff37b5f --- /dev/null +++ b/native/frontend/src/org/jetbrains/kotlin/descriptors/konan/PlatformIntegerClassIds.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.descriptors.konan + +import org.jetbrains.kotlin.name.ClassId + +val KOTLIN_INT_ID = ClassId.fromString("kotlin/Int") +val KOTLIN_LONG_ID = ClassId.fromString("kotlin/Long") + +val KOTLIN_UINT_ID = ClassId.fromString("kotlin/UInt") +val KOTLIN_ULONG_ID = ClassId.fromString("kotlin/ULong") + +val INT_VAR_OF_ID = ClassId.fromString("kotlinx/cinterop/IntVarOf") +val LONG_VAR_OF_ID = ClassId.fromString("kotlinx/cinterop/LongVarOf") + +val UINT_VAR_OF_ID = ClassId.fromString("kotlinx/cinterop/UIntVarOf") +val ULONG_VAR_OF_ID = ClassId.fromString("kotlinx/cinterop/ULongVarOf") + +val INT_ARRAY_ID = ClassId.fromString("kotlin/IntArray") +val LONG_ARRAY_ID = ClassId.fromString("kotlin/LongArray") + +val UINT_ARRAY_ID = ClassId.fromString("kotlin/UIntArray") +val ULONG_ARRAY_ID = ClassId.fromString("kotlin/ULongArray") + +val INT_RANGE_ID = ClassId.fromString("kotlin/ranges/IntRange") +val LONG_RANGE_ID = ClassId.fromString("kotlin/ranges/LongRange") + +val UINT_RANGE_ID = ClassId.fromString("kotlin/ranges/UIntRange") +val ULONG_RANGE_ID = ClassId.fromString("kotlin/ranges/ULongRange") + +val INT_PROGRESSION_ID = ClassId.fromString("kotlin/ranges/IntProgression") +val LONG_PROGRESSION_ID = ClassId.fromString("kotlin/ranges/LongProgression") + +val UINT_PROGRESSION = ClassId.fromString("kotlin/ranges/UIntProgression") +val ULONG_PROGRESSION = ClassId.fromString("kotlin/ranges/ULongProgression") + +val PLATFORM_INT_ID = ClassId.fromString("kotlin/PlatformInt") +val PLATFORM_UINT_ID = ClassId.fromString("kotlin/PlatformUInt") + +val PLATFORM_INT_VAR_OF_ID = ClassId.fromString("kotlinx/cinterop/PlatformIntVarOf") +val PLATFORM_UINT_VAR_OF_ID = ClassId.fromString("kotlinx/cinterop/PlatformUIntVarOf") + +val PLATFORM_INT_ARRAY_ID = ClassId.fromString("kotlin/PlatformIntArray") +val PLATFORM_UINT_ARRAY_ID = ClassId.fromString("kotlin/PlatformUIntArray") + +val PLATFORM_INT_RANGE_ID = ClassId.fromString("kotlin/ranges/PlatformIntRange") +val PLATFORM_UINT_RANGE_ID = ClassId.fromString("kotlin/ranges/PlatformUIntRange") + +val PLATFORM_INT_PROGRESSION_ID = ClassId.fromString("kotlin/ranges/PlatformIntProgression") +val PLATFORM_UINT_PROGRESSION_ID = ClassId.fromString("kotlin/ranges/PlatformUIntProgression") + +val PLATFORM_INTEGERS: Set = setOf( + PLATFORM_INT_ID, PLATFORM_UINT_ID +) + +val PLATFORM_VARIABLES: Set = setOf( + PLATFORM_INT_VAR_OF_ID, PLATFORM_UINT_VAR_OF_ID +) + +val PLATFORM_ARRAYS: Set = setOf( + PLATFORM_INT_ARRAY_ID, PLATFORM_UINT_ARRAY_ID +) + +val PLATFORM_RANGES: Set = setOf( + PLATFORM_INT_RANGE_ID, PLATFORM_UINT_RANGE_ID +) + +val PLATFORM_PROGRESSIONS: Set = setOf( + PLATFORM_INT_PROGRESSION_ID, PLATFORM_UINT_PROGRESSION_ID +) + +val PLATFORM_TYPES: Set = + PLATFORM_INTEGERS + PLATFORM_VARIABLES + PLATFORM_ARRAYS + PLATFORM_RANGES + PLATFORM_PROGRESSIONS