[MPP] Apply @UnsafeNumber to functions and properties
KT-51224 KT-51215
This commit is contained in:
committed by
teamcity
parent
f8a1395a03
commit
6674c3f482
+1
-1
@@ -120,7 +120,7 @@ rootProject.apply {
|
|||||||
IdeVersionConfigurator.setCurrentIde(project)
|
IdeVersionConfigurator.setCurrentIde(project)
|
||||||
|
|
||||||
if (!project.hasProperty("versions.kotlin-native")) {
|
if (!project.hasProperty("versions.kotlin-native")) {
|
||||||
extra["versions.kotlin-native"] = "1.7.0-dev-1132"
|
extra["versions.kotlin-native"] = "1.7.0-dev-1827"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
package kotlinx.cinterop
|
package kotlinx.cinterop
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marker for typealias that will represent numbers of different bit width on at least two platforms,
|
* Marker for declarations that depend on numeric types of different bit width on at least two platforms.
|
||||||
* or function/property that have such numbers in their signature.
|
|
||||||
*
|
*
|
||||||
* @param actualPlatformTypes: Contains platform types represented as `{konanTarget}: {type fqn}`
|
* @param actualPlatformTypes: Contains platform types represented as `{konanTarget}: {type fqn}`
|
||||||
* e.g. ["linux_x64: kotlin.Int", "linux_arm64: kotlin.Long"]
|
* e.g. ["linux_x64: kotlin.Int", "linux_arm64: kotlin.Long"]
|
||||||
|
|||||||
+24
-2
@@ -5,15 +5,20 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.commonizer.core
|
package org.jetbrains.kotlin.commonizer.core
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.commonizer.CommonizerSettings
|
||||||
import org.jetbrains.kotlin.commonizer.cir.*
|
import org.jetbrains.kotlin.commonizer.cir.*
|
||||||
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
||||||
import org.jetbrains.kotlin.commonizer.utils.singleDistinctValueOrNull
|
import org.jetbrains.kotlin.commonizer.utils.singleDistinctValueOrNull
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DELEGATION
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class FunctionOrPropertyBaseCommonizer(
|
class FunctionOrPropertyBaseCommonizer(
|
||||||
|
private val classifiers: CirKnownClassifiers,
|
||||||
|
private val settings: CommonizerSettings,
|
||||||
private val typeCommonizer: TypeCommonizer,
|
private val typeCommonizer: TypeCommonizer,
|
||||||
private val extensionReceiverCommonizer: ExtensionReceiverCommonizer = ExtensionReceiverCommonizer(typeCommonizer),
|
private val extensionReceiverCommonizer: ExtensionReceiverCommonizer = ExtensionReceiverCommonizer(typeCommonizer),
|
||||||
private val returnTypeCommonizer: ReturnTypeCommonizer = ReturnTypeCommonizer(typeCommonizer),
|
private val returnTypeCommonizer: ReturnTypeCommonizer = ReturnTypeCommonizer(typeCommonizer),
|
||||||
@@ -26,7 +31,8 @@ class FunctionOrPropertyBaseCommonizer(
|
|||||||
val visibility: Visibility,
|
val visibility: Visibility,
|
||||||
val extensionReceiver: CirExtensionReceiver?,
|
val extensionReceiver: CirExtensionReceiver?,
|
||||||
val returnType: CirType,
|
val returnType: CirType,
|
||||||
val typeParameters: List<CirTypeParameter>
|
val typeParameters: List<CirTypeParameter>,
|
||||||
|
val additionalAnnotations: List<CirAnnotation>,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun invoke(values: List<CirFunctionOrProperty>): FunctionOrProperty? {
|
override fun invoke(values: List<CirFunctionOrProperty>): FunctionOrProperty? {
|
||||||
@@ -43,6 +49,12 @@ class FunctionOrPropertyBaseCommonizer(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val additionalUnsafeNumberAnnotation =
|
||||||
|
createUnsafeNumberAnnotationIfNecessary(
|
||||||
|
classifiers.classifierIndices.targets, settings, values,
|
||||||
|
getTypeIdFromDeclarationForCheck = ::getFunctionOrPropertyReturnTypeId,
|
||||||
|
)
|
||||||
|
|
||||||
return FunctionOrProperty(
|
return FunctionOrProperty(
|
||||||
name = values.first().name,
|
name = values.first().name,
|
||||||
kind = values.singleDistinctValueOrNull { it.kind } ?: return null,
|
kind = values.singleDistinctValueOrNull { it.kind } ?: return null,
|
||||||
@@ -50,8 +62,18 @@ class FunctionOrPropertyBaseCommonizer(
|
|||||||
visibility = VisibilityCommonizer.lowering().commonize(values) ?: return null,
|
visibility = VisibilityCommonizer.lowering().commonize(values) ?: return null,
|
||||||
extensionReceiver = (extensionReceiverCommonizer(values.map { it.extensionReceiver }) ?: return null).receiver,
|
extensionReceiver = (extensionReceiverCommonizer(values.map { it.extensionReceiver }) ?: return null).receiver,
|
||||||
returnType = returnTypeCommonizer(values) ?: return null,
|
returnType = returnTypeCommonizer(values) ?: return null,
|
||||||
typeParameters = TypeParameterListCommonizer(typeCommonizer).commonize(values.map { it.typeParameters }) ?: return null
|
typeParameters = TypeParameterListCommonizer(typeCommonizer).commonize(values.map { it.typeParameters }) ?: return null,
|
||||||
|
additionalAnnotations = listOfNotNull(additionalUnsafeNumberAnnotation)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getFunctionOrPropertyReturnTypeId(functionOrProperty: CirFunctionOrProperty): CirEntityId? {
|
||||||
|
return functionOrProperty.returnType.let { returnType ->
|
||||||
|
when (returnType) {
|
||||||
|
is CirFlexibleType -> returnType.lowerBound.safeAs<CirClassOrTypeAliasType>()?.classifierId
|
||||||
|
else -> returnType.safeAs<CirClassOrTypeAliasType>()?.classifierId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ class FunctionCommonizer(
|
|||||||
val functionOrProperty = functionOrPropertyBaseCommonizer(values) ?: return null
|
val functionOrProperty = functionOrPropertyBaseCommonizer(values) ?: return null
|
||||||
val valueParametersResult = CallableValueParametersCommonizer(typeCommonizer).commonize(values) ?: return null
|
val valueParametersResult = CallableValueParametersCommonizer(typeCommonizer).commonize(values) ?: return null
|
||||||
return CirFunction(
|
return CirFunction(
|
||||||
annotations = AnnotationsCommonizer().commonize(values.map { it.annotations }) ?: return null,
|
annotations = AnnotationsCommonizer().commonize(values.map { it.annotations })
|
||||||
|
?.plus(functionOrProperty.additionalAnnotations)
|
||||||
|
?: return null,
|
||||||
name = values.first().name,
|
name = values.first().name,
|
||||||
typeParameters = functionOrProperty.typeParameters,
|
typeParameters = functionOrProperty.typeParameters,
|
||||||
visibility = functionOrProperty.visibility,
|
visibility = functionOrProperty.visibility,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class PropertyCommonizer(
|
|||||||
val constCompileTimeInitializer = (constCommonizationState as? ConstSameValue)?.compileTimeInitializer
|
val constCompileTimeInitializer = (constCommonizationState as? ConstSameValue)?.compileTimeInitializer
|
||||||
|
|
||||||
return CirProperty(
|
return CirProperty(
|
||||||
annotations = emptyList(),
|
annotations = functionOrPropertyBase.additionalAnnotations,
|
||||||
name = functionOrPropertyBase.name,
|
name = functionOrPropertyBase.name,
|
||||||
typeParameters = functionOrPropertyBase.typeParameters,
|
typeParameters = functionOrPropertyBase.typeParameters,
|
||||||
visibility = functionOrPropertyBase.visibility,
|
visibility = functionOrPropertyBase.visibility,
|
||||||
|
|||||||
@@ -6,12 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.commonizer.core
|
package org.jetbrains.kotlin.commonizer.core
|
||||||
|
|
||||||
import org.jetbrains.kotlin.commonizer.CommonizerSettings
|
import org.jetbrains.kotlin.commonizer.CommonizerSettings
|
||||||
import org.jetbrains.kotlin.commonizer.CommonizerTarget
|
|
||||||
import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey
|
|
||||||
import org.jetbrains.kotlin.commonizer.allLeaves
|
|
||||||
import org.jetbrains.kotlin.commonizer.cir.*
|
import org.jetbrains.kotlin.commonizer.cir.*
|
||||||
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
import org.jetbrains.kotlin.commonizer.mergedtree.CirKnownClassifiers
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|
||||||
|
|
||||||
class TypeAliasCommonizer(
|
class TypeAliasCommonizer(
|
||||||
typeCommonizer: TypeCommonizer,
|
typeCommonizer: TypeCommonizer,
|
||||||
@@ -41,67 +37,11 @@ class TypeAliasCommonizer(
|
|||||||
underlyingType = underlyingType,
|
underlyingType = underlyingType,
|
||||||
expandedType = underlyingType.expandedType(),
|
expandedType = underlyingType.expandedType(),
|
||||||
annotations = listOfNotNull(
|
annotations = listOfNotNull(
|
||||||
createUnsafeNumberAnnotationIfNecessary(classifiers.classifierIndices.targets, settings, values)
|
createUnsafeNumberAnnotationIfNecessary(
|
||||||
|
classifiers.classifierIndices.targets, settings, values,
|
||||||
|
getTypeIdFromDeclarationForCheck = { typeAlias -> typeAlias.expandedType.classifierId }
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createUnsafeNumberAnnotationIfNecessary(
|
|
||||||
targets: List<CommonizerTarget>,
|
|
||||||
settings: CommonizerSettings,
|
|
||||||
values: List<CirTypeAlias>,
|
|
||||||
): CirAnnotation? {
|
|
||||||
val isOptimisticCommonizationEnabled = settings.getSetting(OptimisticNumberCommonizationEnabledKey)
|
|
||||||
|
|
||||||
if (!isOptimisticCommonizationEnabled)
|
|
||||||
return null
|
|
||||||
|
|
||||||
val expandedTypes = values.map { it.expandedType.classifierId }
|
|
||||||
|
|
||||||
// All typealias have to be potentially substitutable (aka have to be some kind of number type)
|
|
||||||
if (!expandedTypes.all { OptimisticNumbersTypeCommonizer.isOptimisticallySubstitutable(it) }) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val actualPlatformTypes = mutableMapOf<String, CirEntityId>()
|
|
||||||
values.forEachIndexed forEach@{ index, ta ->
|
|
||||||
val existingAnnotation = ta.annotations.firstIsInstanceOrNull<UnsafeNumberAnnotation>()
|
|
||||||
if (existingAnnotation != null) {
|
|
||||||
actualPlatformTypes.putAll(existingAnnotation.actualPlatformTypes)
|
|
||||||
return@forEach
|
|
||||||
}
|
|
||||||
|
|
||||||
targets[index].allLeaves().forEach { target ->
|
|
||||||
actualPlatformTypes[target.name] = ta.expandedType.classifierId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (actualPlatformTypes.values.distinct().size > 1) {
|
|
||||||
return UnsafeNumberAnnotation(actualPlatformTypes)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private class UnsafeNumberAnnotation(val actualPlatformTypes: Map<String, CirEntityId>) : CirAnnotation {
|
|
||||||
override val type: CirClassType = UnsafeNumberAnnotation.type
|
|
||||||
override val annotationValueArguments: Map<CirName, CirAnnotation> = emptyMap()
|
|
||||||
|
|
||||||
override val constantValueArguments: Map<CirName, CirConstantValue> = mapOf(
|
|
||||||
CirName.create("actualPlatformTypes") to CirConstantValue.ArrayValue(
|
|
||||||
actualPlatformTypes.map { (platform, type) -> CirConstantValue.StringValue("$platform: ${type.toQualifiedNameString()}") }
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val type = CirClassType.createInterned(
|
|
||||||
classId = CirEntityId.create("kotlinx/cinterop/UnsafeNumber"),
|
|
||||||
outerType = null,
|
|
||||||
arguments = emptyList(),
|
|
||||||
isMarkedNullable = false
|
|
||||||
)
|
|
||||||
|
|
||||||
val empty = UnsafeNumberAnnotation(emptyMap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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.core
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.commonizer.CommonizerSettings
|
||||||
|
import org.jetbrains.kotlin.commonizer.CommonizerTarget
|
||||||
|
import org.jetbrains.kotlin.commonizer.OptimisticNumberCommonizationEnabledKey
|
||||||
|
import org.jetbrains.kotlin.commonizer.allLeaves
|
||||||
|
import org.jetbrains.kotlin.commonizer.cir.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
|
||||||
|
internal fun <T : CirHasAnnotations> createUnsafeNumberAnnotationIfNecessary(
|
||||||
|
targets: List<CommonizerTarget>,
|
||||||
|
settings: CommonizerSettings,
|
||||||
|
values: List<T>,
|
||||||
|
getTypeIdFromDeclarationForCheck: (declaration: T) -> CirEntityId?,
|
||||||
|
): CirAnnotation? {
|
||||||
|
val isOptimisticCommonizationEnabled = settings.getSetting(OptimisticNumberCommonizationEnabledKey)
|
||||||
|
|
||||||
|
if (!isOptimisticCommonizationEnabled)
|
||||||
|
return null
|
||||||
|
|
||||||
|
val typeIds = values.map { annotated -> getTypeIdFromDeclarationForCheck(annotated) }
|
||||||
|
|
||||||
|
// All typealias have to be potentially substitutable (aka have to be some kind of number type)
|
||||||
|
if (!typeIds.all { it != null && OptimisticNumbersTypeCommonizer.isOptimisticallySubstitutable(it) }) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return createUnsafeNumberAnnotation(targets, values, getTypeIdFromDeclarationForCheck)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : CirHasAnnotations> createUnsafeNumberAnnotation(
|
||||||
|
targets: List<CommonizerTarget>,
|
||||||
|
values: List<T>,
|
||||||
|
getTypeIdFromDeclaration: (declaration: T) -> CirEntityId?,
|
||||||
|
): CirAnnotation? {
|
||||||
|
val actualPlatformTypes = mutableMapOf<String, CirEntityId>()
|
||||||
|
|
||||||
|
values.forEachIndexed forEach@{ index, annotated ->
|
||||||
|
val existingAnnotation = annotated.annotations.firstIsInstanceOrNull<UnsafeNumberAnnotation>()
|
||||||
|
if (existingAnnotation != null) {
|
||||||
|
actualPlatformTypes.putAll(existingAnnotation.actualPlatformTypes)
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
|
targets[index].allLeaves().forEach { target ->
|
||||||
|
actualPlatformTypes[target.name] = getTypeIdFromDeclaration(annotated)
|
||||||
|
?: throw IllegalStateException("Expect class or type alias type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualPlatformTypes.values.distinct().size > 1) {
|
||||||
|
return UnsafeNumberAnnotation(actualPlatformTypes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UnsafeNumberAnnotation(val actualPlatformTypes: Map<String, CirEntityId>) : CirAnnotation {
|
||||||
|
override val type: CirClassType = UnsafeNumberAnnotation.type
|
||||||
|
override val annotationValueArguments: Map<CirName, CirAnnotation> = emptyMap()
|
||||||
|
|
||||||
|
override val constantValueArguments: Map<CirName, CirConstantValue> = mapOf(
|
||||||
|
CirName.create("actualPlatformTypes") to CirConstantValue.ArrayValue(
|
||||||
|
actualPlatformTypes.toSortedMap().map { (platform, type) ->
|
||||||
|
CirConstantValue.StringValue("$platform: ${type.toQualifiedNameString()}")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val type = CirClassType.createInterned(
|
||||||
|
classId = CirEntityId.create("kotlinx/cinterop/UnsafeNumber"),
|
||||||
|
outerType = null,
|
||||||
|
arguments = emptyList(),
|
||||||
|
isMarkedNullable = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,9 @@ internal fun buildPropertyNode(
|
|||||||
storageManager = storageManager,
|
storageManager = storageManager,
|
||||||
size = size,
|
size = size,
|
||||||
nodeRelationship = nodeRelationship,
|
nodeRelationship = nodeRelationship,
|
||||||
commonizerProducer = { PropertyCommonizer(FunctionOrPropertyBaseCommonizer(TypeCommonizer(classifiers, settings))) },
|
commonizerProducer = {
|
||||||
|
PropertyCommonizer(FunctionOrPropertyBaseCommonizer(classifiers, settings, TypeCommonizer(classifiers, settings)))
|
||||||
|
},
|
||||||
nodeProducer = ::CirPropertyNode
|
nodeProducer = ::CirPropertyNode
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ internal fun buildFunctionNode(
|
|||||||
nodeRelationship = nodeRelationship,
|
nodeRelationship = nodeRelationship,
|
||||||
commonizerProducer = {
|
commonizerProducer = {
|
||||||
val typeCommonizer = TypeCommonizer(classifiers, settings)
|
val typeCommonizer = TypeCommonizer(classifiers, settings)
|
||||||
FunctionCommonizer(typeCommonizer, FunctionOrPropertyBaseCommonizer(typeCommonizer)).asCommonizer()
|
FunctionCommonizer(typeCommonizer, FunctionOrPropertyBaseCommonizer(classifiers, settings, typeCommonizer)).asCommonizer()
|
||||||
},
|
},
|
||||||
nodeProducer = ::CirFunctionNode
|
nodeProducer = ::CirFunctionNode
|
||||||
)
|
)
|
||||||
|
|||||||
native/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt
Vendored
+4
@@ -28,9 +28,13 @@ expect fun function6(): Planet
|
|||||||
expect fun function7(): C
|
expect fun function7(): C
|
||||||
|
|
||||||
// Optimistic Number Commonization: KT-48455, KT-48568
|
// Optimistic Number Commonization: KT-48455, KT-48568
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Int", "jvm: kotlin.Long"])
|
||||||
expect val propertyWithMismatchedType1: Int
|
expect val propertyWithMismatchedType1: Int
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Int", "jvm: kotlin.Short"])
|
||||||
expect val propertyWithMismatchedType2: Short
|
expect val propertyWithMismatchedType2: Short
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Int", "jvm: kotlin.Long"])
|
||||||
expect fun functionWithMismatchedType1(): Int
|
expect fun functionWithMismatchedType1(): Int
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Int", "jvm: kotlin.Short"])
|
||||||
expect fun functionWithMismatchedType2(): Short
|
expect fun functionWithMismatchedType2(): Short
|
||||||
|
|
||||||
expect class Box<T>(value: T) {
|
expect class Box<T>(value: T) {
|
||||||
|
|||||||
native/commonizer/testData/callableMemberCommonization/returnTypes/dependency/common/UnsafeNumber.kt
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package kotlinx.cinterop
|
||||||
|
@Target(AnnotationTarget.TYPEALIAS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
annotation class UnsafeNumber(val actualPlatformTypes: Array<String>)
|
||||||
Vendored
+4
@@ -22,7 +22,11 @@ expect val property20: Char
|
|||||||
|
|
||||||
// Optimistic Number Commonization: KT-48455, KT-48568
|
// Optimistic Number Commonization: KT-48455, KT-48568
|
||||||
// Mismatched const types should be commonized as expect val's
|
// Mismatched const types should be commonized as expect val's
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Short", "jvm: kotlin.Byte"])
|
||||||
expect val property22: Byte
|
expect val property22: Byte
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Int", "jvm: kotlin.Short"])
|
||||||
expect val property23: Short
|
expect val property23: Short
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Long", "jvm: kotlin.Int"])
|
||||||
expect val property24: Int
|
expect val property24: Int
|
||||||
|
@kotlinx.cinterop.UnsafeNumber(["js: kotlin.Float", "jvm: kotlin.Double"])
|
||||||
expect val property26: Float
|
expect val property26: Float
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package kotlinx.cinterop
|
||||||
|
@Target(AnnotationTarget.TYPEALIAS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
annotation class UnsafeNumber(val actualPlatformTypes: Array<String>)
|
||||||
+78
-1
@@ -707,12 +707,18 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
|
|||||||
val result = commonize {
|
val result = commonize {
|
||||||
outputTarget("(a, b)")
|
outputTarget("(a, b)")
|
||||||
setting(OptimisticNumberCommonizationEnabledKey, true)
|
setting(OptimisticNumberCommonizationEnabledKey, true)
|
||||||
|
registerFakeStdlibIntegersDependency("(a, b)")
|
||||||
registerDependency("a", "b", "(a, b)") { unsignedIntegers() }
|
registerDependency("a", "b", "(a, b)") { unsignedIntegers() }
|
||||||
simpleSingleSourceTarget("a", "val x: UInt = null!!")
|
simpleSingleSourceTarget("a", "val x: UInt = null!!")
|
||||||
simpleSingleSourceTarget("b", "val x: ULong = null!!")
|
simpleSingleSourceTarget("b", "val x: ULong = null!!")
|
||||||
}
|
}
|
||||||
|
|
||||||
result.assertCommonized("(a, b)", "expect val x: kotlin.UInt")
|
result.assertCommonized(
|
||||||
|
"(a, b)", """
|
||||||
|
@UnsafeNumber(["a: kotlin.UInt", "b: kotlin.ULong"])
|
||||||
|
expect val x: kotlin.UInt
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun `test property with aliased number return type`() {
|
fun `test property with aliased number return type`() {
|
||||||
@@ -790,4 +796,75 @@ class HierarchicalOptimisticNumbersTypeCommonizerTest : AbstractInlineSourcesCom
|
|||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return types, unlike parameter types, don't participate in function signature, and therefore can be commonized optimistically
|
||||||
|
fun `test optimistic commonization in function return types`() {
|
||||||
|
val result = commonize {
|
||||||
|
outputTarget("(a, b)")
|
||||||
|
setting(OptimisticNumberCommonizationEnabledKey, true)
|
||||||
|
registerFakeStdlibIntegersDependency(("(a, b)"))
|
||||||
|
|
||||||
|
"a" withSource """
|
||||||
|
fun explicitReturnType(): Short {
|
||||||
|
return 42
|
||||||
|
}
|
||||||
|
|
||||||
|
fun implicitReturnType() = 42
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
"b" withSource """
|
||||||
|
fun explicitReturnType(): Long {
|
||||||
|
return 42L
|
||||||
|
}
|
||||||
|
|
||||||
|
fun implicitReturnType() = 42L
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
result.assertCommonized(
|
||||||
|
"(a, b)", """
|
||||||
|
import kotlinx.cinterop.*
|
||||||
|
|
||||||
|
@UnsafeNumber(["a: kotlin.Short", "b: kotlin.Long"])
|
||||||
|
expect fun explicitReturnType(): Short
|
||||||
|
|
||||||
|
@UnsafeNumber(["a: kotlin.Int", "b: kotlin.Long"])
|
||||||
|
expect fun implicitReturnType(): Int
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun `test optimistic commonization in property return types`() {
|
||||||
|
val result = commonize {
|
||||||
|
outputTarget("(a, b)")
|
||||||
|
setting(OptimisticNumberCommonizationEnabledKey, true)
|
||||||
|
registerFakeStdlibIntegersDependency(("(a, b)"))
|
||||||
|
|
||||||
|
"a" withSource """
|
||||||
|
val explicitReturnType: Short
|
||||||
|
get() = 42
|
||||||
|
|
||||||
|
val implicitReturnType = 42
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
"b" withSource """
|
||||||
|
val explicitReturnType: Long
|
||||||
|
get() = 42L
|
||||||
|
|
||||||
|
val implicitReturnType = 42L
|
||||||
|
""".trimIndent()
|
||||||
|
}
|
||||||
|
|
||||||
|
result.assertCommonized(
|
||||||
|
"(a, b)", """
|
||||||
|
import kotlinx.cinterop.*
|
||||||
|
|
||||||
|
@UnsafeNumber(["a: kotlin.Short", "b: kotlin.Long"])
|
||||||
|
expect val explicitReturnType: Short
|
||||||
|
|
||||||
|
@UnsafeNumber(["a: kotlin.Int", "b: kotlin.Long"])
|
||||||
|
expect val implicitReturnType: Int
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -60,7 +60,7 @@ internal fun InlineSourceBuilder.ModuleBuilder.unsafeNumberAnnotationSource() {
|
|||||||
source(
|
source(
|
||||||
"""
|
"""
|
||||||
package kotlinx.cinterop
|
package kotlinx.cinterop
|
||||||
@Target(AnnotationTarget.TYPEALIAS)
|
@Target(AnnotationTarget.TYPEALIAS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class UnsafeNumber(val actualPlatformTypes: Array<String>)
|
annotation class UnsafeNumber(val actualPlatformTypes: Array<String>)
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
|
|||||||
Reference in New Issue
Block a user