From 63d74d41af2ef67df054731454b30100c802defc Mon Sep 17 00:00:00 2001 From: svtk Date: Fri, 9 Dec 2011 17:37:38 +0400 Subject: [PATCH] KT-328 completion //Local function in function literals cause exceptions --- .../lang/cfg/JetFlowInformationProvider.java | 10 +++--- .../jet/lang/resolve/BodyResolver.java | 36 ++++++++++++------- .../jet/lang/resolve/ControlFlowAnalyzer.java | 8 ++--- .../lang/resolve/TopDownAnalysisContext.java | 8 ++++- .../jet/lang/resolve/TopDownAnalyzer.java | 13 ++++--- .../tests/RecursiveTypeInference.jet | 6 ++-- .../diagnostics/tests/regressions/Jet81.jet | 4 +-- .../diagnostics/tests/regressions/kt328.jet | 29 +++++++++++++-- .../tests/regressions/kt328Complex.jet | 3 -- .../regressions/kt328DuplicatedByKt329.jet | 6 ---- .../checker/RecursiveTypeInference.jet | 4 +-- idea/testData/checker/regression/Jet81.jet | 2 +- 12 files changed, 79 insertions(+), 50 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/regressions/kt328Complex.jet delete mode 100644 compiler/testData/diagnostics/tests/regressions/kt328DuplicatedByKt329.jet diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index d361c3297d0..4f3446cab05 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -364,12 +364,12 @@ public class JetFlowInformationProvider { JetNamedDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(element, JetNamedDeclaration.class); DeclarationDescriptor declarationDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, parentDeclaration); assert declarationDescriptor != null; - ClassDescriptor variableClass = DescriptorUtils.getParentOfType(variableDescriptor, ClassDescriptor.class); - if (variableClass == null || !DescriptorUtils.isAncestor(variableClass, declarationDescriptor, false)) { - trace.report(Errors.INACCESSIBLE_BACKING_FIELD.on(element)); - return true; + DeclarationDescriptor containingDeclaration = variableDescriptor.getContainingDeclaration(); + if ((containingDeclaration instanceof ClassDescriptor) && DescriptorUtils.isAncestor(containingDeclaration, declarationDescriptor, false)) { + return false; } - return false; + trace.report(Errors.INACCESSIBLE_BACKING_FIELD.on(element)); + return true; } private boolean isBackingFieldReference(@Nullable JetElement element, boolean[] error, boolean reportError) { 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 e4ee2e49354..a7559726cd6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -54,7 +54,9 @@ public class BodyResolver { resolveSecondaryConstructorBodies(); resolveFunctionBodies(); - computeDeferredTypes(); + if (!context.isDeclaredLocally()) { + computeDeferredTypes(); + } } private void resolveDelegationSpecifierLists() { @@ -364,6 +366,8 @@ public class BodyResolver { final PropertyDescriptor propertyDescriptor = this.context.getProperties().get(property); assert propertyDescriptor != null; + computeDeferredType(propertyDescriptor.getReturnType()); + JetExpression initializer = property.getInitializer(); if (initializer != null) { ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); @@ -385,6 +389,9 @@ public class BodyResolver { if (processed.contains(property)) continue; final PropertyDescriptor propertyDescriptor = entry.getValue(); + + computeDeferredType(propertyDescriptor.getReturnType()); + JetScope declaringScope = this.context.getDeclaringScopes().get(property); JetExpression initializer = property.getInitializer(); @@ -395,7 +402,7 @@ public class BodyResolver { resolvePropertyAccessors(property, propertyDescriptor); } } - + private JetScope makeScopeForPropertyAccessor(@NotNull JetPropertyAccessor accessor, PropertyDescriptor propertyDescriptor) { JetScope declaringScope = context.getDeclaringScopes().get(accessor); @@ -462,18 +469,8 @@ 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(); - } + computeDeferredType(descriptor.getReturnType()); JetScope declaringScope = this.context.getDeclaringScopes().get(declaration); assert declaringScope != null; @@ -520,6 +517,19 @@ public class BodyResolver { } } } + + private static void computeDeferredType(JetType type) { + // handle type inference loop: function or property body contains a reference to itself + // fun f() = { f() } + // val x = x + // type resolution must be started before body resolution + if (type instanceof DeferredType) { + DeferredType deferredType = (DeferredType) type; + if (!deferredType.isComputed()) { + deferredType.getActualType(); + } + } + } private void computeDeferredTypes() { Collection> deferredTypes = context.getTrace().getKeys(DEFERRED_TYPE); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java index 699122ea92a..d56355f1331 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ControlFlowAnalyzer.java @@ -19,12 +19,10 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; public class ControlFlowAnalyzer { private TopDownAnalysisContext context; private final JetControlFlowDataTraceFactory flowDataTraceFactory; - private final boolean processLocalDeclaration; - public ControlFlowAnalyzer(TopDownAnalysisContext context, JetControlFlowDataTraceFactory flowDataTraceFactory, boolean processLocalDeclaration) { + public ControlFlowAnalyzer(TopDownAnalysisContext context, JetControlFlowDataTraceFactory flowDataTraceFactory) { this.context = context; this.flowDataTraceFactory = flowDataTraceFactory; - this.processLocalDeclaration = processLocalDeclaration; } public void process() { @@ -58,7 +56,7 @@ public class ControlFlowAnalyzer { private void checkClassOrObject(JetClassOrObject klass) { JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, (JetExpression) klass, flowDataTraceFactory, context.getTrace()); - flowInformationProvider.markUninitializedVariables((JetElement) klass, processLocalDeclaration); + flowInformationProvider.markUninitializedVariables((JetElement) klass, context.isDeclaredLocally()); } private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { @@ -80,7 +78,7 @@ public class ControlFlowAnalyzer { flowInformationProvider.checkDefiniteReturn(function, expectedReturnType); - flowInformationProvider.markUninitializedVariables(function.asElement(), processLocalDeclaration); + flowInformationProvider.markUninitializedVariables(function.asElement(), context.isDeclaredLocally()); flowInformationProvider.markUnusedVariables(function.asElement()); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java index 6ca87908251..31120e2c081 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java @@ -42,13 +42,15 @@ import java.util.Set; private StringBuilder debugOutput; private boolean analyzingBootstrapLibrary = false; + private boolean declaredLocally; - public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate analyzeCompletely, @NotNull Configuration configuration) { + public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate analyzeCompletely, @NotNull Configuration configuration, boolean declaredLocally) { this.trace = new ObservableBindingTrace(trace); this.semanticServices = semanticServices; this.descriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.analyzeCompletely = analyzeCompletely; this.configuration = configuration; + this.declaredLocally = declaredLocally; } public void debug(Object message) { @@ -138,4 +140,8 @@ import java.util.Set; public Configuration getConfiguration() { return configuration; } + + public boolean isDeclaredLocally() { + return declaredLocally; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index d9a8fe008fa..7760ae9f44e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -47,8 +47,8 @@ public class TopDownAnalyzer { @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull Configuration configuration, boolean declaredLocally) { - TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, analyzeCompletely, configuration); - doProcess(context, outerScope, owner, declarations, flowDataTraceFactory, declaredLocally); + TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, analyzeCompletely, configuration, declaredLocally); + doProcess(context, outerScope, owner, declarations, flowDataTraceFactory); } @@ -56,8 +56,7 @@ public class TopDownAnalyzer { TopDownAnalysisContext context, JetScope outerScope, NamespaceLike owner, Collection declarations, - JetControlFlowDataTraceFactory flowDataTraceFactory, - boolean processLocalDeclaration) { + JetControlFlowDataTraceFactory flowDataTraceFactory) { // context.enableDebugOutput(); context.debug("Enter"); @@ -69,7 +68,7 @@ public class TopDownAnalyzer { new OverloadResolver(context).process(); if (!context.analyzingBootstrapLibrary()) { new BodyResolver(context).resolveBehaviorDeclarationBodies(); - new ControlFlowAnalyzer(context, flowDataTraceFactory, processLocalDeclaration).process(); + new ControlFlowAnalyzer(context, flowDataTraceFactory).process(); new DeclarationsChecker(context).process(); } @@ -93,13 +92,13 @@ public class TopDownAnalyzer { @NotNull JetSemanticServices semanticServices, @NotNull BindingTrace trace, @NotNull WritableScope outerScope, @NotNull NamespaceDescriptorImpl standardLibraryNamespace, @NotNull JetNamespace namespace) { - TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.alwaysTrue(), Configuration.EMPTY); + TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.alwaysTrue(), Configuration.EMPTY, false); context.getNamespaceScopes().put(namespace, standardLibraryNamespace.getMemberScope()); context.getNamespaceDescriptors().put(namespace, standardLibraryNamespace); context.getDeclaringScopes().put(namespace, outerScope); context.setAnalyzingBootstrapLibrary(true); - doProcess(context, outerScope, standardLibraryNamespace, namespace.getDeclarations(), JetControlFlowDataTraceFactory.EMPTY, false); + doProcess(context, outerScope, standardLibraryNamespace, namespace.getDeclarations(), JetControlFlowDataTraceFactory.EMPTY); } public static void processObject( diff --git a/compiler/testData/diagnostics/tests/RecursiveTypeInference.jet b/compiler/testData/diagnostics/tests/RecursiveTypeInference.jet index 0a6a5b1e2e7..46e2f2ae7c7 100644 --- a/compiler/testData/diagnostics/tests/RecursiveTypeInference.jet +++ b/compiler/testData/diagnostics/tests/RecursiveTypeInference.jet @@ -1,7 +1,7 @@ namespace a { - val foo = bar() + val foo = bar() - fun bar() = foo + fun bar() = foo } namespace b { @@ -39,4 +39,4 @@ namespace ok { fun bar() = foo() } -} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/regressions/Jet81.jet b/compiler/testData/diagnostics/tests/regressions/Jet81.jet index a3ff4596172..82b6986ed49 100644 --- a/compiler/testData/diagnostics/tests/regressions/Jet81.jet +++ b/compiler/testData/diagnostics/tests/regressions/Jet81.jet @@ -1,7 +1,7 @@ // JET-81 Assertion fails when processing self-referring anonymous objects val y = object { - val a = y; + val a = y; } val z = y.a; @@ -19,4 +19,4 @@ val a = object { } val b = a.x -val c = a.y +val c = a.y \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/regressions/kt328.jet b/compiler/testData/diagnostics/tests/regressions/kt328.jet index 2593c440b51..79ac13f9e0d 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt328.jet +++ b/compiler/testData/diagnostics/tests/regressions/kt328.jet @@ -1,3 +1,28 @@ -fun bar() = { - bar() +//KT-328 Local function in function literals cause exceptions + +fun bar1() = { + bar1() } + +fun bar2() = { + fun foo2() = bar2() +} + +//properties +//in a class +class A() { + val x = { x } +} + +//in a namespace +val x = { x } + +//KT-787 AssertionError on code 'val x = x' +val z = z + +//KT-329 Assertion failure on local function +fun block(f : fun() : Unit) = f() + +fun bar3() = block{ foo3() // <-- missing closing curly bracket +fun foo3() = block{ bar3() } + diff --git a/compiler/testData/diagnostics/tests/regressions/kt328Complex.jet b/compiler/testData/diagnostics/tests/regressions/kt328Complex.jet deleted file mode 100644 index 9caa6193206..00000000000 --- a/compiler/testData/diagnostics/tests/regressions/kt328Complex.jet +++ /dev/null @@ -1,3 +0,0 @@ -fun bar() = { - fun foo() = bar() -} diff --git a/compiler/testData/diagnostics/tests/regressions/kt328DuplicatedByKt329.jet b/compiler/testData/diagnostics/tests/regressions/kt328DuplicatedByKt329.jet deleted file mode 100644 index 5e562547174..00000000000 --- a/compiler/testData/diagnostics/tests/regressions/kt328DuplicatedByKt329.jet +++ /dev/null @@ -1,6 +0,0 @@ -// 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 c8e0006f350..d1e8b6f6c62 100644 --- a/idea/testData/checker/RecursiveTypeInference.jet +++ b/idea/testData/checker/RecursiveTypeInference.jet @@ -1,7 +1,7 @@ namespace a { - val foo = bar() + val foo = bar() - fun bar() = foo + fun bar() = foo } namespace b { diff --git a/idea/testData/checker/regression/Jet81.jet b/idea/testData/checker/regression/Jet81.jet index f6b382d86da..e5a58af2474 100644 --- a/idea/testData/checker/regression/Jet81.jet +++ b/idea/testData/checker/regression/Jet81.jet @@ -1,7 +1,7 @@ // JET-81 Assertion fails when processing self-referring anonymous objects val y = object { - val a = y; + val a = y } val z = y.a;