From ed88aa43a4c2990ca10ebcb608dcbe797919b856 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 8 Apr 2021 19:46:53 +0300 Subject: [PATCH] JVM_IR KT-45868 look for parent for delegating lambda in scope stack --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++++ .../jvm/lower/FunctionReferenceLowering.kt | 15 ++++++++- .../lower/indy/SamDelegatingLambdaBlock.kt | 22 +++++++------ .../box/invokedynamic/sam/insideInitBlock.kt | 33 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++++ .../LightAnalysisModeTestGenerated.java | 5 +++ 7 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt 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 030d9c8d145..4350ff8de9a 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 @@ -20457,6 +20457,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt"); } + @Test + @TestMetadata("insideInitBlock.kt") + public void testInsideInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt"); + } + @Test @TestMetadata("intReturnTypeAsNumber.kt") public void testIntReturnTypeAsNumber() 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 d84d96bc79d..af614b61cf0 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 @@ -132,6 +132,19 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) FunctionReferenceBuilder(expression).build() } + private fun getDeclarationParentForDelegatingLambda(): IrDeclarationParent { + for (s in allScopes.asReversed()) { + val scopeOwner = s.scope.scopeOwnerSymbol.owner + if (scopeOwner is IrDeclarationParent) { + return scopeOwner + } + } + throw AssertionError( + "No IrDeclarationParent found in scopes:\n" + + allScopes.joinToString(separator = "\n") { " " + it.scope.scopeOwnerSymbol.owner.render() } + ) + } + // Handle SAM conversions which wrap a function reference: // class sam$n(private val receiver: R) : Interface { override fun method(...) = receiver.target(...) } // @@ -153,7 +166,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext) invokable.statements.last() as IrFunctionReference } else if (shouldGenerateIndySamConversions && canGenerateIndySamConversionOnFunctionalExpression(samSuperType, invokable)) { val lambdaBlock = SamDelegatingLambdaBuilder(context) - .build(invokable, samSuperType, currentScope!!.scope.scopeOwnerSymbol) + .build(invokable, samSuperType, currentScope!!.scope.scopeOwnerSymbol, getDeclarationParentForDelegatingLambda()) val lambdaMetafactoryArguments = LambdaMetafactoryArgumentsBuilder(context, crossinlineLambdas) .getLambdaMetafactoryArgumentsOrNull(lambdaBlock.ref, samSuperType, false) ?: return super.visitTypeOperator(expression) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt index 0211b355e0a..b279f393a07 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/indy/SamDelegatingLambdaBlock.kt @@ -63,17 +63,18 @@ internal class NullableDelegatingLambdaBlock( internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendContext) { - fun build(expression: IrExpression, superType: IrType, scopeSymbol: IrSymbol): SamDelegatingLambdaBlock { + fun build(expression: IrExpression, superType: IrType, scopeSymbol: IrSymbol, parent: IrDeclarationParent): SamDelegatingLambdaBlock { return if (superType.isNullable() && expression.type.isNullable()) - buildNullableDelegatingLambda(expression, superType, scopeSymbol) + buildNullableDelegatingLambda(expression, superType, scopeSymbol, parent) else - buildRegularDelegatingLambda(expression, superType, scopeSymbol) + buildRegularDelegatingLambda(expression, superType, scopeSymbol, parent) } private fun buildRegularDelegatingLambda( expression: IrExpression, superType: IrType, - scopeSymbol: IrSymbol + scopeSymbol: IrSymbol, + parent: IrDeclarationParent ): SamDelegatingLambdaBlock { lateinit var ref: IrFunctionReference val block = jvmContext.createJvmIrBuilder(scopeSymbol, expression.startOffset, expression.endOffset).run { @@ -86,7 +87,7 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont irBlock(origin = IrStatementOrigin.LAMBDA) { val tmp = irTemporary(expression) - val lambda = createDelegatingLambda(scopeSymbol, expression, superType, tmp) + val lambda = createDelegatingLambda(expression, superType, tmp, parent) .also { +it } ref = createDelegatingLambdaReference(expression, lambda) .also { +it } @@ -99,7 +100,8 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont private fun buildNullableDelegatingLambda( expression: IrExpression, superType: IrType, - scopeSymbol: IrSymbol + scopeSymbol: IrSymbol, + parent: IrDeclarationParent ): SamDelegatingLambdaBlock { lateinit var ref: IrFunctionReference lateinit var ifExpr: IrExpression @@ -119,7 +121,7 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont irBlock(origin = IrStatementOrigin.LAMBDA) { val tmp = irTemporary(expression) ifNotNullBlock = irBlock { - val lambda = createDelegatingLambda(scopeSymbol, expression, superType, tmp) + val lambda = createDelegatingLambda(expression, superType, tmp, parent) .also { +it } ref = createDelegatingLambdaReference(expression, lambda) .also { +it } @@ -133,10 +135,10 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont } private fun createDelegatingLambda( - scopeSymbol: IrSymbol, expression: IrExpression, superType: IrType, - tmp: IrVariable + tmp: IrVariable, + parent: IrDeclarationParent ): IrSimpleFunction { val superMethod = superType.getSingleAbstractMethod() ?: throw AssertionError("SAM type expected: ${superType.render()}") @@ -176,7 +178,7 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont } ) } - lambda.parent = scopeSymbol.owner as IrDeclarationParent + lambda.parent = parent } } diff --git a/compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt b/compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt new file mode 100644 index 00000000000..fa727182a62 --- /dev/null +++ b/compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt @@ -0,0 +1,33 @@ +// TARGET_BACKEND: JVM +// JVM_TARGET: 1.8 +// SAM_CONVERSIONS: INDY + +// FILE: insideInitBlock.kt +class Outer { + class Nested { + class PredicateSource(val condition: Boolean) + + val value: String + + init { + value = Test.test(PredicateSource::condition, PredicateSource(true)) + } + } +} + +fun box() = Outer.Nested().value + +// FILE: Test.java +public class Test { + public static String test(Predicate predicate, T value) { + if (predicate.getResult(value) == true) + return "OK"; + else + return "Failed"; + } +} + +// FILE: Predicate.java +public interface Predicate { + Boolean getResult(T value); +} 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 f72628d0f52..4724cdf0f68 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 @@ -20439,6 +20439,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt"); } + @Test + @TestMetadata("insideInitBlock.kt") + public void testInsideInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt"); + } + @Test @TestMetadata("intReturnTypeAsNumber.kt") public void testIntReturnTypeAsNumber() 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 01d28c8be04..f1922857855 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 @@ -20457,6 +20457,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt"); } + @Test + @TestMetadata("insideInitBlock.kt") + public void testInsideInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt"); + } + @Test @TestMetadata("intReturnTypeAsNumber.kt") public void testIntReturnTypeAsNumber() 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 c68fc345caf..800e1ae0681 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -17084,6 +17084,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/invokedynamic/sam/genericFunInterfaceWithPrimitive.kt"); } + @TestMetadata("insideInitBlock.kt") + public void testInsideInitBlock() throws Exception { + runTest("compiler/testData/codegen/box/invokedynamic/sam/insideInitBlock.kt"); + } + @TestMetadata("intReturnTypeAsNumber.kt") public void testIntReturnTypeAsNumber() throws Exception { runTest("compiler/testData/codegen/box/invokedynamic/sam/intReturnTypeAsNumber.kt");