KT-328 completion //Local function in function literals cause exceptions
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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<JetNamedFunction, FunctionDescriptorImpl> 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<Box<DeferredType>> deferredTypes = context.getTrace().getKeys(DEFERRED_TYPE);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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<PsiFile> analyzeCompletely, @NotNull Configuration configuration) {
|
||||
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace, Predicate<PsiFile> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<? extends JetDeclaration> 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.<PsiFile>alwaysTrue(), Configuration.EMPTY);
|
||||
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace, Predicates.<PsiFile>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(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace a {
|
||||
val foo = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>
|
||||
val foo = bar()
|
||||
|
||||
fun bar() = foo
|
||||
fun bar() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>foo<!>
|
||||
}
|
||||
|
||||
namespace b {
|
||||
@@ -39,4 +39,4 @@ namespace ok {
|
||||
|
||||
fun bar() = foo()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// JET-81 Assertion fails when processing self-referring anonymous objects
|
||||
|
||||
val y = object {
|
||||
val a = y;
|
||||
val a = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>y<!>;
|
||||
}
|
||||
|
||||
val z = y.a;
|
||||
@@ -19,4 +19,4 @@ val a = object {
|
||||
}
|
||||
|
||||
val b = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>a<!>.x
|
||||
val c = a.y
|
||||
val c = a.y
|
||||
@@ -1,3 +1,28 @@
|
||||
fun bar() = {
|
||||
<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>
|
||||
//KT-328 Local function in function literals cause exceptions
|
||||
|
||||
fun bar1() = {
|
||||
<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar1()<!>
|
||||
}
|
||||
|
||||
fun bar2() = {
|
||||
fun foo2() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar2()<!>
|
||||
}
|
||||
|
||||
//properties
|
||||
//in a class
|
||||
class A() {
|
||||
val x = { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>x<!> }
|
||||
}
|
||||
|
||||
//in a namespace
|
||||
val x = { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>x<!> }
|
||||
|
||||
//KT-787 AssertionError on code 'val x = x'
|
||||
val z = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>z<!>
|
||||
|
||||
//KT-329 Assertion failure on local function
|
||||
fun block(f : fun() : Unit) = f()
|
||||
|
||||
fun bar3() = block{ <!UNRESOLVED_REFERENCE!>foo3<!>() // <-- missing closing curly bracket
|
||||
fun foo3() = block{ <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar3()<!> }<!SYNTAX!><!>
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
fun bar() = {
|
||||
fun foo() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
// 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()<!> }<!SYNTAX!><!>
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace a {
|
||||
val foo = <error descr="[TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM] Type checking has run into a recursive problem">bar()</error>
|
||||
val 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 b {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// JET-81 Assertion fails when processing self-referring anonymous objects
|
||||
|
||||
val y = object {
|
||||
val a = y;
|
||||
val a = <error>y</error>
|
||||
}
|
||||
|
||||
val z = y.a;
|
||||
|
||||
Reference in New Issue
Block a user