From e087b080e9b58659c61dd9040824b8e076ce1517 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 13 May 2011 21:14:57 +0400 Subject: [PATCH] A bug with local variable initializers fixed --- .../jet/lang/resolve/BindingTraceContext.java | 1 - .../lang/resolve/ClassDescriptorResolver.java | 64 ++++++++++--------- .../jet/lang/types/JetTypeInferrer.java | 2 +- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index 023e8c6715e..23f9555e2c6 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -72,7 +72,6 @@ public class BindingTraceContext implements BindingContext, BindingTrace { @Override public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { expressionTypes.put(expression, type); - markAsProcessed(expression); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 0168b7319a9..0f1a43d684b 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -401,7 +401,7 @@ public class ClassDescriptorResolver { @NotNull public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, WritableScope scope, JetProperty property) { - JetType type = getType(scope, property); + JetType type = getType(scope, property, false); // For a local variable the type must not be deferred VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor( containingDeclaration, @@ -415,7 +415,7 @@ public class ClassDescriptorResolver { @NotNull public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) { - JetType type = getType(scope, property); + JetType type = getType(scope, property, true); boolean isVar = property.isVar(); JetModifierList modifierList = property.getModifierList(); @@ -436,6 +436,39 @@ public class ClassDescriptorResolver { return propertyDescriptor; } + @NotNull + private JetType getType(@NotNull final JetScope scope, @NotNull JetProperty property, boolean allowDeferred) { + // TODO : receiver? + JetTypeReference propertyTypeRef = property.getPropertyTypeRef(); + + JetType type; + if (propertyTypeRef == null) { + final JetExpression initializer = property.getInitializer(); + if (initializer == null) { + trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized"); + type = ErrorUtils.createErrorType("No type, no body"); + } else { + // TODO : ??? Fix-point here: what if we have something like "val a = foo {a.bar()}" + // TODO : a risk of a memory leak + LazyValue lazyValue = new LazyValue() { + @Override + protected JetType compute() { + return semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).safeGetType(scope, initializer, false); + } + }; + if (allowDeferred) { + type = new DeferredType(lazyValue); + } + else { + type = lazyValue.get(); + } + } + } else { + type = typeResolver.resolveType(scope, propertyTypeRef); + } + return type; + } + @NotNull private MemberModifiers resolveModifiers(@Nullable JetModifierList modifierList, @NotNull MemberModifiers defaultModifiers) { if (modifierList == null) return defaultModifiers; @@ -515,33 +548,6 @@ public class ClassDescriptorResolver { return getterDescriptor; } - @NotNull - private JetType getType(@NotNull final JetScope scope, @NotNull JetProperty property) { - // TODO : receiver? - JetTypeReference propertyTypeRef = property.getPropertyTypeRef(); - - JetType type; - if (propertyTypeRef == null) { - final JetExpression initializer = property.getInitializer(); - if (initializer == null) { - trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized"); - type = ErrorUtils.createErrorType("No type, no body"); - } else { - // TODO : ??? Fix-point here: what if we have something like "val a = foo {a.bar()}" - // TODO : a risk of a memory leak - type = new DeferredType(new LazyValue() { - @Override - protected JetType compute() { - return semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).safeGetType(scope, initializer, false); - } - }); - } - } else { - type = typeResolver.resolveType(scope, propertyTypeRef); - } - return type; - } - @NotNull public ConstructorDescriptor resolveSecondaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetConstructor constructor) { return createConstructorDescriptor(scope, classDescriptor, false, constructor.getModifierList(), constructor, constructor.getParameters()); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 1abed789a2c..8f3938bdb7c 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -599,7 +599,6 @@ public class JetTypeInferrer { } try { expression.accept(this); - trace.markAsProcessed(expression); if (result instanceof DeferredType) { result = ((DeferredType) result).getActualType(); } @@ -615,6 +614,7 @@ public class JetTypeInferrer { result = null; } + trace.markAsProcessed(expression); return result; }