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 518127b824d..d9344709fda 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 @@ -20821,6 +20821,52 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT public void testVoidReturnTypeAsObject() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + public class WithAccessor { + @Test + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("privateBoundOuterClassMemberFun.kt") + public void testPrivateBoundOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateBoundOuterClassMemberFun.kt"); + } + + @Test + @TestMetadata("privateCompanionObjectMember.kt") + public void testPrivateCompanionObjectMember() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateCompanionObjectMember.kt"); + } + + @Test + @TestMetadata("privateOuterClassConstructor.kt") + public void testPrivateOuterClassConstructor() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassConstructor.kt"); + } + + @Test + @TestMetadata("privateOuterClassMemberFun.kt") + public void testPrivateOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassMemberFun.kt"); + } + + @Test + @TestMetadata("privateTopLevelExtFun.kt") + public void testPrivateTopLevelExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelExtFun.kt"); + } + + @Test + @TestMetadata("privateTopLevelFun.kt") + public void testPrivateTopLevelFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelFun.kt"); + } + } } @Nested diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index e73690da85e..3bbd0ed9a24 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -83,74 +83,135 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle val withSuper = (expression as? IrCall)?.superQualifierSymbol != null val thisSymbol = (expression as? IrCall)?.dispatchReceiver?.type?.classifierOrNull as? IrClassSymbol + if (expression is IrCall && callee.symbol == context.ir.symbols.indyLambdaMetafactoryIntrinsic) { + return super.visitExpression(handleLambdaMetafactoryIntrinsic(expression, thisSymbol)) + } + val accessor = when { callee is IrConstructor && callee.isOrShouldBeHidden -> handleHiddenConstructor(callee).symbol - - !expression.symbol.isAccessible(withSuper, thisSymbol) -> { - // Find the right container to insert the accessor. Simply put, when we call a function on a class A, - // we also need to put its accessor into A. However, due to the way that calls are implemented in the - // IR we generally need to look at the type of the dispatchReceiver *argument* in order to find the - // correct class. Consider the following code: - // - // fun run(f : () -> Int): Int = f() - // - // open class A { - // private fun f() = 0 - // fun g() = run { this.f() } - // } - // - // class B : A { - // override fun g() = 1 - // fun h() = run { super.g() } - // } - // - // We have calls to the private methods A.f from a generated Lambda subclass for the argument to `run` - // in class A and a super call to A.g from a generated Lambda subclass in class B. - // - // In the first case, we need to produce an accessor in class A to access the private member of A. - // Both the parent of the function f and the type of the dispatch receiver point to the correct class. - // In the second case we need to call A.g from within class B, since this is the only way to invoke - // a method of a superclass on the JVM. However, the IR for the call to super.g points directly to the - // function g in class A. Confusingly, the `superQualifier` on this call also points to class A. - // The only way to compute the actual enclosing class for the call is by looking at the type of the - // dispatch receiver argument, which points to B. - // - // Beyond this, there can be accessors that are needed because other lowerings produce code calling - // private methods (e.g., local functions for lambdas are private and called from generated - // SAM wrapper classes). In this case we rely on the parent field of the called function. - // - // Finally, we need to produce accessors for calls to protected static methods coming from Java, - // which we put in the closest enclosing class which has access to the method in question. - val symbol = expression.symbol - val dispatchReceiverType = expression.dispatchReceiver?.type - val parent = symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) - - // The key in the cache/map needs to be BOTH the symbol of the function being accessed AND the parent - // of the accessor. Going from the above example, if we have another class C similar to B: - // - // class C : A { - // override fun g() = 2 - // fun i() = run { super.g() } - // } - // - // For the call to super.g in function i, the accessor to A.g must be produced in C. Therefore, we - // cannot use the function symbol (A.g in the example) by itself as the key since there should be - // one accessor per dispatch receiver (i.e., parent of the accessor). - functionMap.getOrPut(symbol to parent) { - when (symbol) { - is IrConstructorSymbol -> symbol.owner.makeConstructorAccessor().also(pendingAccessorsToAdd::add).symbol - is IrSimpleFunctionSymbol -> symbol.owner.makeSimpleFunctionAccessor(expression as IrCall, parent).symbol - else -> error("Unknown subclass of IrFunctionSymbol") - } - } - } - - else -> return super.visitFunctionAccess(expression) + !expression.symbol.isAccessible(withSuper, thisSymbol) -> + createAccessor(expression) + else -> + return super.visitFunctionAccess(expression) } return super.visitExpression(modifyFunctionAccessExpression(expression, accessor)) } + private fun createAccessor(expression: IrFunctionAccessExpression): IrFunctionSymbol = + if (expression is IrCall) + createAccessor(expression.symbol, expression.dispatchReceiver?.type, expression.superQualifierSymbol) + else + createAccessor(expression.symbol, null, null) + + private fun createAccessor( + symbol: IrFunctionSymbol, + dispatchReceiverType: IrType?, + superQualifierSymbol: IrClassSymbol? + ): IrFunctionSymbol { + // Find the right container to insert the accessor. Simply put, when we call a function on a class A, + // we also need to put its accessor into A. However, due to the way that calls are implemented in the + // IR we generally need to look at the type of the dispatchReceiver *argument* in order to find the + // correct class. Consider the following code: + // + // fun run(f : () -> Int): Int = f() + // + // open class A { + // private fun f() = 0 + // fun g() = run { this.f() } + // } + // + // class B : A { + // override fun g() = 1 + // fun h() = run { super.g() } + // } + // + // We have calls to the private methods A.f from a generated Lambda subclass for the argument to `run` + // in class A and a super call to A.g from a generated Lambda subclass in class B. + // + // In the first case, we need to produce an accessor in class A to access the private member of A. + // Both the parent of the function f and the type of the dispatch receiver point to the correct class. + // In the second case we need to call A.g from within class B, since this is the only way to invoke + // a method of a superclass on the JVM. However, the IR for the call to super.g points directly to the + // function g in class A. Confusingly, the `superQualifier` on this call also points to class A. + // The only way to compute the actual enclosing class for the call is by looking at the type of the + // dispatch receiver argument, which points to B. + // + // Beyond this, there can be accessors that are needed because other lowerings produce code calling + // private methods (e.g., local functions for lambdas are private and called from generated + // SAM wrapper classes). In this case we rely on the parent field of the called function. + // + // Finally, we need to produce accessors for calls to protected static methods coming from Java, + // which we put in the closest enclosing class which has access to the method in question. + + val parent = symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) + + // The key in the cache/map needs to be BOTH the symbol of the function being accessed AND the parent + // of the accessor. Going from the above example, if we have another class C similar to B: + // + // class C : A { + // override fun g() = 2 + // fun i() = run { super.g() } + // } + // + // For the call to super.g in function i, the accessor to A.g must be produced in C. Therefore, we + // cannot use the function symbol (A.g in the example) by itself as the key since there should be + // one accessor per dispatch receiver (i.e., parent of the accessor). + return functionMap.getOrPut(symbol to parent) { + when (symbol) { + is IrConstructorSymbol -> + symbol.owner.makeConstructorAccessor() + .also(pendingAccessorsToAdd::add) + .symbol + is IrSimpleFunctionSymbol -> { + symbol.owner.makeSimpleFunctionAccessor(superQualifierSymbol, dispatchReceiverType, parent) + .also(pendingAccessorsToAdd::add) + .symbol + } + else -> error("Unknown subclass of IrFunctionSymbol") + } + } + } + + private fun handleLambdaMetafactoryIntrinsic(call: IrCall, thisSymbol: IrClassSymbol?): IrExpression { + val implFunRef = call.getValueArgument(1) as? IrFunctionReference + ?: throw AssertionError("'implMethodReference' is expected to be 'IrFunctionReference': ${call.dump()}") + val implFunSymbol = implFunRef.symbol + + if (implFunSymbol.isAccessible(false, thisSymbol)) return call + + val accessorSymbol = createAccessor(implFunSymbol, implFunRef.dispatchReceiver?.type, null) + val accessorFun = accessorSymbol.owner + val accessorRef = + IrFunctionReferenceImpl( + implFunRef.startOffset, implFunRef.endOffset, implFunRef.type, + accessorSymbol, + accessorFun.typeParameters.size, + accessorFun.valueParameters.size, + implFunRef.reflectionTarget, implFunRef.origin + ) + + accessorRef.copyTypeArgumentsFrom(implFunRef) + + val implFun = implFunSymbol.owner + var accessorArgIndex = 0 + if (implFun.dispatchReceiverParameter != null) { + accessorRef.putValueArgument(accessorArgIndex++, implFunRef.dispatchReceiver) + } + if (implFun.extensionReceiverParameter != null) { + accessorRef.putValueArgument(accessorArgIndex++, implFunRef.extensionReceiver) + } + for (implArgIndex in 0 until implFunRef.valueArgumentsCount) { + accessorRef.putValueArgument(accessorArgIndex++, implFunRef.getValueArgument(implArgIndex)) + } + if (accessorFun is IrConstructor) { + accessorRef.putValueArgument(accessorArgIndex, createAccessorMarkerArgument()) + } + + call.putValueArgument(1, accessorRef) + return call + } + override fun visitGetField(expression: IrGetField): IrExpression { val dispatchReceiverType = expression.receiver?.type return super.visitExpression( @@ -318,28 +379,31 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle copyAllParamsToArgs(it, accessor) } - private fun IrSimpleFunction.makeSimpleFunctionAccessor(expression: IrCall, parent: IrDeclarationParent): IrSimpleFunction { + private fun IrSimpleFunction.makeSimpleFunctionAccessor( + superQualifierSymbol: IrClassSymbol?, + dispatchReceiverType: IrType?, + parent: IrDeclarationParent + ): IrSimpleFunction { val source = this return factory.buildFun { startOffset = parent.startOffset endOffset = parent.startOffset origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR - name = source.accessorName(expression.superQualifierSymbol) + name = source.accessorName(superQualifierSymbol) visibility = DescriptorVisibilities.PUBLIC modality = if (parent is IrClass && parent.isJvmInterface) Modality.OPEN else Modality.FINAL isSuspend = source.isSuspend // synthetic accessors of suspend functions are handled in codegen }.also { accessor -> accessor.parent = parent - pendingAccessorsToAdd.add(accessor) accessor.copyTypeParametersFrom(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) - accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR, expression.dispatchReceiver?.type) + accessor.copyValueParametersToStatic(source, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR, dispatchReceiverType) accessor.returnType = source.returnType.remapTypeParameters(source, accessor) accessor.body = IrExpressionBodyImpl( accessor.startOffset, accessor.startOffset, - createSimpleFunctionCall(accessor, source.symbol, expression.superQualifierSymbol) + createSimpleFunctionCall(accessor, source.symbol, superQualifierSymbol) ) } } @@ -487,18 +551,14 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle newExpression.putValueArgument(i, irExpression) } if (accessorSymbol is IrConstructorSymbol) { - newExpression.putValueArgument( - receiverAndArgs.size, - IrConstImpl.constNull( - UNDEFINED_OFFSET, - UNDEFINED_OFFSET, - context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable() - ) - ) + newExpression.putValueArgument(receiverAndArgs.size, createAccessorMarkerArgument()) } return newExpression } + private fun createAccessorMarkerArgument() = + IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable()) + private fun modifyGetterExpression( oldExpression: IrGetField, accessorSymbol: IrSimpleFunctionSymbol @@ -618,14 +678,6 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle return "p" + if (isStatic && visibility.isProtected) "\$s" + parentAsClass.syntheticAccessorToSuperSuffix() else "" } - private val DescriptorVisibility.isPrivate - get() = DescriptorVisibilities.isPrivate(this) - - private val DescriptorVisibility.isProtected - get() = this == DescriptorVisibilities.PROTECTED || - this == JavaDescriptorVisibilities.PROTECTED_AND_PACKAGE || - this == JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY - private fun IrSymbol.isAccessible(withSuper: Boolean, thisObjReference: IrClassSymbol?): Boolean { /// We assume that IR code that reaches us has been checked for correctness at the frontend. /// This function needs to single out those cases where Java accessibility rules differ from Kotlin's. @@ -705,4 +757,10 @@ private fun IrClass.syntheticAccessorToSuperSuffix(): String = // TODO: change this to `fqNameUnsafe.asString().replace(".", "_")` as soon as we're ready to break compatibility with pre-KT-21178 code name.asString().hashCode().toString() +val DescriptorVisibility.isPrivate + get() = DescriptorVisibilities.isPrivate(this) +val DescriptorVisibility.isProtected + get() = this == DescriptorVisibilities.PROTECTED || + this == JavaDescriptorVisibilities.PROTECTED_AND_PACKAGE || + this == JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY 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 6cfe429f59d..ca692a7965b 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 @@ -14,6 +14,7 @@ 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.backend.jvm.lower.isPrivate import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.builders.declarations.buildClass @@ -71,6 +72,13 @@ internal class LambdaMetafactoryArgumentsBuilder( val implFun = reference.symbol.owner + if (implFun is IrConstructor && implFun.visibility.isPrivate) { + // Kotlin generates constructor accessors differently from Java. + // TODO more precise accessibility check (see SyntheticAccessorLowering::isAccessible) + // TODO wrap inaccessible constructor with a local function + return null + } + // 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. @@ -323,6 +331,7 @@ internal class LambdaMetafactoryArgumentsBuilder( ) } + private fun IrValueParameter.copy(parent: IrSimpleFunction, newIndex: Int, newName: Name = this.name): IrValueParameter = buildValueParameter(parent) { updateFrom(this@copy) diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateBoundOuterClassMemberFun.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateBoundOuterClassMemberFun.kt new file mode 100644 index 00000000000..567748c0c20 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateBoundOuterClassMemberFun.kt @@ -0,0 +1,25 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// FILE: privateBoundOuterClassMemberFun.kt +interface GetStep { + fun get(): Step +} + +class Outer(val k: String) { + fun gs(x: Outer) = + object : GetStep { + override fun get(): Step = Step(x::test) + } + + private fun test(s: String) = s + k +} + +fun box(): String = + Outer("!").gs(Outer("K")).get().step("O") + +// FILE: Step.java +public interface Step { + String step(String string); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateCompanionObjectMember.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateCompanionObjectMember.kt new file mode 100644 index 00000000000..93839550257 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateCompanionObjectMember.kt @@ -0,0 +1,20 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// FILE: privateCompanionObjectMember.kt +class StepProcessor { + fun build() = Step(::test) + + companion object { + private fun test(string: String): String = string + } +} + +fun box(): String = + StepProcessor().build().step("OK") + +// FILE: Step.java +public interface Step { + String step(String string); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassConstructor.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassConstructor.kt new file mode 100644 index 00000000000..441d4e38240 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassConstructor.kt @@ -0,0 +1,35 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// FILE: privateOuterClassConstructor.kt +interface GetStep { + fun get(): Step +} + +class Outer { + private val ok: String + + private constructor(ok: String) { + this.ok = ok + } + + constructor() { + this.ok = "xxx" + } + + val obj = object : GetStep { + override fun get(): Step = Step(::Outer) + } + + override fun toString() = ok +} + +fun box() = + Outer().obj.get().step("OK").toString() + + +// FILE: Step.java +public interface Step { + Object step(String string); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassMemberFun.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassMemberFun.kt new file mode 100644 index 00000000000..d875d049c20 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassMemberFun.kt @@ -0,0 +1,24 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// FILE: privateOuterClassMemberFun.kt +interface GetStep { + fun get(): Step +} + +class Outer(val k: String) { + val obj = object : GetStep { + override fun get(): Step = Step(::test) + } + + private fun test(s: String) = s + k +} + +fun box(): String = + Outer("K").obj.get().step("O") + +// FILE: Step.java +public interface Step { + String step(String string); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelExtFun.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelExtFun.kt new file mode 100644 index 00000000000..be1d85e9ad5 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelExtFun.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// FILE: privateTopLevelExtFun.kt +class StepProcessor { + fun build() = Step("O"::test) +} + +private fun String.test(string: String): String = + this + string + +fun box(): String = + StepProcessor().build().step("K") + +// FILE: Step.java +public interface Step { + String step(String string); +} diff --git a/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelFun.kt b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelFun.kt new file mode 100644 index 00000000000..11427213d59 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelFun.kt @@ -0,0 +1,18 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// FILE: privateTopLevelFun.kt +class StepProcessor { + fun build() = Step(::test) +} + +private fun test(string: String): String = string + +fun box(): String = + StepProcessor().build().step("OK") + +// FILE: Step.java +public interface Step { + String step(String string); +} 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 94dc81ba189..6bcbd265260 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 @@ -20803,6 +20803,52 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testVoidReturnTypeAsObject() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + public class WithAccessor { + @Test + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @Test + @TestMetadata("privateBoundOuterClassMemberFun.kt") + public void testPrivateBoundOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateBoundOuterClassMemberFun.kt"); + } + + @Test + @TestMetadata("privateCompanionObjectMember.kt") + public void testPrivateCompanionObjectMember() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateCompanionObjectMember.kt"); + } + + @Test + @TestMetadata("privateOuterClassConstructor.kt") + public void testPrivateOuterClassConstructor() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassConstructor.kt"); + } + + @Test + @TestMetadata("privateOuterClassMemberFun.kt") + public void testPrivateOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassMemberFun.kt"); + } + + @Test + @TestMetadata("privateTopLevelExtFun.kt") + public void testPrivateTopLevelExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelExtFun.kt"); + } + + @Test + @TestMetadata("privateTopLevelFun.kt") + public void testPrivateTopLevelFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelFun.kt"); + } + } } @Nested 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 e5fb3cc79e3..7aa3ecb9679 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 @@ -20821,6 +20821,52 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testVoidReturnTypeAsObject() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt"); } + + @Nested + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + public class WithAccessor { + @Test + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("privateBoundOuterClassMemberFun.kt") + public void testPrivateBoundOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateBoundOuterClassMemberFun.kt"); + } + + @Test + @TestMetadata("privateCompanionObjectMember.kt") + public void testPrivateCompanionObjectMember() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateCompanionObjectMember.kt"); + } + + @Test + @TestMetadata("privateOuterClassConstructor.kt") + public void testPrivateOuterClassConstructor() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassConstructor.kt"); + } + + @Test + @TestMetadata("privateOuterClassMemberFun.kt") + public void testPrivateOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassMemberFun.kt"); + } + + @Test + @TestMetadata("privateTopLevelExtFun.kt") + public void testPrivateTopLevelExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelExtFun.kt"); + } + + @Test + @TestMetadata("privateTopLevelFun.kt") + public void testPrivateTopLevelFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelFun.kt"); + } + } } @Nested diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 8785f46f835..cbdc5b7e48e 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -17396,6 +17396,49 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testVoidReturnTypeAsObject() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/voidReturnTypeAsObject.kt"); } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class WithAccessor extends AbstractLightAnalysisModeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); + } + + @TestMetadata("privateBoundOuterClassMemberFun.kt") + public void testPrivateBoundOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateBoundOuterClassMemberFun.kt"); + } + + @TestMetadata("privateCompanionObjectMember.kt") + public void testPrivateCompanionObjectMember() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateCompanionObjectMember.kt"); + } + + @TestMetadata("privateOuterClassConstructor.kt") + public void testPrivateOuterClassConstructor() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassConstructor.kt"); + } + + @TestMetadata("privateOuterClassMemberFun.kt") + public void testPrivateOuterClassMemberFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateOuterClassMemberFun.kt"); + } + + @TestMetadata("privateTopLevelExtFun.kt") + public void testPrivateTopLevelExtFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelExtFun.kt"); + } + + @TestMetadata("privateTopLevelFun.kt") + public void testPrivateTopLevelFun() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor/privateTopLevelFun.kt"); + } + } } @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature") 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 60179f325e1..a0ee0166ed3 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 @@ -14990,6 +14990,19 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes 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); } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class WithAccessor extends AbstractIrJsCodegenBoxES6Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath); + } + + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); + } + } } @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature") 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 bb284e4b272..fa0ff31cec8 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 @@ -14411,6 +14411,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { 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); } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class WithAccessor extends AbstractIrJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); + } + } } @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature") 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 3cfca6a1fdb..413f34ce108 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 @@ -14476,6 +14476,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { 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); } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class WithAccessor extends AbstractJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); + } + } } @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature") 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 868b61a8b1b..7b9e3b709ef 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 @@ -8422,6 +8422,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest 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); } + + @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class WithAccessor extends AbstractIrCodegenBoxWasmTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath); + } + + public void testAllFilesPresentInWithAccessor() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/sam/functionRefToJavaInterface/withAccessor"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); + } + } } @TestMetadata("compiler/testData/codegen/box/invokedynamic/sam/inlineClassInSignature")