Refactor DataFlowInfo.establishSubtyping()

Don't create useless copies of data flow infos.

Also get rid of vararg subject variable in type-checking 'when' expression
This commit is contained in:
Alexander Udalov
2012-11-15 19:30:10 +04:00
parent d52387a7eb
commit f5ed3ff6bd
4 changed files with 27 additions and 33 deletions
@@ -39,7 +39,7 @@ public interface DataFlowInfo {
DataFlowInfo disequate(@NotNull DataFlowValue a, @NotNull DataFlowValue b);
@NotNull
DataFlowInfo establishSubtyping(@NotNull DataFlowValue[] values, @NotNull JetType type);
DataFlowInfo establishSubtyping(@NotNull DataFlowValue value, @NotNull JetType type);
@NotNull
DataFlowInfo and(@NotNull DataFlowInfo other);
@@ -23,10 +23,7 @@ import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.util.CommonSuppliers;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NULL;
@@ -41,6 +38,8 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
@NotNull
private final ListMultimap<DataFlowValue, JetType> typeInfo;
private static final ImmutableMap<DataFlowValue,Nullability> EMPTY_NULLABILITY_INFO =
ImmutableMap.copyOf(Collections.<DataFlowValue, Nullability>emptyMap());
private static final ListMultimap<DataFlowValue, JetType> EMPTY_TYPE_INFO = newTypeInfo();
/* package */ DelegatingDataFlowInfo(
@@ -133,18 +132,13 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
@Override
@NotNull
public DataFlowInfo establishSubtyping(@NotNull DataFlowValue[] values, @NotNull JetType type) {
if (values.length == 0) return this;
ListMultimap<DataFlowValue, JetType> newTypeInfo = newTypeInfo();
Map<DataFlowValue, Nullability> newNullabilityInfo = Maps.newHashMap();
for (DataFlowValue value : values) {
newTypeInfo.put(value, type);
if (!type.isNullable()) {
putNullability(newNullabilityInfo, value, NOT_NULL);
}
}
return new DelegatingDataFlowInfo(this, ImmutableMap.copyOf(newNullabilityInfo), newTypeInfo);
public DataFlowInfo establishSubtyping(@NotNull DataFlowValue value, @NotNull JetType type) {
if (value.getType().equals(type)) return this;
if (getPossibleTypes(value).contains(type)) return this;
ImmutableMap<DataFlowValue, Nullability> newNullabilityInfo =
type.isNullable() ? EMPTY_NULLABILITY_INFO : ImmutableMap.of(value, NOT_NULL);
ListMultimap<DataFlowValue, JetType> newTypeInfo = ImmutableListMultimap.of(value, type);
return new DelegatingDataFlowInfo(this, newNullabilityInfo, newTypeInfo);
}
@NotNull
@@ -222,7 +222,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
dataFlowInfo = typeInfo.getDataFlowInfo();
if (operationType == JetTokens.AS_KEYWORD) {
DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(left, typeInfo.getType(), context.trace.getBindingContext());
dataFlowInfo = dataFlowInfo.establishSubtyping(new DataFlowValue[]{value}, targetType);
dataFlowInfo = dataFlowInfo.establishSubtyping(value, targetType);
}
}
}
@@ -80,7 +80,9 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
subjectType = typeInfo.getType();
context = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo());
}
final DataFlowValue variableDescriptor = subjectExpression != null ? DataFlowValueFactory.INSTANCE.createDataFlowValue(subjectExpression, subjectType, context.trace.getBindingContext()) : DataFlowValue.NULL;
final DataFlowValue subjectDataFlowValue = subjectExpression != null
? DataFlowValueFactory.INSTANCE.createDataFlowValue(subjectExpression, subjectType, context.trace.getBindingContext())
: DataFlowValue.NULL;
// TODO : exhaustive patterns
@@ -103,7 +105,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
DataFlowInfos infos = checkWhenCondition(
subjectExpression, subjectExpression == null,
subjectType, condition,
context, variableDescriptor);
context, subjectDataFlowValue);
newDataFlowInfo = infos.thenInfo;
elseDataFlowInfo = elseDataFlowInfo.and(infos.elseInfo);
}
@@ -113,7 +115,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
newDataFlowInfo = null;
for (JetWhenCondition condition : conditions) {
DataFlowInfos infos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition,
context, variableDescriptor);
context, subjectDataFlowValue);
if (newDataFlowInfo == null) {
newDataFlowInfo = infos.thenInfo;
}
@@ -160,7 +162,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
final JetType subjectType,
JetWhenCondition condition,
final ExpressionTypingContext context,
final DataFlowValue... subjectVariables
final DataFlowValue subjectDataFlowValue
) {
final Ref<DataFlowInfos> newDataFlowInfo = new Ref<DataFlowInfos>(noChange(context));
condition.accept(new JetVisitorVoid() {
@@ -189,7 +191,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(EXPECTED_CONDITION.on(condition));
}
if (condition.getTypeRef() != null) {
DataFlowInfos result = checkTypeForIs(context, subjectType, condition.getTypeRef(), subjectVariables);
DataFlowInfos result = checkTypeForIs(context, subjectType, condition.getTypeRef(), subjectDataFlowValue);
if (condition.isNegated()) {
newDataFlowInfo.set(new DataFlowInfos(result.elseInfo, result.thenInfo));
}
@@ -204,7 +206,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
JetExpression expression = condition.getExpression();
if (expression != null) {
newDataFlowInfo.set(checkTypeForExpressionCondition(context, expression, subjectType, subjectExpression == null,
subjectVariables));
subjectDataFlowValue));
}
}
@@ -231,7 +233,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
JetExpression expression,
JetType subjectType,
boolean conditionExpected,
DataFlowValue... subjectVariables
DataFlowValue subjectDataFlowValue
) {
if (expression == null) {
return noChange(context);
@@ -258,12 +260,10 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
DataFlowValue expressionDataFlowValue =
DataFlowValueFactory.INSTANCE.createDataFlowValue(expression, type, context.trace.getBindingContext());
DataFlowInfos result = noChange(context);
for (DataFlowValue subjectVariable : subjectVariables) {
result = new DataFlowInfos(
result.thenInfo.equate(subjectVariable, expressionDataFlowValue),
result.elseInfo.disequate(subjectVariable, expressionDataFlowValue)
);
}
result = new DataFlowInfos(
result.thenInfo.equate(subjectDataFlowValue, expressionDataFlowValue),
result.elseInfo.disequate(subjectDataFlowValue, expressionDataFlowValue)
);
return result;
}
@@ -271,7 +271,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
ExpressionTypingContext context,
JetType subjectType,
JetTypeReference typeReferenceAfterIs,
DataFlowValue... subjectVariables
DataFlowValue subjectDataFlowValue
) {
if (typeReferenceAfterIs == null) {
return noChange(context);
@@ -281,7 +281,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
if (BasicExpressionTypingVisitor.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, type));
}
return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectVariables, type), context.dataFlowInfo);
return new DataFlowInfos(context.dataFlowInfo.establishSubtyping(subjectDataFlowValue, type), context.dataFlowInfo);
}
private static DataFlowInfos noChange(ExpressionTypingContext context) {