diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index 5724792705d..e6020ae4fa6 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor @@ -39,6 +40,7 @@ import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getSuperCallExpression import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeProjectionImpl @@ -399,11 +401,12 @@ private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, reso generateExpression(it) } - generateSamConversionForValueArgumentsIfRequired(call, resolvedCall.resultingDescriptor) + generateSamConversionForValueArgumentsIfRequired(call, resolvedCall) } -fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: CallBuilder, originalDescriptor: CallableDescriptor) { - val underlyingDescriptor = context.extensions.samConversion.getOriginalForSamAdapter(originalDescriptor) ?: return +fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: CallBuilder, resolvedCall: ResolvedCall<*>) { + val originalDescriptor = resolvedCall.resultingDescriptor + val underlyingDescriptor = context.extensions.samConversion.getOriginalForSamAdapter(originalDescriptor) ?: originalDescriptor val originalValueParameters = originalDescriptor.valueParameters val underlyingValueParameters = underlyingDescriptor.valueParameters @@ -422,17 +425,23 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca "$originalDescriptor has ${originalDescriptor.typeParameters}" } + val partialSamConversionIsSupported = context.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) val substitutionContext = call.original.typeArguments.entries.associate { (typeParameterDescriptor, typeArgument) -> underlyingDescriptor.typeParameters[typeParameterDescriptor.index].typeConstructor to TypeProjectionImpl(typeArgument) } val typeSubstitutor = TypeSubstitutor.create(substitutionContext) for (i in underlyingValueParameters.indices) { - val originalParameterType = originalValueParameters[i].type val underlyingParameterType = underlyingValueParameters[i].type - if (!context.extensions.samConversion.isSamType(underlyingParameterType)) continue - if (!originalParameterType.isFunctionTypeOrSubtype) continue + if (partialSamConversionIsSupported && resolvedCall is NewResolvedCallImpl<*>) { + // TODO support SAM conversion of varargs + val argument = resolvedCall.valueArguments[originalValueParameters[i]]?.arguments?.singleOrNull() ?: continue + if (resolvedCall.getExpectedTypeForSamConvertedArgument(argument) == null) continue + } else { + if (!context.extensions.samConversion.isSamType(underlyingParameterType)) continue + if (!originalValueParameters[i].type.isFunctionTypeOrSubtype) continue + } val originalArgument = call.irValueArgumentsByIndex[i] ?: continue diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt index c43651da906..c581373c03f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/AssignmentGenerator.kt @@ -73,7 +73,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen val opCall = statementGenerator.pregenerateCallReceivers(opResolvedCall) opCall.setExplicitReceiverValue(irLValue) opCall.irValueArgumentsByIndex[0] = ktRight.genExpr() - statementGenerator.generateSamConversionForValueArgumentsIfRequired(opCall, opResolvedCall.resultingDescriptor) + statementGenerator.generateSamConversionForValueArgumentsIfRequired(opCall, opResolvedCall) val irOpCall = CallGenerator(statementGenerator).generateCall(ktExpression, opCall, origin) if (isSimpleAssignment) { diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt index 8f00ce025e6..527b317a6f5 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/intermediate/ArrayAccessAssignmentReceiver.kt @@ -124,6 +124,6 @@ class ArrayAccessAssignmentReceiver( ktExpressionToIrIndexValue[ktExpression]?.load() } value?.let { lastArgument = it } - callGenerator.statementGenerator.generateSamConversionForValueArgumentsIfRequired(this, resolvedCall.resultingDescriptor) + callGenerator.statementGenerator.generateSamConversionForValueArgumentsIfRequired(this, resolvedCall) } } diff --git a/compiler/testData/codegen/box/sam/partialSam.kt b/compiler/testData/codegen/box/sam/partialSam.kt index f0dc010a10b..dde5f61a3f0 100644 --- a/compiler/testData/codegen/box/sam/partialSam.kt +++ b/compiler/testData/codegen/box/sam/partialSam.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference +SamConversionPerArgument // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: Fn.java diff --git a/compiler/testData/codegen/box/sam/partialSamKT.kt b/compiler/testData/codegen/box/sam/partialSamKT.kt index 85d436407be..7d4525d8d0d 100644 --- a/compiler/testData/codegen/box/sam/partialSamKT.kt +++ b/compiler/testData/codegen/box/sam/partialSamKT.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +NewInference +SamConversionForKotlinFunctions +SamConversionPerArgument // IGNORE_BACKEND_FIR: JVM_IR -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: Fn.java diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt index 7cfb1fc72df..483ad701980 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall.txt @@ -5,7 +5,7 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall.kt RETURN type=kotlin.Nothing from='public final fun test1 (f: kotlin.Function1): .C declared in ' CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null : kotlin.String - jxx: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J + jxx: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J? GET_VAR 'f: kotlin.Function1 declared in .test1' type=kotlin.Function1 origin=null FUN name:test2 visibility:public modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:x index:0 type:kotlin.Any @@ -16,5 +16,6 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall.kt TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null : kotlin.String - jxx: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J - GET_VAR 'x: kotlin.Any declared in .test2' type=kotlin.Any origin=null + jxx: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J? + TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String?, kotlin.String?> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String?, kotlin.String?> + GET_VAR 'x: kotlin.Any declared in .test2' type=kotlin.Any origin=null diff --git a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt index 94a5926fe80..179be4310da 100644 --- a/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt +++ b/compiler/testData/ir/irText/expressions/sam/samConversionInGenericConstructorCall_NI.txt @@ -8,9 +8,9 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall_NI.kt : kotlin.Int $outer: CONSTRUCTOR_CALL 'public constructor (jxx: .J.C?, X of .C?>?) declared in .C' type=.C origin=null : kotlin.String - jxx: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J + jxx: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J? GET_VAR 'f1: kotlin.Function1 declared in .test3' type=kotlin.Function1 origin=null - jxy: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J + jxy: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J? GET_VAR 'f2: kotlin.Function1 declared in .test3' type=kotlin.Function1 origin=null CLASS CLASS name:Outer modality:FINAL visibility:public superTypes:[kotlin.Any] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.Outer.Outer> @@ -86,9 +86,9 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall_NI.kt : kotlin.Any $outer: CONSTRUCTOR_CALL 'public constructor (j11: .J.Outer, T1 of .Outer>) [primary] declared in .Outer' type=.Outer origin=null : kotlin.String - j11: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J + j11: TYPE_OP type=.J origin=SAM_CONVERSION typeOperand=.J GET_VAR 'f: kotlin.Function1 declared in .test4' type=kotlin.Function1 origin=null - j12: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J + j12: TYPE_OP type=.J origin=SAM_CONVERSION typeOperand=.J GET_VAR 'g: kotlin.Function1 declared in .test4' type=kotlin.Function1 origin=null FUN name:testGenericJavaCtor1 visibility:public modality:FINAL <> (f:kotlin.Function1) returnType:.G VALUE_PARAMETER name:f index:0 type:kotlin.Function1 @@ -97,7 +97,7 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall_NI.kt CONSTRUCTOR_CALL 'public constructor (x: .J.G.?, TClass of .G?>?) declared in .G' type=.G origin=null : kotlin.String : kotlin.Int - x: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J + x: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J? GET_VAR 'f: kotlin.Function1 declared in .testGenericJavaCtor1' type=kotlin.Function1 origin=null FUN name:testGenericJavaCtor2 visibility:public modality:FINAL <> (x:kotlin.Any) returnType:kotlin.Unit VALUE_PARAMETER name:x index:0 type:kotlin.Any @@ -109,5 +109,6 @@ FILE fqName: fileName:/samConversionInGenericConstructorCall_NI.kt CONSTRUCTOR_CALL 'public constructor (x: .J.G.?, TClass of .G?>?) declared in .G' type=.G origin=null : kotlin.String : kotlin.Int - x: TYPE_OP type=.J origin=IMPLICIT_CAST typeOperand=.J - GET_VAR 'x: kotlin.Any declared in .testGenericJavaCtor2' type=kotlin.Any origin=null + x: TYPE_OP type=.J? origin=SAM_CONVERSION typeOperand=.J? + TYPE_OP type=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String?, kotlin.Int?> origin=IMPLICIT_CAST typeOperand=kotlin.Function1<@[ParameterName(name = 'x')] kotlin.String?, kotlin.Int?> + GET_VAR 'x: kotlin.Any declared in .testGenericJavaCtor2' type=kotlin.Any origin=null