K2: support implicit integer to unsigned conversions...

with dedicated opt-in language feature and special
annotation or module capability.
Not intended for a general use, solves specific K/N
scenario with interop libs.
#KT-55902 fixed
This commit is contained in:
Ilya Chernikov
2023-02-04 13:21:58 +01:00
committed by Space Team
parent 3e2f8b834c
commit be2a85be71
30 changed files with 581 additions and 29 deletions
@@ -18,7 +18,8 @@ class BinaryModuleData(
fun createDependencyModuleData(
name: Name,
platform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices
analyzerServices: PlatformDependentAnalyzerServices,
capabilities: FirModuleCapabilities = FirModuleCapabilities.Empty
): FirModuleData {
return FirModuleDataImpl(
name,
@@ -27,6 +28,7 @@ class BinaryModuleData(
friendDependencies = emptyList(),
platform,
analyzerServices,
capabilities
)
}
@@ -29,17 +29,24 @@ class DependencyListForCliModule(
private val allFriendsDependencies = mutableListOf<FirModuleData>()
private val allDependsOnDependencies = mutableListOf<FirModuleData>()
private val filtersMap: Map<FirModuleData, MutableSet<Path>> =
private val filtersMap =
listOf(
binaryModuleData.dependsOn,
binaryModuleData.friends,
binaryModuleData.regular
).associateWith { mutableSetOf() }
).associateWithTo(mutableMapOf<FirModuleData, MutableSet<Path>>()) { mutableSetOf() }
fun dependency(vararg path: Path) {
filtersMap.getValue(binaryModuleData.regular) += path
}
fun dependency(moduleData: FirModuleData, vararg path: Path) {
filtersMap.getOrPut(moduleData) {
allRegularDependencies.add(moduleData)
mutableSetOf()
} += path
}
fun dependency(vararg path: String) {
path.mapTo(filtersMap.getValue(binaryModuleData.regular)) { Paths.get(it) }
}
@@ -49,6 +56,18 @@ class DependencyListForCliModule(
paths.mapTo(filtersMap.getValue(binaryModuleData.regular)) { Paths.get(it) }
}
@JvmName("dependenciesString")
fun dependencies(moduleData: FirModuleData, paths: Collection<String>) {
paths.mapTo(
filtersMap.getOrPut(moduleData) {
allRegularDependencies.add(moduleData)
mutableSetOf()
}
) {
Paths.get(it)
}
}
@JvmName("friendDependenciesString")
fun friendDependencies(paths: Collection<String>) {
paths.mapTo(filtersMap.getValue(binaryModuleData.friends)) { Paths.get(it) }
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
@@ -14,16 +16,14 @@ import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression
import org.jetbrains.kotlin.fir.getContainingClassLookupTag
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.references.*
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.approximateDeclarationType
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -935,7 +935,9 @@ class CallAndReferenceGenerator(
irArgument = irArgument.applySamConversionIfNeeded(argument, parameter, substitutor)
}
}
return irArgument.applyAssigningArrayElementsToVarargInNamedForm(argument, parameter)
return irArgument
.applyAssigningArrayElementsToVarargInNamedForm(argument, parameter)
.applyImplicitIntegerCoercionIfNeeded(argument, parameter)
}
private fun IrExpression.applyAssigningArrayElementsToVarargInNamedForm(
@@ -962,6 +964,66 @@ class CallAndReferenceGenerator(
return this
}
private fun IrExpression.applyImplicitIntegerCoercionIfNeeded(
argument: FirExpression,
parameter: FirValueParameter?
): IrExpression {
if (!session.languageVersionSettings.supportsFeature(LanguageFeature.ImplicitSignedToUnsignedIntegerConversion)) return this
if (parameter == null || !parameter.isMarkedWithImplicitIntegerCoercion) return this
fun IrExpression.applyToElement(argument: FirExpression, conversionFunction: IrSimpleFunctionSymbol): IrExpression =
if (argument is FirConstExpression<*> ||
argument.calleeReference?.toResolvedCallableSymbol()?.let {
it.resolvedStatus.isConst && it.isMarkedWithImplicitIntegerCoercion
} == true
) {
IrCallImpl(
startOffset, endOffset,
conversionFunction.owner.returnType,
conversionFunction,
typeArgumentsCount = 0,
valueArgumentsCount = 0
).apply {
extensionReceiver = this@applyToElement
}
} else this@applyToElement
if (parameter.isMarkedWithImplicitIntegerCoercion) {
if (this is IrVarargImpl && argument is FirVarargArgumentsExpression) {
val targetTypeFqName = varargElementType.classFqName ?: return this
val conversionFunctions = irBuiltIns.getNonBuiltInFunctionsByExtensionReceiver(
Name.identifier("to" + targetTypeFqName.shortName().asString()),
StandardNames.BUILT_INS_PACKAGE_NAME.asString()
)
if (conversionFunctions.isNotEmpty()) {
elements.forEachIndexed { i, irVarargElement ->
val targetFun = argument.arguments[i].typeRef.toIrType().classifierOrNull?.let { conversionFunctions[it] }
if (targetFun != null && irVarargElement is IrExpression) {
elements[i] =
irVarargElement.applyToElement(argument.arguments[i], targetFun)
}
}
}
return this
} else {
val targetIrType = parameter.returnTypeRef.toIrType()
val targetTypeFqName = targetIrType.classFqName ?: return this
val conversionFunctions = irBuiltIns.getNonBuiltInFunctionsByExtensionReceiver(
Name.identifier("to" + targetTypeFqName.shortName().asString()),
StandardNames.BUILT_INS_PACKAGE_NAME.asString()
)
val sourceTypeClassifier = argument.typeRef.toIrType().classifierOrNull ?: return this
val conversionFunction = conversionFunctions[sourceTypeClassifier] ?: return this
return this.applyToElement(argument, conversionFunction)
}
}
return this
}
internal fun IrExpression.applyTypeArguments(access: FirQualifiedAccessExpression): IrExpression {
if (this !is IrMemberAccessExpression<*>) return this
val argumentsCount = access.typeArguments.size
@@ -51555,6 +51555,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -51555,6 +51555,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2023 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.fir.resolve
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.fir.FirModuleCapability
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.resolvedAnnotationClassIds
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import kotlin.reflect.KClass
object ImplicitIntegerCoercionModuleCapability : FirModuleCapability() {
override val key: KClass<out FirModuleCapability> = ImplicitIntegerCoercionModuleCapability::class
}
private val implicitIntegerCoercionAnnotationClassId =
ClassId(StandardNames.KOTLIN_INTERNAL_FQ_NAME, Name.identifier("ImplicitIntegerCoercion"))
val FirCallableSymbol<*>.isMarkedWithImplicitIntegerCoercion
get() =
fir.moduleData.capabilities.contains(ImplicitIntegerCoercionModuleCapability) ||
resolvedAnnotationClassIds.any { it == implicitIntegerCoercionAnnotationClassId }
val FirCallableDeclaration.isMarkedWithImplicitIntegerCoercion
get() =
moduleData.capabilities.contains(ImplicitIntegerCoercionModuleCapability) ||
resolvedAnnotationClassIds(symbol).any { it == implicitIntegerCoercionAnnotationClassId }
@@ -6,16 +6,16 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.builtins.functions.isBasicFunctionOrKFunction
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.lookupTracker
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.createFunctionType
import org.jetbrains.kotlin.fir.expressions.unwrapSmartcastExpression
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.inference.LambdaWithTypeVariableAsExpectedTypeAtom
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeReceiverConstraintPosition
@@ -487,7 +487,9 @@ private fun Candidate.prepareExpectedType(
)
}
}
} ?: basicExpectedType
}
?: getExpectedTypeWithImplicintIntegerCoercion(session, argument, parameter, basicExpectedType)
?: basicExpectedType
return this.substitutor.substituteOrSelf(expectedType)
}
@@ -510,6 +512,29 @@ private fun Candidate.getExpectedTypeWithSAMConversion(
}
}
private fun getExpectedTypeWithImplicintIntegerCoercion(
session: FirSession,
argument: FirExpression,
parameter: FirValueParameter,
candidateExpectedType: ConeKotlinType
): ConeKotlinType? {
if (!session.languageVersionSettings.supportsFeature(LanguageFeature.ImplicitSignedToUnsignedIntegerConversion)) return null
if (!parameter.isMarkedWithImplicitIntegerCoercion) return null
val argumentType =
if (argument.isIntegerLiteralOrOperatorCall()) argument.resultType.coneType
else {
argument.calleeReference?.toResolvedCallableSymbol()?.takeIf {
it.rawStatus.isConst && it.isMarkedWithImplicitIntegerCoercion
}?.resolvedReturnType
}
// TODO: consider adding a check that argument could be converted to the parameter type (maybe difficult for platform types)
return argumentType?.withNullability(candidateExpectedType.nullability, session.typeContext)
}
fun FirExpression.isFunctional(
session: FirSession,
scopeSession: ScopeSession,
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2023 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.fir
import org.jetbrains.kotlin.fir.util.ConeTypeRegistry
import org.jetbrains.kotlin.util.AttributeArrayOwner
import org.jetbrains.kotlin.util.TypeRegistry
import kotlin.reflect.KClass
abstract class FirModuleCapability {
abstract val key: KClass<out FirModuleCapability>
}
class FirModuleCapabilities private constructor(
capabilities: List<FirModuleCapability>
) : AttributeArrayOwner<FirModuleCapability, FirModuleCapability>() {
companion object : ConeTypeRegistry<FirModuleCapability, FirModuleCapability>() {
val Empty: FirModuleCapabilities = FirModuleCapabilities(emptyList())
fun create(attributes: List<FirModuleCapability>): FirModuleCapabilities {
return if (attributes.isEmpty()) {
Empty
} else {
FirModuleCapabilities(attributes)
}
}
}
init {
for (capability in capabilities) {
registerComponent(capability.key, capability)
}
}
override val typeRegistry: TypeRegistry<FirModuleCapability, FirModuleCapability>
get() = Companion
}
@@ -50,6 +50,9 @@ abstract class FirModuleData : FirSessionComponent {
// refactor them to make API clearer
abstract val analyzerServices: PlatformDependentAnalyzerServices
open val capabilities: FirModuleCapabilities
get() = FirModuleCapabilities.Empty
private var _session: FirSession? = null
val session: FirSession
get() = _session
@@ -73,7 +76,8 @@ class FirModuleDataImpl(
override val dependsOnDependencies: List<FirModuleData>,
override val friendDependencies: List<FirModuleData>,
override val platform: TargetPlatform,
override val analyzerServices: PlatformDependentAnalyzerServices
override val analyzerServices: PlatformDependentAnalyzerServices,
override val capabilities: FirModuleCapabilities = FirModuleCapabilities.Empty
) : FirModuleData()
val FirSession.nullableModuleData: FirModuleData? by FirSession.nullableSessionComponentAccessor()
@@ -31,6 +31,9 @@ val FirTypeRef.coneType: ConeKotlinType
get() = coneTypeSafe()
?: error("Expected FirResolvedTypeRef with ConeKotlinType but was ${this::class.simpleName} ${render()}")
val FirTypeRef.coneTypeOrNull: ConeKotlinType?
get() = coneTypeSafe()
val FirTypeRef.isAny: Boolean get() = isBuiltinType(StandardClassIds.Any, false)
val FirTypeRef.isNullableAny: Boolean get() = isBuiltinType(StandardClassIds.Any, true)
val FirTypeRef.isNothing: Boolean get() = isBuiltinType(StandardClassIds.Nothing, false)
@@ -0,0 +1,57 @@
// WITH_STDLIB
// !LANGUAGE: +ImplicitSignedToUnsignedIntegerConversion
// IGNORE_BACKEND_K1: JVM
// FILE: signedToUnsignedConversions_annotation.kt
package kotlin.internal
annotation class ImplicitIntegerCoercion
// FILE: signedToUnsignedConversions_test.kt
import kotlin.internal.ImplicitIntegerCoercion
@ImplicitIntegerCoercion
const val IMPLICIT_INT = 255
@ImplicitIntegerCoercion
const val EXPLICIT_INT: Int = 255
@ImplicitIntegerCoercion
const val LONG_CONST = 255L
@ImplicitIntegerCoercion
val NON_CONST = 255
@ImplicitIntegerCoercion
const val BIGGER_THAN_UBYTE = 256
@ImplicitIntegerCoercion
const val UINT_CONST = 42u
fun takeUByte(@ImplicitIntegerCoercion u: UByte) {}
fun takeUShort(@ImplicitIntegerCoercion u: UShort) {}
fun takeUInt(@ImplicitIntegerCoercion u: UInt) {}
fun takeULong(@ImplicitIntegerCoercion u: ULong) {}
fun takeUBytes(@ImplicitIntegerCoercion vararg u: UByte) {}
fun takeLong(@ImplicitIntegerCoercion l: Long) {}
fun box(): String {
takeUByte(IMPLICIT_INT)
takeUByte(EXPLICIT_INT)
takeUShort(IMPLICIT_INT)
takeUShort(BIGGER_THAN_UBYTE)
takeUInt(IMPLICIT_INT)
takeULong(IMPLICIT_INT)
takeUBytes(IMPLICIT_INT, EXPLICIT_INT, 42u)
// such kind of conversions (Int <-> Long) actually are not supported
// takeLong(IMPLICIT_INT)
return "OK"
}
@@ -35,6 +35,7 @@ fun takeUShort(@ImplicitIntegerCoercion u: UShort) {}
fun takeUInt(@ImplicitIntegerCoercion u: UInt) {}
fun takeULong(@ImplicitIntegerCoercion u: ULong) {}
@ExperimentalUnsignedTypes
fun takeUBytes(@ImplicitIntegerCoercion vararg u: <!OPT_IN_USAGE!>UByte<!>) {}
fun takeLong(@ImplicitIntegerCoercion l: Long) {}
@@ -44,27 +45,27 @@ fun takeUIntWithoutAnnotaion(u: UInt) {}
fun takeIntWithoutAnnotation(i: Int) {}
fun test() {
takeUByte(<!ARGUMENT_TYPE_MISMATCH!>IMPLICIT_INT<!>)
takeUByte(<!ARGUMENT_TYPE_MISMATCH!>EXPLICIT_INT<!>)
takeUByte(IMPLICIT_INT)
takeUByte(EXPLICIT_INT)
takeUShort(<!ARGUMENT_TYPE_MISMATCH!>IMPLICIT_INT<!>)
takeUShort(<!ARGUMENT_TYPE_MISMATCH!>BIGGER_THAN_UBYTE<!>)
takeUShort(IMPLICIT_INT)
takeUShort(BIGGER_THAN_UBYTE)
takeUInt(<!ARGUMENT_TYPE_MISMATCH!>IMPLICIT_INT<!>)
takeUInt(IMPLICIT_INT)
takeULong(<!ARGUMENT_TYPE_MISMATCH!>IMPLICIT_INT<!>)
takeULong(IMPLICIT_INT)
<!OPT_IN_USAGE!>takeUBytes<!>(<!ARGUMENT_TYPE_MISMATCH!>IMPLICIT_INT<!>, <!ARGUMENT_TYPE_MISMATCH!>EXPLICIT_INT<!>, 42u)
<!OPT_IN_USAGE!>takeUBytes<!>(IMPLICIT_INT, EXPLICIT_INT, 42u)
takeLong(<!ARGUMENT_TYPE_MISMATCH!>IMPLICIT_INT<!>)
takeLong(IMPLICIT_INT)
takeIntWithoutAnnotation(IMPLICIT_INT)
takeUIntWithoutAnnotaion(UINT_CONST)
takeUByte(<!ARGUMENT_TYPE_MISMATCH!>LONG_CONST<!>)
takeUByte(LONG_CONST)
takeUByte(<!ARGUMENT_TYPE_MISMATCH!>NON_CONST<!>)
takeUByte(<!ARGUMENT_TYPE_MISMATCH!>BIGGER_THAN_UBYTE<!>)
takeUByte(<!ARGUMENT_TYPE_MISMATCH!>UINT_CONST<!>)
takeUByte(BIGGER_THAN_UBYTE)
takeUByte(UINT_CONST)
takeUIntWithoutAnnotaion(<!ARGUMENT_TYPE_MISMATCH!>IMPLICIT_INT<!>)
}
@@ -35,6 +35,7 @@ fun takeUShort(@ImplicitIntegerCoercion u: UShort) {}
fun takeUInt(@ImplicitIntegerCoercion u: UInt) {}
fun takeULong(@ImplicitIntegerCoercion u: ULong) {}
@ExperimentalUnsignedTypes
fun takeUBytes(@ImplicitIntegerCoercion vararg u: UByte) {}
fun takeLong(@ImplicitIntegerCoercion l: Long) {}
@@ -9,7 +9,7 @@ package
public fun takeIntWithoutAnnotation(/*0*/ i: kotlin.Int): kotlin.Unit
public fun takeLong(/*0*/ @kotlin.internal.ImplicitIntegerCoercion l: kotlin.Long): kotlin.Unit
public fun takeUByte(/*0*/ @kotlin.internal.ImplicitIntegerCoercion u: kotlin.UByte): kotlin.Unit
public fun takeUBytes(/*0*/ @kotlin.internal.ImplicitIntegerCoercion vararg u: kotlin.UByte /*kotlin.UByteArray*/): kotlin.Unit
@kotlin.ExperimentalUnsignedTypes public fun takeUBytes(/*0*/ @kotlin.internal.ImplicitIntegerCoercion vararg u: kotlin.UByte /*kotlin.UByteArray*/): kotlin.Unit
public fun takeUInt(/*0*/ @kotlin.internal.ImplicitIntegerCoercion u: kotlin.UInt): kotlin.Unit
public fun takeUIntWithoutAnnotaion(/*0*/ u: kotlin.UInt): kotlin.Unit
public fun takeULong(/*0*/ @kotlin.internal.ImplicitIntegerCoercion u: kotlin.ULong): kotlin.Unit
@@ -0,0 +1,144 @@
FILE fqName:kotlin.internal fileName:/signedToUnsignedConversions_annotation.kt
CLASS ANNOTATION_CLASS name:ImplicitIntegerCoercion modality:OPEN visibility:public superTypes:[kotlin.Annotation]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:kotlin.internal.ImplicitIntegerCoercion
CONSTRUCTOR visibility:public <> () returnType:kotlin.internal.ImplicitIntegerCoercion [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:ImplicitIntegerCoercion modality:OPEN visibility:public superTypes:[kotlin.Annotation]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String [fake_override] declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FILE fqName:<root> fileName:/signedToUnsignedConversions_test.kt
PROPERTY name:IMPLICIT_INT visibility:public modality:FINAL [const,val]
annotations:
ImplicitIntegerCoercion
FIELD PROPERTY_BACKING_FIELD name:IMPLICIT_INT type:kotlin.Int visibility:public [final,static]
EXPRESSION_BODY
CONST Int type=kotlin.Int value=255
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-IMPLICIT_INT> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:IMPLICIT_INT visibility:public modality:FINAL [const,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-IMPLICIT_INT> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:IMPLICIT_INT type:kotlin.Int visibility:public [final,static]' type=kotlin.Int origin=null
PROPERTY name:EXPLICIT_INT visibility:public modality:FINAL [const,val]
annotations:
ImplicitIntegerCoercion
FIELD PROPERTY_BACKING_FIELD name:EXPLICIT_INT type:kotlin.Int visibility:public [final,static]
EXPRESSION_BODY
CONST Int type=kotlin.Int value=255
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-EXPLICIT_INT> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:EXPLICIT_INT visibility:public modality:FINAL [const,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-EXPLICIT_INT> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:EXPLICIT_INT type:kotlin.Int visibility:public [final,static]' type=kotlin.Int origin=null
PROPERTY name:LONG_CONST visibility:public modality:FINAL [const,val]
annotations:
ImplicitIntegerCoercion
FIELD PROPERTY_BACKING_FIELD name:LONG_CONST type:kotlin.Long visibility:public [final,static]
EXPRESSION_BODY
CONST Long type=kotlin.Long value=255
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-LONG_CONST> visibility:public modality:FINAL <> () returnType:kotlin.Long
correspondingProperty: PROPERTY name:LONG_CONST visibility:public modality:FINAL [const,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-LONG_CONST> (): kotlin.Long declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:LONG_CONST type:kotlin.Long visibility:public [final,static]' type=kotlin.Long origin=null
PROPERTY name:NON_CONST visibility:public modality:FINAL [val]
annotations:
ImplicitIntegerCoercion
FIELD PROPERTY_BACKING_FIELD name:NON_CONST type:kotlin.Int visibility:private [final,static]
EXPRESSION_BODY
CONST Int type=kotlin.Int value=255
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-NON_CONST> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:NON_CONST visibility:public modality:FINAL [val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-NON_CONST> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:NON_CONST type:kotlin.Int visibility:private [final,static]' type=kotlin.Int origin=null
PROPERTY name:BIGGER_THAN_UBYTE visibility:public modality:FINAL [const,val]
annotations:
ImplicitIntegerCoercion
FIELD PROPERTY_BACKING_FIELD name:BIGGER_THAN_UBYTE type:kotlin.Int visibility:public [final,static]
EXPRESSION_BODY
CONST Int type=kotlin.Int value=256
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-BIGGER_THAN_UBYTE> visibility:public modality:FINAL <> () returnType:kotlin.Int
correspondingProperty: PROPERTY name:BIGGER_THAN_UBYTE visibility:public modality:FINAL [const,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-BIGGER_THAN_UBYTE> (): kotlin.Int declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:BIGGER_THAN_UBYTE type:kotlin.Int visibility:public [final,static]' type=kotlin.Int origin=null
PROPERTY name:UINT_CONST visibility:public modality:FINAL [const,val]
annotations:
ImplicitIntegerCoercion
FIELD PROPERTY_BACKING_FIELD name:UINT_CONST type:kotlin.UInt visibility:public [final,static]
EXPRESSION_BODY
CONST Int type=kotlin.UInt value=42
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-UINT_CONST> visibility:public modality:FINAL <> () returnType:kotlin.UInt
correspondingProperty: PROPERTY name:UINT_CONST visibility:public modality:FINAL [const,val]
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-UINT_CONST> (): kotlin.UInt declared in <root>'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:UINT_CONST type:kotlin.UInt visibility:public [final,static]' type=kotlin.UInt origin=null
FUN name:takeUByte visibility:public modality:FINAL <> (u:kotlin.UByte) returnType:kotlin.Unit
VALUE_PARAMETER name:u index:0 type:kotlin.UByte
annotations:
ImplicitIntegerCoercion
BLOCK_BODY
FUN name:takeUShort visibility:public modality:FINAL <> (u:kotlin.UShort) returnType:kotlin.Unit
VALUE_PARAMETER name:u index:0 type:kotlin.UShort
annotations:
ImplicitIntegerCoercion
BLOCK_BODY
FUN name:takeUInt visibility:public modality:FINAL <> (u:kotlin.UInt) returnType:kotlin.Unit
VALUE_PARAMETER name:u index:0 type:kotlin.UInt
annotations:
ImplicitIntegerCoercion
BLOCK_BODY
FUN name:takeULong visibility:public modality:FINAL <> (u:kotlin.ULong) returnType:kotlin.Unit
VALUE_PARAMETER name:u index:0 type:kotlin.ULong
annotations:
ImplicitIntegerCoercion
BLOCK_BODY
FUN name:takeUBytes visibility:public modality:FINAL <> (u:kotlin.UByteArray) returnType:kotlin.Unit
VALUE_PARAMETER name:u index:0 type:kotlin.UByteArray varargElementType:kotlin.UByte [vararg]
annotations:
ImplicitIntegerCoercion
BLOCK_BODY
FUN name:takeLong visibility:public modality:FINAL <> (l:kotlin.Long) returnType:kotlin.Unit
VALUE_PARAMETER name:l index:0 type:kotlin.Long
annotations:
ImplicitIntegerCoercion
BLOCK_BODY
FUN name:test visibility:public modality:FINAL <> () returnType:kotlin.Unit
BLOCK_BODY
CALL 'public final fun takeUByte (u: kotlin.UByte): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
u: CALL 'public final fun toUByte (): kotlin.UByte [inline] declared in kotlin.UByteKt' type=kotlin.UByte origin=null
$receiver: CONST Int type=kotlin.Int value=255
CALL 'public final fun takeUByte (u: kotlin.UByte): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
u: CALL 'public final fun toUByte (): kotlin.UByte [inline] declared in kotlin.UByteKt' type=kotlin.UByte origin=null
$receiver: CONST Int type=kotlin.Int value=255
CALL 'public final fun takeUShort (u: kotlin.UShort): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
u: CALL 'public final fun toUShort (): kotlin.UShort [inline] declared in kotlin.UShortKt' type=kotlin.UShort origin=null
$receiver: CONST Int type=kotlin.Int value=255
CALL 'public final fun takeUShort (u: kotlin.UShort): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
u: CALL 'public final fun toUShort (): kotlin.UShort [inline] declared in kotlin.UShortKt' type=kotlin.UShort origin=null
$receiver: CONST Int type=kotlin.Int value=256
CALL 'public final fun takeUInt (u: kotlin.UInt): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
u: CALL 'public final fun toUInt (): kotlin.UInt [inline] declared in kotlin.UIntKt' type=kotlin.UInt origin=null
$receiver: CONST Int type=kotlin.Int value=255
CALL 'public final fun takeULong (u: kotlin.ULong): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
u: CALL 'public final fun toULong (): kotlin.ULong [inline] declared in kotlin.ULongKt' type=kotlin.ULong origin=null
$receiver: CONST Int type=kotlin.Int value=255
CALL 'public final fun takeUBytes (vararg u: kotlin.UByte): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
u: VARARG type=kotlin.UByteArray varargElementType=kotlin.UByte
CALL 'public final fun toUByte (): kotlin.UByte [inline] declared in kotlin.UByteKt' type=kotlin.UByte origin=null
$receiver: CONST Int type=kotlin.Int value=255
CALL 'public final fun toUByte (): kotlin.UByte [inline] declared in kotlin.UByteKt' type=kotlin.UByte origin=null
$receiver: CONST Int type=kotlin.Int value=255
CONST Byte type=kotlin.UByte value=42
@@ -0,0 +1,71 @@
// FILE: signedToUnsignedConversions_annotation.kt
package kotlin.internal
open annotation class ImplicitIntegerCoercion : Annotation {
constructor() /* primary */ {
super/*Any*/()
/* <init>() */
}
}
// FILE: signedToUnsignedConversions_test.kt
@ImplicitIntegerCoercion
const val IMPLICIT_INT: Int
field = 255
get
@ImplicitIntegerCoercion
const val EXPLICIT_INT: Int
field = 255
get
@ImplicitIntegerCoercion
const val LONG_CONST: Long
field = 255L
get
@ImplicitIntegerCoercion
val NON_CONST: Int
field = 255
get
@ImplicitIntegerCoercion
const val BIGGER_THAN_UBYTE: Int
field = 256
get
@ImplicitIntegerCoercion
const val UINT_CONST: UInt
field = 42
get
fun takeUByte(@ImplicitIntegerCoercion u: UByte) {
}
fun takeUShort(@ImplicitIntegerCoercion u: UShort) {
}
fun takeUInt(@ImplicitIntegerCoercion u: UInt) {
}
fun takeULong(@ImplicitIntegerCoercion u: ULong) {
}
fun takeUBytes(@ImplicitIntegerCoercion vararg u: UByte) {
}
fun takeLong(@ImplicitIntegerCoercion l: Long) {
}
fun test() {
takeUByte(u = 255.toUByte())
takeUByte(u = 255.toUByte())
takeUShort(u = 255.toUShort())
takeUShort(u = 256.toUShort())
takeUInt(u = 255.toUInt())
takeULong(u = 255.toULong())
takeUBytes(u = [255.toUByte(), 255.toUByte(), 42B])
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_K2: JVM_IR
// WITH_STDLIB
// !LANGUAGE: +ImplicitSignedToUnsignedIntegerConversion
@@ -49125,6 +49125,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -51555,6 +51555,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -51555,6 +51555,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -39805,6 +39805,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnsignedTypes extends AbstractLightAnalysisModeTest {
@TestMetadata("signedToUnsignedConversions.kt")
public void ignoreSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -36497,6 +36497,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -36683,6 +36683,12 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -36683,6 +36683,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -36683,6 +36683,12 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -12,10 +12,13 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirModuleCapabilities
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.pipeline.buildResolveAndCheckFir
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.ImplicitIntegerCoercionModuleCapability
import org.jetbrains.kotlin.library.isInterop
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms
@@ -35,7 +38,17 @@ internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput {
}
val binaryModuleData = BinaryModuleData.initialize(mainModuleName, CommonPlatforms.defaultCommonPlatform, NativePlatformAnalyzerServices)
val dependencyList = DependencyListForCliModule.build(binaryModuleData) {
dependencies(config.resolvedLibraries.getFullList().map { it.libraryFile.absolutePath })
val (interopLibs, regularLibs) = config.resolvedLibraries.getFullList().partition { it.isInterop }
dependencies(regularLibs.map { it.libraryFile.absolutePath })
if (interopLibs.isNotEmpty()) {
val interopModuleData =
BinaryModuleData.createDependencyModuleData(
Name.special("<regular interop dependencies of $mainModuleName>"),
CommonPlatforms.defaultCommonPlatform, NativePlatformAnalyzerServices,
FirModuleCapabilities.create(listOf(ImplicitIntegerCoercionModuleCapability))
)
dependencies(interopModuleData, interopLibs.map { it.libraryFile.absolutePath })
}
friendDependencies(config.friendModuleFiles.map { it.absolutePath })
// TODO: !!! dependencies module data?
}
@@ -5326,7 +5326,7 @@ standaloneTest("interop_zlib") {
}
standaloneTest("interop_objc_illegal_sharing") {
disabled = !isAppleTarget(project) || isK2(project) // KT-55902
disabled = !isAppleTarget(project)
source = "interop/objc/illegal_sharing.kt"
UtilsKt.dependsOnPlatformLibs(it)
if (isExperimentalMM) {
@@ -40359,6 +40359,12 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -39854,6 +39854,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@Test
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@Test
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
@@ -32858,6 +32858,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/unsignedTypes/nullableUnsignedEqualsLiteral.kt");
}
@TestMetadata("signedToUnsignedConversions.kt")
public void testSignedToUnsignedConversions() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/signedToUnsignedConversions.kt");
}
@TestMetadata("unsignedArraySize.kt")
public void testUnsignedArraySize() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/unsignedArraySize.kt");