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 eb76b4b2dfc..067912e8099 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 @@ -22233,6 +22233,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt"); } + @Test + @TestMetadata("inlineFunWithPrivateMethod.kt") + public void testInlineFunWithPrivateMethod() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt"); + } + @Test @TestMetadata("inlineOnly.kt") public void testInlineOnly() throws Exception { @@ -22281,6 +22287,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt"); } + @Test + @TestMetadata("reifiedTypeParameter.kt") + public void testReifiedTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt"); + } + @Test @TestMetadata("samConversionInsideSamConvertedLambda.kt") public void testSamConversionInsideSamConvertedLambda() throws Exception { @@ -22480,6 +22492,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); } + @Test + @TestMetadata("genericBoundInnerConstructorRef.kt") + public void testGenericBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); + } + + @Test + @TestMetadata("genericInnerConstructorRef.kt") + public void testGenericInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); + } + @Test @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { @@ -22534,6 +22558,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt"); } + @Test + @TestMetadata("multipleProxyWrappersForSameFunction.kt") + public void testMultipleProxyWrappersForSameFunction() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt"); + } + @Test @TestMetadata("nonTrivialReceiver.kt") public void testNonTrivialReceiver() throws Exception { @@ -22621,6 +22651,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt"); } + @Test + @TestMetadata("intArrayOf.kt") + public void testIntArrayOf() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt"); + } + @Test @TestMetadata("intPlus.kt") public void testIntPlus() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 147edcda600..60de2b892de 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -341,11 +341,13 @@ private val jvmFilePhases = listOf( propertyReferencePhase, arrayConstructorPhase, constPhase1, + // TODO: merge the next three phases together, as visitors behave incorrectly between them // (backing fields moved out of companion objects are reachable by two paths): moveOrCopyCompanionObjectFieldsPhase, propertiesPhase, remapObjectFieldAccesses, + anonymousObjectSuperConstructorPhase, jvmStandardLibraryBuiltInsPhase, diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt index ccdde365c68..4cba2e084e0 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/FunctionReferenceLowering.kt @@ -16,10 +16,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredStatementOrigin import org.jetbrains.kotlin.backend.jvm.JvmSymbols import org.jetbrains.kotlin.backend.jvm.ir.* -import org.jetbrains.kotlin.backend.jvm.lower.indy.LambdaMetafactoryArguments -import org.jetbrains.kotlin.backend.jvm.lower.indy.LambdaMetafactoryArgumentsBuilder -import org.jetbrains.kotlin.backend.jvm.lower.indy.SamDelegatingLambdaBlock -import org.jetbrains.kotlin.backend.jvm.lower.indy.SamDelegatingLambdaBuilder +import org.jetbrains.kotlin.backend.jvm.lower.indy.* import org.jetbrains.kotlin.config.JvmClosureGenerationScheme import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality @@ -28,9 +25,11 @@ import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid @@ -88,10 +87,11 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) if (shouldGenerateIndyLambdas) { val lambdaMetafactoryArguments = LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas) - .getLambdaMetafactoryArgumentsOrNull(reference, reference.type, true) - if (lambdaMetafactoryArguments != null) { + .getLambdaMetafactoryArguments(reference, reference.type, true) + if (lambdaMetafactoryArguments is LambdaMetafactoryArguments) { return wrapLambdaReferenceWithIndySamConversion(expression, reference, lambdaMetafactoryArguments) } + // TODO MetafactoryArgumentsResult.Failure.FunctionHazard? } return FunctionReferenceBuilder(reference).build() @@ -254,8 +254,13 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) val lambdaBlock = SamDelegatingLambdaBuilder(context) .build(invokable, samSuperType, currentScope!!.scope.scopeOwnerSymbol, getDeclarationParentForDelegatingLambda()) val lambdaMetafactoryArguments = LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas) - .getLambdaMetafactoryArgumentsOrNull(lambdaBlock.ref, samSuperType, false) - ?: return super.visitTypeOperator(expression) + .getLambdaMetafactoryArguments(lambdaBlock.ref, samSuperType, false) + + if (lambdaMetafactoryArguments !is LambdaMetafactoryArguments) { + // TODO MetafactoryArgumentsResult.Failure.FunctionHazard? + return super.visitTypeOperator(expression) + } + invokable.transformChildrenVoid() return wrapSamDelegatingLambdaWithIndySamConversion(samSuperType, lambdaBlock, lambdaMetafactoryArguments) } else { @@ -267,9 +272,25 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) if (shouldGenerateIndySamConversions) { val lambdaMetafactoryArguments = LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas) - .getLambdaMetafactoryArgumentsOrNull(reference, samSuperType, false) - if (lambdaMetafactoryArguments != null) { - return wrapSamConversionArgumentWithIndySamConversion(expression, lambdaMetafactoryArguments) + .getLambdaMetafactoryArguments(reference, samSuperType, false) + if (lambdaMetafactoryArguments is LambdaMetafactoryArguments) { + return wrapSamConversionArgumentWithIndySamConversion(expression) { samType -> + wrapWithIndySamConversion(samType, lambdaMetafactoryArguments) + } + } else if (lambdaMetafactoryArguments is MetafactoryArgumentsResult.Failure.FunctionHazard) { + // Try wrapping function with a proxy local function and see if that helps. + val proxyLocalFunBlock = createProxyLocalFunctionForIndySamConversion(reference) + val proxyLocalFunRef = proxyLocalFunBlock.statements[proxyLocalFunBlock.statements.size - 1] as IrFunctionReference + val proxyLambdaMetafactoryArguments = LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas) + .getLambdaMetafactoryArguments(proxyLocalFunRef, samSuperType, false) + if (proxyLambdaMetafactoryArguments is LambdaMetafactoryArguments) { + return wrapSamConversionArgumentWithIndySamConversion(expression) { samType -> + proxyLocalFunBlock.statements[proxyLocalFunBlock.statements.size - 1] = + wrapWithIndySamConversion(samType, proxyLambdaMetafactoryArguments) + proxyLocalFunBlock.type = samType + proxyLocalFunBlock + } + } } } @@ -280,6 +301,152 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) return FunctionReferenceBuilder(reference, erasedSamSuperType).build() } + private fun createProxyLocalFunctionForIndySamConversion(reference: IrFunctionReference): IrBlock { + val startOffset = reference.startOffset + val endOffset = reference.endOffset + val targetFun = reference.symbol.owner + + // For a function reference with possibly bound value parameters + // [ dispatchReceiver = ..., extensionReceiver = ..., ... ]::foo + // create a proxy wrapper: + // { + // val tmp_proxy_0 = + // ... + // val tmp_proxy_N = + // fun `$proxy`(p_0: TP_0, ..., p_M: TP_M): TR = + // foo(... arg_J ...) + // // here for each J arg_J is either 'tmp_proxy_K' or 'p_K' for some K + // ::`$proxy` + // } + + val temporaryVals = ArrayList() + + val targetCall: IrFunctionAccessExpression = + when (targetFun) { + is IrSimpleFunction -> + IrCallImpl.fromSymbolOwner(startOffset, endOffset, targetFun.symbol) + is IrConstructor -> + IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, targetFun.returnType, targetFun.symbol) + else -> + throw AssertionError("Unexpected callable reference target: ${targetFun.render()}") + } + + val proxyFun = context.irFactory.buildFun { + name = Name.identifier("\$proxy") + returnType = targetFun.returnType + visibility = DescriptorVisibilities.LOCAL + modality = Modality.FINAL + isSuspend = false + isInline = false + origin = JvmLoweredDeclarationOrigin.PROXY_FUN_FOR_INDY_SAM_CONVESION + }.also { proxyFun -> + proxyFun.parent = currentDeclarationParent + ?: throw AssertionError("No declaration parent when processing $reference") + + var temporaryValIndex = 0 + var proxyParameterIndex = 0 + + fun addAndGetTemporaryVal(initializer: IrExpression): IrGetValue { + val tmpVal = IrVariableImpl( + startOffset, endOffset, + IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, + IrVariableSymbolImpl(), + Name.identifier("tmp_proxy_${temporaryValIndex++}"), + initializer.type, + isVar = false, isConst = false, isLateinit = false + ) + tmpVal.initializer = initializer + temporaryVals.add(tmpVal) + return IrGetValueImpl(startOffset, endOffset, tmpVal.symbol) + } + + fun addAndGetProxyValueParameter(originalParameter: IrValueParameter): IrGetValue { + val proxyParameter = buildValueParameter(proxyFun) { + updateFrom(originalParameter) + name = Name.identifier("p$proxyParameterIndex\$${originalParameter.name.asString()}") + index = proxyParameterIndex + proxyParameterIndex++ + }.apply { + parent = proxyFun + } + proxyFun.valueParameters += proxyParameter + return IrGetValueImpl(startOffset, endOffset, proxyParameter.symbol) + } + + fun getTargetCallArgument(boundValue: IrExpression?, originalParameter: IrValueParameter?): IrExpression? = + when { + boundValue != null -> + addAndGetTemporaryVal(boundValue) + originalParameter != null -> + addAndGetProxyValueParameter(originalParameter) + else -> + null + } + + targetCall.dispatchReceiver = getTargetCallArgument(reference.dispatchReceiver, targetFun.dispatchReceiverParameter) + targetCall.extensionReceiver = getTargetCallArgument(reference.extensionReceiver, targetFun.extensionReceiverParameter) + for ((valueParameterIndex, valueParameter) in targetFun.valueParameters.withIndex()) { + targetCall.putValueArgument( + valueParameterIndex, + getTargetCallArgument( + reference.getValueArgument(valueParameterIndex), + valueParameter + ) + ) + } + + val proxyFunBody = IrBlockBodyImpl(startOffset, endOffset).also { proxyFun.body = it } + when { + targetFun.isArrayOf() -> { + // Lower arrayOf-like function in place. + // TODO it seems that VarargLowering does a little bit too much. + // Maybe worth decomposing it into varargs part and arrayOf intrinsics part. + val varargParameter = proxyFun.valueParameters.singleOrNull { it.isVararg } + ?: throw AssertionError( + "Proxy for *arrayOf should have single vararg parameter:\n" + + proxyFun.valueParameters.joinToString(separator = "\n") { it.dump() } + ) + proxyFunBody.statements.add( + IrReturnImpl( + startOffset, endOffset, + context.irBuiltIns.nothingType, + proxyFun.symbol, + IrGetValueImpl(startOffset, endOffset, varargParameter.symbol, null) + ) + ) + } + targetFun.returnType.isUnit() -> { + proxyFunBody.statements.add(targetCall) + } + else -> { + proxyFunBody.statements.add( + IrReturnImpl( + startOffset, endOffset, + context.irBuiltIns.nothingType, + proxyFun.symbol, + targetCall + ) + ) + } + } + } + + val proxyFunRef = IrFunctionReferenceImpl( + startOffset, endOffset, + reference.type, + proxyFun.symbol, + 0, // TODO generic function reference? + proxyFun.valueParameters.size + ) + + return IrBlockImpl( + startOffset, endOffset, + reference.type, + origin = null, + temporaryVals + proxyFun + proxyFunRef + ) + } + private fun canGenerateIndySamConversionOnFunctionalExpression(samSuperType: IrType, expression: IrExpression): Boolean { val samClass = samSuperType.classOrNull ?: throw AssertionError("Class type expected: ${samSuperType.render()}") @@ -302,24 +469,24 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) private fun wrapSamConversionArgumentWithIndySamConversion( expression: IrTypeOperatorCall, - lambdaMetafactoryArguments: LambdaMetafactoryArguments + produceSamConversion: (IrType) -> IrExpression ): IrExpression { val samType = expression.typeOperand return when (val argument = expression.argument) { is IrFunctionReference -> - wrapWithIndySamConversion(samType, lambdaMetafactoryArguments) + produceSamConversion(samType) is IrBlock -> - wrapFunctionReferenceInsideBlockWithIndySamConversion(samType, lambdaMetafactoryArguments, argument) + wrapFunctionReferenceInsideBlockWithIndySamConversion(samType, argument, produceSamConversion) else -> throw AssertionError("Block or function reference expected: ${expression.render()}") } } private fun wrapFunctionReferenceInsideBlockWithIndySamConversion( samType: IrType, - lambdaMetafactoryArguments: LambdaMetafactoryArguments, - block: IrBlock + block: IrBlock, + produceSamConversion: (IrType) -> IrExpression ): IrExpression { - val indySamConversion = wrapWithIndySamConversion(samType, lambdaMetafactoryArguments) + val indySamConversion = produceSamConversion(samType) block.statements[block.statements.size - 1] = indySamConversion block.type = indySamConversion.type return block diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt index 4cc85f04336..15f48a800b4 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/indy/LambdaMetafactoryArguments.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ir.allOverridden import org.jetbrains.kotlin.backend.common.lower.VariableRemapper import org.jetbrains.kotlin.backend.common.lower.parents import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.findSuperDeclaration import org.jetbrains.kotlin.backend.jvm.ir.getSingleAbstractMethod @@ -34,12 +35,49 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.utils.addIfNotNull +internal sealed class MetafactoryArgumentsResult { + abstract val isSuccess: Boolean + + abstract class Success : MetafactoryArgumentsResult() { + override val isSuccess: Boolean + get() = true + } + + abstract class Failure : MetafactoryArgumentsResult() { + override val isSuccess: Boolean + get() = false + + // Objects produced by j.l.invoke.LambdaMetafactory have different semantics (e.g., different 'equals' method) + // that prevents using them in place of objects of corresponding Kotlin classes. + // TODO might use Kotlin-specific metafactory if there would be one. + object LambdaMetafactorySemanticsHazard : Failure() + + // There's an ABI incompatibility between classes generated by j.l.invoke.LambdaMetafactory and classes generatede by Kotlin. + // TODO might use Kotlin-specific metafactory if there would be one. + object LambdaMetafactoryAbiHazard : Failure() + + // An object would be created inside an inline function, which currently doesn't work well with 'invokedynamic'. + // TODO make sure indy and Kotlin bytecode inliner work well together + object InliningHazard : Failure() + + // Resulting object should be Serializable. + // TODO implement serialization support required by j.l.invoke.LambdaMetafactory + object SerializationHazard : Failure() + + // There's something special about a function we are referencing. + // Wrapping it into a proxy local function might help. + object FunctionHazard : Failure() + } +} + + internal class LambdaMetafactoryArguments( val samMethod: IrSimpleFunction, val fakeInstanceMethod: IrSimpleFunction, val implMethodReference: IrFunctionReference, val extraOverriddenMethods: List -) +) : MetafactoryArgumentsResult.Success() + internal class LambdaMetafactoryArgumentsBuilder( private val context: JvmBackendContext, @@ -48,34 +86,44 @@ internal class LambdaMetafactoryArgumentsBuilder( /** * @see java.lang.invoke.LambdaMetafactory */ - fun getLambdaMetafactoryArgumentsOrNull( + fun getLambdaMetafactoryArguments( reference: IrFunctionReference, samType: IrType, plainLambda: Boolean - ): LambdaMetafactoryArguments? { + ): MetafactoryArgumentsResult { val samClass = samType.getClass() ?: throw AssertionError("SAM type is not a class: ${samType.render()}") + var semanticsHazard = false + var abiHazard = false + var inliningHazard = false + var shouldBeSerializable = false + var functionHazard = false + // Can't use JDK LambdaMetafactory for function references by default (because of 'equals'). // TODO special mode that would generate indy everywhere? - if (!reference.origin.isLambda && !samClass.isFromJava()) - return null + if (!reference.origin.isLambda && !samClass.isFromJava()) { + semanticsHazard = true + } // Don't use JDK LambdaMetafactory for serializable lambdas // TODO implement support for serializable lambdas with LambdaMetafactory (requires additional code for deserialization) - if (samClass.isInheritedFromSerializable()) - return null + if (samClass.isInheritedFromSerializable()) { + shouldBeSerializable = true + } val samMethod = samClass.getSingleAbstractMethod() ?: throw AssertionError("SAM class has no single abstract method: ${samClass.render()}") // Can't use JDK LambdaMetafactory for fun interface with suspend fun. - if (samMethod.isSuspend) - return null + if (samMethod.isSuspend) { + abiHazard = true + } // Can't use JDK LambdaMetafactory for fun interfaces that require delegation to $DefaultImpls. - if (samClass.requiresDelegationToDefaultImpls()) - return null + if (samClass.requiresDelegationToDefaultImpls()) { + abiHazard = true + } // TODO in cases where LambdaMetafactory is unusable directly due to problems with the implementation function, // we can still avoid generating an entire class by converting the function reference into a lambda first; @@ -83,32 +131,38 @@ internal class LambdaMetafactoryArgumentsBuilder( val implFun = reference.symbol.owner + if (implFun.typeParameters.any { it.isReified }) { + // TODO support reified type parameters in proxy wrappers somehow? + abiHazard = true + } + // Don't generate references to intrinsic functions as invokedynamic (no such method exists at run-time). - if (context.irIntrinsics.getIntrinsic(implFun.symbol) != null) - return null + if (context.irIntrinsics.getIntrinsic(implFun.symbol) != null) { + functionHazard = true + } // Can't use invokedynamic if the referenced function has to be inlined for correct semantics // Also in some cases like `private inline fun` we'd need accessors, which `SyntheticAccessorLowering` // won't generate under the assumption that the inline function will be inlined. Plus if the function // is in a different module we should probably copy it anyway (and regenerate all objects in it). - if (implFun.isInline) - return null + if (implFun.isInline) { + functionHazard = true + } if (implFun is IrConstructor && DescriptorVisibilities.isPrivate(implFun.visibility)) { // Kotlin generates constructor accessors differently from Java. - // TODO more precise accessibility check (see SyntheticAccessorLowering::isAccessible) - return null + // We don't do exact accessibility check here, just + functionHazard = true } // It's possible to reference through a child class a method declared in a package-private base Java class. // In this case the corresponding method might be inaccessible in the context where it's referenced (see KT-48954). // For now, just prohibit referencing methods from package-private Java classes through indy (without precise accessibility check). - // TODO wrap into lambda? if (implFun is IrSimpleFunction) { val baseFun = findSuperDeclaration(implFun, false, context.state.jvmDefaultMode) val baseFunClass = baseFun.parent as? IrClass if (baseFunClass != null && baseFunClass.visibility == JavaDescriptorVisibilities.PACKAGE_VISIBILITY) { - return null + functionHazard = true } } @@ -117,40 +171,52 @@ internal class LambdaMetafactoryArgumentsBuilder( // LambdaMetafactory treats multifile class part members as non-accessible, // even if the member is referenced via facade, // because corresponding part class is non-accessible - return null + functionHazard = true } // 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 (reference.origin.isLambda && implFun.annotations.isNotEmpty()) - return null + if (reference.origin.isLambda && implFun.annotations.isNotEmpty()) { + abiHazard = true + } // Don't use JDK LambdaMetafactory for big arity lambdas. if (plainLambda) { var parametersCount = implFun.valueParameters.size if (implFun.extensionReceiverParameter != null) ++parametersCount if (parametersCount >= BuiltInFunctionArity.BIG_ARITY) - return null + abiHazard = true } // Can't use indy-based SAM conversion inside inline fun (Ok in inline lambda). - if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() }) - return null + if (implFun.parents.any { it.isInlineFunction() || it.isCrossinlineLambda() }) { + inliningHazard = true + } // Don't try to use indy on SAM types with non-invariant projections because buildFakeOverrideMember doesn't support such supertypes // (and rightly so: supertypes in Kotlin can't have projections in immediate type arguments). This can happen for example in case // the SAM type is instantiated with an intersection type in arguments, which is approximated to an out-projection in psi2ir. if (samType is IrSimpleType) { - if (samType.arguments.any { it is IrStarProjection || it is IrTypeProjection && it.variance != Variance.INVARIANT }) - return null + if (samType.arguments.any { it is IrStarProjection || it is IrTypeProjection && it.variance != Variance.INVARIANT }) { + abiHazard = true + } + } + + when { + semanticsHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactorySemanticsHazard + abiHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactoryAbiHazard + inliningHazard -> return MetafactoryArgumentsResult.Failure.InliningHazard + shouldBeSerializable -> return MetafactoryArgumentsResult.Failure.SerializationHazard + functionHazard -> return MetafactoryArgumentsResult.Failure.FunctionHazard } // 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, implFun) + ?: MetafactoryArgumentsResult.Failure.FunctionHazard } private val javaIoSerializableFqn = @@ -258,7 +324,7 @@ internal class LambdaMetafactoryArgumentsBuilder( return null adaptFakeInstanceMethodSignature(fakeInstanceMethod, signatureAdaptationConstraints) - if (implFun.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) { + if (implFun.origin in adaptableFunctionOrigins) { adaptLambdaSignature(implFun as IrSimpleFunction, fakeInstanceMethod, signatureAdaptationConstraints) } else if ( !checkMethodSignatureCompliance(implFun, fakeInstanceMethod, signatureAdaptationConstraints, reference) @@ -319,13 +385,18 @@ internal class LambdaMetafactoryArgumentsBuilder( TypeAdaptationConstraint.CONFLICT -> false } + private val adaptableFunctionOrigins = setOf( + IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA, + JvmLoweredDeclarationOrigin.PROXY_FUN_FOR_INDY_SAM_CONVESION + ) + 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()}") + if (implFun.origin !in adaptableFunctionOrigins) { + throw AssertionError("Function origin should be one of ${adaptableFunctionOrigins}: ${implFun.dump()}") } val implParameters = collectValueParameters(implFun) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweredDeclarationOrigin.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweredDeclarationOrigin.kt index 95aa0be0258..86049f6bd9e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweredDeclarationOrigin.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLoweredDeclarationOrigin.kt @@ -37,7 +37,7 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object INTERFACE_COMPANION_PRIVATE_INSTANCE : IrDeclarationOriginImpl("INTERFACE_COMPANION_PRIVATE_INSTANCE", isSynthetic = true) object POLYMORPHIC_SIGNATURE_INSTANTIATION : IrDeclarationOriginImpl("POLYMORPHIC_SIGNATURE_INSTANTIATION", isSynthetic = true) object ENUM_CONSTRUCTOR_SYNTHETIC_PARAMETER : IrDeclarationOriginImpl("ENUM_CONSTRUCTOR_SYNTHETIC_PARAMETER", isSynthetic = true) - object OBJECT_SUPER_CONSTRUCTOR_PARAMETER : IrDeclarationOriginImpl("OBJECT_SUPER_CONSTURCTOR_PARAMETER", isSynthetic = true) + object OBJECT_SUPER_CONSTRUCTOR_PARAMETER : IrDeclarationOriginImpl("OBJECT_SUPER_CONSTRUCTOR_PARAMETER", isSynthetic = true) object CONTINUATION_CLASS : IrDeclarationOriginImpl("CONTINUATION_CLASS") object SUSPEND_LAMBDA : IrDeclarationOriginImpl("SUSPEND_LAMBDA") object FOR_INLINE_STATE_MACHINE_TEMPLATE : IrDeclarationOriginImpl("FOR_INLINE_TEMPLATE") @@ -48,4 +48,5 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object ABSTRACT_BRIDGE_STUB : IrDeclarationOriginImpl("ABSTRACT_BRIDGE_STUB") object INVOVEDYNAMIC_CALL_TARGET : IrDeclarationOriginImpl("INVOVEDYNAMIC_CALL_TARGET") object INLINE_LAMBDA : IrDeclarationOriginImpl("INLINE_LAMBDA") + object PROXY_FUN_FOR_INDY_SAM_CONVESION : IrDeclarationOriginImpl("PROXY_FUN_FOR_INDY_SAM_CONVESION") } diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt new file mode 100644 index 00000000000..0082c59f2b6 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt @@ -0,0 +1,21 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: genericBoundInnerConstructorRef.kt +class Outer(val s1: TO) { + inner class Inner(val s2: TI) { + fun t() = s1.toString() + s2.toString() + } +} + +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/genericInnerConstructorRef.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt new file mode 100644 index 00000000000..7e639fc549a --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt @@ -0,0 +1,24 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: genericInnerConstructorRef.kt + +// Can't resolve generic type argument for unbound constructor reference, +// so 'Outer' has no type parameters. +class Outer(val s1: String) { + inner class Inner(val s2: TI) { + fun t() = s1 + s2.toString() + } +} + +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/multifileClassMemberFromStdlib.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt index 3bff105e343..d92dcdc7a73 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt @@ -5,7 +5,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // IGNORE_BACKEND_FIR: JVM_IR // ^ OVERLOAD_RESOLUTION_AMBIGUITY: Overload resolution ambiguity between candidates: [kotlin/collections/plus, kotlin/collections/plus] diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt new file mode 100644 index 00000000000..1c6bc157a30 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt @@ -0,0 +1,30 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 4 java/lang/invoke/LambdaMetafactory + +// FILE: voidReturnTypeAsObject.kt + +var t = "Failed" + +fun ok(s: String) { t = s } + +fun box(): String { + Sam(::ok).get("1") + Sam(::ok).get("2") + Sam(::ok).get("3") + + val r = Sam(::ok).get("OK") + if (r != Unit) { + return "Failed: $r" + } + return t +} + +// FILE: Sam.java +public interface Sam { + Object get(String s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/anyNToString.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/anyNToString.kt index fbc8dce53f3..f5d14beb575 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/anyNToString.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/anyNToString.kt @@ -4,7 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: anyNToString.kt fun box() = diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt index 7fc952ddbe4..852f60281fb 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/arrayConstructor.kt @@ -4,7 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: arrayConstructor.kt fun box(): String { diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt index e6e06852775..c108ab5bad5 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/charArrayOf.kt @@ -4,7 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: charArrayOf.kt fun box(): String { diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt new file mode 100644 index 00000000000..152365af9a2 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: intArrayOf.kt +fun box(): String { + val sam = Sam(::intArrayOf) + val arr = sam.get(intArrayOf('O'.toInt(), 'K'.toInt())) + return "${arr[0].toChar()}${arr[1].toChar()}" +} + +// FILE: Sam.java +public interface Sam { + int[] get(int[] s); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/stringNPlus.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/stringNPlus.kt index 06362ee9596..9a0c2cf7795 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/stringNPlus.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/stringNPlus.kt @@ -4,7 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: stringNPlus.kt fun test(x: String?, y: Any?) = diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt index cdb72f426a0..6e8d5530f42 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt @@ -4,8 +4,7 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory -// 1 final synthetic class VoidReturnTypeAsObjectKt\$box\$r\$[0-9]+ +// 1 java/lang/invoke/LambdaMetafactory // FILE: voidReturnTypeAsObject.kt var t = "Failed" diff --git a/compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt b/compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt new file mode 100644 index 00000000000..e729d595544 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt @@ -0,0 +1,27 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// WITH_RUNTIME +// FULL_JDK + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 1 java/lang/invoke/LambdaMetafactory + +// FILE: inlineFunWithPrivateMethod.kt + +private inline fun g(x: String) = println(x) + +fun call(c: Consumer) = c.accept("") + +fun box(): String { + val obj = { call(::g) } // `g` is inaccessible in this scope + obj() + return "OK" +} + +// FILE: Consumer.java + +public interface Consumer { + void accept(T t); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt b/compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt index 632d3546d28..c8b7d1433f2 100644 --- a/compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt +++ b/compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt @@ -6,22 +6,13 @@ // CHECK_BYTECODE_TEXT // JVM_IR_TEMPLATES -// 0 java/lang/invoke/LambdaMetafactory +// 1 java/lang/invoke/LambdaMetafactory // FILE: inlineOnly.kt - -inline fun f(x: T) = - println("${T::class.simpleName}($x)") - -private inline fun g(x: String) = println(x) - fun call(c: Consumer) = c.accept("") fun box(): String { - call(::println) // `println` is `@InlineOnly` - call(::f) // `f` has a reified type parameter and thus isn't callable directly - val obj = { call(::g) } // `g` is inaccessible in this scope - obj() + call(::println) // 'println' is @InlineOnly return "OK" } diff --git a/compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt b/compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt new file mode 100644 index 00000000000..d1491fcd726 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt @@ -0,0 +1,27 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY +// WITH_RUNTIME +// FULL_JDK + +// CHECK_BYTECODE_TEXT +// JVM_IR_TEMPLATES +// 0 java/lang/invoke/LambdaMetafactory + +// FILE: reifiedTypeParameter.kt + +inline fun f(x: T) = + println("${T::class.simpleName}($x)") + +fun call(c: Consumer) = c.accept("") + +fun box(): String { + call(::f) // `f` has a reified type parameter and thus isn't callable directly + return "OK" +} + +// FILE: Consumer.java + +public interface Consumer { + void accept(T t); +} 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 02852e3c896..6f983780d64 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 @@ -22095,6 +22095,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt"); } + @Test + @TestMetadata("inlineFunWithPrivateMethod.kt") + public void testInlineFunWithPrivateMethod() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt"); + } + @Test @TestMetadata("inlineOnly.kt") public void testInlineOnly() throws Exception { @@ -22143,6 +22149,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt"); } + @Test + @TestMetadata("reifiedTypeParameter.kt") + public void testReifiedTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt"); + } + @Test @TestMetadata("samConversionInsideSamConvertedLambda.kt") public void testSamConversionInsideSamConvertedLambda() throws Exception { @@ -22342,6 +22354,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); } + @Test + @TestMetadata("genericBoundInnerConstructorRef.kt") + public void testGenericBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); + } + + @Test + @TestMetadata("genericInnerConstructorRef.kt") + public void testGenericInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); + } + @Test @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { @@ -22396,6 +22420,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt"); } + @Test + @TestMetadata("multipleProxyWrappersForSameFunction.kt") + public void testMultipleProxyWrappersForSameFunction() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt"); + } + @Test @TestMetadata("nonTrivialReceiver.kt") public void testNonTrivialReceiver() throws Exception { @@ -22483,6 +22513,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt"); } + @Test + @TestMetadata("intArrayOf.kt") + public void testIntArrayOf() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt"); + } + @Test @TestMetadata("intPlus.kt") public void testIntPlus() 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 6b0461c4367..10f80599d72 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 @@ -22233,6 +22233,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt"); } + @Test + @TestMetadata("inlineFunWithPrivateMethod.kt") + public void testInlineFunWithPrivateMethod() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt"); + } + @Test @TestMetadata("inlineOnly.kt") public void testInlineOnly() throws Exception { @@ -22281,6 +22287,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt"); } + @Test + @TestMetadata("reifiedTypeParameter.kt") + public void testReifiedTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt"); + } + @Test @TestMetadata("samConversionInsideSamConvertedLambda.kt") public void testSamConversionInsideSamConvertedLambda() throws Exception { @@ -22480,6 +22492,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); } + @Test + @TestMetadata("genericBoundInnerConstructorRef.kt") + public void testGenericBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); + } + + @Test + @TestMetadata("genericInnerConstructorRef.kt") + public void testGenericInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); + } + @Test @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { @@ -22534,6 +22558,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt"); } + @Test + @TestMetadata("multipleProxyWrappersForSameFunction.kt") + public void testMultipleProxyWrappersForSameFunction() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt"); + } + @Test @TestMetadata("nonTrivialReceiver.kt") public void testNonTrivialReceiver() throws Exception { @@ -22621,6 +22651,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt"); } + @Test + @TestMetadata("intArrayOf.kt") + public void testIntArrayOf() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt"); + } + @Test @TestMetadata("intPlus.kt") public void testIntPlus() 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 3c4172e7f6b..464e3d98155 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -18495,6 +18495,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt"); } + @TestMetadata("inlineFunWithPrivateMethod.kt") + public void testInlineFunWithPrivateMethod() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineFunWithPrivateMethod.kt"); + } + @TestMetadata("inlineOnly.kt") public void testInlineOnly() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt"); @@ -18535,6 +18540,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/primitiveVsWrapperInSam.kt"); } + @TestMetadata("reifiedTypeParameter.kt") + public void testReifiedTypeParameter() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/reifiedTypeParameter.kt"); + } + @TestMetadata("samConversionInsideSamConvertedLambda.kt") public void testSamConversionInsideSamConvertedLambda() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/samConversionInsideSamConvertedLambda.kt"); @@ -18705,6 +18715,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/enhancedNullability.kt"); } + @TestMetadata("genericBoundInnerConstructorRef.kt") + public void testGenericBoundInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericBoundInnerConstructorRef.kt"); + } + + @TestMetadata("genericInnerConstructorRef.kt") + public void testGenericInnerConstructorRef() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/genericInnerConstructorRef.kt"); + } + @TestMetadata("innerConstructorRef.kt") public void testInnerConstructorRef() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/innerConstructorRef.kt"); @@ -18750,6 +18770,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multifileClassMemberFromStdlib.kt"); } + @TestMetadata("multipleProxyWrappersForSameFunction.kt") + public void testMultipleProxyWrappersForSameFunction() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/multipleProxyWrappersForSameFunction.kt"); + } + @TestMetadata("nonTrivialReceiver.kt") public void testNonTrivialReceiver() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/nonTrivialReceiver.kt"); @@ -18827,6 +18852,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/enumValues.kt"); } + @TestMetadata("intArrayOf.kt") + public void testIntArrayOf() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intArrayOf.kt"); + } + @TestMetadata("intPlus.kt") public void testIntPlus() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/specialFunctions/intPlus.kt");