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:
+1
-1
@@ -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);
|
||||||
|
|||||||
+10
-16
@@ -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
|
||||||
|
|||||||
+1
-1
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-15
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user