Problem caused by the asymmetry of equals() for deferred types solved (ad hoc)

This commit is contained in:
Andrey Breslav
2011-05-13 19:48:56 +04:00
parent 5aad7021af
commit b67359a861
10 changed files with 110 additions and 35 deletions
@@ -64,30 +64,51 @@ public interface BindingTrace {
public ErrorHandler getErrorHandler() { public ErrorHandler getErrorHandler() {
return ErrorHandler.DO_NOTHING; return ErrorHandler.DO_NOTHING;
} }
@Override
public boolean isProcessed(@NotNull JetExpression expression) {
return false;
}
@Override
public void markAsProcessed(@NotNull JetExpression expression) {
}
@Override
public BindingContext getBindingContext() {
throw new UnsupportedOperationException();
}
}; };
public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type); void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type);
public void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor); void recordReferenceResolution(@NotNull JetReferenceExpression expression, @NotNull DeclarationDescriptor descriptor);
public void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element); void recordLabelResolution(@NotNull JetReferenceExpression expression, @NotNull PsiElement element);
public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor); void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor);
public void recordValueParameterAsPropertyResolution(@NotNull JetParameter declaration, @NotNull PropertyDescriptor descriptor); void recordValueParameterAsPropertyResolution(@NotNull JetParameter declaration, @NotNull PropertyDescriptor descriptor);
public void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type); void recordTypeResolution(@NotNull JetTypeReference typeReference, @NotNull JetType type);
public void recordBlock(JetFunctionLiteralExpression expression); void recordBlock(JetFunctionLiteralExpression expression);
public void recordStatement(@NotNull JetElement statement); void recordStatement(@NotNull JetElement statement);
public void removeStatementRecord(@NotNull JetElement statement); void removeStatementRecord(@NotNull JetElement statement);
public void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression); void removeReferenceResolution(@NotNull JetReferenceExpression referenceExpression);
public void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor); void requireBackingField(@NotNull PropertyDescriptor propertyDescriptor);
@NotNull @NotNull
public ErrorHandler getErrorHandler(); ErrorHandler getErrorHandler();
boolean isProcessed(@NotNull JetExpression expression);
void markAsProcessed(@NotNull JetExpression expression);
BindingContext getBindingContext();
} }
@@ -71,4 +71,19 @@ public class BindingTraceAdapter implements BindingTrace {
public void removeStatementRecord(@NotNull JetElement statement) { public void removeStatementRecord(@NotNull JetElement statement) {
originalTrace.removeStatementRecord(statement); originalTrace.removeStatementRecord(statement);
} }
@Override
public void markAsProcessed(@NotNull JetExpression expression) {
originalTrace.markAsProcessed(expression);
}
@Override
public boolean isProcessed(@NotNull JetExpression expression) {
return originalTrace.isProcessed(expression);
}
@Override
public BindingContext getBindingContext() {
return originalTrace.getBindingContext();
}
} }
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -31,6 +32,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
private final Set<JetFunctionLiteralExpression> blocks = new HashSet<JetFunctionLiteralExpression>(); private final Set<JetFunctionLiteralExpression> blocks = new HashSet<JetFunctionLiteralExpression>();
private final Set<JetElement> statements = new HashSet<JetElement>(); private final Set<JetElement> statements = new HashSet<JetElement>();
private final Set<PropertyDescriptor> backingFieldRequired = new HashSet<PropertyDescriptor>(); private final Set<PropertyDescriptor> backingFieldRequired = new HashSet<PropertyDescriptor>();
private final Set<JetExpression> processed = Sets.newHashSet();
private Collection<JetDiagnostic> diagnostics = Lists.newArrayList(); private Collection<JetDiagnostic> diagnostics = Lists.newArrayList();
private ErrorHandler errorHandler = new ErrorHandler() { private ErrorHandler errorHandler = new ErrorHandler() {
@@ -70,6 +72,7 @@ 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
@@ -279,4 +282,19 @@ public class BindingTraceContext implements BindingContext, BindingTrace {
public Collection<JetDiagnostic> getDiagnostics() { public Collection<JetDiagnostic> getDiagnostics() {
return diagnostics; return diagnostics;
} }
@Override
public void markAsProcessed(@NotNull JetExpression expression) {
processed.add(expression);
}
@Override
public boolean isProcessed(@NotNull JetExpression expression) {
return processed.contains(expression);
}
@Override
public BindingContext getBindingContext() {
return this;
}
} }
@@ -259,7 +259,7 @@ public class ClassDescriptorResolver {
returnType = new DeferredType(new LazyValue<JetType>() { returnType = new DeferredType(new LazyValue<JetType>() {
@Override @Override
protected JetType compute() { protected JetType compute() {
JetFlowInformationProvider flowInformationProvider = computeFlowData(function.asElement(), bodyExpression); JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
return semanticServices.getTypeInferrer(trace, flowInformationProvider).getFunctionReturnType(scope, function, functionDescriptor); return semanticServices.getTypeInferrer(trace, flowInformationProvider).getFunctionReturnType(scope, function, functionDescriptor);
} }
}); });
@@ -863,6 +863,7 @@ public class TopDownAnalyzer {
@NotNull MutableFunctionDescriptor functionDescriptor, @NotNull MutableFunctionDescriptor functionDescriptor,
@NotNull JetScope declaringScope) { @NotNull JetScope declaringScope) {
JetExpression bodyExpression = function.getBodyExpression(); JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) { if (bodyExpression != null) {
JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(function.asElement(), bodyExpression); JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(function.asElement(), bodyExpression);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, flowInformationProvider); JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, flowInformationProvider);
@@ -57,4 +57,14 @@ public class DeferredType implements JetType {
return "<Failed to compute this type>"; return "<Failed to compute this type>";
} }
} }
@Override
public boolean equals(Object obj) {
return getActualType().equals(obj);
}
@Override
public int hashCode() {
return getActualType().hashCode();
}
} }
@@ -161,7 +161,8 @@ public class ErrorUtils {
} }
public static boolean isErrorType(JetType type) { public static boolean isErrorType(JetType type) {
return type instanceof ErrorTypeImpl || return (type instanceof DeferredType && ((DeferredType) type).getActualType() == null) ||
type instanceof ErrorTypeImpl ||
isError(type.getConstructor()); isError(type.getConstructor());
} }
@@ -16,4 +16,7 @@ public interface JetType extends Annotated {
@NotNull @NotNull
JetScope getMemberScope(); JetScope getMemberScope();
@Override
public boolean equals(Object other);
} }
@@ -63,7 +63,7 @@ public class JetTypeInferrer {
assignmentOperationCounterparts.put(JetTokens.MINUSEQ, JetTokens.MINUS); assignmentOperationCounterparts.put(JetTokens.MINUSEQ, JetTokens.MINUS);
} }
private final Map<JetExpression, JetType> typeCache = new HashMap<JetExpression, JetType>(); // private final Map<JetExpression, JetType> typeCache = new HashMap<JetExpression, JetType>();
private final BindingTrace trace; private final BindingTrace trace;
private final JetSemanticServices semanticServices; private final JetSemanticServices semanticServices;
@@ -72,7 +72,7 @@ public class JetTypeInferrer {
private final JetFlowInformationProvider flowInformationProvider; private final JetFlowInformationProvider flowInformationProvider;
public JetTypeInferrer(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) { public JetTypeInferrer(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) {
this.trace = new CachedBindingTrace(trace); this.trace = trace; //new CachedBindingTrace(trace);
this.semanticServices = semanticServices; this.semanticServices = semanticServices;
this.typeResolver = new TypeResolver(semanticServices, trace, true); this.typeResolver = new TypeResolver(semanticServices, trace, true);
this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
@@ -280,10 +280,10 @@ public class JetTypeInferrer {
return types.isEmpty() ? JetStandardClasses.getNothingType() : semanticServices.getTypeChecker().commonSupertype(types); return types.isEmpty() ? JetStandardClasses.getNothingType() : semanticServices.getTypeChecker().commonSupertype(types);
} }
private JetType getCachedType(@NotNull JetExpression expression) { // private JetType getCachedType(@NotNull JetExpression expression) {
// assert typeCache.containsKey(expression) : "No type cached for " + expression.getText(); //// assert typeCache.containsKey(expression) : "No type cached for " + expression.getText();
return typeCache.get(expression); // return typeCache.get(expression);
} // }
public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) { public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
Map<JetElement, JetType> typeMap = collectReturnedExpressions(outerScope, function, functionDescriptor); Map<JetElement, JetType> typeMap = collectReturnedExpressions(outerScope, function, functionDescriptor);
@@ -330,7 +330,7 @@ public class JetTypeInferrer {
flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit); flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit);
Map<JetElement,JetType> typeMap = new HashMap<JetElement, JetType>(); Map<JetElement,JetType> typeMap = new HashMap<JetElement, JetType>();
for (JetExpression returnedExpression : returnedExpressions) { for (JetExpression returnedExpression : returnedExpressions) {
JetType cachedType = getCachedType(returnedExpression); JetType cachedType = trace.getBindingContext().getExpressionType(returnedExpression);// getCachedType(returnedExpression);
trace.removeStatementRecord(returnedExpression); trace.removeStatementRecord(returnedExpression);
if (cachedType != null) { if (cachedType != null) {
typeMap.put(returnedExpression, cachedType); typeMap.put(returnedExpression, cachedType);
@@ -592,10 +592,17 @@ public class JetTypeInferrer {
} }
@Nullable @Nullable
public JetType getType(@NotNull JetExpression expression) { public final JetType getType(@NotNull JetExpression expression) {
assert result == null; assert result == null;
if (trace.isProcessed(expression)) {
return trace.getBindingContext().getExpressionType(expression);
}
try { try {
expression.accept(this); expression.accept(this);
trace.markAsProcessed(expression);
if (result instanceof DeferredType) {
result = ((DeferredType) result).getActualType();
}
if (result != null) { if (result != null) {
trace.recordExpressionType(expression, result); trace.recordExpressionType(expression, result);
if (JetStandardClasses.isNothing(result) && !result.isNullable()) { if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
@@ -1688,16 +1695,16 @@ public class JetTypeInferrer {
} }
} }
private class CachedBindingTrace extends BindingTraceAdapter { // private class CachedBindingTrace extends BindingTraceAdapter {
//
public CachedBindingTrace(BindingTrace originalTrace) { // public CachedBindingTrace(BindingTrace originalTrace) {
super(originalTrace); // super(originalTrace);
} // }
//
@Override // @Override
public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { // public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) {
super.recordExpressionType(expression, type); // super.recordExpressionType(expression, type);
typeCache.put(expression, type); // typeCache.put(expression, type);
} // }
} // }
} }
@@ -23,7 +23,6 @@ public abstract class LazyValue<T> {
return state; return state;
} }
@NotNull
public final T get() { public final T get() {
switch (state) { switch (state) {
case NOT_COMPUTED: case NOT_COMPUTED: