A bug with local variable initializers fixed

This commit is contained in:
Andrey Breslav
2011-05-13 21:14:57 +04:00
parent b75354f4b9
commit e087b080e9
3 changed files with 36 additions and 31 deletions
@@ -72,7 +72,6 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
@Override @Override
public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
expressionTypes.put(expression, type); expressionTypes.put(expression, type);
markAsProcessed(expression);
} }
@Override @Override
@@ -401,7 +401,7 @@ public class ClassDescriptorResolver {
@NotNull @NotNull
public VariableDescriptor resolveLocalVariableDescriptor(DeclarationDescriptor containingDeclaration, WritableScope scope, JetProperty property) { 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( VariableDescriptorImpl variableDescriptor = new LocalVariableDescriptor(
containingDeclaration, containingDeclaration,
@@ -415,7 +415,7 @@ public class ClassDescriptorResolver {
@NotNull @NotNull
public PropertyDescriptor resolvePropertyDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope scope, JetProperty property) { 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(); boolean isVar = property.isVar();
JetModifierList modifierList = property.getModifierList(); JetModifierList modifierList = property.getModifierList();
@@ -436,6 +436,39 @@ public class ClassDescriptorResolver {
return propertyDescriptor; 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<JetType> lazyValue = new LazyValue<JetType>() {
@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 @NotNull
private MemberModifiers resolveModifiers(@Nullable JetModifierList modifierList, @NotNull MemberModifiers defaultModifiers) { private MemberModifiers resolveModifiers(@Nullable JetModifierList modifierList, @NotNull MemberModifiers defaultModifiers) {
if (modifierList == null) return defaultModifiers; if (modifierList == null) return defaultModifiers;
@@ -515,33 +548,6 @@ public class ClassDescriptorResolver {
return getterDescriptor; 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<JetType>() {
@Override
protected JetType compute() {
return semanticServices.getTypeInferrer(trace, JetFlowInformationProvider.THROW_EXCEPTION).safeGetType(scope, initializer, false);
}
});
}
} else {
type = typeResolver.resolveType(scope, propertyTypeRef);
}
return type;
}
@NotNull @NotNull
public ConstructorDescriptor resolveSecondaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetConstructor constructor) { public ConstructorDescriptor resolveSecondaryConstructorDescriptor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetConstructor constructor) {
return createConstructorDescriptor(scope, classDescriptor, false, constructor.getModifierList(), constructor, constructor.getParameters()); return createConstructorDescriptor(scope, classDescriptor, false, constructor.getModifierList(), constructor, constructor.getParameters());
@@ -599,7 +599,6 @@ public class JetTypeInferrer {
} }
try { try {
expression.accept(this); expression.accept(this);
trace.markAsProcessed(expression);
if (result instanceof DeferredType) { if (result instanceof DeferredType) {
result = ((DeferredType) result).getActualType(); result = ((DeferredType) result).getActualType();
} }
@@ -615,6 +614,7 @@ public class JetTypeInferrer {
result = null; result = null;
} }
trace.markAsProcessed(expression);
return result; return result;
} }