diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index af28c640ed0..1d3841fa3bb 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -19997,6 +19997,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/covariantOverrideWithPrimitive.kt"); } + @Test + @TestMetadata("enhancedNullabilityMix.kt") + public void testEnhancedNullabilityMix() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/enhancedNullabilityMix.kt"); + } + @Test @TestMetadata("genericFunInterface.kt") public void testGenericFunInterface() throws Exception { @@ -20088,54 +20094,154 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT } @Nested - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") - public class FunctionExpressionArgument { + public class FunctionExprToJavaInterface { @Test - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } @Test @TestMetadata("capturedSamArgument.kt") public void testCapturedSamArgument() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturedSamArgument.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturedSamArgument.kt"); } @Test @TestMetadata("capturingLambda.kt") public void testCapturingLambda() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturingLambda.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturingLambda.kt"); } @Test @TestMetadata("extensionLambda1.kt") public void testExtensionLambda1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda1.kt"); } @Test @TestMetadata("extensionLambda2.kt") public void testExtensionLambda2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda2.kt"); } @Test @TestMetadata("genericSam1.kt") public void testGenericSam1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam1.kt"); } @Test @TestMetadata("genericSam2.kt") public void testGenericSam2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam2.kt"); } @Test @TestMetadata("simple.kt") public void testSimple() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/simple.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/simple.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + public class FunctionRefToJavaInterface { + @Test + @TestMetadata("adaptedFunRefWithCoercionToUnit.kt") + public void testAdaptedFunRefWithCoercionToUnit() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithCoercionToUnit.kt"); + } + + @Test + @TestMetadata("adaptedFunRefWithDefaultParameters.kt") + public void testAdaptedFunRefWithDefaultParameters() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithDefaultParameters.kt"); + } + + @Test + @TestMetadata("adaptedFunRefWithVararg.kt") + public void testAdaptedFunRefWithVararg() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithVararg.kt"); + } + + @Test + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("boundExtFun.kt") + public void testBoundExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundExtFun.kt"); + } + + @Test + @TestMetadata("boundInnerConstructorRef.kt") + public void testBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundInnerConstructorRef.kt"); + } + + @Test + @TestMetadata("boundLocalExtFun.kt") + public void testBoundLocalExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundLocalExtFun.kt"); + } + + @Test + @TestMetadata("boundMemberRef.kt") + public void testBoundMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundMemberRef.kt"); + } + + @Test + @TestMetadata("constructorRef.kt") + public void testConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/constructorRef.kt"); + } + + @Test + @TestMetadata("enhancedNullability.kt") + public void testEnhancedNullability() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); + } + + @Test + @TestMetadata("innerConstructorRef.kt") + public void testInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt"); + } + + @Test + @TestMetadata("localFunction1.kt") + public void testLocalFunction1() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction1.kt"); + } + + @Test + @TestMetadata("localFunction2.kt") + public void testLocalFunction2() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction2.kt"); + } + + @Test + @TestMetadata("memberRef.kt") + public void testMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/memberRef.kt"); + } + + @Test + @TestMetadata("nonTrivialReceiver.kt") + public void testNonTrivialReceiver() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/simple.kt"); } } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java index 85754daa4a0..e7d11e266c3 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java @@ -3944,6 +3944,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("functionRefToJavaInterface.kt") + public void testFunctionRefToJavaInterface() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/invokedynamic/functionRefToJavaInterface.kt"); + } + @Test @TestMetadata("lambdas.kt") public void testLambdas() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt index 1cebd00bcd4..e885719c80a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt @@ -157,6 +157,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) } else { return super.visitTypeOperator(expression) } + reference.transformChildrenVoid() if (shouldGenerateIndySamConversions) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt index 0622b0ec63c..60cdcacfcb4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt @@ -174,7 +174,10 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil override fun visitCall(expression: IrCall): IrExpression { return when (expression.symbol) { - jvmIndyLambdaMetafactoryIntrinsic -> rewriteIndyLambdaMetafactoryCall(expression) + jvmIndyLambdaMetafactoryIntrinsic -> { + expression.transformChildrenVoid() + rewriteIndyLambdaMetafactoryCall(expression) + } else -> super.visitCall(expression) } } @@ -267,10 +270,10 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil private fun wrapClosureInDynamicCall( erasedSamType: IrSimpleType, samMethod: IrSimpleFunction, - irFunRef: IrFunctionReference + targetRef: IrFunctionReference ): IrCall { fun fail(message: String): Nothing = - throw AssertionError("$message, irFunRef:\n${irFunRef.dump()}") + throw AssertionError("$message, irFunRef:\n${targetRef.dump()}") val dynamicCallArguments = ArrayList() @@ -281,32 +284,45 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil }.apply { parent = context.ir.symbols.kotlinJvmInternalInvokeDynamicPackage + val targetFun = targetRef.symbol.owner + val refDispatchReceiver = targetRef.dispatchReceiver + val refExtensionReceiver = targetRef.extensionReceiver + var syntheticParameterIndex = 0 - val targetFun = irFunRef.symbol.owner - - val targetDispatchReceiverParameter = targetFun.dispatchReceiverParameter - if (targetDispatchReceiverParameter != null) { - addValueParameter("p${syntheticParameterIndex++}", targetDispatchReceiverParameter.type) - val dispatchReceiver = irFunRef.dispatchReceiver - ?: fail("Captured dispatch receiver is not provided") - dynamicCallArguments.add(dispatchReceiver) - } - - val targetExtensionReceiverParameter = targetFun.extensionReceiverParameter - if (targetExtensionReceiverParameter != null && irFunRef.extensionReceiver != null) { - addValueParameter("p${syntheticParameterIndex++}", targetExtensionReceiverParameter.type) - val extensionReceiver = irFunRef.extensionReceiver!! - dynamicCallArguments.add(extensionReceiver) + var argumentStart = 0 + when (targetFun) { + is IrSimpleFunction -> { + if (refDispatchReceiver != null) { + addValueParameter("p${syntheticParameterIndex++}", targetFun.dispatchReceiverParameter!!.type) + dynamicCallArguments.add(refDispatchReceiver) + } + if (refExtensionReceiver != null) { + addValueParameter("p${syntheticParameterIndex++}", targetFun.extensionReceiverParameter!!.type) + dynamicCallArguments.add(refExtensionReceiver) + } + } + is IrConstructor -> { + // At this point, outer class instances in inner class constructors are represented as regular value parameters. + // However, in a function reference to such constructors, bound receiver value is stored as a dispatch receiver. + if (refDispatchReceiver != null) { + addValueParameter("p${syntheticParameterIndex++}", targetFun.valueParameters[0].type) + dynamicCallArguments.add(refDispatchReceiver) + argumentStart++ + } + } + else -> { + throw AssertionError("Unexpected function: ${targetFun.render()}") + } } val samMethodValueParametersCount = samMethod.valueParameters.size + - if (samMethod.extensionReceiverParameter != null && irFunRef.extensionReceiver == null) 1 else 0 + if (samMethod.extensionReceiverParameter != null && refExtensionReceiver == null) 1 else 0 val targetFunValueParametersCount = targetFun.valueParameters.size - for (i in 0 until targetFunValueParametersCount - samMethodValueParametersCount) { + for (i in argumentStart until targetFunValueParametersCount - samMethodValueParametersCount) { val targetFunValueParameter = targetFun.valueParameters[i] addValueParameter("p${syntheticParameterIndex++}", targetFunValueParameter.type) - val capturedValueArgument = irFunRef.getValueArgument(i) - ?: fail("Captured value argument #$i (${targetFunValueParameter.name}) not provided") + val capturedValueArgument = targetRef.getValueArgument(i) + ?: fail("Captured value argument #$i (${targetFunValueParameter.render()}) not provided") dynamicCallArguments.add(capturedValueArgument) } } @@ -320,7 +336,7 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil "dynamicCallArguments:\n" + dynamicCallArguments .withIndex() - .joinToString(separator = "\n ", prefix = "[\n ", postfix = "\n]") { (index, irArg) -> + .joinToString(separator = "\n ", prefix = "[\n ", postfix = "\n]") { (index, irArg) -> "#$index: ${irArg.dump()}" } ) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt index bcf1aa2ffa5..f23c451fc17 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod import org.jetbrains.kotlin.backend.jvm.ir.isCompiledToJvmDefault +import org.jetbrains.kotlin.backend.jvm.ir.isFromJava import org.jetbrains.kotlin.backend.jvm.lower.findInterfaceImplementation import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity import org.jetbrains.kotlin.descriptors.Modality @@ -24,12 +25,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl import org.jetbrains.kotlin.ir.overrides.buildFakeOverrideMember import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.dump -import org.jetbrains.kotlin.ir.util.functions -import org.jetbrains.kotlin.ir.util.getInlineClassUnderlyingType -import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addIfNotNull internal class LambdaMetafactoryArguments( val samMethod: IrSimpleFunction, @@ -50,13 +49,14 @@ internal class LambdaMetafactoryArgumentsBuilder( samType: IrType, plainLambda: Boolean ): LambdaMetafactoryArguments? { - // Can't use JDK LambdaMetafactory for function references by default (because of 'equals'). - // TODO special mode that would generate indy everywhere? - if (reference.origin != IrStatementOrigin.LAMBDA) - return null - val samClass = samType.getClass() ?: throw AssertionError("SAM type is not a class: ${samType.render()}") + + // Can't use JDK LambdaMetafactory for function references by default (because of 'equals'). + // TODO special mode that would generate indy everywhere? + if (reference.origin != IrStatementOrigin.LAMBDA && !samClass.isFromJava()) + return null + val samMethod = samClass.getSingleAbstractMethod() ?: throw AssertionError("SAM class has no single abstract method: ${samClass.render()}") @@ -68,32 +68,31 @@ internal class LambdaMetafactoryArgumentsBuilder( if (samClass.requiresDelegationToDefaultImpls()) return null - val target = reference.symbol.owner as? IrSimpleFunction - ?: throw AssertionError("Simple function expected: ${reference.symbol.owner.render()}") + val implFun = reference.symbol.owner // Can't use JDK LambdaMetafactory for annotated lambdas. // JDK LambdaMetafactory doesn't copy annotations from implementation method to an instance method in a // corresponding synthetic class, which doesn't look like a binary compatible change. // TODO relaxed mode? - if (target.annotations.isNotEmpty()) + if (implFun.annotations.isNotEmpty()) return null // Don't use JDK LambdaMetafactory for big arity lambdas. if (plainLambda) { - var parametersCount = target.valueParameters.size - if (target.extensionReceiverParameter != null) ++parametersCount + var parametersCount = implFun.valueParameters.size + if (implFun.extensionReceiverParameter != null) ++parametersCount if (parametersCount >= BuiltInFunctionArity.BIG_ARITY) return null } // Can't use indy-based SAM conversion inside inline fun (Ok in inline lambda). - if (target.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() }) + if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() }) return null // Do the hard work of matching Kotlin functional interface hierarchy against LambdaMetafactory constraints. // Briefly: sometimes we have to force boxing on the primitive and inline class values, sometimes we have to keep them unboxed. // If this results in conflicting requirements, we can't use INVOKEDYNAMIC with LambdaMetafactory for creating a closure. - return getLambdaMetafactoryArgsOrNullInner(reference, samMethod, samType, target) + return getLambdaMetafactoryArgsOrNullInner(reference, samMethod, samType, implFun) } private fun IrClass.requiresDelegationToDefaultImpls(): Boolean { @@ -118,7 +117,7 @@ internal class LambdaMetafactoryArgumentsBuilder( reference: IrFunctionReference, samMethod: IrSimpleFunction, samType: IrType, - implLambda: IrSimpleFunction + implFun: IrFunction ): LambdaMetafactoryArguments? { val nonFakeOverriddenFuns = samMethod.allOverridden().filterNot { it.isFakeOverride } val relevantOverriddenFuns = if (samMethod.isFakeOverride) nonFakeOverriddenFuns else nonFakeOverriddenFuns + samMethod @@ -191,16 +190,23 @@ internal class LambdaMetafactoryArgumentsBuilder( // We should have bailed out before if we encountered any kind of type adaptation conflict. // Still, check that we are fine - just in case. - if (signatureAdaptationConstraints.returnType == TypeAdaptationConstraint.CONFLICT || - signatureAdaptationConstraints.valueParameters.values.any { it == TypeAdaptationConstraint.CONFLICT } - ) + if (signatureAdaptationConstraints.hasConflicts()) return null adaptFakeInstanceMethodSignature(fakeInstanceMethod, signatureAdaptationConstraints) + if (implFun.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) { + adaptLambdaSignature(implFun as IrSimpleFunction, fakeInstanceMethod, signatureAdaptationConstraints) + } else if ( + !checkMethodSignatureCompliance(implFun, fakeInstanceMethod, signatureAdaptationConstraints, reference) + ) { + return null + } - adaptLambdaSignature(implLambda, fakeInstanceMethod, signatureAdaptationConstraints) - - val newReference = remapExtensionLambda(implLambda, reference) + val newReference = + if (implFun.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) + remapExtensionLambda(implFun as IrSimpleFunction, reference) + else + reference if (samMethod.isFakeOverride && nonFakeOverriddenFuns.size == 1) { return LambdaMetafactoryArguments(nonFakeOverriddenFuns.single(), fakeInstanceMethod, newReference, listOf()) @@ -208,32 +214,73 @@ internal class LambdaMetafactoryArgumentsBuilder( return LambdaMetafactoryArguments(samMethod, fakeInstanceMethod, newReference, nonFakeOverriddenFuns) } - private fun adaptLambdaSignature( - lambda: IrSimpleFunction, + private fun checkMethodSignatureCompliance( + implFun: IrFunction, fakeInstanceMethod: IrSimpleFunction, - constraints: SignatureAdaptationConstraints - ) { - val lambdaParameters = collectValueParameters(lambda) + constraints: SignatureAdaptationConstraints, + reference: IrFunctionReference + ): Boolean { + val implParameters = collectValueParameters( + implFun, + withDispatchReceiver = reference.dispatchReceiver == null, + withExtensionReceiver = reference.extensionReceiver == null + ) val methodParameters = collectValueParameters(fakeInstanceMethod) - if (lambdaParameters.size != methodParameters.size) + if (implParameters.size != methodParameters.size) throw AssertionError( "Mismatching lambda and instance method parameters:\n" + - "lambda: ${lambda.render()}\n" + - " (${lambdaParameters.size} parameters)\n" + + "implFun: ${implFun.render()}\n" + + " (${implParameters.size} parameters)\n" + "instance method: ${fakeInstanceMethod.render()}\n" + " (${methodParameters.size} parameters)" ) - for ((lambdaParameter, methodParameter) in lambdaParameters.zip(methodParameters)) { - // TODO box inline class parameters only? - val parameterConstraint = constraints.valueParameters[methodParameter] - if (parameterConstraint == TypeAdaptationConstraint.FORCE_BOXING) { - lambdaParameter.type = lambdaParameter.type.makeNullable() - } + for ((implParameter, methodParameter) in implParameters.zip(methodParameters)) { + val constraint = constraints.valueParameters[methodParameter] + if (!checkTypeCompliesWithConstraint(implParameter.type, constraint)) + return false } - if (constraints.returnType == TypeAdaptationConstraint.FORCE_BOXING) { - lambda.returnType = lambda.returnType.makeNullable() + if (!checkTypeCompliesWithConstraint(implFun.returnType, constraints.returnType)) + return false + return true + } + + private fun checkTypeCompliesWithConstraint(irType: IrType, constraint: TypeAdaptationConstraint?): Boolean = + when (constraint) { + null -> true + TypeAdaptationConstraint.FORCE_BOXING -> irType.isNullable() + TypeAdaptationConstraint.KEEP_UNBOXED -> !irType.isNullable() + TypeAdaptationConstraint.BOX_PRIMITIVE -> irType.isJvmPrimitiveOrNullable() + TypeAdaptationConstraint.CONFLICT -> false } + private fun adaptLambdaSignature( + implFun: IrSimpleFunction, + fakeInstanceMethod: IrSimpleFunction, + constraints: SignatureAdaptationConstraints + ) { + if (implFun.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) { + throw AssertionError("Can't adapt non-lambda function signature: ${implFun.render()}") + } + + val implParameters = collectValueParameters(implFun) + val methodParameters = collectValueParameters(fakeInstanceMethod) + if (implParameters.size != methodParameters.size) + throw AssertionError( + "Mismatching lambda and instance method parameters:\n" + + "implFun: ${implFun.render()}\n" + + " (${implParameters.size} parameters)\n" + + "instance method: ${fakeInstanceMethod.render()}\n" + + " (${methodParameters.size} parameters)" + ) + for ((implParameter, methodParameter) in implParameters.zip(methodParameters)) { + val parameterConstraint = constraints.valueParameters[methodParameter] + if (parameterConstraint.requiresImplLambdaBoxing()) { + implParameter.type = implParameter.type.makeNullable() + } + } + if (constraints.returnType.requiresImplLambdaBoxing()) { + implFun.returnType = implFun.returnType.makeNullable() + } } private fun remapExtensionLambda(lambda: IrSimpleFunction, reference: IrFunctionReference): IrFunctionReference { @@ -285,25 +332,36 @@ internal class LambdaMetafactoryArgumentsBuilder( "Unexpected value parameter: ${valueParameter.render()}; fakeInstanceMethod:\n" + fakeInstanceMethod.dump() ) - if (constraint == TypeAdaptationConstraint.FORCE_BOXING) { + if (constraint.requiresInstanceMethodBoxing()) { valueParameter.type = valueParameter.type.makeNullable() } } - if (constraints.returnType == TypeAdaptationConstraint.FORCE_BOXING) { + if (constraints.returnType.requiresInstanceMethodBoxing()) { fakeInstanceMethod.returnType = fakeInstanceMethod.returnType.makeNullable() } } private enum class TypeAdaptationConstraint { FORCE_BOXING, + BOX_PRIMITIVE, KEEP_UNBOXED, CONFLICT } + private fun TypeAdaptationConstraint?.requiresInstanceMethodBoxing() = + this == TypeAdaptationConstraint.FORCE_BOXING || this == TypeAdaptationConstraint.BOX_PRIMITIVE + + private fun TypeAdaptationConstraint?.requiresImplLambdaBoxing() = + this == TypeAdaptationConstraint.FORCE_BOXING + private class SignatureAdaptationConstraints( val valueParameters: Map, val returnType: TypeAdaptationConstraint? - ) + ) { + fun hasConflicts() = + returnType == TypeAdaptationConstraint.CONFLICT || + TypeAdaptationConstraint.CONFLICT in valueParameters.values + } private fun computeSignatureAdaptationConstraints( adapteeFun: IrSimpleFunction, @@ -353,10 +411,13 @@ internal class LambdaMetafactoryArgumentsBuilder( // All Kotlin types mapped to JVM primitive are final, // and their supertypes are trivially mapped reference types. if (adapteeType.isJvmPrimitiveType()) { - return if (expectedType.isJvmPrimitiveType()) + return if ( + expectedType.isJvmPrimitiveType() && + !expectedType.hasAnnotation(context.ir.symbols.enhancedNullabilityAnnotationFqName) + ) TypeAdaptationConstraint.KEEP_UNBOXED else - TypeAdaptationConstraint.FORCE_BOXING + TypeAdaptationConstraint.BOX_PRIMITIVE } // ** Inline classes ** @@ -459,13 +520,29 @@ internal class LambdaMetafactoryArgumentsBuilder( private fun IrType.isJvmPrimitiveType() = isBoolean() || isChar() || isByte() || isShort() || isInt() || isLong() || isFloat() || isDouble() -} -fun collectValueParameters(irFun: IrFunction): List { - if (irFun.extensionReceiverParameter == null) - return irFun.valueParameters - return ArrayList().apply { - add(irFun.extensionReceiverParameter!!) - addAll(irFun.valueParameters) + private fun IrType.isJvmPrimitiveOrNullable() = + isBooleanOrNullable() || isCharOrNullable() || + isByteOrNullable() || isShortOrNullable() || isIntOrNullable() || isLongOrNullable() || + isFloatOrNullable() || isDoubleOrNullable() + + fun collectValueParameters( + irFun: IrFunction, + withDispatchReceiver: Boolean = false, + withExtensionReceiver: Boolean = true + ): List { + if ((!withDispatchReceiver || irFun.dispatchReceiverParameter == null) && + (!withExtensionReceiver || irFun.extensionReceiverParameter == null) + ) + return irFun.valueParameters + return ArrayList().apply { + if (withDispatchReceiver) { + addIfNotNull(irFun.dispatchReceiverParameter) + } + if (withExtensionReceiver) { + addIfNotNull(irFun.extensionReceiverParameter) + } + addAll(irFun.valueParameters) + } } -} \ No newline at end of file +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt index ad70cbe9834..f023b5dfdfa 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/types/irTypePredicates.kt @@ -109,17 +109,25 @@ fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: fals fun IrType.isUnit() = isNotNullClassType(IdSignatureValues.unit) fun IrType.isBoolean(): Boolean = isNotNullClassType(IdSignatureValues._boolean) +fun IrType.isBooleanOrNullable(): Boolean = isClassType(IdSignatureValues._boolean) fun IrType.isChar(): Boolean = isNotNullClassType(IdSignatureValues._char) +fun IrType.isCharOrNullable(): Boolean = isClassType(IdSignatureValues._char) fun IrType.isByte(): Boolean = isNotNullClassType(IdSignatureValues._byte) +fun IrType.isByteOrNullable(): Boolean = isClassType(IdSignatureValues._byte) fun IrType.isShort(): Boolean = isNotNullClassType(IdSignatureValues._short) +fun IrType.isShortOrNullable(): Boolean = isClassType(IdSignatureValues._short) fun IrType.isInt(): Boolean = isNotNullClassType(IdSignatureValues._int) +fun IrType.isIntOrNullable(): Boolean = isClassType(IdSignatureValues._int) fun IrType.isLong(): Boolean = isNotNullClassType(IdSignatureValues._long) +fun IrType.isLongOrNullable(): Boolean = isClassType(IdSignatureValues._long) fun IrType.isUByte(): Boolean = isNotNullClassType(IdSignatureValues.uByte) fun IrType.isUShort(): Boolean = isNotNullClassType(IdSignatureValues.uShort) fun IrType.isUInt(): Boolean = isNotNullClassType(IdSignatureValues.uInt) fun IrType.isULong(): Boolean = isNotNullClassType(IdSignatureValues.uLong) fun IrType.isFloat(): Boolean = isNotNullClassType(IdSignatureValues._float) +fun IrType.isFloatOrNullable(): Boolean = isClassType(IdSignatureValues._float) fun IrType.isDouble(): Boolean = isNotNullClassType(IdSignatureValues._double) +fun IrType.isDoubleOrNullable(): Boolean = isClassType(IdSignatureValues._double) fun IrType.isNumber(): Boolean = isNotNullClassType(IdSignatureValues.number) fun IrType.isComparable(): Boolean = isNotNullClassType(IdSignatureValues.comparable) diff --git a/compiler/testData/codegen/box/invokedynamic/sam/enhancedNullabilityMix.kt b/compiler/testData/codegen/box/invokedynamic/sam/enhancedNullabilityMix.kt new file mode 100644 index 00000000000..af1503754b8 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/enhancedNullabilityMix.kt @@ -0,0 +1,29 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: enhancedNullability.kt +fun interface IGetInt { + fun get(x: Int): Int +} + +// fun interface IGetIntMix0 : IGetInt, Sam +// ^ Error: [FUN_INTERFACE_WRONG_COUNT_OF_ABSTRACT_MEMBERS] Fun interfaces must have exactly one abstract method + +fun interface IGetIntMix1 : IGetInt, Sam { + override fun get(x: Int): Int +} + +fun box(): String { + val t1 = IGetIntMix1 { it: Int -> it * 2 }.get(21) + if (t1 != 42) + return "Failed: t1=$t1" + + return "OK" +} + +// FILE: Sam.java +import org.jetbrains.annotations.*; + +public interface Sam { + @NotNull Integer get(@NotNull Integer arg); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturedSamArgument.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturedSamArgument.kt similarity index 100% rename from compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturedSamArgument.kt rename to compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturedSamArgument.kt diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturingLambda.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturingLambda.kt similarity index 100% rename from compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturingLambda.kt rename to compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturingLambda.kt diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda1.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda1.kt similarity index 100% rename from compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda1.kt rename to compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda1.kt diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda2.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda2.kt similarity index 100% rename from compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda2.kt rename to compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda2.kt diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam1.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam1.kt similarity index 100% rename from compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam1.kt rename to compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam1.kt diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam2.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam2.kt similarity index 100% rename from compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam2.kt rename to compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam2.kt diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/simple.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/simple.kt similarity index 100% rename from compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/simple.kt rename to compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/simple.kt diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithCoercionToUnit.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithCoercionToUnit.kt new file mode 100644 index 00000000000..051139d22f3 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithCoercionToUnit.kt @@ -0,0 +1,20 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: adaptedFunRefWithCoercionToUnit.kt +var ok = "Failed" + +fun test(s: String): Int { + ok = s + return 42 +} + +fun box(): String { + Sam(::test).foo("OK") + return ok +} + +// FILE: Sam.java +public interface Sam { + void foo(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithDefaultParameters.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithDefaultParameters.kt new file mode 100644 index 00000000000..1dece0518bd --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithDefaultParameters.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: adaptedFunRefWithDefaultParameters.kt +var ok = "Failed" + +fun test(s1: String, s2: String = "K") { + ok = s1 + s2 +} + +fun box(): String { + Sam(::test).foo("O") + return ok +} + +// FILE: Sam.java +public interface Sam { + void foo(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithVararg.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithVararg.kt new file mode 100644 index 00000000000..6aedd90a58b --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithVararg.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: adaptedFunRefWithVararg.kt +var ok = "Failed" + +fun test(vararg ss: String) { + ok = ss[0] +} + +fun box(): String { + Sam(::test).foo("OK") + return ok +} + +// FILE: Sam.java +public interface Sam { + void foo(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundExtFun.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundExtFun.kt new file mode 100644 index 00000000000..37b2778d920 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundExtFun.kt @@ -0,0 +1,13 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: boundExtFun.kt +fun String.k(s: String) = this + s + "K" + +fun box() = Sam("O"::k).get("") +// NB simply '::k' is a compilation error + +// FILE: Sam.java +public interface Sam { + String get(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundInnerConstructorRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundInnerConstructorRef.kt new file mode 100644 index 00000000000..a93ede92537 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundInnerConstructorRef.kt @@ -0,0 +1,16 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: boundInnerConstructorRef.kt +class Outer(val s1: String) { + inner class Inner(val s2: String) { + fun t() = s1 + s2 + } +} + +fun box() = Sam(Outer("O")::Inner).get("K").t() + +// FILE: Sam.java +public interface Sam { + Outer.Inner get(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundLocalExtFun.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundLocalExtFun.kt new file mode 100644 index 00000000000..d81e9f15824 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundLocalExtFun.kt @@ -0,0 +1,15 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: boundLocalExtFun.kt +fun box(): String { + fun String.k(s: String) = this + s + "K" + + return Sam("O"::k).get("") + // NB simply '::k' is a compilation error +} + +// FILE: Sam.java +public interface Sam { + String get(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundMemberRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundMemberRef.kt new file mode 100644 index 00000000000..09a7ccf3d88 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundMemberRef.kt @@ -0,0 +1,14 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: boundMemberRef.kt +class C(val t: String) { + fun test() = t +} + +fun box() = Sam(C("OK")::test).get() + +// FILE: Sam.java +public interface Sam { + String get(); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/constructorRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/constructorRef.kt new file mode 100644 index 00000000000..ddb91892162 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/constructorRef.kt @@ -0,0 +1,12 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: constructorRef.kt +class C(val t: String) + +fun box() = Sam(::C).get("OK").t + +// FILE: Sam.java +public interface Sam { + C get(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt new file mode 100644 index 00000000000..ee4031fb43a --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt @@ -0,0 +1,20 @@ +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: enhancedNullability.kt +fun mul2(x: Int) = x * 2 + +fun box(): String { + val t = Sam(::mul2).get(21) + if (t != 42) + return "Failed: t=$t" + return "OK" +} + +// FILE: Sam.java +import org.jetbrains.annotations.*; + +public interface Sam { + @NotNull Integer get(@NotNull Integer arg); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt new file mode 100644 index 00000000000..0a9ca2cd817 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt @@ -0,0 +1,16 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: innerConstructorRef.kt +class Outer(val s1: String) { + inner class Inner(val s2: String) { + fun t() = s1 + s2 + } +} + +fun box() = Sam(Outer::Inner).get(Outer("O"), "K").t() + +// FILE: Sam.java +public interface Sam { + Outer.Inner get(Outer outer, String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction1.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction1.kt new file mode 100644 index 00000000000..3fa6e721122 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction1.kt @@ -0,0 +1,13 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: localFunction1.kt +fun box(): String { + fun ok() = "OK" + return Sam(::ok).get() +} + +// FILE: Sam.java +public interface Sam { + String get(); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction2.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction2.kt new file mode 100644 index 00000000000..8555c03b2f9 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction2.kt @@ -0,0 +1,14 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: localFunction2.kt +fun box(): String { + val t = "O" + fun ok() = t + "K" + return Sam(::ok).get() +} + +// FILE: Sam.java +public interface Sam { + String get(); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/memberRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/memberRef.kt new file mode 100644 index 00000000000..fb96f2b3755 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/memberRef.kt @@ -0,0 +1,14 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: memberRef.kt +class C(val t: String) { + fun test() = t +} + +fun box() = Sam(C::test).get(C("OK")) + +// FILE: Sam.java +public interface Sam { + String get(C c); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt new file mode 100644 index 00000000000..92bbfbfb287 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt @@ -0,0 +1,23 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// WITH_RUNTIME +// FILE: JavaRunner.java +public class JavaRunner { + public static void runTwice(Runnable runnable) { + runnable.run(); + runnable.run(); + } +} + +// FILE: nonTrivialReceiver.kt +class A() { + fun f() {} +} + +fun box(): String { + var x = 0 + JavaRunner.runTwice({ x++; A() }()::f) + if (x != 1) return "Fail" + return "OK" +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/simple.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/simple.kt new file mode 100644 index 00000000000..161c04b8c87 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/simple.kt @@ -0,0 +1,12 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// FILE: simple.kt +fun ok() = "OK" + +fun box() = Sam(::ok).get() + +// FILE: Sam.java +public interface Sam { + String get(); +} diff --git a/compiler/testData/codegen/bytecodeText/invokedynamic/functionRefToJavaInterface.kt b/compiler/testData/codegen/bytecodeText/invokedynamic/functionRefToJavaInterface.kt new file mode 100644 index 00000000000..be636c2ae6f --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/invokedynamic/functionRefToJavaInterface.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// WITH_RUNTIME +// FULL_JDK + +fun hello() { println("Hello, world!") } + +val test = Runnable(::hello) + +// JVM_TEMPLATES: +// 1 public final class FunctionRefToJavaInterfaceKt +// 1 final synthetic class FunctionRefToJavaInterfaceKt\$sam\$java_lang_Runnable\$0 +// 1 final synthetic class FunctionRefToJavaInterfaceKt\$test\$1 + +// JVM_IR_TEMPLATES: +// 1 INVOKEDYNAMIC +// 1 class FunctionRefToJavaInterfaceKt diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index c05ea81c681..04cd5241f1a 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -19997,6 +19997,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/covariantOverrideWithPrimitive.kt"); } + @Test + @TestMetadata("enhancedNullabilityMix.kt") + public void testEnhancedNullabilityMix() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/enhancedNullabilityMix.kt"); + } + @Test @TestMetadata("genericFunInterface.kt") public void testGenericFunInterface() throws Exception { @@ -20088,54 +20094,154 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } @Nested - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") - public class FunctionExpressionArgument { + public class FunctionExprToJavaInterface { @Test - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } @Test @TestMetadata("capturedSamArgument.kt") public void testCapturedSamArgument() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturedSamArgument.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturedSamArgument.kt"); } @Test @TestMetadata("capturingLambda.kt") public void testCapturingLambda() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturingLambda.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturingLambda.kt"); } @Test @TestMetadata("extensionLambda1.kt") public void testExtensionLambda1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda1.kt"); } @Test @TestMetadata("extensionLambda2.kt") public void testExtensionLambda2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda2.kt"); } @Test @TestMetadata("genericSam1.kt") public void testGenericSam1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam1.kt"); } @Test @TestMetadata("genericSam2.kt") public void testGenericSam2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam2.kt"); } @Test @TestMetadata("simple.kt") public void testSimple() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/simple.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/simple.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + public class FunctionRefToJavaInterface { + @Test + @TestMetadata("adaptedFunRefWithCoercionToUnit.kt") + public void testAdaptedFunRefWithCoercionToUnit() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithCoercionToUnit.kt"); + } + + @Test + @TestMetadata("adaptedFunRefWithDefaultParameters.kt") + public void testAdaptedFunRefWithDefaultParameters() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithDefaultParameters.kt"); + } + + @Test + @TestMetadata("adaptedFunRefWithVararg.kt") + public void testAdaptedFunRefWithVararg() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithVararg.kt"); + } + + @Test + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @Test + @TestMetadata("boundExtFun.kt") + public void testBoundExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundExtFun.kt"); + } + + @Test + @TestMetadata("boundInnerConstructorRef.kt") + public void testBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundInnerConstructorRef.kt"); + } + + @Test + @TestMetadata("boundLocalExtFun.kt") + public void testBoundLocalExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundLocalExtFun.kt"); + } + + @Test + @TestMetadata("boundMemberRef.kt") + public void testBoundMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundMemberRef.kt"); + } + + @Test + @TestMetadata("constructorRef.kt") + public void testConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/constructorRef.kt"); + } + + @Test + @TestMetadata("enhancedNullability.kt") + public void testEnhancedNullability() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); + } + + @Test + @TestMetadata("innerConstructorRef.kt") + public void testInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt"); + } + + @Test + @TestMetadata("localFunction1.kt") + public void testLocalFunction1() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction1.kt"); + } + + @Test + @TestMetadata("localFunction2.kt") + public void testLocalFunction2() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction2.kt"); + } + + @Test + @TestMetadata("memberRef.kt") + public void testMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/memberRef.kt"); + } + + @Test + @TestMetadata("nonTrivialReceiver.kt") + public void testNonTrivialReceiver() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/simple.kt"); } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java index 8129e3d2031..2953fa9dad3 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java @@ -3812,6 +3812,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("functionRefToJavaInterface.kt") + public void testFunctionRefToJavaInterface() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/invokedynamic/functionRefToJavaInterface.kt"); + } + @Test @TestMetadata("lambdas.kt") public void testLambdas() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 74aeafa291a..3ee926efb95 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -19997,6 +19997,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/covariantOverrideWithPrimitive.kt"); } + @Test + @TestMetadata("enhancedNullabilityMix.kt") + public void testEnhancedNullabilityMix() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/enhancedNullabilityMix.kt"); + } + @Test @TestMetadata("genericFunInterface.kt") public void testGenericFunInterface() throws Exception { @@ -20088,54 +20094,154 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } @Nested - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") - public class FunctionExpressionArgument { + public class FunctionExprToJavaInterface { @Test - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } @Test @TestMetadata("capturedSamArgument.kt") public void testCapturedSamArgument() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturedSamArgument.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturedSamArgument.kt"); } @Test @TestMetadata("capturingLambda.kt") public void testCapturingLambda() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturingLambda.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturingLambda.kt"); } @Test @TestMetadata("extensionLambda1.kt") public void testExtensionLambda1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda1.kt"); } @Test @TestMetadata("extensionLambda2.kt") public void testExtensionLambda2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda2.kt"); } @Test @TestMetadata("genericSam1.kt") public void testGenericSam1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam1.kt"); } @Test @TestMetadata("genericSam2.kt") public void testGenericSam2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam2.kt"); } @Test @TestMetadata("simple.kt") public void testSimple() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/simple.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/simple.kt"); + } + } + + @Nested + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + public class FunctionRefToJavaInterface { + @Test + @TestMetadata("adaptedFunRefWithCoercionToUnit.kt") + public void testAdaptedFunRefWithCoercionToUnit() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithCoercionToUnit.kt"); + } + + @Test + @TestMetadata("adaptedFunRefWithDefaultParameters.kt") + public void testAdaptedFunRefWithDefaultParameters() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithDefaultParameters.kt"); + } + + @Test + @TestMetadata("adaptedFunRefWithVararg.kt") + public void testAdaptedFunRefWithVararg() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithVararg.kt"); + } + + @Test + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("boundExtFun.kt") + public void testBoundExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundExtFun.kt"); + } + + @Test + @TestMetadata("boundInnerConstructorRef.kt") + public void testBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundInnerConstructorRef.kt"); + } + + @Test + @TestMetadata("boundLocalExtFun.kt") + public void testBoundLocalExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundLocalExtFun.kt"); + } + + @Test + @TestMetadata("boundMemberRef.kt") + public void testBoundMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundMemberRef.kt"); + } + + @Test + @TestMetadata("constructorRef.kt") + public void testConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/constructorRef.kt"); + } + + @Test + @TestMetadata("enhancedNullability.kt") + public void testEnhancedNullability() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); + } + + @Test + @TestMetadata("innerConstructorRef.kt") + public void testInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt"); + } + + @Test + @TestMetadata("localFunction1.kt") + public void testLocalFunction1() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction1.kt"); + } + + @Test + @TestMetadata("localFunction2.kt") + public void testLocalFunction2() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction2.kt"); + } + + @Test + @TestMetadata("memberRef.kt") + public void testMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/memberRef.kt"); + } + + @Test + @TestMetadata("nonTrivialReceiver.kt") + public void testNonTrivialReceiver() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/simple.kt"); } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java index e2bc8b6d9f3..67908bf703c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java @@ -3944,6 +3944,12 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/invokedynamic"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("functionRefToJavaInterface.kt") + public void testFunctionRefToJavaInterface() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/invokedynamic/functionRefToJavaInterface.kt"); + } + @Test @TestMetadata("lambdas.kt") public void testLambdas() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 640a8f49110..e155f40e682 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -16771,6 +16771,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/covariantOverrideWithPrimitive.kt"); } + @TestMetadata("enhancedNullabilityMix.kt") + public void testEnhancedNullabilityMix() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/enhancedNullabilityMix.kt"); + } + @TestMetadata("genericFunInterface.kt") public void testGenericFunInterface() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterface.kt"); @@ -16841,51 +16846,139 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/unboundFunctionReferenceEquality.kt"); } - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class FunctionExpressionArgument extends AbstractLightAnalysisModeTest { + public static class FunctionExprToJavaInterface extends AbstractLightAnalysisModeTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } @TestMetadata("capturedSamArgument.kt") public void testCapturedSamArgument() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturedSamArgument.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturedSamArgument.kt"); } @TestMetadata("capturingLambda.kt") public void testCapturingLambda() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/capturingLambda.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/capturingLambda.kt"); } @TestMetadata("extensionLambda1.kt") public void testExtensionLambda1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda1.kt"); } @TestMetadata("extensionLambda2.kt") public void testExtensionLambda2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/extensionLambda2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/extensionLambda2.kt"); } @TestMetadata("genericSam1.kt") public void testGenericSam1() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam1.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam1.kt"); } @TestMetadata("genericSam2.kt") public void testGenericSam2() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/genericSam2.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/genericSam2.kt"); } @TestMetadata("simple.kt") public void testSimple() throws Exception { - runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument/simple.kt"); + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface/simple.kt"); + } + } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunctionRefToJavaInterface extends AbstractLightAnalysisModeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + @TestMetadata("adaptedFunRefWithCoercionToUnit.kt") + public void testAdaptedFunRefWithCoercionToUnit() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithCoercionToUnit.kt"); + } + + @TestMetadata("adaptedFunRefWithDefaultParameters.kt") + public void testAdaptedFunRefWithDefaultParameters() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithDefaultParameters.kt"); + } + + @TestMetadata("adaptedFunRefWithVararg.kt") + public void testAdaptedFunRefWithVararg() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/adaptedFunRefWithVararg.kt"); + } + + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @TestMetadata("boundExtFun.kt") + public void testBoundExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundExtFun.kt"); + } + + @TestMetadata("boundInnerConstructorRef.kt") + public void testBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundInnerConstructorRef.kt"); + } + + @TestMetadata("boundLocalExtFun.kt") + public void testBoundLocalExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundLocalExtFun.kt"); + } + + @TestMetadata("boundMemberRef.kt") + public void testBoundMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/boundMemberRef.kt"); + } + + @TestMetadata("constructorRef.kt") + public void testConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/constructorRef.kt"); + } + + @TestMetadata("enhancedNullability.kt") + public void testEnhancedNullability() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); + } + + @TestMetadata("innerConstructorRef.kt") + public void testInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt"); + } + + @TestMetadata("localFunction1.kt") + public void testLocalFunction1() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction1.kt"); + } + + @TestMetadata("localFunction2.kt") + public void testLocalFunction2() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/localFunction2.kt"); + } + + @TestMetadata("memberRef.kt") + public void testMemberRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/memberRef.kt"); + } + + @TestMetadata("nonTrivialReceiver.kt") + public void testNonTrivialReceiver() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/simple.kt"); } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 9c44c09e21d..4169114a9ee 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -14626,16 +14626,29 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class FunctionExpressionArgument extends AbstractIrJsCodegenBoxES6Test { + public static class FunctionExprToJavaInterface extends AbstractIrJsCodegenBoxES6Test { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); } - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunctionRefToJavaInterface extends AbstractIrJsCodegenBoxES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index bae8d522aad..015b67503e4 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -14111,16 +14111,29 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class FunctionExpressionArgument extends AbstractIrJsCodegenBoxTest { + public static class FunctionExprToJavaInterface extends AbstractIrJsCodegenBoxTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); } - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + } + } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunctionRefToJavaInterface extends AbstractIrJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index e2ae4ca6ee8..3ad154677cb 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -14176,16 +14176,29 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class FunctionExpressionArgument extends AbstractJsCodegenBoxTest { + public static class FunctionExprToJavaInterface extends AbstractJsCodegenBoxTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); } - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + } + } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunctionRefToJavaInterface extends AbstractJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 15b59cf2c7b..503d850450b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -8212,16 +8212,29 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); } - @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument") + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class FunctionExpressionArgument extends AbstractIrCodegenBoxWasmTest { + public static class FunctionExprToJavaInterface extends AbstractIrCodegenBoxWasmTest { private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath); } - public void testAllFilesPresentInFunctionExpressionArgument() throws Exception { - KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExpressionArgument"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); + public void testAllFilesPresentInFunctionExprToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionExprToJavaInterface"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); + } + } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunctionRefToJavaInterface extends AbstractIrCodegenBoxWasmTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath); + } + + public void testAllFilesPresentInFunctionRefToJavaInterface() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); } }