From c325dfffd91272ca44238e2ca2be4aa1c38f4460 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 30 Oct 2013 16:00:17 +0400 Subject: [PATCH] KT-3523: VerifyError for invoke function in inner class KT-4106: VerifyError: Can't access outer this in a lambda in inner class' constructor KT-3152: VerifyError when accessing from a function of object to a field of outer outer class #KT-3523 Fixed #KT-4106 Fixed #KT-3152 Fixed --- .../jet/codegen/ExpressionCodegen.java | 44 ++++++++++++------- .../testData/codegen/box/closures/kt3152.kt | 14 ++++++ .../testData/codegen/box/closures/kt3523.kt | 18 ++++++++ .../testData/codegen/box/closures/kt4106.kt | 15 +++++++ .../BlackBoxCodegenTestGenerated.java | 15 +++++++ 5 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 compiler/testData/codegen/box/closures/kt3152.kt create mode 100644 compiler/testData/codegen/box/closures/kt3523.kt create mode 100644 compiler/testData/codegen/box/closures/kt4106.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 25715cdb827..dffff7dcf64 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2218,9 +2218,10 @@ public class ExpressionCodegen extends JetVisitor implem private void generateScript(@NotNull ScriptReceiver receiver) { CodegenContext cur = context; StackValue result = StackValue.local(0, OBJECT_TYPE); + boolean inStartConstructorContext = cur instanceof ConstructorContext; while (cur != null) { - if (cur instanceof MethodContext && !(cur instanceof ConstructorContext)) { - cur = cur.getParentContext(); + if (!inStartConstructorContext) { + cur = getNotNullParentContextForMethod(cur); } if (cur instanceof ScriptContext) { @@ -2239,13 +2240,13 @@ public class ExpressionCodegen extends JetVisitor implem return; } - assert cur != null; result = cur.getOuterExpression(result, false); - if (cur instanceof ConstructorContext) { - cur = cur.getParentContext(); + if (inStartConstructorContext) { + cur = getNotNullParentContextForMethod(cur); + inStartConstructorContext = false; } - assert cur != null; + cur = cur.getParentContext(); } @@ -2268,6 +2269,7 @@ public class ExpressionCodegen extends JetVisitor implem CodegenContext cur = context; Type type = asmType(calleeContainingClass.getDefaultType()); StackValue result = StackValue.local(0, type); + boolean inStartConstructorContext = cur instanceof ConstructorContext; while (cur != null) { ClassDescriptor thisDescriptor = cur.getThisDescriptor(); if (!isSuper && thisDescriptor.equals(calleeContainingClass) @@ -2275,25 +2277,33 @@ public class ExpressionCodegen extends JetVisitor implem return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); } - if (cur instanceof MethodContext && !(cur instanceof ConstructorContext)) { - cur = cur.getParentContext(); + //for constructor super call we should access to outer instance through parameter in locals, in other cases through field for captured outer + if (inStartConstructorContext) { + result = cur.getOuterExpression(result, false); + cur = getNotNullParentContextForMethod(cur); + inStartConstructorContext = false; + } + else { + cur = getNotNullParentContextForMethod(cur); + result = cur.getOuterExpression(result, false); } - assert cur != null; - - - result = cur.getOuterExpression(result, false); - - if (cur instanceof ConstructorContext) { - cur = cur.getParentContext(); - } - assert cur != null; cur = cur.getParentContext(); } throw new UnsupportedOperationException(); } + @NotNull + private CodegenContext getNotNullParentContextForMethod(@NotNull CodegenContext cur) { + if (cur instanceof MethodContext) { + cur = cur.getParentContext(); + } + assert cur != null; + return cur; + } + + private static boolean isReceiver(PsiElement expression) { PsiElement parent = expression.getParent(); if (parent instanceof JetQualifiedExpression) { diff --git a/compiler/testData/codegen/box/closures/kt3152.kt b/compiler/testData/codegen/box/closures/kt3152.kt new file mode 100644 index 00000000000..59bf3eaaeeb --- /dev/null +++ b/compiler/testData/codegen/box/closures/kt3152.kt @@ -0,0 +1,14 @@ +public class Test { + val content = 1 + inner class A { + val v = object { + fun f() = content + } + } +} + +fun box(): String { + Test().A() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/closures/kt3523.kt b/compiler/testData/codegen/box/closures/kt3523.kt new file mode 100644 index 00000000000..bbc225f8fd8 --- /dev/null +++ b/compiler/testData/codegen/box/closures/kt3523.kt @@ -0,0 +1,18 @@ +open class Base { + fun doSomething() { + + } +} + +class X(val action: () -> Unit) { } + +class Foo : Base() { + inner class Bar() { + val x = X({ doSomething() }) + } +} + +fun box() : String { + Foo().Bar() + return "OK" +} diff --git a/compiler/testData/codegen/box/closures/kt4106.kt b/compiler/testData/codegen/box/closures/kt4106.kt new file mode 100644 index 00000000000..2a05e203aee --- /dev/null +++ b/compiler/testData/codegen/box/closures/kt4106.kt @@ -0,0 +1,15 @@ +class Foo(private val s: String) { + private inner class Inner { + private val x = { + this@Foo.s + }() + } + + val f = Inner() + +} + +fun box(): String { + Foo("!") + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index a2e37e0f4ad..18b5fcb2acb 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -1257,11 +1257,26 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/closures/kt2151.kt"); } + @TestMetadata("kt3152.kt") + public void testKt3152() throws Exception { + doTest("compiler/testData/codegen/box/closures/kt3152.kt"); + } + + @TestMetadata("kt3523.kt") + public void testKt3523() throws Exception { + doTest("compiler/testData/codegen/box/closures/kt3523.kt"); + } + @TestMetadata("kt3905.kt") public void testKt3905() throws Exception { doTest("compiler/testData/codegen/box/closures/kt3905.kt"); } + @TestMetadata("kt4106.kt") + public void testKt4106() throws Exception { + doTest("compiler/testData/codegen/box/closures/kt4106.kt"); + } + @TestMetadata("kt4137.kt") public void testKt4137() throws Exception { doTest("compiler/testData/codegen/box/closures/kt4137.kt");