[IR] Support reflection for MFVC

Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com>

#KT-1179
This commit is contained in:
Evgeniy.Zhelenskiy
2023-03-02 01:48:02 +01:00
committed by Space Team
parent 1ff4906880
commit 88f293d4a9
52 changed files with 2910 additions and 172 deletions
@@ -43521,6 +43521,100 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("constructorWithMfvcParameters.kt")
public void testConstructorWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt");
}
@Test
@TestMetadata("fieldAccessors.kt")
public void testFieldAccessors() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt");
}
@Test
@TestMetadata("functionsWithMfvcParameters.kt")
public void testFunctionsWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt");
}
@Test
@TestMetadata("internalPrimaryValOfMfvc.kt")
public void testInternalPrimaryValOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt");
}
@Test
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt");
}
@Test
@TestMetadata("jvmStaticFunction.kt")
public void testJvmStaticFunction() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt");
}
@Test
@TestMetadata("mfvcConstructor.kt")
public void testMfvcConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt");
}
@Test
@TestMetadata("nonOverridingFunOfMfvc.kt")
public void testNonOverridingFunOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt");
}
@Test
@TestMetadata("nonOverridingVarOfMfvc.kt")
public void testNonOverridingVarOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt");
}
@Test
@TestMetadata("overridingFunOfMfvc.kt")
public void testOverridingFunOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt");
}
@Test
@TestMetadata("overridingVarOfMfvc.kt")
public void testOverridingVarOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt");
}
@Test
@TestMetadata("primaryValOfMfvc.kt")
public void testPrimaryValOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt");
}
@Test
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt");
}
@Test
@TestMetadata("suspendFunction.kt")
public void testSuspendFunction() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt");
}
}
}
@Nested
@@ -43640,6 +43734,24 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/callBy/manyMaskArguments.kt");
}
@Test
@TestMetadata("mfvcDefaultArguments.kt")
public void testMfvcDefaultArguments() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt");
}
@Test
@TestMetadata("mfvcFunctionsAndConstructors.kt")
public void testMfvcFunctionsAndConstructors() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt");
}
@Test
@TestMetadata("mfvcMembers.kt")
public void testMfvcMembers() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt");
}
@Test
@TestMetadata("nonDefaultParameterOmitted.kt")
public void testNonDefaultParameterOmitted() throws Exception {
@@ -44484,6 +44596,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithInlineClassArgument.kt");
}
@Test
@TestMetadata("reflectOnDefaultWithMfvcArgument.kt")
public void testReflectOnDefaultWithMfvcArgument() throws Exception {
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt");
}
@Test
@TestMetadata("reflectOnLambdaInArrayConstructor.kt")
public void testReflectOnLambdaInArrayConstructor() throws Exception {
@@ -44554,6 +44672,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithInlineClassParameters.kt");
}
@Test
@TestMetadata("constructorWithMfvcParameters.kt")
public void testConstructorWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt");
}
@Test
@TestMetadata("extensionProperty.kt")
public void testExtensionProperty() throws Exception {
@@ -44815,6 +44939,18 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/mapping/types/memberFunctions.kt");
}
@Test
@TestMetadata("mfvcInSignature.kt")
public void testMfvcInSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt");
}
@Test
@TestMetadata("mfvcPrimaryVal.kt")
public void testMfvcPrimaryVal() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt");
}
@Test
@TestMetadata("overrideAnyWithPrimitive.kt")
public void testOverrideAnyWithPrimitive() throws Exception {
@@ -44881,6 +45017,28 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("mfvcPrimaryVal.kt")
public void testMfvcPrimaryVal() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt");
}
@Test
@TestMetadata("suspendFunctionWithMfvcInSignature.kt")
public void testSuspendFunctionWithMfvcInSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt");
}
}
}
@Nested
@@ -45094,6 +45252,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/modifiers/javaVisibility.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/modifiers/mfvc.kt");
}
@Test
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
@@ -45904,6 +46068,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/typeOf/manyTypeArguments.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/mfvc.kt");
}
@Test
@TestMetadata("multipleLayers.kt")
public void testMultipleLayers() throws Exception {
@@ -46013,6 +46183,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt");
}
@Test
@TestMetadata("mutableCollections_after.kt")
public void testMutableCollections_after() throws Exception {
@@ -43521,6 +43521,100 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("constructorWithMfvcParameters.kt")
public void testConstructorWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt");
}
@Test
@TestMetadata("fieldAccessors.kt")
public void testFieldAccessors() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt");
}
@Test
@TestMetadata("functionsWithMfvcParameters.kt")
public void testFunctionsWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt");
}
@Test
@TestMetadata("internalPrimaryValOfMfvc.kt")
public void testInternalPrimaryValOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt");
}
@Test
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt");
}
@Test
@TestMetadata("jvmStaticFunction.kt")
public void testJvmStaticFunction() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt");
}
@Test
@TestMetadata("mfvcConstructor.kt")
public void testMfvcConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt");
}
@Test
@TestMetadata("nonOverridingFunOfMfvc.kt")
public void testNonOverridingFunOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt");
}
@Test
@TestMetadata("nonOverridingVarOfMfvc.kt")
public void testNonOverridingVarOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt");
}
@Test
@TestMetadata("overridingFunOfMfvc.kt")
public void testOverridingFunOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt");
}
@Test
@TestMetadata("overridingVarOfMfvc.kt")
public void testOverridingVarOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt");
}
@Test
@TestMetadata("primaryValOfMfvc.kt")
public void testPrimaryValOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt");
}
@Test
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt");
}
@Test
@TestMetadata("suspendFunction.kt")
public void testSuspendFunction() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt");
}
}
}
@Nested
@@ -43640,6 +43734,24 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/callBy/manyMaskArguments.kt");
}
@Test
@TestMetadata("mfvcDefaultArguments.kt")
public void testMfvcDefaultArguments() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt");
}
@Test
@TestMetadata("mfvcFunctionsAndConstructors.kt")
public void testMfvcFunctionsAndConstructors() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt");
}
@Test
@TestMetadata("mfvcMembers.kt")
public void testMfvcMembers() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt");
}
@Test
@TestMetadata("nonDefaultParameterOmitted.kt")
public void testNonDefaultParameterOmitted() throws Exception {
@@ -44484,6 +44596,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithInlineClassArgument.kt");
}
@Test
@TestMetadata("reflectOnDefaultWithMfvcArgument.kt")
public void testReflectOnDefaultWithMfvcArgument() throws Exception {
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt");
}
@Test
@TestMetadata("reflectOnLambdaInArrayConstructor.kt")
public void testReflectOnLambdaInArrayConstructor() throws Exception {
@@ -44554,6 +44672,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithInlineClassParameters.kt");
}
@Test
@TestMetadata("constructorWithMfvcParameters.kt")
public void testConstructorWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt");
}
@Test
@TestMetadata("extensionProperty.kt")
public void testExtensionProperty() throws Exception {
@@ -44815,6 +44939,18 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/mapping/types/memberFunctions.kt");
}
@Test
@TestMetadata("mfvcInSignature.kt")
public void testMfvcInSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt");
}
@Test
@TestMetadata("mfvcPrimaryVal.kt")
public void testMfvcPrimaryVal() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt");
}
@Test
@TestMetadata("overrideAnyWithPrimitive.kt")
public void testOverrideAnyWithPrimitive() throws Exception {
@@ -44881,6 +45017,28 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("mfvcPrimaryVal.kt")
public void testMfvcPrimaryVal() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt");
}
@Test
@TestMetadata("suspendFunctionWithMfvcInSignature.kt")
public void testSuspendFunctionWithMfvcInSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt");
}
}
}
@Nested
@@ -45094,6 +45252,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/modifiers/javaVisibility.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/modifiers/mfvc.kt");
}
@Test
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
@@ -45904,6 +46068,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/typeOf/manyTypeArguments.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/mfvc.kt");
}
@Test
@TestMetadata("multipleLayers.kt")
public void testMultipleLayers() throws Exception {
@@ -46013,6 +46183,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt");
}
@Test
@TestMetadata("mutableCollections_after.kt")
public void testMutableCollections_after() throws Exception {
@@ -105,15 +105,14 @@ internal class JvmMultiFieldValueClassLowering(
return expressions.subList(0, expressions.size - repeatable.size) to repeatable
}
private fun IrBuilderWithScope.castedToNotNull(expression: IrExpression) =
if (expression.type.isNullable()) irImplicitCast(expression, expression.type.makeNotNull()) else expression
fun IrBlockBuilder.addReplacement(expression: IrSetValue, safe: Boolean): IrExpression? {
oldValueSymbol2NewValueSymbol[expression.symbol]?.let {
return irSet(it.owner, expression.value).also { irSet -> +irSet }
}
val instance = oldSymbol2MfvcNodeInstance[expression.symbol] ?: return null
val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(instance.node, safe, castedToNotNull(expression.value))
val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(
instance.node, safe, castExpressionToNotNullTypeIfNeeded(expression.value, instance.type)
)
val setterExpressions = instance.makeSetterExpressions(this, values)
expression2MfvcNodeInstanceAccessor[setterExpressions] = MfvcNodeInstanceAccessor.Setter(instance, values)
+setterExpressions
@@ -166,7 +165,9 @@ internal class JvmMultiFieldValueClassLowering(
accessType = AccessType.AlwaysPrivate,
saveVariable = ::variablesSaver
)
val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(node, safe, castedToNotNull(expression.value))
val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(
node, safe, castExpressionToNotNullTypeIfNeeded(expression.value, node.type)
)
val setterExpressions = instance.makeSetterExpressions(this, values)
expression2MfvcNodeInstanceAccessor[setterExpressions] = MfvcNodeInstanceAccessor.Setter(instance, values)
+setterExpressions
@@ -318,6 +319,12 @@ internal class JvmMultiFieldValueClassLowering(
if (replacingDeclaration in possibleExtraBoxUsageGenerated) removeAllExtraBoxes()
} as IrBlockBody
is IrField -> replacingDeclaration.initializer = replacingDeclaration.initializer?.makeBodyWithAddedVariables(
context, variablesToAdd[replacingDeclaration] ?: emptySet(), replacingDeclaration.symbol
)?.apply {
if (replacingDeclaration in possibleExtraBoxUsageGenerated) removeAllExtraBoxes()
} as IrExpressionBody?
else -> Unit
}
}
@@ -326,13 +333,15 @@ internal class JvmMultiFieldValueClassLowering(
irClass.primaryConstructor?.let {
replacements.getReplacementForRegularClassConstructor(it)?.let { replacement -> addBindingsFor(it, replacement) }
}
val propertiesOrFields = collectPropertiesOrFieldsAfterLowering(irClass)
val oldBackingFields = propertiesOrFields.mapNotNull { propertyOrField ->
val property = (propertyOrField as? IrPropertyOrIrField.Property)?.property ?: return@mapNotNull null
property.backingField?.let { property to it }
}.toMap()
val propertiesOrFieldsReplacement =
collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields) // resets backing fields
val propertiesOrFields = collectPropertiesOrFieldsAfterLowering(irClass, context)
val oldBackingFields = buildMap {
for (propertyOrField in propertiesOrFields) {
val property = (propertyOrField as? IrPropertyOrIrField.Property)?.property ?: continue
val field = property.backingField ?: continue
put(property, field)
}
}
val propertiesOrFieldsReplacement = collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields)
val fieldsToRemove = propertiesOrFieldsReplacement.keys.mapNotNull {
when (it) {
@@ -390,12 +399,15 @@ internal class JvmMultiFieldValueClassLowering(
context.irFactory.createAnonymousInitializer(
startOffset = UNDEFINED_OFFSET,
endOffset = UNDEFINED_OFFSET, origin = IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER,
symbol = IrAnonymousInitializerSymbolImpl()
symbol = IrAnonymousInitializerSymbolImpl(),
isStatic = element.isStatic,
).apply {
parent = irClass
body = context.createJvmIrBuilder(symbol).irBlockBody {
+irSetField(
irClass.thisReceiver!!.takeUnless { element.isStatic }?.let { irGet(it) }, element, initializer.expression,
receiver = irClass.thisReceiver!!.takeUnless { element.isStatic }?.let { irGet(it) },
field = element,
value = initializer.expression.patchDeclarationParents(irClass),
origin = UNSAFE_MFVC_SET_ORIGIN
)
}
@@ -800,18 +812,18 @@ internal class JvmMultiFieldValueClassLowering(
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val originalFunction = expression.symbol.owner
if (originalFunction.getReplacement() == null) return super.visitFunctionReference(expression)
return makeNewLambda(originalFunction, expression, makeBody = { wrapper ->
with(context.createJvmIrBuilder(wrapper.symbol)) {
irExprBody(irCall(originalFunction).apply {
passTypeArgumentsFrom(wrapper)
for ((newParam, originalParam) in wrapper.explicitParameters zip originalFunction.explicitParameters) {
putArgument(originalParam, irGet(newParam))
}
}).transform(this@JvmMultiFieldValueClassLowering, null)
val function = expression.symbol.owner
val replacement = function.getReplacement() ?: return super.visitFunctionReference(expression)
return context.createJvmIrBuilder(expression.symbol, expression).irBlock {
// Bridge call is added in BridgeLowering
buildReplacement(function, expression, replacement) {
IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset,
expression.type, replacement.symbol, function.typeParameters.size, replacement.valueParameters.size,
expression.reflectionTarget, expression.origin
).copyAttributes(expression)
}
})
}.unwrapBlock()
}
private fun IrFunction.getReplacement(): IrFunction? =
@@ -995,7 +1007,7 @@ internal class JvmMultiFieldValueClassLowering(
require(parameter2expression.size == structure.size)
require(structure.sumOf { it.valueParameters.size } == replacement.explicitParametersCount)
val newArguments: List<IrExpression?> =
makeNewArguments(parameter2expression.map { (_, argument) -> argument }, structure.map { it.valueParameters })
makeNewArguments(parameter2expression.map { (_, argument) -> argument }, structure)
val resultExpression = makeMemberAccessExpression(replacement.symbol).apply {
passTypeArgumentsWithOffsets(replacement, originalFunction) { original.getTypeArgument(it)!! }
for ((parameter, argument) in replacement.explicitParameters zip newArguments) {
@@ -1023,21 +1035,15 @@ internal class JvmMultiFieldValueClassLowering(
return super.visitStringConcatenation(expression)
}
private fun IrBlockBuilder.makeNewArguments(
oldArguments: List<IrExpression?>,
structure: List<List<IrValueParameter>>
): List<IrExpression?> {
val argumentSizes: List<Int> = structure.map { argTemplate -> argTemplate.size }
val newArguments = (oldArguments zip argumentSizes).flatMap { (oldArgument, parametersCount) ->
private fun IrBlockBuilder.makeNewArguments(oldArguments: List<IrExpression?>, structure: List<RemappedParameter>): List<IrExpression?> {
val argumentSizes: List<Int> = structure.map { argTemplate -> argTemplate.valueParameters.size }
val newArguments = (oldArguments zip argumentSizes).flatMapIndexed { index, (oldArgument, parametersCount) ->
when {
oldArgument == null -> List(parametersCount) { null }
parametersCount == 1 -> listOf(oldArgument.transform(this@JvmMultiFieldValueClassLowering, null))
else -> {
val castedIfNeeded = when {
oldArgument.type.needsMfvcFlattening() -> oldArgument
oldArgument.type.makeNotNull().needsMfvcFlattening() -> irImplicitCast(oldArgument, oldArgument.type.makeNotNull())
else -> error("Unexpected type: ${oldArgument.type.render()}")
}
val expectedType = (structure[index] as MultiFieldValueClassMapping).boxedType
val castedIfNeeded = castExpressionToNotNullTypeIfNeeded(oldArgument, expectedType)
flattenExpression(castedIfNeeded).also {
require(it.size == parametersCount) { "Expected $parametersCount arguments but got ${it.size}" }
}
@@ -1047,6 +1053,12 @@ internal class JvmMultiFieldValueClassLowering(
return newArguments
}
private fun IrBuilderWithScope.castExpressionToNotNullTypeIfNeeded(expression: IrExpression, type: IrType) = when (type) {
expression.type -> expression
expression.type.makeNotNull() -> irImplicitCast(expression, type)
else -> irAs(expression, type)
}
/**
* Inlines initialization of variables when possible and returns their values
*
@@ -1212,7 +1224,7 @@ internal class JvmMultiFieldValueClassLowering(
)
val type = if (expression is IrConstructorCall) expression.symbol.owner.constructedClass.defaultType else expression.type
val lowering = this@JvmMultiFieldValueClassLowering
if (rootNode == null || !type.needsMfvcFlattening()) {
if (rootNode == null || !type.needsMfvcFlattening() || instance.size == 1) {
require(instance.size == 1) { "Required 1 variable/field to store regular value but got ${instance.size}" }
instance.addSetterStatements(this, listOf(expression.transform(lowering, null)))
return
@@ -1263,11 +1275,7 @@ internal class JvmMultiFieldValueClassLowering(
}
}
val nullableTransformedExpression = expression.transform(this@JvmMultiFieldValueClassLowering, null)
val transformedExpression =
if (nullableTransformedExpression.type.isNullable())
irImplicitCast(nullableTransformedExpression, nullableTransformedExpression.type.makeNotNull())
else
nullableTransformedExpression
val transformedExpression = castExpressionToNotNullTypeIfNeeded(nullableTransformedExpression, instance.type)
val addedSettersToFlattened = valueDeclarationsRemapper.handleFlattenedGetterExpressions(this, transformedExpression) {
require(it.size == instance.size) { "Incompatible assignment sizes: ${it.size}, ${instance.size}" }
instance.makeSetterExpressions(this, it)
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -61,7 +60,7 @@ fun createLeafMfvcNode(
this.name = fullFieldName
this.type = type
this.visibility = DescriptorVisibilities.PRIVATE
this.metadata = null
oldBackingField.metadata = null
}.apply {
this.parent = oldBackingField.parent
this.annotations = fieldAnnotations.map { it.deepCopyWithVariables() }
@@ -246,19 +245,27 @@ fun createIntermediateMfvcNode(
)
}
fun collectPropertiesAfterLowering(irClass: IrClass): LinkedHashSet<IrProperty> =
LinkedHashSet(collectPropertiesOrFieldsAfterLowering(irClass).map { (it as Property).property })
fun collectPropertiesAfterLowering(irClass: IrClass, context: JvmBackendContext): LinkedHashSet<IrProperty> =
LinkedHashSet(collectPropertiesOrFieldsAfterLowering(irClass, context).map { (it as Property).property })
sealed class IrPropertyOrIrField {
data class Property(val property: IrProperty) : IrPropertyOrIrField()
data class Field(val field: IrField) : IrPropertyOrIrField()
}
fun collectPropertiesOrFieldsAfterLowering(irClass: IrClass): LinkedHashSet<IrPropertyOrIrField> =
fun collectPropertiesOrFieldsAfterLowering(irClass: IrClass, context: JvmBackendContext): LinkedHashSet<IrPropertyOrIrField> =
LinkedHashSet<IrPropertyOrIrField>().apply {
for (element in irClass.declarations) {
if (element is IrField) {
element.correspondingPropertySymbol?.owner?.takeUnless { it.isDelegated }?.let { add(Property(it)) } ?: add(Field(element))
val property = element.correspondingPropertySymbol?.owner
if (
property != null && !property.isDelegated &&
!context.multiFieldValueClassReplacements.getFieldsToRemove(element.parentAsClass).contains(element)
) {
add(Property(property))
} else {
add(Field(element))
}
} else if (element is IrSimpleFunction && element.extensionReceiverParameter == null && element.contextReceiverParametersCount == 0) {
element.correspondingPropertySymbol?.owner?.let { add(Property(it)) }
}
@@ -275,7 +282,7 @@ fun getRootNode(context: JvmBackendContext, mfvc: IrClass): RootMfvcNode {
val oldPrimaryConstructor = mfvc.primaryConstructor!!
val oldFields = mfvc.fields.filter { !it.isStatic }.toList()
val representation = mfvc.multiFieldValueClassRepresentation!!
val properties = collectPropertiesAfterLowering(mfvc).associateBy { it.isStatic(mfvc) to it.name }
val properties = collectPropertiesAfterLowering(mfvc, context).associateBy { it.isStatic(mfvc) to it.name }
val subnodes = makeRootMfvcNodeSubnodes(representation, properties, context, mfvc)
@@ -394,6 +401,11 @@ private fun makePrimaryConstructorImpl(
}
}
annotations = oldPrimaryConstructor.annotations
if (oldPrimaryConstructor.metadata != null) {
metadata = oldPrimaryConstructor.metadata
oldPrimaryConstructor.metadata = null
}
copyAttributes(oldPrimaryConstructor as? IrAttributeContainer)
// body is added in the Lowering file as it needs to be lowered
}
@@ -448,20 +460,18 @@ private fun makeRootMfvcNodeSubnodes(
Modality.FINAL,
oldBackingField,
).also {
updateAnnotationsAndPropertyFromOldProperty(oldProperty)
updateAnnotationsAndPropertyFromOldProperty(oldProperty, context, it)
it.unboxMethod.overriddenSymbols = listOf() // the getter is saved so it overrides itself
}
}
private fun updateAnnotationsAndPropertyFromOldProperty(
oldProperty: IrProperty
oldProperty: IrProperty,
context: JvmBackendContext,
node: MfvcNode,
) {
oldProperty.setter?.apply {
name = Name.identifier(JvmAbi.setterName(oldProperty.name.asString()))
correspondingPropertySymbol = null
origin = IrDeclarationOrigin.DEFINED
}
oldProperty.setter = null
if (node is LeafMfvcNode) return
oldProperty.backingField?.let { context.multiFieldValueClassReplacements.addFieldToRemove(it.parentAsClass, it) }
oldProperty.backingField = null
}
@@ -482,7 +492,7 @@ fun createIntermediateNodeForMfvcPropertyOfRegularClass(
parent, context, type, makeTypeArgumentsFromType(type), MethodFullNameMode.Getter, listOf(oldProperty.name),
fieldAnnotations, static, overriddenNode, null, oldGetter, modality, oldField
).also {
updateAnnotationsAndPropertyFromOldProperty(oldProperty)
updateAnnotationsAndPropertyFromOldProperty(oldProperty, context, it)
}
}
@@ -243,9 +243,11 @@ fun IrSimpleFunction.copyCorrespondingPropertyFrom(source: IrSimpleFunction) {
fun IrProperty.needsAccessor(accessor: IrSimpleFunction): Boolean = when {
// Properties in annotation classes become abstract methods named after the property.
(parent as? IrClass)?.kind == ClassKind.ANNOTATION_CLASS -> true
// Multi-field value class getters must always be added. Getters for properties of MFVC itself follow general rules.
// Multi-field value class accessors must always be added.
accessor.isGetter && accessor.contextReceiverParametersCount == 0 && accessor.extensionReceiverParameter == null &&
!accessor.parent.let { it is IrClass && it.isMultiFieldValueClass } && accessor.returnType.needsMfvcFlattening() -> true
accessor.returnType.needsMfvcFlattening() -> true
accessor.isSetter && accessor.contextReceiverParametersCount == 0 && accessor.extensionReceiverParameter == null &&
accessor.valueParameters.single().type.needsMfvcFlattening() -> true
// @JvmField properties have no getters/setters
resolveFakeOverride()?.backingField?.hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME) == true -> false
// We do not produce default accessors for private fields
@@ -0,0 +1,51 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
@JvmInline
value class Z(val x1: UInt, val x2: Int)
class Outer(val z1: Z, val z2: Z?) {
inner class Inner(val z3: Z, val z4: Z?) {
val test = "$z1 $z2 $z3 $z4"
}
}
@JvmInline
value class ValueNonNullOuter(val z11: Z, val z12: Z) {
class Inner(val t: ValueNonNullOuter, val z2: Z, val z3: Z?) {
val test = "${t.z11} ${t.z12} $z2 $z3"
}
}
@JvmInline
value class ValueNullableOuter(val z11: Z?, val z12: Z?) {
class Inner(val t: ValueNullableOuter, val z2: Z, val z3: Z?) {
val test = "${t.z11} ${t.z12} $z2 $z3"
}
}
fun box(): String {
val z1 = Z(1U, -1)
val z2 = Z(2U, -2)
val z3 = Z(3U, -3)
val z4 = Z(4U, -4)
val outer = ::Outer.call(z1, z2)
assertEquals(z1, outer.z1)
assertEquals(z2, outer.z2)
assertEquals("Z(x1=1, x2=-1) Z(x1=2, x2=-2) Z(x1=3, x2=-3) Z(x1=4, x2=-4)", Outer::Inner.call(outer, z3, z4).test)
assertEquals("Z(x1=1, x2=-1) Z(x1=2, x2=-2) Z(x1=2, x2=-2) Z(x1=4, x2=-4)", outer::Inner.call(z2, z4).test)
val valueNonNullOuter = ValueNonNullOuter(z1, z4)
assertEquals("Z(x1=1, x2=-1) Z(x1=4, x2=-4) Z(x1=2, x2=-2) Z(x1=3, x2=-3)", ValueNonNullOuter::Inner.call(valueNonNullOuter, z2, z3).test)
val valueNullableOuter = ValueNullableOuter(z1, z4)
assertEquals("Z(x1=1, x2=-1) Z(x1=4, x2=-4) Z(x1=2, x2=-2) Z(x1=3, x2=-3)", ValueNullableOuter::Inner.call(valueNullableOuter, z2, z3).test)
return "OK"
}
@@ -0,0 +1,59 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.jvm.isAccessible
import kotlin.test.assertEquals
@JvmInline
value class S(val value1: UInt, val value2: Int) {
operator fun plus(other: S): S = S(this.value1 + other.value1, this.value2 + other.value2)
}
class C {
private var nonNullMember: S = S(UInt.MAX_VALUE, -10)
private var nullableMember: S? = S(UInt.MAX_VALUE, -10)
fun nonNullUnboundRef() = C::nonNullMember.apply { isAccessible = true }
fun nonNullBoundRef() = this::nonNullMember.apply { isAccessible = true }
fun nullableUnboundRef() = C::nullableMember.apply { isAccessible = true }
fun nullableBoundRef() = this::nullableMember.apply { isAccessible = true }
}
private var nonNullTopLevel: S = S(UInt.MAX_VALUE, -10)
private var nullableTopLevel: S? = S(UInt.MAX_VALUE, -10)
fun box(): String {
val c = C()
val zero = S(0U, 5)
val one = S(1U, 10)
val two = S(2U, 20)
assertEquals(Unit, c.nonNullUnboundRef().setter.call(c, zero))
assertEquals(zero, c.nonNullUnboundRef().call(c))
assertEquals(zero, c.nonNullUnboundRef().getter.call(c))
assertEquals(Unit, c.nonNullBoundRef().setter.call(one))
assertEquals(one, c.nonNullBoundRef().call())
assertEquals(one, c.nonNullBoundRef().getter.call())
assertEquals(Unit, c.nullableUnboundRef().setter.call(c, zero))
assertEquals(zero, c.nullableUnboundRef().call(c))
assertEquals(zero, c.nullableUnboundRef().getter.call(c))
assertEquals(Unit, c.nullableBoundRef().setter.call(one))
assertEquals(one, c.nullableBoundRef().call())
assertEquals(one, c.nullableBoundRef().getter.call())
val nonNullTopLevel = ::nonNullTopLevel.apply { isAccessible = true }
assertEquals(Unit, nonNullTopLevel.setter.call(two))
assertEquals(two, nonNullTopLevel.call())
assertEquals(two, nonNullTopLevel.getter.call())
val nullableTopLevel = ::nullableTopLevel.apply { isAccessible = true }
assertEquals(Unit, nullableTopLevel.setter.call(two))
assertEquals(two, nullableTopLevel.call())
assertEquals(two, nullableTopLevel.getter.call())
return "OK"
}
@@ -0,0 +1,53 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
@JvmInline
value class S(val value1: UInt, val value2: Int) {
operator fun plus(other: S): S = S(this.value1 + other.value1, this.value2 + other.value2)
}
class C {
fun member(x: S, y1: UInt, y2: Int, z: S?): S = x + S(y1, y2) + z!!
}
fun topLevel(x1: UInt, x2: Int, y: S, z: S?): S = S(x1, x2) + y + z!!
fun S.extension1(y: S, z: S?): S = this + y + z!!
fun S?.extension2(y: S, z: S?) = this!! + y + z!!
fun S.extension3_1(): UInt = value1
fun S.extension3_2(): Int = value2
fun S?.extension4_1(): UInt = this!!.value1
fun S?.extension4_2(): Int = this!!.value2
fun box(): String {
val zero = S(0U, 1000)
val one = S(1U, -1)
val two = S(2U, -2)
val four = S(4U, -4)
val seven = S(7U, -7)
assertEquals(seven, C::member.call(C(), one, 2U, -2, four))
assertEquals(seven, ::topLevel.call(1U, -1, two, four))
assertEquals(seven, S::extension1.call(one, two, four))
assertEquals(seven, S::extension2.call(one, two, four))
assertEquals(0U, S::extension3_1.call(zero))
assertEquals(1000, S::extension3_2.call(zero))
assertEquals(0U, S?::extension4_1.call(zero))
assertEquals(1000, S?::extension4_2.call(zero))
assertEquals(seven, C()::member.call(one, 2U, -2, four))
assertEquals(seven, one::extension1.call(two, four))
assertEquals(seven, one::extension2.call(two, four))
assertEquals(0U, zero::extension3_1.call())
assertEquals(1000, zero::extension3_2.call())
assertEquals(0U, zero::extension4_1.call())
assertEquals(1000, zero::extension4_2.call())
return "OK"
}
@@ -0,0 +1,74 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
@JvmInline
value class Z(internal val x1: UInt, internal val x2: Int)
@JvmInline
value class Z2(internal val x1: Z, internal val x2: Z)
@JvmInline
value class L(internal val x1: ULong, internal val x2: Long)
@JvmInline
value class L2(internal val x1: L, internal val x2: L)
@JvmInline
value class A1(internal val x1: Any?, internal val x2: Any?)
@JvmInline
value class A1_2(internal val x1: A1, internal val x2: A1)
@JvmInline
value class A2(internal val x1: Any, internal val x2: Any)
@JvmInline
value class A2_2(internal val x1: A2, internal val x2: A2)
fun box(): String {
assertEquals(42U, Z::x1.call(Z(42U, 43)))
assertEquals(43, Z::x2.call(Z(42U, 43)))
assertEquals(42U, Z(42U, 43)::x1.call())
assertEquals(43, Z(42U, 43)::x2.call())
assertEquals(1234UL, L::x1.call(L(1234UL, 5678L)))
assertEquals(5678L, L::x2.call(L(1234UL, 5678L)))
assertEquals(1234UL, L(1234UL, 5678L)::x1.call())
assertEquals(5678L, L(1234UL, 5678L)::x2.call())
assertEquals("abc", A1::x1.call(A1("abc", "def")))
assertEquals("def", A1::x2.call(A1("abc", "def")))
assertEquals("abc", A1("abc", "def")::x1.call())
assertEquals("def", A1("abc", "def")::x2.call())
assertEquals(null, A1::x1.call(A1(null, null)))
assertEquals(null, A1::x2.call(A1(null, null)))
assertEquals(null, A1(null, null)::x1.call())
assertEquals(null, A1(null, null)::x2.call())
assertEquals("abc", A2::x1.call(A2("abc", "def")))
assertEquals("def", A2::x2.call(A2("abc", "def")))
assertEquals("abc", A2("abc", "def")::x1.call())
assertEquals("def", A2("abc", "def")::x2.call())
assertEquals(Z(42U, 43), Z2::x1.call(Z2(Z(42U, 43), Z(44U, 45))))
assertEquals(Z(44U, 45), Z2::x2.call(Z2(Z(42U, 43), Z(44U, 45))))
assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x1.call())
assertEquals(Z(44U, 45), Z2(Z(42U, 43), Z(44U, 45))::x2.call())
assertEquals(L(1234UL, 5678L), L2::x1.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
assertEquals(L(12340UL, -5678L), L2::x2.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x1.call())
assertEquals(L(12340UL, -5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x2.call())
assertEquals(A1("abc", "def"), A1_2::x1.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
assertEquals(A1("geh", "ijk"), A1_2::x2.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x1.call())
assertEquals(A1("geh", "ijk"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x2.call())
assertEquals(A1(null, null), A1_2::x1.call(A1_2(A1(null, null), A1(null, null))))
assertEquals(A1(null, null), A1_2::x2.call(A1_2(A1(null, null), A1(null, null))))
assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x1.call())
assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x2.call())
assertEquals(A2("abc", "def"), A2_2::x1.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
assertEquals(A2("geh", "ijk"), A2_2::x2.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x1.call())
assertEquals(A2("geh", "ijk"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x2.call())
return "OK"
}
@@ -0,0 +1,53 @@
// TARGET_BACKEND: JVM_IR
// JVM_TARGET: 1.8
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.jvm.isAccessible
import kotlin.test.assertEquals
@JvmInline
value class Z(val value1: UInt, val value2: Int) {
operator fun plus(other: Z): Z = Z(this.value1 + other.value1, this.value2 + other.value2)
}
object C {
@JvmStatic
private var p1: Z = Z(UInt.MAX_VALUE, -10)
@JvmStatic
private var p2: Z? = Z(UInt.MAX_VALUE, -10)
fun nonNullBoundRef() = this::p1.apply { isAccessible = true }
fun nullableBoundRef() = this::p2.apply { isAccessible = true }
}
fun box(): String {
val one = Z(1U, 10)
val two = Z(2U, 20)
val nonNullUnboundRef = C::class.members.single { it.name == "p1" } as KMutableProperty1<C, Z>
nonNullUnboundRef.isAccessible = true
assertEquals(Unit, nonNullUnboundRef.setter.call(C, one))
assertEquals(one, nonNullUnboundRef.call(C))
assertEquals(one, nonNullUnboundRef.getter.call(C))
val nullableUnboundRef = C::class.members.single { it.name == "p2" } as KMutableProperty1<C, Z?>
nullableUnboundRef.isAccessible = true
assertEquals(Unit, nullableUnboundRef.setter.call(C, one))
assertEquals(one, nullableUnboundRef.call(C))
assertEquals(one, nullableUnboundRef.getter.call(C))
val nonNullBoundRef = C.nonNullBoundRef()
assertEquals(Unit, nonNullBoundRef.setter.call(two))
assertEquals(two, nonNullBoundRef.call())
assertEquals(two, nonNullBoundRef.getter.call())
val nullableBoundRef = C.nullableBoundRef()
assertEquals(Unit, nullableBoundRef.setter.call(two))
assertEquals(two, nullableBoundRef.call())
assertEquals(two, nullableBoundRef.getter.call())
return "OK"
}
@@ -0,0 +1,42 @@
// TARGET_BACKEND: JVM_IR
// JVM_TARGET: 1.8
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.KFunction
import kotlin.test.assertEquals
@JvmInline
value class Z(val value1: UInt, val value2: Int) {
operator fun plus(other: Z): Z = Z(this.value1 + other.value1, this.value2 + other.value2)
}
object C {
@JvmStatic
fun foo(x: Z, y1: UInt, y2: Int, z: Z?): Z = x + Z(y1, y2) + z!!
}
interface I {
companion object {
@JvmStatic
fun bar(x1: UInt, x2: Int, y: Z, z: Z?): Z = Z(x1, x2) + y + z!!
}
}
fun box(): String {
val one = Z(1U, -1)
val two = Z(2U, -2)
val four = Z(4U, -4)
val seven = Z(7U, -7)
assertEquals(seven, C::foo.call(one, 2U, -2, four))
assertEquals(seven, (I)::bar.call(1U, -1, two, four))
val unboundFoo = C::class.members.single { it.name == "foo" } as KFunction<*>
assertEquals(seven, unboundFoo.call(C, one, 2U, -2, four))
val unboundBar = I.Companion::class.members.single { it.name == "bar" } as KFunction<*>
assertEquals(seven, unboundBar.call(I, 1U, -1, two, four))
return "OK"
}
@@ -0,0 +1,82 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.KCallable
import kotlin.test.assertEquals
@JvmInline
value class Z(val x1: UInt, val x2: Int) {
constructor(a: UInt, b: UInt, c: Int, d: Int) : this(a + b, c + d)
}
@JvmInline
value class L(val x1: ULong, val x2: Long) {
constructor(a: ULong, b: ULong, c: Long, d: Long) : this(a + b, c + d)
}
@JvmInline
value class S1(val x1: String, val x2: String) {
constructor(a: String, b: String, c: String, d: String) : this(a + b, c + d)
}
@JvmInline
value class S2(val x1: String?, val x2: String?) {
constructor(a: String?, b: String?, c: String?, d: String?) : this(a!! + b!!, c!! + d!!)
}
@JvmInline
value class A(val x1: Any, val x2: Any) {
constructor(a: String, b: String, c: String, d: String) : this(a + b, c + d)
}
@JvmInline
value class Z2(val z1: Z, val z2: Z) {
constructor(z1: Z, z2: Z, z3: Z, z4: Z) : this(Z(z1.x1 + z2.x1, z1.x2 + z2.x2), Z(z3.x1 + z4.x1, z3.x2 + z4.x2))
}
@JvmInline
value class Z3(val z1: Z?, val z2: Z?) {
constructor(z1: Z?, z2: Z?, z3: Z?, z4: Z?) : this(Z(z1!!.x1 + z2!!.x1, z1!!.x2 + z2!!.x2), Z(z3!!.x1 + z4!!.x1, z3!!.x2 + z4!!.x2))
}
fun box(): String {
val ctorZ1_1: (UInt, Int) -> Z = ::Z
val ctorZ1_2: (UInt, UInt, Int, Int) -> Z = ::Z
val ctorL1: (ULong, Long) -> L = ::L
val ctorL2: (ULong, ULong, Long, Long) -> L = ::L
val ctorS1_1: (String, String) -> S1 = ::S1
val ctorS1_2: (String, String, String, String) -> S1 = ::S1
val ctorS2_1: (String, String) -> S2 = ::S2
val ctorS2_2: (String, String, String, String) -> S2 = ::S2
val ctorA1: (Any, Any) -> A = ::A
val ctorA2: (String, String, String, String) -> A = ::A
val ctorZ2_2: (Z, Z) -> Z2 = ::Z2
val ctorZ2_4: (Z, Z, Z, Z) -> Z2 = ::Z2
val ctorZ3_2: (Z, Z) -> Z3 = ::Z3
val ctorZ3_4: (Z, Z, Z, Z) -> Z3 = ::Z3
assertEquals(Z(42U, 43), (ctorZ1_1 as KCallable<Z>).call(42U, 43))
assertEquals(Z(123U, 224), (ctorZ1_2 as KCallable<Z>).call(100U, 23U, 200, 24))
assertEquals(L(1UL, 2L), (ctorL1 as KCallable<L>).call(1UL, 2L))
assertEquals(L(123UL, 224L), (ctorL2 as KCallable<L>).call(100UL, 23UL, 200L, 24L))
assertEquals(S1("abc", "def"), (ctorS1_1 as KCallable<S1>).call("abc", "def"))
assertEquals(S1("abc", "def"), (ctorS1_2 as KCallable<S1>).call("ab", "c", "de", "f"))
assertEquals(S2("abc", "def"), (ctorS2_1 as KCallable<S2>).call("abc", "def"))
assertEquals(S2("abc", "def"), (ctorS2_2 as KCallable<S2>).call("ab", "c", "de", "f"))
assertEquals(A("abc", "def"), (ctorA1 as KCallable<A>).call("abc", "def"))
assertEquals(A("abc", "def"), (ctorA2 as KCallable<A>).call("a", "bc", "d", "ef"))
assertEquals(Z2(Z(42U, 43), Z(44U, 45)), (ctorZ2_2 as KCallable<Z2>).call(Z(42U, 43), Z(44U, 45)))
assertEquals(Z3(Z(42U, 43), Z(44U, 45)), (ctorZ3_2 as KCallable<Z3>).call(Z(42U, 43), Z(44U, 45)))
assertEquals(
Z2(Z(142U, 243), Z(344U, 445)),
(ctorZ2_4 as KCallable<Z2>).call(Z(42U, 43), Z(100U, 200), Z(44U, 45), Z(300U, 400))
)
assertEquals(
Z3(Z(142U, 243), Z(344U, 445)),
(ctorZ3_4 as KCallable<Z3>).call(Z(42U, 43), Z(100U, 200), Z(44U, 45), Z(300U, 400))
)
return "OK"
}
@@ -0,0 +1,37 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
@JvmInline
value class Z(val x1: UInt, val x2: Int) {
fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
}
@JvmInline
value class S(val x1: String, val x2: String) {
fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
}
@JvmInline
value class A(val x1: Any, val x2: Any) {
fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
}
fun box(): String {
val two = Z(2U, 3)
val four = Z(4U, 5)
val expected = "0912345"
assertEquals(expected, Z::test.call(Z(0U, 9), 1, two, four))
assertEquals(expected, Z(0U, 9)::test.call(1, two, four))
assertEquals(expected, S::test.call(S("0", "9"), 1, two, four))
assertEquals(expected, S("0", "9")::test.call(1, two, four))
assertEquals(expected, A::test.call(A(0U, 9), 1, two, four))
assertEquals(expected, A(0U, 9)::test.call(1, two, four))
return "OK"
}
@@ -0,0 +1,127 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
var global = Z(0U, 0)
@JvmInline
value class Z(val x1: UInt, val x2: Int) {
var nonNullTest: Z
get() = Z(global.x1 + this.x1, global.x2 + this.x2)
set(value) {
global = Z(this.x1 + value.x1, this.x2 + value.x2)
}
var nullableTest: Z?
get() = Z(global.x1 + this.x1, global.x2 + this.x2)
set(value) {
global = Z(this.x1 + value!!.x1, this.x2 + value!!.x2)
}
}
@JvmInline
value class S(val x1: String, val x2: String) {
var nonNullTest: Z
get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
set(value) {
global = Z(this.x1.toUInt() + value.x1, this.x2.toInt() + value.x2)
}
var nullableTest: Z?
get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
set(value) {
global = Z(this.x1.toUInt() + value!!.x1, this.x2.toInt() + value!!.x2)
}
}
@JvmInline
value class A(val x1: Any, val x2: Any) {
var nonNullTest: Z
get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
set(value) {
global = Z(this.x1 as UInt + value.x1, this.x2 as Int + value.x2)
}
var nullableTest: Z?
get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
set(value) {
global = Z(this.x1 as UInt + value!!.x1, this.x2 as Int + value!!.x2)
}
}
fun box(): String {
val zZero = Z(0U, 0)
val zOne = Z(1U, -1)
val zTwo = Z(2U, -2)
val zThree = Z(3U, -3)
val zFour = Z(4U, -4)
val sOne = S("1", "-1")
val aOne = A(1U, -1)
global = zZero
assertEquals(zOne, Z::nonNullTest.call(zOne))
assertEquals(zOne, zOne::nonNullTest.call())
assertEquals(zOne, Z::nonNullTest.getter.call(zOne))
assertEquals(zOne, zOne::nonNullTest.getter.call())
Z::nonNullTest.setter.call(zOne, zTwo)
assertEquals(zThree, global)
zOne::nonNullTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, Z::nullableTest.call(zOne))
assertEquals(zOne, zOne::nullableTest.call())
assertEquals(zOne, Z::nullableTest.getter.call(zOne))
assertEquals(zOne, zOne::nullableTest.getter.call())
Z::nullableTest.setter.call(zOne, zTwo)
assertEquals(zThree, global)
zOne::nullableTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, S::nonNullTest.call(sOne))
assertEquals(zOne, sOne::nonNullTest.call())
assertEquals(zOne, S::nonNullTest.getter.call(sOne))
assertEquals(zOne, sOne::nonNullTest.getter.call())
S::nonNullTest.setter.call(sOne, zTwo)
assertEquals(zThree, global)
sOne::nonNullTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, S::nullableTest.call(sOne))
assertEquals(zOne, sOne::nullableTest.call())
assertEquals(zOne, S::nullableTest.getter.call(sOne))
assertEquals(zOne, sOne::nullableTest.getter.call())
S::nullableTest.setter.call(sOne, zTwo)
assertEquals(zThree, global)
sOne::nullableTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, A::nonNullTest.call(aOne))
assertEquals(zOne, aOne::nonNullTest.call())
assertEquals(zOne, A::nonNullTest.getter.call(aOne))
assertEquals(zOne, aOne::nonNullTest.getter.call())
A::nonNullTest.setter.call(aOne, zTwo)
assertEquals(zThree, global)
aOne::nonNullTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, A::nullableTest.call(aOne))
assertEquals(zOne, aOne::nullableTest.call())
assertEquals(zOne, A::nullableTest.getter.call(aOne))
assertEquals(zOne, aOne::nullableTest.getter.call())
A::nullableTest.setter.call(aOne, zTwo)
assertEquals(zThree, global)
aOne::nullableTest.setter.call(zThree)
assertEquals(zFour, global)
return "OK"
}
@@ -0,0 +1,40 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
interface ITest {
fun test(a: Int, b: Z, c: Z?): String
}
@JvmInline
value class Z(val x1: UInt, val x2: Int) : ITest {
override fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
}
@JvmInline
value class S(val x1: String, val x2: String) : ITest {
override fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
}
@JvmInline
value class A(val x1: Any, val x2: Any) : ITest {
override fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
}
fun box(): String {
val two = Z(2U, 3)
val four = Z(4U, 5)
assertEquals("0912345", Z::test.call(Z(0U, 9), 1, two, four))
assertEquals("0912345", Z(0U, 9)::test.call(1, two, four))
assertEquals("0912345", S::test.call(S("0", "9"), 1, two, four))
assertEquals("0912345", S("0", "9")::test.call(1, two, four))
assertEquals("0912345", A::test.call(A(0U, 9), 1, two, four))
assertEquals("0912345", A(0U, 9)::test.call(1, two, four))
return "OK"
}
@@ -0,0 +1,132 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
var global = Z(0U, 0)
interface ITest {
var nonNullTest: Z
var nullableTest: Z?
}
@JvmInline
value class Z(val x1: UInt, val x2: Int) : ITest {
override var nonNullTest: Z
get() = Z(global.x1 + this.x1, global.x2 + this.x2)
set(value) {
global = Z(this.x1 + value.x1, this.x2 + value.x2)
}
override var nullableTest: Z?
get() = Z(global.x1 + this.x1, global.x2 + this.x2)
set(value) {
global = Z(this.x1 + value!!.x1, this.x2 + value!!.x2)
}
}
@JvmInline
value class S(val x1: String, val x2: String) : ITest {
override var nonNullTest: Z
get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
set(value) {
global = Z(this.x1.toUInt() + value.x1, this.x2.toInt() + value.x2)
}
override var nullableTest: Z?
get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
set(value) {
global = Z(this.x1.toUInt() + value!!.x1, this.x2.toInt() + value!!.x2)
}
}
@JvmInline
value class A(val x1: Any, val x2: Any) : ITest {
override var nonNullTest: Z
get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
set(value) {
global = Z(this.x1 as UInt + value.x1, this.x2 as Int + value.x2)
}
override var nullableTest: Z?
get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
set(value) {
global = Z(this.x1 as UInt + value!!.x1, this.x2 as Int + value!!.x2)
}
}
fun box(): String {
val zZero = Z(0U, 0)
val zOne = Z(1U, -1)
val zTwo = Z(2U, -2)
val zThree = Z(3U, -3)
val zFour = Z(4U, -4)
val sOne = S("1", "-1")
val aOne = A(1U, -1)
global = zZero
assertEquals(zOne, Z::nonNullTest.call(zOne))
assertEquals(zOne, zOne::nonNullTest.call())
assertEquals(zOne, Z::nonNullTest.getter.call(zOne))
assertEquals(zOne, zOne::nonNullTest.getter.call())
Z::nonNullTest.setter.call(zOne, zTwo)
assertEquals(zThree, global)
zOne::nonNullTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, Z::nullableTest.call(zOne))
assertEquals(zOne, zOne::nullableTest.call())
assertEquals(zOne, Z::nullableTest.getter.call(zOne))
assertEquals(zOne, zOne::nullableTest.getter.call())
Z::nullableTest.setter.call(zOne, zTwo)
assertEquals(zThree, global)
zOne::nullableTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, S::nonNullTest.call(sOne))
assertEquals(zOne, sOne::nonNullTest.call())
assertEquals(zOne, S::nonNullTest.getter.call(sOne))
assertEquals(zOne, sOne::nonNullTest.getter.call())
S::nonNullTest.setter.call(sOne, zTwo)
assertEquals(zThree, global)
sOne::nonNullTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, S::nullableTest.call(sOne))
assertEquals(zOne, sOne::nullableTest.call())
assertEquals(zOne, S::nullableTest.getter.call(sOne))
assertEquals(zOne, sOne::nullableTest.getter.call())
S::nullableTest.setter.call(sOne, zTwo)
assertEquals(zThree, global)
sOne::nullableTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, A::nonNullTest.call(aOne))
assertEquals(zOne, aOne::nonNullTest.call())
assertEquals(zOne, A::nonNullTest.getter.call(aOne))
assertEquals(zOne, aOne::nonNullTest.getter.call())
A::nonNullTest.setter.call(aOne, zTwo)
assertEquals(zThree, global)
aOne::nonNullTest.setter.call(zThree)
assertEquals(zFour, global)
global = zZero
assertEquals(zOne, A::nullableTest.call(aOne))
assertEquals(zOne, aOne::nullableTest.call())
assertEquals(zOne, A::nullableTest.getter.call(aOne))
assertEquals(zOne, aOne::nullableTest.getter.call())
A::nullableTest.setter.call(aOne, zTwo)
assertEquals(zThree, global)
aOne::nullableTest.setter.call(zThree)
assertEquals(zFour, global)
return "OK"
}
@@ -0,0 +1,180 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
@JvmInline
value class Z(val x1: UInt, val x2: Int) {
var x3
get() = x1
set(value) = Unit
}
@JvmInline
value class Z2(val x1: Z, val x2: Z) {
var x3
get() = x1
set(value) = Unit
}
@JvmInline
value class L(val x1: ULong, val x2: Long) {
var x3
get() = x1
set(value) = Unit
}
@JvmInline
value class L2(val x1: L, val x2: L) {
var x3
get() = x1
set(value) = Unit
}
@JvmInline
value class A1(val x1: Any?, val x2: Any?) {
var x3
get() = x1
set(value) = Unit
}
@JvmInline
value class A1_2(val x1: A1, val x2: A1) {
var x3
get() = x1
set(value) = Unit
}
@JvmInline
value class A2(val x1: Any, val x2: Any) {
var x3
get() = x1
set(value) = Unit
}
@JvmInline
value class A2_2(val x1: A2, val x2: A2) {
var x3
get() = x1
set(value) = Unit
}
fun box(): String {
assertEquals(42U, Z::x1.call(Z(42U, 43)))
assertEquals(43, Z::x2.call(Z(42U, 43)))
assertEquals(42U, Z::x3.call(Z(42U, 43)))
assertEquals(42U, Z::x3.getter.call(Z(42U, 43)))
assertEquals(Unit, Z::x3.setter.call(Z(42U, 43), 42U))
assertEquals(42U, Z(42U, 43)::x1.call())
assertEquals(43, Z(42U, 43)::x2.call())
assertEquals(42U, Z(42U, 43)::x3.call())
assertEquals(42U, Z(42U, 43)::x3.getter.call())
assertEquals(Unit, Z(42U, 43)::x3.setter.call(42U))
assertEquals(1234UL, L::x1.call(L(1234UL, 5678L)))
assertEquals(5678L, L::x2.call(L(1234UL, 5678L)))
assertEquals(1234UL, L::x3.call(L(1234UL, 5678L)))
assertEquals(1234UL, L::x3.getter.call(L(1234UL, 5678L)))
assertEquals(Unit, L::x3.setter.call(L(1234UL, 5678L), 1234UL))
assertEquals(1234UL, L(1234UL, 5678L)::x1.call())
assertEquals(5678L, L(1234UL, 5678L)::x2.call())
assertEquals(1234UL, L(1234UL, 5678L)::x3.call())
assertEquals(1234UL, L(1234UL, 5678L)::x3.getter.call())
assertEquals(Unit, L(1234UL, 5678L)::x3.setter.call(1234UL))
assertEquals("abc", A1::x1.call(A1("abc", "def")))
assertEquals("def", A1::x2.call(A1("abc", "def")))
assertEquals("abc", A1::x3.call(A1("abc", "def")))
assertEquals("abc", A1::x3.getter.call(A1("abc", "def")))
assertEquals(Unit, A1::x3.setter.call(A1("abc", "def"), "abc"))
assertEquals("abc", A1("abc", "def")::x1.call())
assertEquals("def", A1("abc", "def")::x2.call())
assertEquals("abc", A1("abc", "def")::x3.call())
assertEquals("abc", A1("abc", "def")::x3.getter.call())
assertEquals(Unit, A1("abc", "def")::x3.setter.call("abc"))
assertEquals(null, A1::x1.call(A1(null, null)))
assertEquals(null, A1::x2.call(A1(null, null)))
assertEquals(null, A1::x3.call(A1(null, null)))
assertEquals(null, A1::x3.getter.call(A1(null, null)))
assertEquals(Unit, A1::x3.setter.call(A1(null, null), null))
assertEquals(null, A1(null, null)::x1.call())
assertEquals(null, A1(null, null)::x2.call())
assertEquals(null, A1(null, null)::x3.call())
assertEquals(null, A1(null, null)::x3.getter.call())
assertEquals(Unit, A1(null, null)::x3.setter.call(null))
assertEquals("abc", A2::x1.call(A2("abc", "def")))
assertEquals("def", A2::x2.call(A2("abc", "def")))
assertEquals("abc", A2::x3.call(A2("abc", "def")))
assertEquals("abc", A2::x3.getter.call(A2("abc", "def")))
assertEquals(Unit, A2::x3.setter.call(A2("abc", "def"), "abc"))
assertEquals("abc", A2("abc", "def")::x1.call())
assertEquals("def", A2("abc", "def")::x2.call())
assertEquals("abc", A2("abc", "def")::x3.call())
assertEquals("abc", A2("abc", "def")::x3.getter.call())
assertEquals(Unit, A2("abc", "def")::x3.setter.call("abc"))
assertEquals(Z(42U, 43), Z2::x1.call(Z2(Z(42U, 43), Z(44U, 45))))
assertEquals(Z(44U, 45), Z2::x2.call(Z2(Z(42U, 43), Z(44U, 45))))
assertEquals(Z(42U, 43), Z2::x3.call(Z2(Z(42U, 43), Z(44U, 45))))
assertEquals(Z(42U, 43), Z2::x3.getter.call(Z2(Z(42U, 43), Z(44U, 45))))
assertEquals(Unit, Z2::x3.setter.call(Z2(Z(42U, 43), Z(44U, 45)), Z(42U, 43)))
assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x1.call())
assertEquals(Z(44U, 45), Z2(Z(42U, 43), Z(44U, 45))::x2.call())
assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x3.call())
assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x3.getter.call())
assertEquals(Unit, Z2(Z(42U, 43), Z(44U, 45))::x3.setter.call(Z(42U, 43)))
assertEquals(L(1234UL, 5678L), L2::x1.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
assertEquals(L(12340UL, -5678L), L2::x2.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
assertEquals(L(1234UL, 5678L), L2::x3.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
assertEquals(L(1234UL, 5678L), L2::x3.getter.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
assertEquals(Unit, L2::x3.setter.call(L2(L(1234UL, 5678L), L(12340UL, -5678L)), L(1234UL, 5678L)))
assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x1.call())
assertEquals(L(12340UL, -5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x2.call())
assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x3.call())
assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x3.getter.call())
assertEquals(Unit, L2(L(1234UL, 5678L), L(12340UL, -5678L))::x3.setter.call(L(1234UL, 5678L)))
assertEquals(A1("abc", "def"), A1_2::x1.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
assertEquals(A1("geh", "ijk"), A1_2::x2.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
assertEquals(A1("abc", "def"), A1_2::x3.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
assertEquals(A1("abc", "def"), A1_2::x3.getter.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
assertEquals(Unit, A1_2::x3.setter.call(A1_2(A1("abc", "def"), A1("geh", "ijk")), A1("abc", "def")))
assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x1.call())
assertEquals(A1("geh", "ijk"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x2.call())
assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x3.call())
assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x3.getter.call())
assertEquals(Unit, A1_2(A1("abc", "def"), A1("geh", "ijk"))::x3.setter.call(A1("abc", "def")))
assertEquals(A1(null, null), A1_2::x1.call(A1_2(A1(null, null), A1(null, null))))
assertEquals(A1(null, null), A1_2::x2.call(A1_2(A1(null, null), A1(null, null))))
assertEquals(A1(null, null), A1_2::x3.call(A1_2(A1(null, null), A1(null, null))))
assertEquals(A1(null, null), A1_2::x3.getter.call(A1_2(A1(null, null), A1(null, null))))
assertEquals(Unit, A1_2::x3.setter.call(A1_2(A1(null, null), A1(null, null)), A1(null, null)))
assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x1.call())
assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x2.call())
assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x3.call())
assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x3.getter.call())
assertEquals(Unit, A1_2(A1(null, null), A1(null, null))::x3.setter.call(A1(null, null)))
assertEquals(A2("abc", "def"), A2_2::x1.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
assertEquals(A2("geh", "ijk"), A2_2::x2.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
assertEquals(A2("abc", "def"), A2_2::x3.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
assertEquals(A2("abc", "def"), A2_2::x3.getter.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
assertEquals(Unit, A2_2::x3.setter.call(A2_2(A2("abc", "def"), A2("geh", "ijk")), A2("abc", "def")))
assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x1.call())
assertEquals(A2("geh", "ijk"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x2.call())
assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x3.call())
assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x3.getter.call())
assertEquals(Unit, A2_2(A2("abc", "def"), A2("geh", "ijk"))::x3.setter.call(A2("abc", "def")))
return "OK"
}
@@ -0,0 +1,122 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.KMutableProperty2
import kotlin.test.assertEquals
@JvmInline
value class Z(val value1: UInt, val value2: Int) {
operator fun plus(other: Z): Z = Z(this.value1 + other.value1, this.value2 + other.value2)
}
class C {
var nonNullMember: Z = Z(0U, 0)
var nullableMember: Z? = Z(0U, 0)
private var offset = Z(0U, 0)
var Z.nonNull_nonNullMemExt: Z
get() = this + offset
set(value) { offset = this + value }
var Z.nonNull_nullableMemExt: Z?
get() = this + offset
set(value) { offset = this + value!! }
var Z?.nullable_nonNullMemExt: Z
get() = this!! + offset
set(value) { offset = this!! + value }
var Z?.nullable_nullableMemExt: Z?
get() = this!! + offset
set(value) { offset = this!! + value!! }
}
var nonNullTopLevel: Z = Z(0U, 0)
var nullableTopLevel: Z? = Z(0U, 0)
private var offset = Z(0U, 0)
var Z.nonNull_nonNullExt: Z
get() = this + offset
set(value) { offset = this + value }
var Z.nonNull_nullableExt: Z?
get() = this + offset
set(value) { offset = this + value!! }
var Z?.nullable_nonNullExt: Z
get() = this!! + offset
set(value) { offset = this!! + value }
var Z?.nullable_nullableExt: Z?
get() = this!! + offset
set(value) { offset = this!! + value!! }
fun box(): String {
val one = Z(1U, -1)
val two = Z(2U, -2)
val three = Z(3U, -3)
val c = C()
assertEquals(Unit, C::nonNullMember.setter.call(c, one))
assertEquals(one, C::nonNullMember.call(c))
assertEquals(one, C::nonNullMember.getter.call(c))
assertEquals(Unit, c::nonNullMember.setter.call(two))
assertEquals(two, c::nonNullMember.call())
assertEquals(two, c::nonNullMember.getter.call())
assertEquals(Unit, C::nullableMember.setter.call(c, one))
assertEquals(one, C::nullableMember.call(c))
assertEquals(one, C::nullableMember.getter.call(c))
assertEquals(Unit, c::nullableMember.setter.call(two))
assertEquals(two, c::nullableMember.call())
assertEquals(two, c::nullableMember.getter.call())
val nonNull_nonNullMemExt = C::class.members.single { it.name == "nonNull_nonNullMemExt" } as KMutableProperty2<C, Z, Z>
assertEquals(Unit, nonNull_nonNullMemExt.setter.call(c, Z(0U, 0), two))
assertEquals(three, nonNull_nonNullMemExt.call(c, one))
assertEquals(three, nonNull_nonNullMemExt.getter.call(c, one))
val nonNull_nullableMemExt = C::class.members.single { it.name == "nonNull_nullableMemExt" } as KMutableProperty2<C, Z, Z?>
assertEquals(Unit, nonNull_nullableMemExt.setter.call(c, Z(0U, 0), two))
assertEquals(three, nonNull_nullableMemExt.call(c, one))
assertEquals(three, nonNull_nullableMemExt.getter.call(c, one))
val nullable_nonNullMemExt = C::class.members.single { it.name == "nullable_nonNullMemExt" } as KMutableProperty2<C, Z?, Z>
assertEquals(Unit, nullable_nonNullMemExt.setter.call(c, Z(0U, 0), two))
assertEquals(three, nullable_nonNullMemExt.call(c, one))
assertEquals(three, nullable_nonNullMemExt.getter.call(c, one))
val nullable_nullableMemExt = C::class.members.single { it.name == "nullable_nullableMemExt" } as KMutableProperty2<C, Z?, Z?>
assertEquals(Unit, nullable_nullableMemExt.setter.call(c, Z(0U, 0), two))
assertEquals(three, nullable_nullableMemExt.call(c, one))
assertEquals(three, nullable_nullableMemExt.getter.call(c, one))
assertEquals(Unit, ::nonNullTopLevel.setter.call(one))
assertEquals(one, ::nonNullTopLevel.call())
assertEquals(one, ::nonNullTopLevel.getter.call())
assertEquals(Unit, ::nullableTopLevel.setter.call(one))
assertEquals(one, ::nullableTopLevel.call())
assertEquals(one, ::nullableTopLevel.getter.call())
assertEquals(Unit, Z::nonNull_nonNullExt.setter.call(Z(0U, 0), two))
assertEquals(three, Z::nonNull_nonNullExt.call(one))
assertEquals(three, Z::nonNull_nonNullExt.getter.call(one))
assertEquals(Unit, Z::nonNull_nullableExt.setter.call(Z(0U, 0), two))
assertEquals(three, Z::nonNull_nullableExt.call(one))
assertEquals(three, Z::nonNull_nullableExt.getter.call(one))
assertEquals(Unit, Z?::nullable_nonNullExt.setter.call(Z(0U, 0), two))
assertEquals(three, Z?::nullable_nonNullExt.call(one))
assertEquals(three, Z?::nullable_nonNullExt.getter.call(one))
assertEquals(Unit, Z?::nullable_nullableExt.setter.call(Z(0U, 0), two))
assertEquals(three, Z?::nullable_nullableExt.call(one))
assertEquals(three, Z?::nullable_nullableExt.getter.call(one))
return "OK"
}
@@ -0,0 +1,91 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// WITH_COROUTINES
// LANGUAGE: +ValueClasses
import kotlin.coroutines.startCoroutine
import kotlin.reflect.full.callSuspend
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import helpers.*
@JvmInline
value class Z(val value1: UInt, val value2: Int)
class C {
private var value: Z = Z(0U, 0)
suspend fun nonNullConsume(z: Z) { value = z }
suspend fun nonNullProduce(): Z = value
suspend fun nullableConsume(z: Z?) { value = z!! }
suspend fun nullableProduce(): Z? = value
suspend fun nonNull_nonNullConsumeAndProduce(z: Z): Z = z
suspend fun nonNull_nullableConsumeAndProduce(z: Z): Z? = z
suspend fun nullable_nonNullConsumeAndProduce(z: Z?): Z = z!!
suspend fun nullable_nullableConsumeAndProduce(z: Z?): Z? = z
}
private fun run0(f: suspend () -> Int): Int {
var result = -1
f.startCoroutine(handleResultContinuation { result = it })
return result
}
private fun run0U(f: suspend () -> UInt): UInt {
var result = UInt.MAX_VALUE
f.startCoroutine(handleResultContinuation { result = it })
return result
}
fun box(): String {
val c = C()
run0U {
C::nonNullConsume.callSuspend(c, Z(1U, -1))
C::nonNullProduce.callSuspend(c).value1
}.let { assertEquals(1U, it) }
run0 {
C::nonNullConsume.callSuspend(c, Z(1U, -1))
C::nonNullProduce.callSuspend(c).value2
}.let { assertEquals(-1, it) }
run0U {
C::nullableConsume.callSuspend(c, Z(2U, -2))
C::nullableProduce.callSuspend(c)!!.value1
}.let { assertEquals(2U, it) }
run0 {
C::nullableConsume.callSuspend(c, Z(2U, -2))
C::nullableProduce.callSuspend(c)!!.value2
}.let { assertEquals(-2, it) }
run0U {
C::nonNull_nonNullConsumeAndProduce.callSuspend(c, Z(3U, -3)).value1
}.let { assertEquals(3U, it) }
run0 {
C::nonNull_nonNullConsumeAndProduce.callSuspend(c, Z(3U, -3)).value2
}.let { assertEquals(-3, it) }
run0U {
C::nonNull_nullableConsumeAndProduce.callSuspend(c, Z(4U, -4))!!.value1
}.let { assertEquals(4U, it) }
run0 {
C::nonNull_nullableConsumeAndProduce.callSuspend(c, Z(4U, -4))!!.value2
}.let { assertEquals(-4, it) }
run0U {
C::nullable_nonNullConsumeAndProduce.callSuspend(c, Z(5U, -5)).value1
}.let { assertEquals(5U, it) }
run0 {
C::nullable_nonNullConsumeAndProduce.callSuspend(c, Z(5U, -5)).value2
}.let { assertEquals(-5, it) }
run0U {
C::nullable_nullableConsumeAndProduce.callSuspend(c, Z(6U, -6))!!.value1
}.let { assertEquals(6U, it) }
run0 {
C::nullable_nullableConsumeAndProduce.callSuspend(c, Z(6U, -6))!!.value2
}.let { assertEquals(-6, it) }
return "OK"
}
@@ -0,0 +1,72 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
@JvmInline
value class A(val x: UInt, val y: Int)
fun test1(x: A = A(0U, 1)) = "OK"
fun test32(
arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
arg30: Long = 0L, x: A = A(0U, 1)
) = "OK"
fun test33(
arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
arg30: Long = 0L, arg31: Long = 0L, x: A = A(0U, 1)
) = "OK"
fun test64(
arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
arg30: Long = 0L, arg31: Long = 0L, arg32: Long = 0L, arg33: Long = 0L, arg34: Long = 0L,
arg35: Long = 0L, arg36: Long = 0L, arg37: Long = 0L, arg38: Long = 0L, arg39: Long = 0L,
arg40: Long = 0L, arg41: Long = 0L, arg42: Long = 0L, arg43: Long = 0L, arg44: Long = 0L,
arg45: Long = 0L, arg46: Long = 0L, arg47: Long = 0L, arg48: Long = 0L, arg49: Long = 0L,
arg50: Long = 0L, arg51: Long = 0L, arg52: Long = 0L, arg53: Long = 0L, arg54: Long = 0L,
arg55: Long = 0L, arg56: Long = 0L, arg57: Long = 0L, arg58: Long = 0L, arg59: Long = 0L,
arg60: Long = 0L, arg61: Long = 0L, arg62: Long = 0L, x: A = A(0U, 1)
) = "OK"
fun test65(
arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
arg30: Long = 0L, arg31: Long = 0L, arg32: Long = 0L, arg33: Long = 0L, arg34: Long = 0L,
arg35: Long = 0L, arg36: Long = 0L, arg37: Long = 0L, arg38: Long = 0L, arg39: Long = 0L,
arg40: Long = 0L, arg41: Long = 0L, arg42: Long = 0L, arg43: Long = 0L, arg44: Long = 0L,
arg45: Long = 0L, arg46: Long = 0L, arg47: Long = 0L, arg48: Long = 0L, arg49: Long = 0L,
arg50: Long = 0L, arg51: Long = 0L, arg52: Long = 0L, arg53: Long = 0L, arg54: Long = 0L,
arg55: Long = 0L, arg56: Long = 0L, arg57: Long = 0L, arg58: Long = 0L, arg59: Long = 0L,
arg60: Long = 0L, arg61: Long = 0L, arg62: Long = 0L, arg63: Long = 0L, x: A = A(0U, 1)
) = "OK"
fun box(): String {
assertEquals("OK", ::test1.callBy(mapOf()))
assertEquals("OK", ::test32.callBy(mapOf()))
assertEquals("OK", ::test33.callBy(mapOf()))
assertEquals("OK", ::test64.callBy(mapOf()))
assertEquals("OK", ::test65.callBy(mapOf()))
return "OK"
}
@@ -0,0 +1,53 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@JvmInline
value class S(val value1: UInt, val value2: String) {
operator fun plus(other: S): S = S(this.value1 * 10U + other.value1, this.value2 + other.value2)
}
class C {
fun member(a: S, b: S = S(1U, "b2")): S = a + b
}
fun topLevel(c: S, d: S = S(1U, "d2")): S = c + d
class D(e: S, f: S = S(1U, "f2")) {
val result = e + f
}
fun S.extension(h: S = S(1U, "h2")): S = this + h
fun box(): String {
assertEquals(S(11U, "a2b2"), C().member(S(1U, "a2")))
assertEquals(
S(11U, "a2b2"),
C::member.callBy(C::member.parameters.filter { it.name != "b" }.associateWith { (if (it.name == "a") S(1U, "a2") else C()) })
)
assertEquals(S(11U, "c2d2"), topLevel(S(1U, "c2")))
assertEquals(S(11U, "c2d2"), ::topLevel.callBy(::topLevel.parameters.filter { it.name != "d" }.associateWith { S(1U, "c2") }))
assertEquals(S(11U, "e2f2"), ::D.callBy(::D.parameters.filter { it.name != "f" }.associateWith { S(1U, "e2") }).result)
assertEquals(S(11U, "g2h2"), S(1U, "g2").extension())
assertEquals(S(11U, "g2h2"), S::extension.callBy(S::extension.parameters.filter { it.name != "h" }.associateWith { S(1U, "g2") }))
val boundMember = C()::member
assertEquals(S(11U, "a2b2"), boundMember.callBy(boundMember.parameters.associateWith { S(1U, it.name!! + "2") }))
val boundExtension = S(1U, "g2")::extension
assertEquals(S(11U, "g2h2"), boundExtension.callBy(boundExtension.parameters.associateWith { S(1U, it.name!! + "2") }))
val mfvcConstructor = ::S
val exception = runCatching { mfvcConstructor.callBy(mapOf(mfvcConstructor.parameters.first() to 1U)) }.exceptionOrNull()!!
assertTrue(exception is IllegalArgumentException)
assertTrue(exception.message!!.startsWith("No argument provided for a required parameter: parameter #1 value2 of fun `<init>`(kotlin.UInt, kotlin.String): "), exception.message)
assertTrue(exception.message!!.endsWith("S"), exception.message)
return "OK"
}
@@ -0,0 +1,77 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.test.assertEquals
interface IFoo {
fun fooFun(z: Z): Z
var fooVar: Z
}
var global = Z(0U, 0)
@JvmInline
value class Z(val x1: UInt, val x2: Int) : IFoo {
override fun fooFun(z: Z): Z = Z(z.x1 + x1, z.x2 + x2)
override var fooVar: Z
get() = Z(global.x1 + x1, global.x2 + x2)
set(value) {
global = Z(value.x1 + x1, value.x2 + x2)
}
fun barFun(z: Z): Z = Z(z.x1 * 100U + x1, z.x2 * 100 + x2)
var barVar: Z
get() = Z(global.x1 * 100U + x1, global.x2 * 100 + x2)
set(value) {
global = Z(value.x1 * 100U + x1, value.x2 * 100 + x2)
}
}
fun box(): String {
val fooFunR = Z::fooFun
assertEquals(Z(53U, -53), fooFunR.callBy(mapOf(fooFunR.parameters[0] to Z(42U, -42), fooFunR.parameters[1] to Z(11U, -11))))
val fooFunBR = Z(42U, -42)::fooFun
assertEquals(Z(142U, -142), fooFunBR.callBy(mapOf(fooFunBR.parameters[0] to Z(100U, -100))))
global = Z(0U, 0)
val fooVarR = Z::fooVar
assertEquals(Z(42U, -42), fooVarR.callBy(mapOf(fooVarR.parameters[0] to Z(42U, -42))))
assertEquals(Z(42U, -42), fooVarR.getter.callBy(mapOf(fooVarR.getter.parameters[0] to Z(42U, -42))))
fooVarR.setter.callBy(mapOf(fooVarR.setter.parameters[0] to Z(42U, -42), fooVarR.setter.parameters[1] to Z(1U, -1)))
assertEquals(Z(43U, -43), global)
global = Z(100U, -100)
val fooVarBR = Z(42U, -42)::fooVar
assertEquals(Z(142U, -142), fooVarBR.callBy(mapOf()))
assertEquals(Z(142U, -142), fooVarBR.getter.callBy(mapOf()))
fooVarBR.setter.callBy(mapOf(fooVarBR.setter.parameters[0] to Z(1U, -1)))
assertEquals(Z(43U, -43), global)
val barFunR = Z::barFun
assertEquals(Z(1142U, -1142), barFunR.callBy(mapOf(barFunR.parameters[0] to Z(42U, -42), barFunR.parameters[1] to Z(11U, -11))))
val barFunBR = Z(42U, -42)::barFun
assertEquals(Z(2242U, -2242), barFunBR.callBy(mapOf(barFunBR.parameters[0] to Z(22U, -22))))
global = Z(1U, -1)
val barVarR = Z::barVar
assertEquals(Z(142U, -142), barVarR.callBy(mapOf(barVarR.parameters[0] to Z(42U, -42))))
assertEquals(Z(142U, -142), barVarR.getter.callBy(mapOf(barVarR.getter.parameters[0] to Z(42U, -42))))
barVarR.setter.callBy(mapOf(barVarR.setter.parameters[0] to Z(42U, -42), barVarR.setter.parameters[1] to Z(3U, -3)))
assertEquals(Z(342U, -342), global)
global = Z(2U, -2)
val barVarBR = Z(42U, -42)::barVar
assertEquals(Z(242U, -242), barVarBR.callBy(mapOf()))
assertEquals(Z(242U, -242), barVarBR.getter.callBy(mapOf()))
barVarBR.setter.callBy(mapOf(barVarBR.setter.parameters[0] to Z(4U, -4)))
assertEquals(Z(442U, -442), global)
return "OK"
}
@@ -0,0 +1,14 @@
// LAMBDAS: CLASS
// !OPT_IN: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.jvm.reflect
@JvmInline
value class C(val x1: UInt, val x2: Int)
fun C.f(x: (String) -> Unit = { OK: String -> }) = x.reflect()?.parameters?.singleOrNull()?.name
fun box(): String = C(0U, 1).f() ?: "null"
@@ -0,0 +1,23 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.javaConstructor
import kotlin.reflect.jvm.kotlinFunction
import kotlin.test.assertEquals
@JvmInline
value class Z(val x1: UInt, val x2: Int)
class Test(val x: Z)
fun box(): String {
val kctor1 = Test::class.primaryConstructor ?: throw AssertionError("No primary constructor")
val jctor1 = kctor1.javaConstructor ?: throw AssertionError("No javaConstructor for $kctor1")
val kctor2 = jctor1.kotlinFunction ?: throw AssertionError("No kotlinFunction for $jctor1")
assertEquals(kctor1, kctor2)
assertEquals("[x]", kctor2.parameters.map { it.name }.toString())
return "OK"
}
@@ -8,20 +8,16 @@ inline class S(val value: String)
fun S.foo(x: Int, s: S): S = this
/* TODO: Support calling members of inline classes in reflection (KT-26748)
inline class T(val s: S) {
fun bar(u: S): T = this
}
*/
fun box(): String {
assertEquals(listOf(String::class.java, Int::class.java, String::class.java), S::foo.parameters.map { it.type.javaType })
assertEquals(String::class.java, S::foo.returnType.javaType)
/*
assertEquals(listOf(), T::bar.parameters.map { it.type.javaType })
assertEquals(listOf(String::class.java, String::class.java), T::bar.parameters.map { it.type.javaType })
assertEquals(String::class.java, T::bar.returnType.javaType)
*/
return "OK"
}
@@ -0,0 +1,46 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
import java.lang.reflect.Type
@JvmInline
value class S(val value1: UInt, val value2: String)
fun S.foo(x: Int, s: S): S = this
fun compoundType(vararg types: Type) = listOf(*types).toString()
@JvmInline
value class T(val s: S) {
fun bar(u: S): T = this
}
data class U(val s: S) {
fun bar(u: S): U = this
}
@kotlin.ExperimentalStdlibApi
fun box(): String {
assertEquals(listOf(Int::class.java, String::class.java), ::S.parameters.map { it.type.javaType })
assertEquals(S::class.java, ::S.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java)), ::T.parameters.map { it.type.javaType.toString() })
assertEquals(T::class.java, ::T.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java)), ::U.parameters.map { it.type.javaType.toString() })
assertEquals(U::class.java, ::U.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java), Int::class.java.toString(), compoundType(Int::class.java, String::class.java)), S::foo.parameters.map { it.type.javaType.toString() })
assertEquals(S::class.java, S::foo.returnType.javaType)
assertEquals(listOf(compoundType(Int::class.java, String::class.java), compoundType(Int::class.java, String::class.java)), T::bar.parameters.map { it.type.javaType.toString() })
assertEquals(T::class.java, T::bar.returnType.javaType)
assertEquals(listOf(U::class.java.toString(), compoundType(Int::class.java, String::class.java)), U::bar.parameters.map { it.type.javaType.toString() })
assertEquals(U::class.java, U::bar.returnType.javaType)
return "OK"
}
@@ -0,0 +1,85 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
package test
import kotlin.reflect.KCallable
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
@JvmInline
value class Z1(val publicX1: UInt, val publicX2: Int) {
companion object {
val publicX1Ref = Z1::publicX1
val publicX2Ref = Z1::publicX2
val publicX1BoundRef = Z1(42U, 43)::publicX1
val publicX2BoundRef = Z1(42U, 43)::publicX2
}
}
@JvmInline
value class Z2(internal val internalX1: UInt, internal val internalX2: Int) {
companion object {
val internalX1Ref = Z2::internalX1
val internalX2Ref = Z2::internalX2
val internalX1BoundRef = Z2(42U, 43)::internalX1
val internalX2BoundRef = Z2(42U, 43)::internalX2
}
}
@JvmInline
value class Z3(private val privateX1: UInt, private val privateX2: Int) {
companion object {
val privateX1Ref = Z3::privateX1
val privateX2Ref = Z3::privateX2
val privateX1BoundRef = Z3(42U, 43)::privateX1
val privateX2BoundRef = Z3(42U, 43)::privateX2
}
}
@JvmInline
value class ZZ(val x1: Z1, val x2: Z1)
fun KCallable<*>.getJavaTypesOfParams() = parameters.map { it.type.javaType }.toString()
fun KCallable<*>.getJavaTypeOfResult() = returnType.javaType.toString()
fun box(): String {
assertEquals("[class test.Z1]", Z1.publicX1Ref.getJavaTypesOfParams())
assertEquals("[class test.Z1]", Z1.publicX2Ref.getJavaTypesOfParams())
assertEquals("int", Z1.publicX1Ref.getJavaTypeOfResult())
assertEquals("int", Z1.publicX2Ref.getJavaTypeOfResult())
assertEquals("[]", Z1.publicX1BoundRef.getJavaTypesOfParams())
assertEquals("[]", Z1.publicX2BoundRef.getJavaTypesOfParams())
assertEquals("int", Z1.publicX1BoundRef.getJavaTypeOfResult())
assertEquals("int", Z1.publicX2BoundRef.getJavaTypeOfResult())
assertEquals("[class test.Z2]", Z2.internalX1Ref.getJavaTypesOfParams())
assertEquals("[class test.Z2]", Z2.internalX2Ref.getJavaTypesOfParams())
assertEquals("int", Z2.internalX1Ref.getJavaTypeOfResult())
assertEquals("int", Z2.internalX2Ref.getJavaTypeOfResult())
assertEquals("[]", Z2.internalX1BoundRef.getJavaTypesOfParams())
assertEquals("[]", Z2.internalX2BoundRef.getJavaTypesOfParams())
assertEquals("int", Z2.internalX1BoundRef.getJavaTypeOfResult())
assertEquals("int", Z2.internalX2BoundRef.getJavaTypeOfResult())
assertEquals("[class test.Z3]", Z3.privateX1Ref.getJavaTypesOfParams())
assertEquals("[class test.Z3]", Z3.privateX2Ref.getJavaTypesOfParams())
assertEquals("int", Z3.privateX1Ref.getJavaTypeOfResult())
assertEquals("int", Z3.privateX2Ref.getJavaTypeOfResult())
assertEquals("[]", Z3.privateX1BoundRef.getJavaTypesOfParams())
assertEquals("[]", Z3.privateX2BoundRef.getJavaTypesOfParams())
assertEquals("int", Z3.privateX1BoundRef.getJavaTypeOfResult())
assertEquals("int", Z3.privateX2BoundRef.getJavaTypeOfResult())
assertEquals("[class test.ZZ]", ZZ::x1.getJavaTypesOfParams())
assertEquals("[class test.ZZ]", ZZ::x2.getJavaTypesOfParams())
assertEquals("class test.Z1", ZZ::x1.getJavaTypeOfResult())
assertEquals("class test.Z1", ZZ::x2.getJavaTypeOfResult())
return "OK"
}
@@ -0,0 +1,90 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@JvmInline
value class Z1(val publicX1: UInt, val publicX2: Int) {
companion object {
val publicX1Ref = Z1::publicX1
val publicX2Ref = Z1::publicX2
val publicX1BoundRef = Z1(42U, -42)::publicX1
val publicX2BoundRef = Z1(42U, -42)::publicX2
}
}
@JvmInline
value class Z2(internal val internalX1: UInt, internal val internalX2: Int) {
companion object {
val internalX1Ref = Z2::internalX1
val internalX2Ref = Z2::internalX2
val internalX1BoundRef = Z2(42U, -42)::internalX1
val internalX2BoundRef = Z2(42U, -42)::internalX2
}
}
@JvmInline
value class Z3(private val privateX1: UInt, private val privateX2: Int) {
companion object {
val privateX1Ref = Z3::privateX1
val privateX2Ref = Z3::privateX2
val privateX1BoundRef = Z3(42U, -42)::privateX1
val privateX2BoundRef = Z3(42U, -42)::privateX2
}
}
@JvmInline
value class Z1_2(val publicX: Z1) {
companion object {
val publicXRef = Z1_2::publicX
val publicXBoundRef = Z1_2(Z1(42U, -42))::publicX
}
}
@JvmInline
value class Z2_2(internal val internalX: Z2) {
companion object {
val internalXRef = Z2_2::internalX
val internalXBoundRef = Z2_2(Z2(42U, -42))::internalX
}
}
@JvmInline
value class Z3_2(private val privateX: Z3) {
companion object {
val privateXRef = Z3_2::privateX
val privateXBoundRef = Z3_2(Z3(42U, -42))::privateX
}
}
fun box(): String {
val suffix = "-pVg5ArA"
assertEquals("getPublicX1$suffix", Z1.publicX1Ref.javaGetter!!.name)
assertEquals("getPublicX2", Z1.publicX2Ref.javaGetter!!.name)
assertEquals("getPublicX1$suffix", Z1.publicX1BoundRef.javaGetter!!.name)
assertEquals("getPublicX2", Z1.publicX2BoundRef.javaGetter!!.name)
assertTrue(Z2.internalX1Ref.javaGetter!!.name.startsWith("getInternalX1$suffix\$"), Z2.internalX1Ref.javaGetter!!.name)
assertTrue(Z2.internalX2Ref.javaGetter!!.name.startsWith("getInternalX2\$"), Z2.internalX2Ref.javaGetter!!.name)
assertTrue(Z2.internalX1BoundRef.javaGetter!!.name.startsWith("getInternalX1$suffix\$"), Z2.internalX1BoundRef.javaGetter!!.name)
assertTrue(Z2.internalX2BoundRef.javaGetter!!.name.startsWith("getInternalX2\$"), Z2.internalX2BoundRef.javaGetter!!.name)
assertEquals(null, Z3.privateX1Ref.javaGetter)
assertEquals(null, Z3.privateX2Ref.javaGetter)
assertEquals(null, Z3.privateX1BoundRef.javaGetter)
assertEquals(null, Z3.privateX2BoundRef.javaGetter)
assertEquals("getPublicX", Z1_2.publicXRef.javaGetter!!.name)
assertEquals("getPublicX", Z1_2.publicXBoundRef.javaGetter!!.name)
assertTrue(Z2_2.internalXRef.javaGetter!!.name.startsWith("getInternalX\$"), Z2_2.internalXRef.javaGetter!!.name)
assertTrue(Z2_2.internalXBoundRef.javaGetter!!.name.startsWith("getInternalX\$"), Z2_2.internalXBoundRef.javaGetter!!.name)
assertEquals("getPrivateX", Z3_2.privateXRef.javaGetter!!.name)
assertEquals("getPrivateX", Z3_2.privateXBoundRef.javaGetter!!.name)
return "OK"
}
@@ -0,0 +1,49 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
package test
import kotlin.reflect.*
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@JvmInline
value class Z(val value1: UInt, val value2: String)
class S {
suspend fun consumeZ(z: Z) {}
suspend fun produceZ(): Z = Z(0U, "")
suspend fun consumeAndProduceZ(z: Z): Z = z
}
fun box(): String {
val members = S::class.members.filterIsInstance<KFunction<*>>().associateBy(KFunction<*>::name)
members["consumeZ"]!!.let { cz ->
val czj = cz.javaMethod!!
assertTrue(czj.name.startsWith("consumeZ-"), czj.name)
assertEquals("int, java.lang.String, kotlin.coroutines.Continuation", czj.parameterTypes.joinToString { it.name })
val czjk = czj.kotlinFunction
assertEquals(cz, czjk)
}
members["produceZ"]!!.let { pz ->
val pzj = pz.javaMethod!!
assertEquals("produceZ", pzj.name)
assertEquals("kotlin.coroutines.Continuation", pzj.parameterTypes.joinToString { it.name })
val pzjk = pzj!!.kotlinFunction
assertEquals(pz, pzjk)
}
members["consumeAndProduceZ"]!!.let { cpz ->
val cpzj = cpz.javaMethod!!
assertTrue(cpzj.name.startsWith("consumeAndProduceZ-"), cpzj.name)
assertEquals("int, java.lang.String, kotlin.coroutines.Continuation", cpzj.parameterTypes.joinToString { it.name })
val cpzjk = cpzj!!.kotlinFunction
assertEquals(cpz, cpzjk)
}
return "OK"
}
@@ -0,0 +1,20 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
// FILE: box.kt
import kotlin.test.assertTrue
import kotlin.test.assertFalse
@JvmInline
value class V(val value: String, val value1: String)
fun box(): String {
assertFalse(V::class.isSealed)
assertFalse(V::class.isData)
assertFalse(V::class.isInner)
assertFalse(V::class.isCompanion)
assertFalse(V::class.isFun)
assertTrue(V::class.isValue)
return "OK"
}
+25
View File
@@ -0,0 +1,25 @@
// TARGET_BACKEND: JVM_IR
// WITH_REFLECT
// LANGUAGE: +ValueClasses
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
import kotlin.test.assertEquals
@JvmInline
value class Z(val value1: String, val value2: String)
fun check(expected: String, actual: KType) {
assertEquals(expected, actual.toString())
}
fun box(): String {
check("test.Z", typeOf<Z>())
check("test.Z?", typeOf<Z?>())
check("kotlin.Array<test.Z>", typeOf<Array<Z>>())
check("kotlin.Array<test.Z?>", typeOf<Array<Z?>>())
return "OK"
}
@@ -0,0 +1,25 @@
// TARGET_BACKEND: JVM_IR
// WITH_STDLIB
// LANGUAGE: +ValueClasses
package test
import kotlin.reflect.KType
import kotlin.reflect.typeOf
import kotlin.test.assertEquals
@JvmInline
value class Z(val value1: String, val value2: String)
fun check(expected: String, actual: KType) {
assertEquals(expected + " (Kotlin reflection is not available)", actual.toString())
}
fun box(): String {
check("test.Z", typeOf<Z>())
check("test.Z?", typeOf<Z?>())
check("kotlin.Array<test.Z>", typeOf<Array<Z>>())
check("kotlin.Array<test.Z?>", typeOf<Array<Z?>>())
return "OK"
}
@@ -41385,6 +41385,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
}
@Nested
@@ -42739,6 +42749,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
}
@Nested
@@ -43521,6 +43521,100 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("constructorWithMfvcParameters.kt")
public void testConstructorWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt");
}
@Test
@TestMetadata("fieldAccessors.kt")
public void testFieldAccessors() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt");
}
@Test
@TestMetadata("functionsWithMfvcParameters.kt")
public void testFunctionsWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt");
}
@Test
@TestMetadata("internalPrimaryValOfMfvc.kt")
public void testInternalPrimaryValOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt");
}
@Test
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt");
}
@Test
@TestMetadata("jvmStaticFunction.kt")
public void testJvmStaticFunction() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt");
}
@Test
@TestMetadata("mfvcConstructor.kt")
public void testMfvcConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt");
}
@Test
@TestMetadata("nonOverridingFunOfMfvc.kt")
public void testNonOverridingFunOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt");
}
@Test
@TestMetadata("nonOverridingVarOfMfvc.kt")
public void testNonOverridingVarOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt");
}
@Test
@TestMetadata("overridingFunOfMfvc.kt")
public void testOverridingFunOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt");
}
@Test
@TestMetadata("overridingVarOfMfvc.kt")
public void testOverridingVarOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt");
}
@Test
@TestMetadata("primaryValOfMfvc.kt")
public void testPrimaryValOfMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt");
}
@Test
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt");
}
@Test
@TestMetadata("suspendFunction.kt")
public void testSuspendFunction() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt");
}
}
}
@Nested
@@ -43640,6 +43734,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/callBy/manyMaskArguments.kt");
}
@Test
@TestMetadata("mfvcDefaultArguments.kt")
public void testMfvcDefaultArguments() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt");
}
@Test
@TestMetadata("mfvcFunctionsAndConstructors.kt")
public void testMfvcFunctionsAndConstructors() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt");
}
@Test
@TestMetadata("mfvcMembers.kt")
public void testMfvcMembers() throws Exception {
runTest("compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt");
}
@Test
@TestMetadata("nonDefaultParameterOmitted.kt")
public void testNonDefaultParameterOmitted() throws Exception {
@@ -44484,6 +44596,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithInlineClassArgument.kt");
}
@Test
@TestMetadata("reflectOnDefaultWithMfvcArgument.kt")
public void testReflectOnDefaultWithMfvcArgument() throws Exception {
runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt");
}
@Test
@TestMetadata("reflectOnLambdaInArrayConstructor.kt")
public void testReflectOnLambdaInArrayConstructor() throws Exception {
@@ -44554,6 +44672,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithInlineClassParameters.kt");
}
@Test
@TestMetadata("constructorWithMfvcParameters.kt")
public void testConstructorWithMfvcParameters() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt");
}
@Test
@TestMetadata("extensionProperty.kt")
public void testExtensionProperty() throws Exception {
@@ -44815,6 +44939,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/mapping/types/memberFunctions.kt");
}
@Test
@TestMetadata("mfvcInSignature.kt")
public void testMfvcInSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt");
}
@Test
@TestMetadata("mfvcPrimaryVal.kt")
public void testMfvcPrimaryVal() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt");
}
@Test
@TestMetadata("overrideAnyWithPrimitive.kt")
public void testOverrideAnyWithPrimitive() throws Exception {
@@ -44881,6 +45017,28 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("mfvcPrimaryVal.kt")
public void testMfvcPrimaryVal() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt");
}
@Test
@TestMetadata("suspendFunctionWithMfvcInSignature.kt")
public void testSuspendFunctionWithMfvcInSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt");
}
}
}
@Nested
@@ -45094,6 +45252,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/modifiers/javaVisibility.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/modifiers/mfvc.kt");
}
@Test
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
@@ -45904,6 +46068,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/typeOf/manyTypeArguments.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/mfvc.kt");
}
@Test
@TestMetadata("multipleLayers.kt")
public void testMultipleLayers() throws Exception {
@@ -46013,6 +46183,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt");
}
@Test
@TestMetadata("mfvc.kt")
public void testMfvc() throws Exception {
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt");
}
@Test
@TestMetadata("mutableCollections_after.kt")
public void testMutableCollections_after() throws Exception {
@@ -33110,6 +33110,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
}
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ValueClasses extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/callBy")
@@ -34313,6 +34326,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ValueClasses extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/methodsFromAny")
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.inlineClassRepresentation
import org.jetbrains.kotlin.resolve.descriptorUtil.multiFieldValueClassRepresentation
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.TypeUtils
@@ -42,6 +43,8 @@ fun KotlinType.unsubstitutedUnderlyingTypes(): List<KotlinType> {
fun KotlinType.isInlineClassType(): Boolean = constructor.declarationDescriptor?.isInlineClass() ?: false
fun KotlinType.isMultiFieldValueClassType(): Boolean = constructor.declarationDescriptor?.isMultiFieldValueClass() ?: false
fun KotlinType.isValueClassType(): Boolean = constructor.declarationDescriptor?.isValueClass() ?: false
fun KotlinType.needsMfvcFlattening(): Boolean =
constructor.declarationDescriptor?.run { isMultiFieldValueClass() && !isNullableType() } == true
@@ -77,6 +80,20 @@ fun KotlinType.isNullableUnderlyingType(): Boolean {
fun CallableDescriptor.isGetterOfUnderlyingPropertyOfInlineClass() =
this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfInlineClass()
fun CallableDescriptor.isGetterOfUnderlyingPropertyOfMultiFieldValueClass() =
this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfMultiFieldValueClass()
fun CallableDescriptor.isGetterOfUnderlyingPropertyOfValueClass() =
this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfValueClass()
fun VariableDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean =
extensionReceiverParameter == null &&
(containingDeclaration as? ClassDescriptor)?.inlineClassRepresentation?.underlyingPropertyName == this.name
fun VariableDescriptor.isUnderlyingPropertyOfMultiFieldValueClass(): Boolean =
extensionReceiverParameter == null &&
(containingDeclaration as? ClassDescriptor)?.multiFieldValueClassRepresentation?.containsPropertyWithName(this.name) == true
fun VariableDescriptor.isUnderlyingPropertyOfValueClass(): Boolean =
extensionReceiverParameter == null &&
(containingDeclaration as? ClassDescriptor)?.valueClassRepresentation?.containsPropertyWithName(this.name) == true
@@ -8,13 +8,14 @@ package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.types.asSimpleType
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.lang.reflect.WildcardType
import java.util.*
import kotlin.coroutines.Continuation
import kotlin.reflect.*
import kotlin.reflect.jvm.internal.calls.Caller
import kotlin.reflect.jvm.internal.calls.getMfvcUnboxMethods
import kotlin.reflect.jvm.javaType
import kotlin.reflect.jvm.jvmErasure
import java.lang.reflect.Array as ReflectArray
@@ -113,7 +114,9 @@ internal abstract class KCallableImpl<out R> : KCallable<R>, KTypeParameterOwner
private val _absentArguments = ReflectProperties.lazySoft {
val parameterSize = parameters.size + (if (isSuspend) 1 else 0)
val maskSize = (parameters.size + Integer.SIZE - 1) / Integer.SIZE
val flattenedParametersSize =
if (parametersNeedMFVCFlattening.value) parameters.sumOf { getParameterTypeSize(it) } else parameters.size
val maskSize = (flattenedParametersSize + Integer.SIZE - 1) / Integer.SIZE
// Array containing the actual function arguments, masks, and +1 for DefaultConstructorMarker or MethodHandle.
val arguments = arrayOfNulls<Any?>(parameterSize + maskSize + 1)
@@ -161,14 +164,23 @@ internal abstract class KCallableImpl<out R> : KCallable<R>, KTypeParameterOwner
var valueParameterIndex = 0
var anyOptional = false
val hasMfvcParameters = parametersNeedMFVCFlattening.value
for (parameter in parameters) {
val parameterTypeSize = if (hasMfvcParameters) getParameterTypeSize(parameter) else 1
when {
args.containsKey(parameter) -> {
arguments[parameter.index] = args[parameter]
}
parameter.isOptional -> {
val maskIndex = parameterSize + (valueParameterIndex / Integer.SIZE)
arguments[maskIndex] = (arguments[maskIndex] as Int) or (1 shl (valueParameterIndex % Integer.SIZE))
if (hasMfvcParameters) {
for (valueSubParameterIndex in valueParameterIndex until (valueParameterIndex + parameterTypeSize)) {
val maskIndex = parameterSize + (valueSubParameterIndex / Integer.SIZE)
arguments[maskIndex] = (arguments[maskIndex] as Int) or (1 shl (valueSubParameterIndex % Integer.SIZE))
}
} else {
val maskIndex = parameterSize + (valueParameterIndex / Integer.SIZE)
arguments[maskIndex] = (arguments[maskIndex] as Int) or (1 shl (valueParameterIndex % Integer.SIZE))
}
anyOptional = true
}
parameter.isVararg -> {}
@@ -178,7 +190,7 @@ internal abstract class KCallableImpl<out R> : KCallable<R>, KTypeParameterOwner
}
if (parameter.kind == KParameter.Kind.VALUE) {
valueParameterIndex++
valueParameterIndex += parameterTypeSize
}
}
@@ -197,6 +209,20 @@ internal abstract class KCallableImpl<out R> : KCallable<R>, KTypeParameterOwner
}
}
private val parametersNeedMFVCFlattening = lazy(LazyThreadSafetyMode.PUBLICATION) {
parameters.any { it.type.needsMultiFieldValueClassFlattening }
}
private fun getParameterTypeSize(parameter: KParameter): Int {
require(parametersNeedMFVCFlattening.value) { "Check if parametersNeedMFVCFlattening is true before" }
return if (parameter.type.needsMultiFieldValueClassFlattening) {
val type = (parameter.type as KTypeImpl).type.asSimpleType()
getMfvcUnboxMethods(type)!!.size
} else {
1
}
}
private fun callAnnotationConstructor(args: Map<KParameter, Any?>): R {
val arguments = parameters.map { parameter ->
when {
@@ -24,10 +24,12 @@ import org.jetbrains.kotlin.descriptors.runtime.structure.wrapperByPrimitive
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.isMultiFieldValueClass
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import java.lang.reflect.Constructor
import java.lang.reflect.Method
import kotlin.jvm.internal.ClassBasedDeclarationContainer
import kotlin.reflect.jvm.internal.calls.toJvmDescriptor
internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
abstract inner class Data {
@@ -119,9 +121,25 @@ internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContain
}
fun findFunctionDescriptor(name: String, signature: String): FunctionDescriptor {
val members = if (name == "<init>") constructorDescriptors.toList() else getFunctions(Name.identifier(name))
val functions = members.filter { descriptor ->
RuntimeTypeMapper.mapSignature(descriptor).asString() == signature
val members: Collection<FunctionDescriptor>
val functions: List<FunctionDescriptor>
if (name == "<init>") {
members = constructorDescriptors.toList()
functions = members.filter { descriptor ->
val descriptorSignature = if (descriptor.isPrimary && descriptor.containingDeclaration.isMultiFieldValueClass()) {
val initial = RuntimeTypeMapper.mapSignature(descriptor).asString()
require(initial.startsWith("constructor-impl") && initial.endsWith(")V")) {
"Invalid signature of $descriptor: $initial"
}
initial.removeSuffix("V") + descriptor.containingDeclaration.toJvmDescriptor()
} else {
RuntimeTypeMapper.mapSignature(descriptor).asString()
}
descriptorSignature == signature
}
} else {
members = getFunctions(Name.identifier(name))
functions = members.filter { descriptor -> RuntimeTypeMapper.mapSignature(descriptor).asString() == signature }
}
if (functions.size != 1) {
@@ -17,8 +17,10 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.jvm.shouldHideConstructorDueToInlineClassTypeValueParameters
import org.jetbrains.kotlin.resolve.isMultiFieldValueClass
import org.jetbrains.kotlin.resolve.jvm.shouldHideConstructorDueToValueClassTypeValueParameters
import java.lang.reflect.Constructor
import java.lang.reflect.Member
import java.lang.reflect.Method
@@ -66,7 +68,14 @@ internal class KFunctionImpl private constructor(
return@caller AnnotationConstructorCaller(container.jClass, parameters.map { it.name!! }, POSITIONAL_CALL, KOTLIN)
container.findConstructorBySignature(jvmSignature.constructorDesc)
}
is KotlinFunction -> container.findMethodBySignature(jvmSignature.methodName, jvmSignature.methodDesc)
is KotlinFunction -> {
if (descriptor.let { it.containingDeclaration.isMultiFieldValueClass() && it is ConstructorDescriptor && it.isPrimary }) {
return@caller ValueClassAwareCaller.MultiFieldValueClassPrimaryConstructorCaller(
descriptor, container, jvmSignature.methodDesc, descriptor.valueParameters
)
}
container.findMethodBySignature(jvmSignature.methodName, jvmSignature.methodDesc)
}
is JavaMethod -> jvmSignature.method
is JavaConstructor -> jvmSignature.constructor
is FakeJavaAnnotationConstructor -> {
@@ -87,13 +96,16 @@ internal class KFunctionImpl private constructor(
createStaticMethodCaller(member)
}
else -> throw KotlinReflectionInternalError("Could not compute caller for function: $descriptor (member = $member)")
}.createInlineClassAwareCallerIfNeeded(descriptor)
}.createValueClassAwareCallerIfNeeded(descriptor)
}
override val defaultCaller: Caller<*>? by lazy(PUBLICATION) defaultCaller@{
val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
val member: Member? = when (jvmSignature) {
is KotlinFunction -> {
if (descriptor.let { it.containingDeclaration.isMultiFieldValueClass() && it is ConstructorDescriptor && it.isPrimary }) {
throw KotlinReflectionInternalError("${descriptor.containingDeclaration} cannot have default arguments")
}
container.findDefaultMethod(jvmSignature.methodName, jvmSignature.methodDesc, !Modifier.isStatic(caller.member!!.modifiers))
}
is KotlinConstructor -> {
@@ -126,7 +138,7 @@ internal class KFunctionImpl private constructor(
createStaticMethodCaller(member)
}
else -> null
}?.createInlineClassAwareCallerIfNeeded(descriptor, isDefault = true)
}?.createValueClassAwareCallerIfNeeded(descriptor, isDefault = true)
}
private val boundReceiver
@@ -144,7 +156,7 @@ internal class KFunctionImpl private constructor(
private fun createConstructorCaller(
member: Constructor<*>, descriptor: FunctionDescriptor, isDefault: Boolean
): CallerImpl<Constructor<*>> {
return if (!isDefault && shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) {
return if (!isDefault && shouldHideConstructorDueToValueClassTypeValueParameters(descriptor)) {
if (isBound)
CallerImpl.AccessorForHiddenBoundConstructor(member, boundReceiver)
else
@@ -18,8 +18,10 @@ package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue
import java.lang.reflect.Type
import kotlin.reflect.KParameter
import kotlin.reflect.KType
import kotlin.reflect.jvm.internal.calls.ValueClassAwareCaller
internal class KParameterImpl(
val callable: KCallableImpl<*>,
@@ -39,6 +41,27 @@ internal class KParameterImpl(
return if (name.isSpecial) null else name.asString()
}
private fun compoundType(vararg types: Type): Type = when (types.size) {
0 -> throw KotlinReflectionNotSupportedError("Expected at least 1 type for compound type")
1 -> types.single()
else -> CompoundTypeImpl(types)
}
private class CompoundTypeImpl(val types: Array<out Type>) : Type {
private val hashCode = types.contentHashCode()
override fun getTypeName(): String {
return types.joinToString(", ", "[", "]")
}
override fun equals(other: Any?): Boolean =
other is CompoundTypeImpl && this.types contentEquals other.types
override fun hashCode(): Int = hashCode
override fun toString(): String = typeName
}
override val type: KType
get() = KTypeImpl(descriptor.type) {
val descriptor = descriptor
@@ -53,7 +76,16 @@ internal class KParameterImpl(
(callable.descriptor.containingDeclaration as ClassDescriptor).toJavaClass()
?: throw KotlinReflectionInternalError("Cannot determine receiver Java type of inherited declaration: $descriptor")
} else {
callable.caller.parameterTypes[index]
when (val caller = callable.caller) {
is ValueClassAwareCaller -> {
val slice = caller.getRealSlicesOfParameters(index)
val parameterTypes = caller.parameterTypes.slice(slice)
compoundType(*parameterTypes.toTypedArray())
}
is ValueClassAwareCaller.MultiFieldValueClassPrimaryConstructorCaller ->
compoundType(*caller.originalParametersGroups[index].toTypedArray())
else -> caller.parameterTypes[index]
}
}
}
@@ -271,8 +271,9 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool
if (property.descriptor.isUnderlyingPropertyOfInlineClass() &&
property.descriptor.visibility == DescriptorVisibilities.INTERNAL
) {
val unboxMethod = property.descriptor.containingDeclaration.toInlineClass()?.getUnboxMethod(property.descriptor)
?: throw KotlinReflectionInternalError("Underlying property of inline class $property should have a field")
val unboxMethod =
property.descriptor.containingDeclaration.toInlineClass()?.getInlineClassUnboxMethod(property.descriptor)
?: throw KotlinReflectionInternalError("Underlying property of inline class $property should have a field")
if (isBound) InternalUnderlyingValOfInlineClass.Bound(unboxMethod, boundReceiver)
else InternalUnderlyingValOfInlineClass.Unbound(unboxMethod)
} else {
@@ -316,7 +317,7 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool
return if (isBound) CallerImpl.Method.BoundInstance(accessor, boundReceiver)
else CallerImpl.Method.Instance(accessor)
}
}.createInlineClassAwareCallerIfNeeded(descriptor)
}.createValueClassAwareCallerIfNeeded(descriptor)
}
private fun PropertyDescriptor.isJvmFieldPropertyInCompanionObject(): Boolean {
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.isMultiFieldValueClass
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
@@ -51,6 +52,7 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Method
import kotlin.reflect.jvm.internal.calls.toJvmDescriptor
internal sealed class JvmFunctionSignature {
abstract fun asString(): String
@@ -174,10 +176,27 @@ internal object RuntimeTypeMapper {
}
if (proto is ProtoBuf.Constructor) {
JvmProtoBufUtil.getJvmConstructorSignature(proto, function.nameResolver, function.typeTable)?.let { signature ->
return if (possiblySubstitutedFunction.containingDeclaration.isInlineClass())
JvmFunctionSignature.KotlinFunction(signature)
else
JvmFunctionSignature.KotlinConstructor(signature)
return when {
possiblySubstitutedFunction.containingDeclaration.isInlineClass() ->
JvmFunctionSignature.KotlinFunction(signature)
possiblySubstitutedFunction.containingDeclaration.isMultiFieldValueClass() -> {
val realSignature = if ((possiblySubstitutedFunction as ConstructorDescriptor).isPrimary) {
require(signature.name == "constructor-impl" && signature.desc.endsWith(")V")) { "Invalid signature: $signature" }
signature
} else {
require(signature.name == "constructor-impl") { "Invalid signature: $signature" }
val constructedClass = possiblySubstitutedFunction.constructedClass.toJvmDescriptor()
if (signature.desc.endsWith(")V")) {
signature.copy(desc = signature.desc.removeSuffix("V") + constructedClass)
} else {
require(signature.desc.endsWith(constructedClass)) { "Invalid signature: $signature" }
signature
}
}
JvmFunctionSignature.KotlinFunction(realSignature)
}
else -> JvmFunctionSignature.KotlinConstructor(signature)
}
}
}
return mapJvmFunctionSignature(function)
@@ -122,7 +122,7 @@ internal sealed class CallerImpl<out M : Member>(
}
}
class BoundStatic(method: ReflectMethod, private val boundReceiver: Any?) : BoundCaller, Method(
class BoundStatic(method: ReflectMethod, internal val boundReceiver: Any?) : BoundCaller, Method(
method, requiresInstance = false, parameterTypes = method.genericParameterTypes.dropFirst()
) {
override fun call(args: Array<*>): Any? {
@@ -131,6 +131,21 @@ internal sealed class CallerImpl<out M : Member>(
}
}
class BoundStaticMultiFieldValueClass(
method: ReflectMethod, internal val boundReceiverComponents: Array<Any?>
) : BoundCaller, Method(
method = method,
requiresInstance = false,
parameterTypes = method.genericParameterTypes.drop(boundReceiverComponents.size).toTypedArray()
) {
override fun call(args: Array<*>): Any? {
checkArguments(args)
return callMethod(null, arrayOf(*boundReceiverComponents, *args))
}
val receiverComponentsCount: Int get() = boundReceiverComponents.size
}
class BoundInstance(method: ReflectMethod, private val boundReceiver: Any?) : BoundCaller,
Method(method, requiresInstance = false) {
override fun call(args: Array<*>): Any? {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -7,29 +7,50 @@ package kotlin.reflect.jvm.internal.calls
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.runtime.structure.desc
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.multiFieldValueClassRepresentation
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.asSimpleType
import java.lang.reflect.Member
import java.lang.reflect.Method
import java.lang.reflect.Type
import kotlin.reflect.jvm.internal.KDeclarationContainerImpl
import kotlin.reflect.jvm.internal.KotlinReflectionInternalError
import kotlin.reflect.jvm.internal.defaultPrimitiveValue
import kotlin.reflect.jvm.internal.toJavaClass
/**
* A caller that is used whenever the declaration has inline classes in its parameter types or return type.
* Each argument of an inline class type is unboxed, and the return value (if it's of an inline class type) is boxed.
* A caller that is used whenever the declaration has value classes in its parameter types or inline class in return type.
* Each argument of an value class type is unboxed, and the return value (if it's of an inline class type) is boxed.
*/
internal class InlineClassAwareCaller<out M : Member?>(
internal class ValueClassAwareCaller<out M : Member?>(
descriptor: CallableMemberDescriptor,
private val caller: Caller<M>,
oldCaller: Caller<M>,
private val isDefault: Boolean
) : Caller<M> {
override val member: M
get() = caller.member
private val caller: Caller<M> = if (oldCaller is CallerImpl.Method.BoundStatic) {
val receiverType = (descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter)?.type
if (receiverType != null && receiverType.needsMfvcFlattening()) {
val unboxMethods = getMfvcUnboxMethods(receiverType.asSimpleType())!!
val boundReceiverComponents = unboxMethods.map { it.invoke(oldCaller.boundReceiver) }.toTypedArray()
@Suppress("UNCHECKED_CAST")
CallerImpl.Method.BoundStaticMultiFieldValueClass(oldCaller.member, boundReceiverComponents) as Caller<M>
} else {
oldCaller
}
} else {
oldCaller
}
override val member: M = caller.member
override val returnType: Type
get() = caller.returnType
@@ -37,24 +58,18 @@ internal class InlineClassAwareCaller<out M : Member?>(
override val parameterTypes: List<Type>
get() = caller.parameterTypes
private class BoxUnboxData(val argumentRange: IntRange, val unbox: Array<Method?>, val box: Method?) {
operator fun component1(): IntRange = argumentRange
operator fun component2(): Array<Method?> = unbox
operator fun component3(): Method? = box
}
private class BoxUnboxData(val argumentRange: IntRange, val unboxParameters: Array<List<Method>?>, val box: Method?)
private val data: BoxUnboxData = run {
val box = descriptor.returnType!!.toInlineClass()?.getBoxMethod(descriptor)
if (descriptor.isGetterOfUnderlyingPropertyOfInlineClass()) {
// Getter of the underlying val of an inline class is always called on a boxed receiver,
// no argument boxing/unboxing is required.
// However, its result might require boxing if it is an inline class type.
if (descriptor.isGetterOfUnderlyingPropertyOfValueClass()) {
// Getter of the underlying val of a value class is always called on a boxed receiver,
// no argument unboxing is required.
return@run BoxUnboxData(IntRange.EMPTY, emptyArray(), box)
}
val shift = when {
caller is CallerImpl.Method.BoundStatic -> {
caller is CallerImpl.Method.BoundStatic || caller is CallerImpl.Method.BoundStaticMultiFieldValueClass -> {
// Bound reference to a static method is only possible for a top level extension function/property,
// and in that case the number of expected arguments is one less than usual, hence -1
-1
@@ -64,9 +79,9 @@ internal class InlineClassAwareCaller<out M : Member?>(
if (caller is BoundCaller) -1 else 0
descriptor.dispatchReceiverParameter != null && caller !is BoundCaller -> {
// If we have an unbound reference to the inline class member,
// If we have an unbound reference to the value class member,
// its receiver (which is passed as argument 0) should also be unboxed.
if (descriptor.containingDeclaration.isInlineClass())
if (descriptor.containingDeclaration.isValueClass())
0
else
1
@@ -75,117 +90,229 @@ internal class InlineClassAwareCaller<out M : Member?>(
else -> 0
}
val kotlinParameterTypes: List<KotlinType> = ArrayList<KotlinType>().also { kotlinParameterTypes ->
val extensionReceiverType = descriptor.extensionReceiverParameter?.type
if (extensionReceiverType != null) {
kotlinParameterTypes.add(extensionReceiverType)
} else if (descriptor is ConstructorDescriptor) {
val constructedClass = descriptor.constructedClass
if (constructedClass.isInner) {
kotlinParameterTypes.add((constructedClass.containingDeclaration as ClassDescriptor).defaultType)
}
} else {
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is ClassDescriptor && containingDeclaration.isInlineClass()) {
kotlinParameterTypes.add(containingDeclaration.defaultType)
}
}
val flattenedShift = if (caller is CallerImpl.Method.BoundStaticMultiFieldValueClass) -caller.receiverComponentsCount else shift
descriptor.valueParameters.mapTo(kotlinParameterTypes, ValueParameterDescriptor::getType)
}
val kotlinParameterTypes: List<KotlinType> = makeKotlinParameterTypes(descriptor) { isValueClass() }
fun typeSize(type: KotlinType): Int = getMfvcUnboxMethods(type.asSimpleType())?.size ?: 1
// If the default argument is set,
// (kotlinParameterTypes.size + Integer.SIZE - 1) / Integer.SIZE masks and one marker are added to the end of the argument.
val extraArgumentsTail = (if (isDefault) ((kotlinParameterTypes.size + Integer.SIZE - 1) / Integer.SIZE) + 1 else 0) +
(if (descriptor is FunctionDescriptor && descriptor.isSuspend) 1 else 0)
val expectedArgsSize = kotlinParameterTypes.size + shift + extraArgumentsTail
if (arity != expectedArgsSize) {
throw KotlinReflectionInternalError(
"Inconsistent number of parameters in the descriptor and Java reflection object: $arity != $expectedArgsSize\n" +
"Calling: $descriptor\n" +
"Parameter types: ${this.parameterTypes})\n" +
"Default: $isDefault"
)
}
// (kotlinParameterTypes.size + Int.SIZE_BITS - 1) / Int.SIZE_BITS masks and one marker are added to the end of the argument.
val extraArgumentsTail =
(if (isDefault) ((kotlinParameterTypes.sumOf(::typeSize) + Int.SIZE_BITS - 1) / Int.SIZE_BITS) + 1 else 0) +
(if (descriptor is FunctionDescriptor && descriptor.isSuspend) 1 else 0)
val expectedArgsSize = kotlinParameterTypes.sumOf(::typeSize) + flattenedShift + extraArgumentsTail
checkParametersSize(expectedArgsSize, descriptor, isDefault)
// maxOf is needed because in case of a bound top level extension, shift can be -1 (see above). But in that case, we need not unbox
// the extension receiver argument, since it has already been unboxed at compile time and generated into the reference
val argumentRange = maxOf(shift, 0) until (kotlinParameterTypes.size + shift)
val unbox = Array(expectedArgsSize) { i ->
if (i in argumentRange) {
kotlinParameterTypes[i - shift].toInlineClass()?.getUnboxMethod(descriptor)
} else null
if (i in argumentRange)
getValueClassUnboxMethods(kotlinParameterTypes[i - shift].asSimpleType(), descriptor)
else null
}
BoxUnboxData(argumentRange, unbox, box)
}
private val slices = buildList {
var currentOffset = when (caller) {
is CallerImpl.Method.BoundStaticMultiFieldValueClass -> caller.boundReceiverComponents.size
is CallerImpl.Method.BoundStatic -> 1
else -> 0
}
if (currentOffset > 0) {
add(0 until currentOffset)
}
for (parameterUnboxMethods in data.unboxParameters) {
val length = parameterUnboxMethods?.size ?: 1
add(currentOffset until (currentOffset + length))
currentOffset += length
}
}.toTypedArray()
fun getRealSlicesOfParameters(index: Int): IntRange = when {
index in slices.indices -> slices[index]
slices.isEmpty() -> index..index
else -> {
val start = (index - slices.size) + (slices.last().last + 1)
start..start
}
}
private val hasMfvcParameters = data.argumentRange.any { (data.unboxParameters[it] ?: return@any false).size > 1 }
override fun call(args: Array<*>): Any? {
val (range, unbox, box) = data
val range = data.argumentRange
val unbox = data.unboxParameters
val box = data.box
@Suppress("UNCHECKED_CAST")
val unboxed = Array(args.size) { index ->
val arg = args[index]
if (index in range) {
// Note that arg may be null in case we're calling a $default method and it's an optional parameter of an inline class type
val method = unbox[index]
if (method != null) {
if (arg != null) {
method.invoke(arg)
val unboxedArguments = when {
range.isEmpty() -> args
hasMfvcParameters -> buildList(args.size) {
for (index in 0 until range.first) {
add(args[index])
}
for (index in range) {
val methods = unbox[index]
val arg = args[index]
// Note that arg may be null in case we're calling a $default method, and it's an optional parameter of a value class type
if (methods != null) {
methods.mapTo(this) { if (arg != null) it.invoke(arg) else defaultPrimitiveValue(it.returnType) }
} else {
defaultPrimitiveValue(method.returnType)
add(arg)
}
}
for (index in (range.last + 1)..args.lastIndex) {
add(args[index])
}
}.toTypedArray()
else -> Array(args.size) { index ->
if (index in range) {
val method = unbox[index]?.single()
val arg = args[index]
// Note that arg may be null in case we're calling a $default method, and it's an optional parameter of a inline class type
when {
method == null -> arg
arg != null -> method.invoke(arg)
else -> defaultPrimitiveValue(method.returnType)
}
} else {
arg
args[index]
}
} else {
arg
}
}
val result = caller.call(unboxed)
val result = caller.call(unboxedArguments)
// box is not null only for inline classes
return box?.invoke(null, result) ?: result
}
class MultiFieldValueClassPrimaryConstructorCaller(
descriptor: FunctionDescriptor,
container: KDeclarationContainerImpl,
constructorDesc: String,
originalParameters: List<ParameterDescriptor>
) : Caller<Nothing?> {
private val constructorImpl = container.findMethodBySignature("constructor-impl", constructorDesc)!!
private val boxMethod = container.findMethodBySignature("box-impl", constructorDesc.removeSuffix("V") + container.jClass.desc)!!
private val parameterUnboxMethods: List<List<Method>?> = originalParameters.map { parameter ->
getValueClassUnboxMethods(parameter.type.asSimpleType(), descriptor)
}
override val member: Nothing?
get() = null
override val returnType: Type
get() = boxMethod.returnType
val originalParametersGroups: List<List<Class<*>>> = originalParameters.mapIndexed { index, it ->
val classDescriptor = it.type.constructor.declarationDescriptor as ClassDescriptor
parameterUnboxMethods[index]?.map { it.returnType } ?: listOf(classDescriptor.toJavaClass()!!)
}
override val parameterTypes: List<Type> = originalParametersGroups.flatten()
override fun call(args: Array<*>): Any? {
val newArgs = (args zip parameterUnboxMethods)
.flatMap { (arg, unboxMethods) -> unboxMethods?.map { it.invoke(arg) } ?: listOf(arg) }.toTypedArray()
constructorImpl.invoke(null, *newArgs)
return boxMethod.invoke(null, *newArgs)
}
}
}
internal fun <M : Member?> Caller<M>.createInlineClassAwareCallerIfNeeded(
internal fun ClassifierDescriptor.toJvmDescriptor(): String = ClassMapperLite.mapClass(classId!!.asString())
private fun getValueClassUnboxMethods(type: SimpleType, descriptor: CallableMemberDescriptor): List<Method>? =
getMfvcUnboxMethods(type) ?: type.toInlineClass()?.getInlineClassUnboxMethod(descriptor)?.let(::listOf)
internal fun getMfvcUnboxMethods(type: SimpleType): List<Method>? {
fun getUnboxMethodNameSuffixes(type: SimpleType): List<String>? =
if (type.needsMfvcFlattening()) (type.constructor.declarationDescriptor as ClassDescriptor)
.multiFieldValueClassRepresentation!!.underlyingPropertyNamesToTypes.flatMap { (name, innerType) ->
getUnboxMethodNameSuffixes(innerType)?.map { "${name.identifier}-${it}" } ?: listOf(name.identifier)
}
else null
val unboxMethodsNames = getUnboxMethodNameSuffixes(type.asSimpleType())?.map { "unbox-impl-$it" } ?: return null
val javaClass = (type.constructor.declarationDescriptor as ClassDescriptor).toJavaClass()!!
return unboxMethodsNames.map { javaClass.getDeclaredMethod(it) }
}
private fun Caller<*>.checkParametersSize(
expectedArgsSize: Int,
descriptor: CallableMemberDescriptor,
isDefault: Boolean,
) {
if (arity != expectedArgsSize) {
throw KotlinReflectionInternalError(
"Inconsistent number of parameters in the descriptor and Java reflection object: $arity != $expectedArgsSize\n" +
"Calling: $descriptor\n" +
"Parameter types: ${this.parameterTypes})\n" +
"Default: $isDefault"
)
}
}
private fun makeKotlinParameterTypes(
descriptor: CallableMemberDescriptor, isSpecificClass: ClassDescriptor.() -> Boolean
): List<KotlinType> = ArrayList<KotlinType>().also { kotlinParameterTypes ->
val extensionReceiverType = descriptor.extensionReceiverParameter?.type
if (extensionReceiverType != null) {
kotlinParameterTypes.add(extensionReceiverType)
} else if (descriptor is ConstructorDescriptor) {
val constructedClass = descriptor.constructedClass
if (constructedClass.isInner) {
kotlinParameterTypes.add((constructedClass.containingDeclaration as ClassDescriptor).defaultType)
}
} else {
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is ClassDescriptor && containingDeclaration.isSpecificClass()) {
kotlinParameterTypes.add(containingDeclaration.defaultType)
}
}
descriptor.valueParameters.mapTo(kotlinParameterTypes, ValueParameterDescriptor::getType)
}
internal fun <M : Member?> Caller<M>.createValueClassAwareCallerIfNeeded(
descriptor: CallableMemberDescriptor,
isDefault: Boolean = false
): Caller<M> {
val needsInlineAwareCaller: Boolean =
descriptor.isGetterOfUnderlyingPropertyOfInlineClass() ||
descriptor.valueParameters.any { it.type.isInlineClassType() } ||
val needsValueClassAwareCaller: Boolean =
descriptor.isGetterOfUnderlyingPropertyOfValueClass() ||
descriptor.contextReceiverParameters.any { it.type.isValueClassType() } ||
descriptor.valueParameters.any { it.type.isValueClassType() } ||
descriptor.returnType?.isInlineClassType() == true ||
this !is BoundCaller && descriptor.hasInlineClassReceiver()
descriptor.hasValueClassReceiver()
return if (needsInlineAwareCaller) InlineClassAwareCaller(descriptor, this, isDefault) else this
return if (needsValueClassAwareCaller) ValueClassAwareCaller(descriptor, this, isDefault) else this
}
private fun CallableMemberDescriptor.hasInlineClassReceiver() =
expectedReceiverType?.isInlineClassType() == true
private fun CallableMemberDescriptor.hasValueClassReceiver() =
expectedReceiverType?.isValueClassType() == true
internal fun Class<*>.getUnboxMethod(descriptor: CallableMemberDescriptor): Method =
internal fun Class<*>.getInlineClassUnboxMethod(descriptor: CallableMemberDescriptor): Method =
try {
getDeclaredMethod("unbox" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS)
} catch (e: NoSuchMethodException) {
throw KotlinReflectionInternalError("No unbox method found in inline class: $this (calling $descriptor)")
}
internal fun Class<*>.getBoxMethod(descriptor: CallableMemberDescriptor): Method =
private fun Class<*>.getBoxMethod(descriptor: CallableMemberDescriptor): Method =
try {
getDeclaredMethod("box" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS, getUnboxMethod(descriptor).returnType)
getDeclaredMethod("box" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS, getInlineClassUnboxMethod(descriptor).returnType)
} catch (e: NoSuchMethodException) {
throw KotlinReflectionInternalError("No box method found in inline class: $this (calling $descriptor)")
}
internal fun KotlinType.toInlineClass(): Class<*>? {
private fun KotlinType.toInlineClass(): Class<*>? {
// See computeExpandedTypeForInlineClass.
// TODO: add tests on type parameters with inline class bounds.
// TODO: add tests on usages of inline classes in Java.
// TODO: add tests on type parameters with value class bounds.
// TODO: add tests on usages of value classes in Java.
val klass = constructor.declarationDescriptor.toInlineClass() ?: return null
if (!TypeUtils.isNullableType(this)) return klass
@@ -217,7 +344,7 @@ internal fun Any?.coerceToExpectedReceiverType(descriptor: CallableMemberDescrip
if (descriptor is PropertyDescriptor && descriptor.isUnderlyingPropertyOfInlineClass()) return this
val expectedReceiverType = descriptor.expectedReceiverType
val unboxMethod = expectedReceiverType?.toInlineClass()?.getUnboxMethod(descriptor) ?: return this
val unboxMethod = expectedReceiverType?.toInlineClass()?.getInlineClassUnboxMethod(descriptor) ?: return this
return unboxMethod.invoke(this)
}
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.isInlineClassType
import org.jetbrains.kotlin.resolve.needsMfvcFlattening
import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext
import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
import java.lang.reflect.Field
@@ -268,6 +269,8 @@ internal fun <M : MessageLite, D : CallableDescriptor> deserializeToDescriptor(
internal val KType.isInlineClassType: Boolean
get() = (this as? KTypeImpl)?.type?.isInlineClassType() == true
internal val KType.needsMultiFieldValueClassFlattening: Boolean
get() = (this as? KTypeImpl)?.type?.needsMfvcFlattening() == true
internal fun defaultPrimitiveValue(type: Type): Any? =
if (type is Class<*> && type.isPrimitive) {
@@ -31931,6 +31931,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
}
}
@Nested
@@ -32391,6 +32401,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
}
}
@Nested
@@ -32117,6 +32117,16 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@Nested
@@ -32577,6 +32587,16 @@ public class FirJsCodegenBoxTestGenerated extends AbstractFirJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@Nested
@@ -32117,6 +32117,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@Nested
@@ -32577,6 +32587,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
}
}
@Nested
@@ -32117,6 +32117,16 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
}
}
@Nested
@@ -32577,6 +32587,16 @@ public class IrJsES6CodegenBoxTestGenerated extends AbstractIrJsES6CodegenBoxTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
}
}
@Nested
@@ -35571,6 +35571,19 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@Tag("codegenK2")
@UseExtTestCaseGroupProvider()
@K2Pipeline()
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
}
}
@Nested
@@ -36091,6 +36104,19 @@ public class K2NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@Tag("codegenK2")
@UseExtTestCaseGroupProvider()
@K2Pipeline()
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
}
}
@Nested
@@ -35148,6 +35148,18 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
}
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@Tag("codegen")
@UseExtTestCaseGroupProvider()
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
}
}
@Nested
@@ -35652,6 +35664,18 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@Tag("codegen")
@UseExtTestCaseGroupProvider()
public class ValueClasses {
@Test
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
}
}
}
@Nested
@@ -28720,6 +28720,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
}
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ValueClasses extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/callBy")
@@ -29178,6 +29191,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ValueClasses extends AbstractIrCodegenBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInValueClasses() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
}
@TestMetadata("compiler/testData/codegen/box/reflection/methodsFromAny")