Deferred types are computed at the end of the top-down analysis

This commit is contained in:
Andrey Breslav
2011-09-28 14:19:51 +04:00
parent f6cc7b4cfe
commit 1c299fe536
17 changed files with 171 additions and 50 deletions
@@ -22,7 +22,7 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas
@Override @Override
public String getName() { public String getName() {
JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
return nameAsDeclaration == null ? "ClassObj" : nameAsDeclaration.getName(); return nameAsDeclaration == null ? null : nameAsDeclaration.getName();
} }
@Override @Override
@@ -9,7 +9,9 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.util.CommonSuppliers;
import org.jetbrains.jet.util.slicedmap.*; import org.jetbrains.jet.util.slicedmap.*;
import java.util.Collection; import java.util.Collection;
@@ -42,6 +44,10 @@ public interface BindingContext {
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice("STATEMENT"); WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice("STATEMENT");
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice("DELEGATED"); WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice("DELEGATED");
enum DeferredTypeKey {DEFERRED_TYPE_KEY}
WritableSlice<DeferredTypeKey, Collection<DeferredType>> DEFERRED_TYPES = Slices.createSimpleSlice("DEFERRED_TYPES");
WritableSlice<DeferredTypeKey, DeferredType> DEFERRED_TYPE = new CollectionSliceWrapper<DeferredTypeKey, DeferredType>(DEFERRED_TYPES, CommonSuppliers.<DeferredType>getArrayListSupplier());
WritableSlice<PropertyDescriptor, Boolean> BACKING_FIELD_REQUIRED = new Slices.SetSlice<PropertyDescriptor>("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) { WritableSlice<PropertyDescriptor, Boolean> BACKING_FIELD_REQUIRED = new Slices.SetSlice<PropertyDescriptor>("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) {
@Override @Override
public Boolean computeValue(SlicedMap map, PropertyDescriptor propertyDescriptor, Boolean backingFieldRequired, boolean valueNotFound) { public Boolean computeValue(SlicedMap map, PropertyDescriptor propertyDescriptor, Boolean backingFieldRequired, boolean valueNotFound) {
@@ -5,6 +5,7 @@ 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 com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
@@ -21,6 +22,9 @@ import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPES;
import static org.jetbrains.jet.lang.resolve.BindingContext.DeferredTypeKey.DEFERRED_TYPE_KEY;
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
/** /**
@@ -29,14 +33,14 @@ import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
public class BodyResolver { public class BodyResolver {
private final TopDownAnalysisContext context; private final TopDownAnalysisContext context;
private final BindingTraceAdapter traceForConstructors; private final ObservableBindingTrace traceForConstructors;
private final BindingTraceAdapter traceForMembers; private final ObservableBindingTrace traceForMembers;
public BodyResolver(TopDownAnalysisContext context) { public BodyResolver(TopDownAnalysisContext context) {
this.context = context; this.context = context;
// This allows access to backing fields // This allows access to backing fields
this.traceForConstructors = new BindingTraceAdapter(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() { this.traceForConstructors = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
@Override @Override
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) { public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
if (expression instanceof JetSimpleNameExpression) { if (expression instanceof JetSimpleNameExpression) {
@@ -52,7 +56,7 @@ public class BodyResolver {
}); });
// This tracks access to properties in order to register primary constructor parameters that yield real fields (JET-9) // This tracks access to properties in order to register primary constructor parameters that yield real fields (JET-9)
this.traceForMembers = new BindingTraceAdapter(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() { this.traceForMembers = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
@Override @Override
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) { public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
if (descriptor instanceof PropertyDescriptor) { if (descriptor instanceof PropertyDescriptor) {
@@ -68,8 +72,6 @@ public class BodyResolver {
public void resolveBehaviorDeclarationBodies() { public void resolveBehaviorDeclarationBodies() {
// bindOverrides();
resolveDelegationSpecifierLists(); resolveDelegationSpecifierLists();
resolveClassAnnotations(); resolveClassAnnotations();
@@ -81,7 +83,34 @@ public class BodyResolver {
checkIfPrimaryConstructorIsNecessary(); checkIfPrimaryConstructorIsNecessary();
// checkOverrides(); computeDeferredTypes();
}
private void computeDeferredTypes() {
Collection<DeferredType> deferredTypes = context.getTrace().get(DEFERRED_TYPES, DEFERRED_TYPE_KEY);
if (deferredTypes != null) {
final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size());
context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<BindingContext.DeferredTypeKey, DeferredType>() {
@Override
public void handleRecord(WritableSlice<BindingContext.DeferredTypeKey, DeferredType> deferredTypeKeyDeferredTypeWritableSlice, BindingContext.DeferredTypeKey key, DeferredType value) {
queue.addLast(value);
}
});
for (DeferredType deferredType : deferredTypes) {
queue.addLast(deferredType);
}
while (!queue.isEmpty()) {
DeferredType deferredType = queue.pullFirst();
if (!deferredType.isComputed()) {
try {
deferredType.getActualType(); // to compute
}
catch (ReenteringLazyValueComputationException e) {
// A problem should be reported while computing the type
}
}
}
}
} }
private void checkIfPrimaryConstructorIsNecessary() { private void checkIfPrimaryConstructorIsNecessary() {
@@ -476,7 +505,7 @@ public class BodyResolver {
} }
private void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor, JetScope declaringScope) { private void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor, JetScope declaringScope) {
BindingTraceAdapter fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor); ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Accessor scope"); WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Accessor scope");
accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
@@ -597,8 +626,8 @@ public class BodyResolver {
} }
} }
private BindingTraceAdapter createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) { private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
return new BindingTraceAdapter(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() { return new ObservableBindingTrace(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
@Override @Override
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) { public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
if (expression instanceof JetSimpleNameExpression) { if (expression instanceof JetSimpleNameExpression) {
@@ -614,8 +643,8 @@ public class BodyResolver {
}); });
} }
private BindingTraceAdapter createFieldAssignTrackingTrace() { private ObservableBindingTrace createFieldAssignTrackingTrace() {
return new BindingTraceAdapter(traceForConstructors).addHandler(BindingContext.VARIABLE_ASSIGNMENT, new BindingTraceAdapter.RecordHandler<JetExpression, DeclarationDescriptor>() { return new ObservableBindingTrace(traceForConstructors).addHandler(BindingContext.VARIABLE_ASSIGNMENT, new ObservableBindingTrace.RecordHandler<JetExpression, DeclarationDescriptor>() {
@Override @Override
public void handleRecord(WritableSlice<JetExpression, DeclarationDescriptor> jetExpressionBooleanWritableSlice, JetExpression expression, DeclarationDescriptor descriptor) { public void handleRecord(WritableSlice<JetExpression, DeclarationDescriptor> jetExpressionBooleanWritableSlice, JetExpression expression, DeclarationDescriptor descriptor) {
if (expression instanceof JetSimpleNameExpression) { if (expression instanceof JetSimpleNameExpression) {
@@ -177,7 +177,7 @@ public class ClassDescriptorResolver {
else { else {
final JetExpression bodyExpression = function.getBodyExpression(); final JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) { if (bodyExpression != null) {
returnType = new DeferredType(new LazyValue<JetType>() { returnType = DeferredType.create(trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override @Override
protected JetType compute() { protected JetType compute() {
JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression); JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
@@ -532,7 +532,7 @@ public class ClassDescriptorResolver {
return ErrorUtils.createErrorType("No type, no body"); return ErrorUtils.createErrorType("No type, no body");
} else { } else {
// TODO : a risk of a memory leak // TODO : a risk of a memory leak
LazyValue<JetType> lazyValue = new LazyValue<JetType>() { LazyValue<JetType> lazyValue = new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override @Override
protected JetType compute() { protected JetType compute() {
JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer); JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
@@ -540,7 +540,7 @@ public class ClassDescriptorResolver {
} }
}; };
if (allowDeferred) { if (allowDeferred) {
return new DeferredType(lazyValue); return DeferredType.create(trace, lazyValue);
} }
else { else {
return lazyValue.get(); return lazyValue.get();
@@ -11,7 +11,7 @@ import java.util.Map;
/** /**
* @author abreslav * @author abreslav
*/ */
public class BindingTraceAdapter implements BindingTrace { public class ObservableBindingTrace implements BindingTrace {
public interface RecordHandler<K, V> { public interface RecordHandler<K, V> {
void handleRecord(WritableSlice<K, V> slice, K key, V value); void handleRecord(WritableSlice<K, V> slice, K key, V value);
@@ -19,7 +19,7 @@ public class BindingTraceAdapter implements BindingTrace {
private final BindingTrace originalTrace; private final BindingTrace originalTrace;
private Map<WritableSlice, RecordHandler> handlers = Maps.newHashMap(); private Map<WritableSlice, RecordHandler> handlers = Maps.newHashMap();
public BindingTraceAdapter(BindingTrace originalTrace) { public ObservableBindingTrace(BindingTrace originalTrace) {
this.originalTrace = originalTrace; this.originalTrace = originalTrace;
} }
@@ -52,7 +52,7 @@ public class BindingTraceAdapter implements BindingTrace {
return originalTrace.get(slice, key); return originalTrace.get(slice, key);
} }
public <K, V> BindingTraceAdapter addHandler(@NotNull WritableSlice<K, V> slice, @NotNull RecordHandler<K, V> handler) { public <K, V> ObservableBindingTrace addHandler(@NotNull WritableSlice<K, V> slice, @NotNull RecordHandler<K, V> handler) {
handlers.put(slice, handler); handlers.put(slice, handler);
return this; return this;
} }
@@ -16,7 +16,7 @@ import java.util.Set;
*/ */
/*package*/ class TopDownAnalysisContext { /*package*/ class TopDownAnalysisContext {
private final BindingTrace trace; private final ObservableBindingTrace trace;
private final JetSemanticServices semanticServices; private final JetSemanticServices semanticServices;
private final ClassDescriptorResolver classDescriptorResolver; private final ClassDescriptorResolver classDescriptorResolver;
@@ -32,12 +32,12 @@ import java.util.Set;
private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap(); private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace) { public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace) {
this.trace = trace; this.trace = new ObservableBindingTrace(trace);
this.semanticServices = semanticServices; this.semanticServices = semanticServices;
this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
} }
public BindingTrace getTrace() { public ObservableBindingTrace getTrace() {
return trace; return trace;
} }
@@ -2,17 +2,28 @@ package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
import static org.jetbrains.jet.lang.resolve.BindingContext.DeferredTypeKey.DEFERRED_TYPE_KEY;
/** /**
* @author abreslav * @author abreslav
*/ */
public class DeferredType implements JetType { public class DeferredType implements JetType {
public static DeferredType create(BindingTrace trace, LazyValue<JetType> lazyValue) {
DeferredType deferredType = new DeferredType(lazyValue);
trace.record(DEFERRED_TYPE, DEFERRED_TYPE_KEY, deferredType);
return deferredType;
}
private final LazyValue<JetType> lazyValue; private final LazyValue<JetType> lazyValue;
public DeferredType(LazyValue<JetType> lazyValue) { private DeferredType(LazyValue<JetType> lazyValue) {
this.lazyValue = lazyValue; this.lazyValue = lazyValue;
} }
@@ -432,13 +432,13 @@ public class JetTypeInferrer {
// This implements coercion to Unit // This implements coercion to Unit
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace); TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace);
final boolean[] mismatch = new boolean[1]; final boolean[] mismatch = new boolean[1];
BindingTraceAdapter errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch); ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
newContext = newContext(errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType); newContext = newContext(errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
result = blockLevelVisitor.getType(statementExpression, newContext); result = blockLevelVisitor.getType(statementExpression, newContext);
if (mismatch[0]) { if (mismatch[0]) {
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace); TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
mismatch[0] = false; mismatch[0] = false;
BindingTraceAdapter interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch); ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
newContext = newContext(interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType); newContext = newContext(interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
result = blockLevelVisitor.getType(statementExpression, newContext); result = blockLevelVisitor.getType(statementExpression, newContext);
if (mismatch[0]) { if (mismatch[0]) {
@@ -474,8 +474,8 @@ public class JetTypeInferrer {
return result; return result;
} }
private BindingTraceAdapter makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) { private ObservableBindingTrace makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) {
return new BindingTraceAdapter(trace) { return new ObservableBindingTrace(trace) {
@Override @Override
public void report(@NotNull Diagnostic diagnostic) { public void report(@NotNull Diagnostic diagnostic) {
@@ -875,12 +875,12 @@ public class JetTypeInferrer {
@Override @Override
public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final TypeInferenceContext context) { public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final TypeInferenceContext context) {
final JetType[] result = new JetType[1]; final JetType[] result = new JetType[1];
BindingTraceAdapter.RecordHandler<PsiElement, ClassDescriptor> handler = new BindingTraceAdapter.RecordHandler<PsiElement, ClassDescriptor>() { ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler = new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() {
@Override @Override
public void handleRecord(WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) { public void handleRecord(WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) {
if (slice == CLASS && declaration == expression.getObjectDeclaration()) { if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
JetType defaultType = new DeferredType(new LazyValue<JetType>() { JetType defaultType = DeferredType.create(context.trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override @Override
protected JetType compute() { protected JetType compute() {
return descriptor.getDefaultType(); return descriptor.getDefaultType();
@@ -894,7 +894,7 @@ public class JetTypeInferrer {
} }
} }
}; };
BindingTraceAdapter traceAdapter = new BindingTraceAdapter(context.trace); ObservableBindingTrace traceAdapter = new ObservableBindingTrace(context.trace);
traceAdapter.addHandler(CLASS, handler); traceAdapter.addHandler(CLASS, handler);
TopDownAnalyzer.processObject(semanticServices, traceAdapter, context.scope, context.scope.getContainingDeclaration(), expression.getObjectDeclaration()); TopDownAnalyzer.processObject(semanticServices, traceAdapter, context.scope, context.scope.getContainingDeclaration(), expression.getObjectDeclaration());
return context.services.checkType(result[0], expression, context); return context.services.checkType(result[0], expression, context);
@@ -17,6 +17,10 @@ public abstract class LazyValue<T> {
protected abstract T compute(); protected abstract T compute();
protected T getValueOnErrorReentry() {
throw new ReenteringLazyValueComputationException();
}
public boolean isComputed() { public boolean isComputed() {
return state == State.ERROR || state == State.COMPUTED; return state == State.ERROR || state == State.COMPUTED;
} }
@@ -34,7 +38,7 @@ public abstract class LazyValue<T> {
case COMPUTED: case COMPUTED:
return value; return value;
case ERROR: case ERROR:
throw new ReenteringLazyValueComputationException(); return getValueOnErrorReentry();
} }
throw new IllegalStateException("Unreachable"); throw new IllegalStateException("Unreachable");
} }
@@ -0,0 +1,17 @@
package org.jetbrains.jet.lang.types;
/**
* @author abreslav
*/
public abstract class LazyValueWithDefault<T> extends LazyValue<T> {
private final T defaultValue;
protected LazyValueWithDefault(T defaultValue) {
this.defaultValue = defaultValue;
}
@Override
protected T getValueOnErrorReentry() {
return defaultValue;
}
}
@@ -7,15 +7,8 @@ public class ReenteringLazyValueComputationException extends RuntimeException {
public ReenteringLazyValueComputationException() { public ReenteringLazyValueComputationException() {
} }
public ReenteringLazyValueComputationException(String message) { @Override
super(message); public synchronized Throwable fillInStackTrace() {
} return this;
public ReenteringLazyValueComputationException(String message, Throwable cause) {
super(message, cause);
}
public ReenteringLazyValueComputationException(Throwable cause) {
super(cause);
} }
} }
@@ -0,0 +1,57 @@
package org.jetbrains.jet.util.slicedmap;
import com.google.common.base.Supplier;
import java.util.Collection;
/**
* @author abreslav
*/
public class CollectionSliceWrapper<K, V> implements WritableSlice<K, V> {
private final WritableSlice<K, Collection<V>> wrapped;
private final SlicedMapKey<K, V> myKey;
private final Supplier<? extends Collection<V>> supplier;
public CollectionSliceWrapper(WritableSlice<K, Collection<V>> wrapped, Supplier<? extends Collection<V>> supplier) {
this.wrapped = wrapped;
this.supplier = supplier;
this.myKey = new SlicedMapKey<K, V>(this, null);
}
@Override
public SlicedMapKey<K, V> makeKey(K key) {
return myKey;
}
@Override
public boolean check(K key, V value) {
assert value != null;
return true;
}
@Override
public void afterPut(MutableSlicedMap map, K key, V value) {
Collection<V> collection = map.get(wrapped, key);
if (collection == null) {
collection = supplier.get();
map.put(wrapped, key, collection);
}
collection.add(value);
}
@Override
public RewritePolicy getRewritePolicy() {
return RewritePolicy.DO_NOTHING;
}
@Override
public V computeValue(SlicedMap map, K key, V value, boolean valueNotFound) {
throw new UnsupportedOperationException("Don't read by this slice, use the wrapped one");
}
@Override
public ReadOnlySlice<K, V> makeRawValueVersion() {
return this;
}
}
@@ -34,10 +34,11 @@ public class SlicedMapImpl implements MutableSlicedMap {
return; return;
} }
SlicedMapKey<K, V> slicedMapKey = slice.makeKey(key); SlicedMapKey<K, V> slicedMapKey = slice.makeKey(key);
if (slice.getRewritePolicy().rewriteProcessingNeeded(key)) { RewritePolicy rewritePolicy = slice.getRewritePolicy();
if (rewritePolicy.rewriteProcessingNeeded(key)) {
if (map.containsKey(slicedMapKey)) { if (map.containsKey(slicedMapKey)) {
//noinspection unchecked //noinspection unchecked
if (!slice.getRewritePolicy().processRewrite(slice, key, (V) map.get(slicedMapKey), value)) { if (!rewritePolicy.processRewrite(slice, key, (V) map.get(slicedMapKey), value)) {
return; return;
} }
} }
@@ -160,10 +160,10 @@ public class Slices {
public static class SetSlice<K> extends BasicRemovableSlice<K, Boolean> { public static class SetSlice<K> extends BasicRemovableSlice<K, Boolean> {
protected SetSlice(String debugName, RewritePolicy rewritePolicy) { protected SetSlice(String debugName, RewritePolicy rewritePolicy) {
super(debugName, rewritePolicy); super(debugName, rewritePolicy);
} }
@Override @Override
public Boolean computeValue(SlicedMap map, K key, Boolean value, boolean valueNotFound) { public Boolean computeValue(SlicedMap map, K key, Boolean value, boolean valueNotFound) {
if (valueNotFound) return false; if (valueNotFound) return false;
+2 -2
View File
@@ -14,9 +14,9 @@ val a = object {
{ {
b + 1 b + 1
} }
val x = <error>b</error> val x = b
val y = 1 val y = 1
} }
val b = a.x val b = <error>a</error>.x
val c = a.y val c = a.y
@@ -14,9 +14,9 @@ val a = object {
{ {
b + 1 b + 1
} }
val x = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>b<!> val x = b
val y = 1 val y = 1
} }
val b = a.x val b = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>a<!>.x
val c = a.y val c = a.y
@@ -0,0 +1,3 @@
trait T {
val a = <!PROPERTY_INITIALIZER_IN_TRAIT!><!UNRESOLVED_REFERENCE!>Foo<!>.bar()<!>
}