KT-328 Local function in function literals cause exceptions

===
fun bar() = {
  bar()
}
===
This commit is contained in:
Stepan Koltsov
2011-11-23 16:40:50 +04:00
parent ba700ebdbe
commit e33af7f729
7 changed files with 40 additions and 13 deletions
@@ -82,7 +82,7 @@ public class BodyResolver {
resolveSecondaryConstructorBodies(); resolveSecondaryConstructorBodies();
resolveFunctionBodies(); resolveFunctionBodies();
computeDeferredTypes(); computeDeferredTypes();
} }
private void resolveDelegationSpecifierLists() { private void resolveDelegationSpecifierLists() {
@@ -501,6 +501,18 @@ public class BodyResolver {
for (Map.Entry<JetNamedFunction, FunctionDescriptorImpl> entry : this.context.getFunctions().entrySet()) { for (Map.Entry<JetNamedFunction, FunctionDescriptorImpl> entry : this.context.getFunctions().entrySet()) {
JetNamedFunction declaration = entry.getKey(); JetNamedFunction declaration = entry.getKey();
FunctionDescriptor descriptor = entry.getValue(); 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); JetScope declaringScope = this.context.getDeclaringScopes().get(declaration);
assert declaringScope != null; assert declaringScope != null;
@@ -545,7 +557,8 @@ public class BodyResolver {
private void computeDeferredTypes() { private void computeDeferredTypes() {
Collection<Box<DeferredType>> deferredTypes = context.getTrace().getKeys(DEFERRED_TYPE); Collection<Box<DeferredType>> deferredTypes = context.getTrace().getKeys(DEFERRED_TYPE);
if (deferredTypes != null) { if (deferredTypes != null) {
final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size()); // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21
final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1);
context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() { context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() {
@Override @Override
public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) { public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) {
@@ -222,6 +222,7 @@ public class DescriptorRenderer implements Renderer {
renderName(descriptor, builder); renderName(descriptor, builder);
renderValueParameters(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()))); builder.append(" : ").append(escape(renderType(descriptor.getReturnType())));
return super.visitFunctionDescriptor(descriptor, builder); return super.visitFunctionDescriptor(descriptor, builder);
} }
@@ -5,15 +5,15 @@ namespace a {
} }
namespace b { namespace b {
fun foo() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> fun foo() = bar()
fun bar() = foo() fun bar() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>foo()<!>
} }
namespace c { namespace c {
fun bazz() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> fun bazz() = bar()
fun foo() = bazz() fun foo() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bazz()<!>
fun bar() = foo() fun bar() = foo()
} }
@@ -39,4 +39,4 @@ namespace ok {
fun bar() = foo() fun bar() = foo()
} }
} }
@@ -0,0 +1,3 @@
fun bar() = {
<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>
}
@@ -0,0 +1,3 @@
fun bar() = {
fun foo() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>
}
@@ -0,0 +1,7 @@
// http://youtrack.jetbrains.net/issue/KT-329
fun block(f : fun() : Unit) = f()
fun bar() = block{ <!UNRESOLVED_REFERENCE!>foo<!>() // <-- missing closing curly bracket
fun foo() = block{ <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> }
@@ -1,19 +1,19 @@
namespace a { namespace a {
val foo = <error>bar()</error> val foo = <error descr="[TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM] Type checking has run into a recursive problem">bar()</error>
fun bar() = foo fun bar() = foo
} }
namespace b { namespace b {
fun foo() = <error>bar()</error> fun foo() = bar()
fun bar() = foo() fun bar() = <error descr="[TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM] Type checking has run into a recursive problem">foo()</error>
} }
namespace c { namespace c {
fun bazz() = <error>bar()</error> fun bazz() = bar()
fun foo() = bazz() fun foo() = <error descr="[TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM] Type checking has run into a recursive problem">bazz()</error>
fun bar() = foo() fun bar() = foo()
} }
@@ -39,4 +39,4 @@ namespace ok {
fun bar() = foo() fun bar() = foo()
} }
} }