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); DataFlowInfo disequate(@NotNull DataFlowValue a, @NotNull DataFlowValue b);
@NotNull @NotNull
DataFlowInfo establishSubtyping(@NotNull DataFlowValue[] values, @NotNull JetType type); DataFlowInfo establishSubtyping(@NotNull DataFlowValue value, @NotNull JetType type);
@NotNull @NotNull
DataFlowInfo and(@NotNull DataFlowInfo other); 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.lang.types.TypeUtils;
import org.jetbrains.jet.util.CommonSuppliers; import org.jetbrains.jet.util.CommonSuppliers;
import java.util.Collection; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NULL; 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 @NotNull
private final ListMultimap<DataFlowValue, JetType> typeInfo; 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(); private static final ListMultimap<DataFlowValue, JetType> EMPTY_TYPE_INFO = newTypeInfo();
/* package */ DelegatingDataFlowInfo( /* package */ DelegatingDataFlowInfo(
@@ -133,18 +132,13 @@ import static org.jetbrains.jet.lang.resolve.calls.autocasts.Nullability.NOT_NUL
@Override @Override
@NotNull @NotNull
public DataFlowInfo establishSubtyping(@NotNull DataFlowValue[] values, @NotNull JetType type) { public DataFlowInfo establishSubtyping(@NotNull DataFlowValue value, @NotNull JetType type) {
if (values.length == 0) return this; if (value.getType().equals(type)) return this;
if (getPossibleTypes(value).contains(type)) return this;
ListMultimap<DataFlowValue, JetType> newTypeInfo = newTypeInfo(); ImmutableMap<DataFlowValue, Nullability> newNullabilityInfo =
Map<DataFlowValue, Nullability> newNullabilityInfo = Maps.newHashMap(); type.isNullable() ? EMPTY_NULLABILITY_INFO : ImmutableMap.of(value, NOT_NULL);
for (DataFlowValue value : values) { ListMultimap<DataFlowValue, JetType> newTypeInfo = ImmutableListMultimap.of(value, type);
newTypeInfo.put(value, type); return new DelegatingDataFlowInfo(this, newNullabilityInfo, newTypeInfo);
if (!type.isNullable()) {
putNullability(newNullabilityInfo, value, NOT_NULL);
}
}
return new DelegatingDataFlowInfo(this, ImmutableMap.copyOf(newNullabilityInfo), newTypeInfo);
} }
@NotNull @NotNull
@@ -222,7 +222,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
dataFlowInfo = typeInfo.getDataFlowInfo(); dataFlowInfo = typeInfo.getDataFlowInfo();
if (operationType == JetTokens.AS_KEYWORD) { if (operationType == JetTokens.AS_KEYWORD) {
DataFlowValue value = DataFlowValueFactory.INSTANCE.createDataFlowValue(left, typeInfo.getType(), context.trace.getBindingContext()); 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(); subjectType = typeInfo.getType();
context = context.replaceDataFlowInfo(typeInfo.getDataFlowInfo()); 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 // TODO : exhaustive patterns
@@ -103,7 +105,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
DataFlowInfos infos = checkWhenCondition( DataFlowInfos infos = checkWhenCondition(
subjectExpression, subjectExpression == null, subjectExpression, subjectExpression == null,
subjectType, condition, subjectType, condition,
context, variableDescriptor); context, subjectDataFlowValue);
newDataFlowInfo = infos.thenInfo; newDataFlowInfo = infos.thenInfo;
elseDataFlowInfo = elseDataFlowInfo.and(infos.elseInfo); elseDataFlowInfo = elseDataFlowInfo.and(infos.elseInfo);
} }
@@ -113,7 +115,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
newDataFlowInfo = null; newDataFlowInfo = null;
for (JetWhenCondition condition : conditions) { for (JetWhenCondition condition : conditions) {
DataFlowInfos infos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition, DataFlowInfos infos = checkWhenCondition(subjectExpression, subjectExpression == null, subjectType, condition,
context, variableDescriptor); context, subjectDataFlowValue);
if (newDataFlowInfo == null) { if (newDataFlowInfo == null) {
newDataFlowInfo = infos.thenInfo; newDataFlowInfo = infos.thenInfo;
} }
@@ -160,7 +162,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
final JetType subjectType, final JetType subjectType,
JetWhenCondition condition, JetWhenCondition condition,
final ExpressionTypingContext context, final ExpressionTypingContext context,
final DataFlowValue... subjectVariables final DataFlowValue subjectDataFlowValue
) { ) {
final Ref<DataFlowInfos> newDataFlowInfo = new Ref<DataFlowInfos>(noChange(context)); final Ref<DataFlowInfos> newDataFlowInfo = new Ref<DataFlowInfos>(noChange(context));
condition.accept(new JetVisitorVoid() { condition.accept(new JetVisitorVoid() {
@@ -189,7 +191,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(EXPECTED_CONDITION.on(condition)); context.trace.report(EXPECTED_CONDITION.on(condition));
} }
if (condition.getTypeRef() != null) { if (condition.getTypeRef() != null) {
DataFlowInfos result = checkTypeForIs(context, subjectType, condition.getTypeRef(), subjectVariables); DataFlowInfos result = checkTypeForIs(context, subjectType, condition.getTypeRef(), subjectDataFlowValue);
if (condition.isNegated()) { if (condition.isNegated()) {
newDataFlowInfo.set(new DataFlowInfos(result.elseInfo, result.thenInfo)); newDataFlowInfo.set(new DataFlowInfos(result.elseInfo, result.thenInfo));
} }
@@ -204,7 +206,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
JetExpression expression = condition.getExpression(); JetExpression expression = condition.getExpression();
if (expression != null) { if (expression != null) {
newDataFlowInfo.set(checkTypeForExpressionCondition(context, expression, subjectType, subjectExpression == null, newDataFlowInfo.set(checkTypeForExpressionCondition(context, expression, subjectType, subjectExpression == null,
subjectVariables)); subjectDataFlowValue));
} }
} }
@@ -231,7 +233,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
JetExpression expression, JetExpression expression,
JetType subjectType, JetType subjectType,
boolean conditionExpected, boolean conditionExpected,
DataFlowValue... subjectVariables DataFlowValue subjectDataFlowValue
) { ) {
if (expression == null) { if (expression == null) {
return noChange(context); return noChange(context);
@@ -258,12 +260,10 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
DataFlowValue expressionDataFlowValue = DataFlowValue expressionDataFlowValue =
DataFlowValueFactory.INSTANCE.createDataFlowValue(expression, type, context.trace.getBindingContext()); DataFlowValueFactory.INSTANCE.createDataFlowValue(expression, type, context.trace.getBindingContext());
DataFlowInfos result = noChange(context); DataFlowInfos result = noChange(context);
for (DataFlowValue subjectVariable : subjectVariables) { result = new DataFlowInfos(
result = new DataFlowInfos( result.thenInfo.equate(subjectDataFlowValue, expressionDataFlowValue),
result.thenInfo.equate(subjectVariable, expressionDataFlowValue), result.elseInfo.disequate(subjectDataFlowValue, expressionDataFlowValue)
result.elseInfo.disequate(subjectVariable, expressionDataFlowValue) );
);
}
return result; return result;
} }
@@ -271,7 +271,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
ExpressionTypingContext context, ExpressionTypingContext context,
JetType subjectType, JetType subjectType,
JetTypeReference typeReferenceAfterIs, JetTypeReference typeReferenceAfterIs,
DataFlowValue... subjectVariables DataFlowValue subjectDataFlowValue
) { ) {
if (typeReferenceAfterIs == null) { if (typeReferenceAfterIs == null) {
return noChange(context); return noChange(context);
@@ -281,7 +281,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
if (BasicExpressionTypingVisitor.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) { if (BasicExpressionTypingVisitor.isCastErased(subjectType, type, JetTypeChecker.INSTANCE)) {
context.trace.report(Errors.CANNOT_CHECK_FOR_ERASED.on(typeReferenceAfterIs, type)); 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) { private static DataFlowInfos noChange(ExpressionTypingContext context) {