From fa9ca54e7830af5680ea32a6a3bf32f07d5c8a69 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Fri, 6 Feb 2015 08:10:13 +0300 Subject: [PATCH] Fixed local return inside function expression. --- .../kotlin/codegen/ExpressionCodegen.java | 2 +- .../codegen/binding/CodegenBinding.java | 5 +++ .../functionExpressionWithThisReference.kt | 34 +++++++++++++++++++ .../localReturnInsideFunctionExpression.kt | 17 ++++++++++ .../BlackBoxCodegenTestGenerated.java | 12 +++++++ 5 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/functions/functionExpressionWithThisReference.kt create mode 100644 compiler/testData/codegen/box/functions/localReturnInsideFunctionExpression.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 72daa45a10a..e1c6abd5f76 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1820,7 +1820,7 @@ public class ExpressionCodegen extends JetVisitor implem @Nullable private NonLocalReturnInfo getNonLocalReturnInfo(@NotNull CallableMemberDescriptor descriptor, @NotNull JetReturnExpression expression) { //call inside lambda - if (isLocalFunOrLambda(descriptor) && descriptor.getName().isSpecial()) { + if (isLambda(descriptor)) { if (expression.getLabelName() == null) { //non labeled return couldn't be local in lambda FunctionDescriptor containingFunction = diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java index 598afcaf7c9..8d62df29fa7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.codegen.SamType; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; @@ -264,6 +265,10 @@ public class CodegenBinding { return false; } + public static boolean isLambda(@Nullable DeclarationDescriptor fd) { + return fd instanceof AnonymousFunctionDescriptor; + } + @NotNull public static Type getAsmType(@NotNull BindingContext bindingContext, @NotNull ClassDescriptor klass) { Type type = bindingContext.get(ASM_TYPE, klass); diff --git a/compiler/testData/codegen/box/functions/functionExpressionWithThisReference.kt b/compiler/testData/codegen/box/functions/functionExpressionWithThisReference.kt new file mode 100644 index 00000000000..a9e1d43173e --- /dev/null +++ b/compiler/testData/codegen/box/functions/functionExpressionWithThisReference.kt @@ -0,0 +1,34 @@ + +fun Int.thisRef1() = fun () = this +fun Int.thisRef2() = fun (): Int {return this} + +fun T.genericThisRef1() = fun () = this +fun T.genericThisRef2() = fun (): T {return this} + +val Int.valThisRef1: () -> Int get() = fun () = this +val Int.valThisRef2: () -> Int get() = fun (): Int {return this} + +val T.valGenericThisRef1: ()->T get() = fun () = this +val T.valGenericThisRef2: ()->T get() = fun (): T {return this} + +val T.withLabel1: ()->T get() = fun () = this@withLabel1 +val T.withLabel2: ()->T get() = fun (): T {return this@withLabel2} + +fun box(): String { + if (1.thisRef1()() != 1) return "Test 1 failed" + if (2.thisRef2()() != 2) return "Test 2 failed" + + if (3.genericThisRef1()() != 3) return "Test 3 failed" + if (4.genericThisRef2()() != 4) return "Test 4 failed" + + if (5.valThisRef1() != 5) return "Test 5 failed" + if (6.valThisRef2() != 6) return "Test 6 failed" + + if (7.valGenericThisRef1() != 7) return "Test 7 failed" + if (8.valGenericThisRef2() != 8) return "Test 8 failed" + + if ("bar".withLabel1() != "bar") return "Test 9 failed" + if ("bar".withLabel2() != "bar") return "Test 10 failed" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/localReturnInsideFunctionExpression.kt b/compiler/testData/codegen/box/functions/localReturnInsideFunctionExpression.kt new file mode 100644 index 00000000000..4fc99057d94 --- /dev/null +++ b/compiler/testData/codegen/box/functions/localReturnInsideFunctionExpression.kt @@ -0,0 +1,17 @@ +fun simple() = fun (): Boolean { return true } + +fun simpleNamed() = fun name(): Boolean { return true } +fun simpleNamed2() = fun name(): Boolean { return@name true } + +fun withLabel() = @l fun (): Boolean { return@l true } +fun withLabelNamed() = @l fun name(): Boolean { return@l true } + +fun box(): String { + if (!simple()()) return "Test simple failed" + if (!simpleNamed()()) return "Test simpleNamed failed" + if (!simpleNamed2()()) return "Test simpleNamed2 failed" + if (!withLabel()()) return "Test withLabel failed" + if (!withLabelNamed()()) return "Test withLabelNamed failed" + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java index 546d1f80422..cff58a07348 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -3704,6 +3704,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("functionExpressionWithThisReference.kt") + public void testFunctionExpressionWithThisReference() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionExpressionWithThisReference.kt"); + doTest(fileName); + } + @TestMetadata("functionLiteralExpression.kt") public void testFunctionLiteralExpression() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/functionLiteralExpression.kt"); @@ -3848,6 +3854,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("localReturnInsideFunctionExpression.kt") + public void testLocalReturnInsideFunctionExpression() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/localReturnInsideFunctionExpression.kt"); + doTest(fileName); + } + @TestMetadata("nothisnoclosure.kt") public void testNothisnoclosure() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/functions/nothisnoclosure.kt");