From b67359a86124b05095c3ee5e414720e796bd912a Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 13 May 2011 19:48:56 +0400 Subject: [PATCH] Problem caused by the asymmetry of equals() for deferred types solved (ad hoc) --- .../jet/lang/resolve/BindingTrace.java | 45 +++++++++++++----- .../jet/lang/resolve/BindingTraceAdapter.java | 15 ++++++ .../jet/lang/resolve/BindingTraceContext.java | 18 +++++++ .../lang/resolve/ClassDescriptorResolver.java | 2 +- .../jet/lang/resolve/TopDownAnalyzer.java | 1 + .../jet/lang/types/DeferredType.java | 10 ++++ .../jetbrains/jet/lang/types/ErrorUtils.java | 3 +- .../org/jetbrains/jet/lang/types/JetType.java | 3 ++ .../jet/lang/types/JetTypeInferrer.java | 47 +++++++++++-------- .../jetbrains/jet/lang/types/LazyValue.java | 1 - 10 files changed, 110 insertions(+), 35 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java index 5fd514f0b10..80093635c6f 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTrace.java @@ -64,30 +64,51 @@ public interface BindingTrace { public ErrorHandler getErrorHandler() { 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 - public ErrorHandler getErrorHandler(); + ErrorHandler getErrorHandler(); + + boolean isProcessed(@NotNull JetExpression expression); + + void markAsProcessed(@NotNull JetExpression expression); + + BindingContext getBindingContext(); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java index b001482f252..423961c8998 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java @@ -71,4 +71,19 @@ public class BindingTraceAdapter implements BindingTrace { public void removeStatementRecord(@NotNull JetElement 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(); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index 029219e0659..023e8c6715e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -31,6 +32,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace { private final Set blocks = new HashSet(); private final Set statements = new HashSet(); private final Set backingFieldRequired = new HashSet(); + private final Set processed = Sets.newHashSet(); private Collection diagnostics = Lists.newArrayList(); private ErrorHandler errorHandler = new ErrorHandler() { @@ -70,6 +72,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace { @Override public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { expressionTypes.put(expression, type); + markAsProcessed(expression); } @Override @@ -279,4 +282,19 @@ public class BindingTraceContext implements BindingContext, BindingTrace { public Collection getDiagnostics() { 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; + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 6e1076d1b0c..ec836f3418c 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -259,7 +259,7 @@ public class ClassDescriptorResolver { returnType = new DeferredType(new LazyValue() { @Override protected JetType compute() { - JetFlowInformationProvider flowInformationProvider = computeFlowData(function.asElement(), bodyExpression); + JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression); return semanticServices.getTypeInferrer(trace, flowInformationProvider).getFunctionReturnType(scope, function, functionDescriptor); } }); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 8b22941836a..449859922d3 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -863,6 +863,7 @@ public class TopDownAnalyzer { @NotNull MutableFunctionDescriptor functionDescriptor, @NotNull JetScope declaringScope) { JetExpression bodyExpression = function.getBodyExpression(); + if (bodyExpression != null) { JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(function.asElement(), bodyExpression); JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(trace, flowInformationProvider); diff --git a/idea/src/org/jetbrains/jet/lang/types/DeferredType.java b/idea/src/org/jetbrains/jet/lang/types/DeferredType.java index b3fdc929e31..565703c0f49 100644 --- a/idea/src/org/jetbrains/jet/lang/types/DeferredType.java +++ b/idea/src/org/jetbrains/jet/lang/types/DeferredType.java @@ -57,4 +57,14 @@ public class DeferredType implements JetType { return ""; } } + + @Override + public boolean equals(Object obj) { + return getActualType().equals(obj); + } + + @Override + public int hashCode() { + return getActualType().hashCode(); + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java index 0e80076c7a6..6a2c8f52b28 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -161,7 +161,8 @@ public class ErrorUtils { } public static boolean isErrorType(JetType type) { - return type instanceof ErrorTypeImpl || + return (type instanceof DeferredType && ((DeferredType) type).getActualType() == null) || + type instanceof ErrorTypeImpl || isError(type.getConstructor()); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetType.java b/idea/src/org/jetbrains/jet/lang/types/JetType.java index ca7a60bf2f5..f59cb98eee0 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetType.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetType.java @@ -16,4 +16,7 @@ public interface JetType extends Annotated { @NotNull JetScope getMemberScope(); + + @Override + public boolean equals(Object other); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 0e1486598ac..1abed789a2c 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -63,7 +63,7 @@ public class JetTypeInferrer { assignmentOperationCounterparts.put(JetTokens.MINUSEQ, JetTokens.MINUS); } - private final Map typeCache = new HashMap(); +// private final Map typeCache = new HashMap(); private final BindingTrace trace; private final JetSemanticServices semanticServices; @@ -72,7 +72,7 @@ public class JetTypeInferrer { private final JetFlowInformationProvider flowInformationProvider; 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.typeResolver = new TypeResolver(semanticServices, trace, true); this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); @@ -280,10 +280,10 @@ public class JetTypeInferrer { return types.isEmpty() ? JetStandardClasses.getNothingType() : semanticServices.getTypeChecker().commonSupertype(types); } - private JetType getCachedType(@NotNull JetExpression expression) { -// assert typeCache.containsKey(expression) : "No type cached for " + expression.getText(); - return typeCache.get(expression); - } +// private JetType getCachedType(@NotNull JetExpression expression) { +//// assert typeCache.containsKey(expression) : "No type cached for " + expression.getText(); +// return typeCache.get(expression); +// } public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) { Map typeMap = collectReturnedExpressions(outerScope, function, functionDescriptor); @@ -330,7 +330,7 @@ public class JetTypeInferrer { flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit); Map typeMap = new HashMap(); for (JetExpression returnedExpression : returnedExpressions) { - JetType cachedType = getCachedType(returnedExpression); + JetType cachedType = trace.getBindingContext().getExpressionType(returnedExpression);// getCachedType(returnedExpression); trace.removeStatementRecord(returnedExpression); if (cachedType != null) { typeMap.put(returnedExpression, cachedType); @@ -592,10 +592,17 @@ public class JetTypeInferrer { } @Nullable - public JetType getType(@NotNull JetExpression expression) { + public final JetType getType(@NotNull JetExpression expression) { assert result == null; + if (trace.isProcessed(expression)) { + return trace.getBindingContext().getExpressionType(expression); + } try { expression.accept(this); + trace.markAsProcessed(expression); + if (result instanceof DeferredType) { + result = ((DeferredType) result).getActualType(); + } if (result != null) { trace.recordExpressionType(expression, result); if (JetStandardClasses.isNothing(result) && !result.isNullable()) { @@ -1688,16 +1695,16 @@ public class JetTypeInferrer { } } - private class CachedBindingTrace extends BindingTraceAdapter { - - public CachedBindingTrace(BindingTrace originalTrace) { - super(originalTrace); - } - - @Override - public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { - super.recordExpressionType(expression, type); - typeCache.put(expression, type); - } - } +// private class CachedBindingTrace extends BindingTraceAdapter { +// +// public CachedBindingTrace(BindingTrace originalTrace) { +// super(originalTrace); +// } +// +// @Override +// public void recordExpressionType(@NotNull JetExpression expression, @NotNull JetType type) { +// super.recordExpressionType(expression, type); +// typeCache.put(expression, type); +// } +// } } diff --git a/idea/src/org/jetbrains/jet/lang/types/LazyValue.java b/idea/src/org/jetbrains/jet/lang/types/LazyValue.java index c40b4420bae..75dd977d7ac 100644 --- a/idea/src/org/jetbrains/jet/lang/types/LazyValue.java +++ b/idea/src/org/jetbrains/jet/lang/types/LazyValue.java @@ -23,7 +23,6 @@ public abstract class LazyValue { return state; } - @NotNull public final T get() { switch (state) { case NOT_COMPUTED: