From e33af7f7295aadab2e9cdc2941bbb57d6113bfdd Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 23 Nov 2011 16:40:50 +0400 Subject: [PATCH] KT-328 Local function in function literals cause exceptions === fun bar() = { bar() } === --- .../jet/lang/resolve/BodyResolver.java | 17 +++++++++++++++-- .../jet/resolve/DescriptorRenderer.java | 1 + .../full/RecursiveTypeInference.jet | 10 +++++----- .../quick/regressions/kt328.jet | 3 +++ .../quick/regressions/kt328Complex.jet | 3 +++ .../regressions/kt328DuplicatedByKt329.jet | 7 +++++++ .../testData/checker/RecursiveTypeInference.jet | 12 ++++++------ 7 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/checkerWithErrorTypes/quick/regressions/kt328.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/regressions/kt328Complex.jet create mode 100644 compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index ef5e309947f..7637f611a8e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -82,7 +82,7 @@ public class BodyResolver { resolveSecondaryConstructorBodies(); resolveFunctionBodies(); - computeDeferredTypes(); + computeDeferredTypes(); } private void resolveDelegationSpecifierLists() { @@ -501,6 +501,18 @@ public class BodyResolver { for (Map.Entry entry : this.context.getFunctions().entrySet()) { JetNamedFunction declaration = entry.getKey(); FunctionDescriptor descriptor = entry.getValue(); + + if (descriptor.getReturnType() instanceof DeferredType) { + // handle type inference loop: function body contains a closure that calls that function + // + // fun f() = { f() } + // + // function type resolution must be started before function body resolution + // + + DeferredType returnType = (DeferredType) descriptor.getReturnType(); + returnType.getActualType(); + } JetScope declaringScope = this.context.getDeclaringScopes().get(declaration); assert declaringScope != null; @@ -545,7 +557,8 @@ public class BodyResolver { private void computeDeferredTypes() { Collection> deferredTypes = context.getTrace().getKeys(DEFERRED_TYPE); if (deferredTypes != null) { - final Queue queue = new Queue(deferredTypes.size()); + // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21 + final Queue queue = new Queue(deferredTypes.size() + 1); context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler, Boolean>() { @Override public void handleRecord(WritableSlice, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box key, Boolean value) { diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index b744988a594..a378e31d39b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -222,6 +222,7 @@ public class DescriptorRenderer implements Renderer { renderName(descriptor, builder); renderValueParameters(descriptor, builder); + // TODO: getReturnType may be uninitialized and throw IllegalStateException // stepan.koltsov@ 2011-11-21 builder.append(" : ").append(escape(renderType(descriptor.getReturnType()))); return super.visitFunctionDescriptor(descriptor, builder); } diff --git a/compiler/testData/checkerWithErrorTypes/full/RecursiveTypeInference.jet b/compiler/testData/checkerWithErrorTypes/full/RecursiveTypeInference.jet index 11eb880a193..0a6a5b1e2e7 100644 --- a/compiler/testData/checkerWithErrorTypes/full/RecursiveTypeInference.jet +++ b/compiler/testData/checkerWithErrorTypes/full/RecursiveTypeInference.jet @@ -5,15 +5,15 @@ namespace a { } namespace b { - fun foo() = bar() + fun foo() = bar() - fun bar() = foo() + fun bar() = foo() } namespace c { - fun bazz() = bar() + fun bazz() = bar() - fun foo() = bazz() + fun foo() = bazz() fun bar() = foo() } @@ -39,4 +39,4 @@ namespace ok { fun bar() = foo() } -} \ No newline at end of file +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328.jet new file mode 100644 index 00000000000..2593c440b51 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328.jet @@ -0,0 +1,3 @@ +fun bar() = { + bar() +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328Complex.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328Complex.jet new file mode 100644 index 00000000000..9caa6193206 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328Complex.jet @@ -0,0 +1,3 @@ +fun bar() = { + fun foo() = bar() +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet new file mode 100644 index 00000000000..35a66da2884 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet @@ -0,0 +1,7 @@ +// http://youtrack.jetbrains.net/issue/KT-329 + +fun block(f : fun() : Unit) = f() + +fun bar() = block{ foo() // <-- missing closing curly bracket +fun foo() = block{ bar() } + diff --git a/idea/testData/checker/RecursiveTypeInference.jet b/idea/testData/checker/RecursiveTypeInference.jet index a73cf01cc0e..c8e0006f350 100644 --- a/idea/testData/checker/RecursiveTypeInference.jet +++ b/idea/testData/checker/RecursiveTypeInference.jet @@ -1,19 +1,19 @@ namespace a { - val foo = bar() + val foo = bar() fun bar() = foo } namespace b { - fun foo() = bar() + fun foo() = bar() - fun bar() = foo() + fun bar() = foo() } namespace c { - fun bazz() = bar() + fun bazz() = bar() - fun foo() = bazz() + fun foo() = bazz() fun bar() = foo() } @@ -39,4 +39,4 @@ namespace ok { fun bar() = foo() } -} \ No newline at end of file +}