From 38e7dde8f6d7605a456434042193d362857321a2 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 13 Jun 2012 17:14:37 +0400 Subject: [PATCH 01/11] visitor methods return JetTypeInfo instead of JetType --- .../jet/lang/resolve/ScriptBodyResolver.java | 2 +- .../jetbrains/jet/lang/types/JetTypeInfo.java | 50 +++++++ .../BasicExpressionTypingVisitor.java | 140 +++++++++--------- .../ClosureExpressionsTypingVisitor.java | 14 +- .../ControlStructureTypingVisitor.java | 68 ++++----- .../lang/types/expressions/DataFlowUtils.java | 22 ++- .../expressions/ExpressionTypingFacade.java | 12 +- .../expressions/ExpressionTypingServices.java | 23 +-- .../expressions/ExpressionTypingUtils.java | 4 +- .../expressions/ExpressionTypingVisitor.java | 4 +- .../ExpressionTypingVisitorDispatcher.java | 71 ++++----- .../ExpressionTypingVisitorForStatements.java | 61 ++++---- .../PatternMatchingTypingVisitor.java | 21 +-- 13 files changed, 283 insertions(+), 209 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInfo.java diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java index d3d8262d944..857150b7bc6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java @@ -77,7 +77,7 @@ public class ScriptBodyResolver { DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, false); - JetType returnType = expressionTypingServices.getBlockReturnedType(scope, declaration.getBlockExpression(), CoercionStrategy.NO_COERCION, context, trace); + JetType returnType = expressionTypingServices.getBlockReturnedType(scope, declaration.getBlockExpression(), CoercionStrategy.NO_COERCION, context, trace).getType(); if (returnType == null) { returnType = ErrorUtils.createErrorType("getBlockReturnedType returned null"); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInfo.java new file mode 100644 index 00000000000..b1c3c131831 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInfo.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.types; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; + +/** + * @author udalov + */ +public class JetTypeInfo { + + @NotNull + public static JetTypeInfo create(@Nullable JetType type, @NotNull DataFlowInfo dataFlowInfo) { + return new JetTypeInfo(type, dataFlowInfo); + } + + private final JetType type; + private final DataFlowInfo dataFlowInfo; + + private JetTypeInfo(@Nullable JetType type, @NotNull DataFlowInfo dataFlowInfo) { + this.type = type; + this.dataFlowInfo = dataFlowInfo; + } + + @Nullable + public JetType getType() { + return type; + } + + @NotNull + public DataFlowInfo getDataFlowInfo() { + return dataFlowInfo; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 131c84d9432..a8973e53394 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -69,12 +69,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) { // TODO : other members // TODO : type substitutions??? JetType type = DataFlowUtils.checkType(getSelectorReturnType(NO_RECEIVER, null, expression, context), expression, context); ExpressionTypingUtils.checkWrappingInRef(expression, context); - return type; // TODO : Extensions to this + return JetTypeInfo.create(type, context.dataFlowInfo); // TODO : Extensions to this } @Nullable @@ -137,20 +137,21 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) { return visitParenthesizedExpression(expression, context, false); } - public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) { + public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context, boolean isStatement) { JetExpression innerExpression = expression.getExpression(); if (innerExpression == null) { - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } - return DataFlowUtils.checkType(facade.getType(innerExpression, context.replaceScope(context.scope), isStatement), expression, context); + JetTypeInfo typeInfo = facade.getType(innerExpression, context.replaceScope(context.scope), isStatement); + return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); } @Override - public JetType visitConstantExpression(JetConstantExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitConstantExpression(JetConstantExpression expression, ExpressionTypingContext context) { ASTNode node = expression.getNode(); IElementType elementType = node.getElementType(); String text = node.getText(); @@ -179,16 +180,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (value instanceof ErrorValue) { ErrorValue errorValue = (ErrorValue) value; context.trace.report(ERROR_COMPILE_TIME_VALUE.on(node.getPsi(), errorValue.getMessage())); - return getDefaultType(elementType); + return JetTypeInfo.create(getDefaultType(elementType), context.dataFlowInfo); } else { context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, value); - return DataFlowUtils.checkType(value.getType(standardLibrary), expression, context); + return DataFlowUtils.checkType(value.getType(standardLibrary), expression, context, context.dataFlowInfo); } } @Override - public JetType visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) { + public JetTypeInfo visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context) { JetTypeReference right = expression.getRight(); JetType result = null; if (right != null) { @@ -214,12 +215,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { else { facade.getType(expression.getLeft(), context.replaceExpectedType(NO_EXPECTED_TYPE)); } - return DataFlowUtils.checkType(result, expression, context); + return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); } private boolean checkBinaryWithTypeRHS(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context, @NotNull JetType targetType) { - JetType actualType = facade.getType(expression.getLeft(), context); + JetType actualType = facade.getType(expression.getLeft(), context).getType(); if (actualType == null) return false; JetSimpleNameExpression operationSign = expression.getOperationSign(); @@ -345,7 +346,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitTupleExpression(JetTupleExpression expression, ExpressionTypingContext context) { List entries = expression.getEntries(); List types = new ArrayList(); for (JetExpression entry : entries) { @@ -354,11 +355,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (context.expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isTupleType(context.expectedType)) { List enrichedTypes = checkArgumentTypes(types, entries, context.expectedType.getArguments(), context); if (enrichedTypes != types) { - return JetStandardClasses.getTupleType(enrichedTypes); + return JetTypeInfo.create(JetStandardClasses.getTupleType(enrichedTypes), context.dataFlowInfo); } } // TODO : labels - return DataFlowUtils.checkType(JetStandardClasses.getTupleType(types), expression, context); + return DataFlowUtils.checkType(JetStandardClasses.getTupleType(types), expression, context, context.dataFlowInfo); } @NotNull @@ -374,7 +375,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitThisExpression(JetThisExpression expression, ExpressionTypingContext context) { JetType result = null; ReceiverDescriptor thisReceiver = resolveToReceiver(expression, context, false); @@ -387,19 +388,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { context.trace.record(BindingContext.EXPRESSION_TYPE, expression.getInstanceReference(), result); } } - return DataFlowUtils.checkType(result, expression, context); + return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); } @Override - public JetType visitSuperExpression(JetSuperExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitSuperExpression(JetSuperExpression expression, ExpressionTypingContext context) { if (!context.namespacesAllowed) { context.trace.report(SUPER_IS_NOT_AN_EXPRESSION.on(expression, expression.getText())); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } JetType result = null; ReceiverDescriptor thisReceiver = resolveToReceiver(expression, context, true); - if (thisReceiver == null) return null; + if (thisReceiver == null) return JetTypeInfo.create(null, context.dataFlowInfo); if (!thisReceiver.exists()) { context.trace.report(SUPER_NOT_AVAILABLE.on(expression)); @@ -476,7 +477,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } } } - return DataFlowUtils.checkType(result, expression, context); + return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); } @Nullable // No class receivers @@ -509,30 +510,31 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) { return visitBlockExpression(expression, context, false); } - public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) { + public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context, boolean isStatement) { return context.expressionTypingServices.getBlockReturnedType(context.scope, expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context, context.trace); } @Override - public JetType visitHashQualifiedExpression(JetHashQualifiedExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitHashQualifiedExpression(JetHashQualifiedExpression expression, ExpressionTypingContext context) { context.trace.report(UNSUPPORTED.on(expression, getClass().getCanonicalName())); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } @Override - public JetType visitQualifiedExpression(JetQualifiedExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitQualifiedExpression(JetQualifiedExpression expression, ExpressionTypingContext context) { // TODO : functions as values JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression receiverExpression = expression.getReceiverExpression(); ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE); - JetType receiverType = facade.getType(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true)); - if (selectorExpression == null) return null; + JetTypeInfo receiverTypeInfo = facade.getType(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true)); + JetType receiverType = receiverTypeInfo.getType(); + if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo); if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText()); if (selectorExpression instanceof JetSimpleNameExpression) { @@ -555,7 +557,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (result != null) { context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, result); } - return DataFlowUtils.checkType(result, expression, context); + return DataFlowUtils.checkType(result, expression, context, receiverTypeInfo.getDataFlowInfo()); } private void propagateConstantValues(JetQualifiedExpression expression, ExpressionTypingContext context, JetSimpleNameExpression selectorExpression) { @@ -740,19 +742,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) { JetType expressionType = getCallExpressionType(expression, NO_RECEIVER, null, context); - return DataFlowUtils.checkType(expressionType, expression, context); + return DataFlowUtils.checkType(expressionType, expression, context, context.dataFlowInfo); } @Override - public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) { return visitUnaryExpression(expression, context, false); } - public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) { + public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context, boolean isStatement) { JetExpression baseExpression = expression.getBaseExpression(); - if (baseExpression == null) return null; + if (baseExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo); JetSimpleNameExpression operationSign = expression.getOperationReference(); @@ -762,32 +764,34 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { referencedName = referencedName == null ? " " : referencedName; context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression); // TODO : Some processing for the label? - JetType type = facade.getType(baseExpression, context, isStatement); + JetTypeInfo typeInfo = facade.getType(baseExpression, context, isStatement); context.labelResolver.exitLabeledElement(baseExpression); - return DataFlowUtils.checkType(type, expression, context); + return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); } IElementType operationType = operationSign.getReferencedNameElementType(); // Type check the base expression - JetType type = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE)); + JetTypeInfo typeInfo = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE)); + JetType type = typeInfo.getType(); if (type == null) { - return null; + return typeInfo; } + DataFlowInfo dataFlowInfo = typeInfo.getDataFlowInfo(); // Special case for expr!! if (operationType == JetTokens.EXCLEXCL) { if (isKnownToBeNotNull(baseExpression, context)) { context.trace.report(UNNECESSARY_NOT_NULL_ASSERTION.on(operationSign, type)); } - return DataFlowUtils.checkType(TypeUtils.makeNotNullable(type), expression, context); + return DataFlowUtils.checkType(TypeUtils.makeNotNullable(type), expression, context, dataFlowInfo); } // Conventions for unary operations Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType); if (name == null) { context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression")); - return null; + return JetTypeInfo.create(null, dataFlowInfo); } // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc()) @@ -808,7 +812,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { name); if (!resolutionResults.isSuccess()) { - return null; + return JetTypeInfo.create(null, dataFlowInfo); } // Computing the return type @@ -836,7 +840,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { else { result = returnType; } - return DataFlowUtils.checkType(result, expression, context); + return DataFlowUtils.checkType(result, expression, context, dataFlowInfo); } private boolean isKnownToBeNotNull(JetExpression expression, ExpressionTypingContext context) { @@ -871,13 +875,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext context) { context.trace.report(UNRESOLVED_IDE_TEMPLATE.on(expression, ObjectUtils.notNull(expression.getText(), ""))); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } @Override - public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) { + public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) { ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetSimpleNameExpression operationSign = expression.getOperationReference(); @@ -951,13 +955,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) { if (right == null) { result = ErrorUtils.createErrorType("No right argument"); // TODO - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } checkInExpression(expression, expression.getOperationReference(), expression.getLeft(), expression.getRight(), context); result = booleanType; } else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) { - JetType leftType = facade.getType(left, context.replaceScope(context.scope)); + JetType leftType = facade.getType(left, context.replaceScope(context.scope)).getType(); WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||"); DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope, context); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition WritableScopeImpl rightScope = operationType == JetTokens.ANDAND @@ -965,7 +969,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { : newWritableScopeImpl(context, "Right scope of && or ||"); JetType rightType = right == null ? null - : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)); + : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType(); if (leftType != null && !isBoolean(leftType)) { context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType)); } @@ -975,17 +979,17 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { result = booleanType; } else if (operationType == JetTokens.ELVIS) { - JetType leftType = facade.getType(left, context.replaceScope(context.scope)); + JetType leftType = facade.getType(left, context.replaceScope(context.scope)).getType(); JetType rightType = right == null ? null - : facade.getType(right, contextWithExpectedType.replaceScope(context.scope)); + : facade.getType(right, contextWithExpectedType.replaceScope(context.scope)).getType(); if (leftType != null) { if (!leftType.isNullable()) { context.trace.report(USELESS_ELVIS.on(left, leftType)); } if (rightType != null) { DataFlowUtils.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType); - return TypeUtils.makeNullableAsSpecified(CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable()); + return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable()), context.dataFlowInfo); } } } @@ -993,7 +997,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation")); } } - return DataFlowUtils.checkType(result, expression, contextWithExpectedType); + return DataFlowUtils.checkType(result, expression, contextWithExpectedType, context.dataFlowInfo); } public boolean checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) { @@ -1014,9 +1018,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetExpression right = expression.getRight(); // TODO : duplicated effort for == and != - JetType leftType = facade.getType(left, context.replaceScope(context.scope)); + JetType leftType = facade.getType(left, context.replaceScope(context.scope)).getType(); if (leftType != null && right != null) { - JetType rightType = facade.getType(right, context.replaceScope(context.scope)); + JetType rightType = facade.getType(right, context.replaceScope(context.scope)).getType(); if (rightType != null) { if (TypeUtils.isIntersectionEmpty(leftType, rightType)) { @@ -1049,10 +1053,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitArrayAccessExpression(JetArrayAccessExpression expression, ExpressionTypingContext context) { JetType type = resolveArrayAccessGetMethod(expression, context.replaceExpectedType(NO_EXPECTED_TYPE)); DataFlowUtils.checkType(type, expression, context); - return type; + return JetTypeInfo.create(type, context.dataFlowInfo); } @Nullable @@ -1072,23 +1076,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) { + public JetTypeInfo visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) { context.trace.report(DECLARATION_IN_ILLEGAL_CONTEXT.on(dcl)); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } @Override - public JetType visitRootNamespaceExpression(JetRootNamespaceExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitRootNamespaceExpression(JetRootNamespaceExpression expression, ExpressionTypingContext context) { if (context.namespacesAllowed) { - return DataFlowUtils.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context); + return DataFlowUtils.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context, context.dataFlowInfo); } context.trace.report(NAMESPACE_IS_NOT_AN_EXPRESSION.on(expression)); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } @Override - public JetType visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) { + public JetTypeInfo visitStringTemplateExpression(JetStringTemplateExpression expression, ExpressionTypingContext contextWithExpectedType) { final ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); final StringBuilder builder = new StringBuilder(); final CompileTimeConstant[] value = new CompileTimeConstant[1]; @@ -1127,22 +1131,22 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (value[0] != CompileTimeConstantResolver.OUT_OF_RANGE) { context.trace.record(BindingContext.COMPILE_TIME_VALUE, expression, new StringValue(builder.toString())); } - return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getStringType(), expression, contextWithExpectedType); + return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getStringType(), expression, contextWithExpectedType, context.dataFlowInfo); } @Override - public JetType visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) { + public JetTypeInfo visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) { JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression == null) { - return null; + return JetTypeInfo.create(null, data.dataFlowInfo); } return facade.getType(baseExpression, data); } @Override - public JetType visitJetElement(JetElement element, ExpressionTypingContext context) { + public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext context) { context.trace.report(UNSUPPORTED.on(element, getClass().getCanonicalName())); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } @Nullable @@ -1161,7 +1165,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult, boolean isGet) { - JetType arrayType = facade.getType(arrayAccessExpression.getArrayExpression(), context); + JetType arrayType = facade.getType(arrayAccessExpression.getArrayExpression(), context).getType(); if (arrayType == null) return null; ExpressionReceiver receiver = new ExpressionReceiver(arrayAccessExpression.getArrayExpression(), arrayType); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 928d5abd6e9..2104323bb1c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -50,12 +50,12 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final ExpressionTypingContext context) { + public JetTypeInfo visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final ExpressionTypingContext context) { DelegatingBindingTrace delegatingBindingTrace = context.trace.get(TRACE_DELTAS_CACHE, expression.getObjectDeclaration()); if (delegatingBindingTrace != null) { delegatingBindingTrace.addAllMyDataTo(context.trace); JetType type = context.trace.get(EXPRESSION_TYPE, expression); - return DataFlowUtils.checkType(type, expression, context); + return DataFlowUtils.checkType(type, expression, context, context.dataFlowInfo); } final JetType[] result = new JetType[1]; final TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace); @@ -87,11 +87,11 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { temporaryTrace.addAllMyDataTo(cloneDelta); context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta); temporaryTrace.commit(); - return DataFlowUtils.checkType(result[0], expression, context); + return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo); } @Override - public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) { JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); if (bodyExpression == null) return null; @@ -123,7 +123,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { returnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); } returnType = context.expressionTypingServices.getBlockReturnedType(functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT, - context.replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace); + context.replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace).getType(); } temporaryTrace.commit(new Predicate() { @Override @@ -140,11 +140,11 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { JetType expectedReturnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType); if (JetStandardClasses.isUnit(expectedReturnType)) { functionDescriptor.setReturnType(JetStandardClasses.getUnitType()); - return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context); + return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context, context.dataFlowInfo); } } - return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.emptyList(), receiver, parameterTypes, safeReturnType), expression, context); + return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.emptyList(), receiver, parameterTypes, safeReturnType), expression, context, context.dataFlowInfo); } private SimpleFunctionDescriptorImpl createFunctionDescriptor(JetFunctionLiteralExpression expression, ExpressionTypingContext context, boolean functionTypeExpected) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index c5acf6daa01..9e302b454ee 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -65,7 +65,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) { if (condition != null) { - JetType conditionType = facade.getType(condition, context.replaceScope(scope)); + JetType conditionType = facade.getType(condition, context.replaceScope(scope)).getType(); if (conditionType != null && !isBoolean(conditionType)) { context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType)); @@ -77,11 +77,11 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { @Override - public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) { return visitIfExpression(expression, context, false); } - public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { + public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); JetExpression condition = expression.getCondition(); checkCondition(context.scope, condition, context); @@ -96,24 +96,24 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (elseBranch == null) { if (thenBranch != null) { - JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo), context.trace); + JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo), context.trace).getType(); if (type != null && JetStandardClasses.isNothing(type)) { facade.setResultingDataFlowInfo(elseInfo); } - return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement); + return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, context.dataFlowInfo); } - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } if (thenBranch == null) { - JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo), context.trace); + JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo), context.trace).getType(); if (type != null && JetStandardClasses.isNothing(type)) { facade.setResultingDataFlowInfo(thenInfo); } - return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement); + return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, context.dataFlowInfo); } CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION; - JetType thenType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo), context.trace); - JetType elseType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo), context.trace); + JetType thenType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo), context.trace).getType(); + JetType elseType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo), context.trace).getType(); JetType result; if (thenType == null) { @@ -135,16 +135,16 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { else if (jumpInElse && !jumpInThen) { facade.setResultingDataFlowInfo(thenInfo); } - if (result == null) return null; - return DataFlowUtils.checkImplicitCast(result, expression, contextWithExpectedType, isStatement); + if (result == null) return JetTypeInfo.create(null, context.dataFlowInfo); + return DataFlowUtils.checkImplicitCast(result, expression, contextWithExpectedType, isStatement, context.dataFlowInfo); } @Override - public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) { return visitWhileExpression(expression, context, false); } - public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { + public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade); ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); @@ -159,7 +159,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (!containsBreak(expression, context)) { facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context)); } - return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); + return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, context.dataFlowInfo); } private boolean containsBreak(final JetLoopExpression loopExpression, final ExpressionTypingContext context) { @@ -187,10 +187,10 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) { return visitDoWhileExpression(expression, context, false); } - public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { + public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade); ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); @@ -225,15 +225,15 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (!containsBreak(expression, context)) { facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context)); } - return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); + return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, context.dataFlowInfo); } @Override - public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext context) { return visitForExpression(expression, context, false); } - public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { + public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { if (!isStatement) return DataFlowUtils.illegalStatementType(expression, contextWithExpectedType, facade); ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); @@ -286,7 +286,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context, context.trace); } - return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); + return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, context.dataFlowInfo); } @Nullable @@ -403,7 +403,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitTryExpression(JetTryExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext context) { JetExpression tryBlock = expression.getTryBlock(); List catchClauses = expression.getCatchClauses(); JetFinallySection finallyBlock = expression.getFinallyBlock(); @@ -419,7 +419,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (catchBody != null) { WritableScope catchScope = newWritableScopeImpl(context, "Catch scope"); catchScope.addVariableDescriptor(variableDescriptor); - JetType type = facade.getType(catchBody, context.replaceScope(catchScope)); + JetType type = facade.getType(catchBody, context.replaceScope(catchScope)).getType(); if (type != null) { types.add(type); } @@ -429,30 +429,30 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (finallyBlock != null) { facade.getType(finallyBlock.getFinalExpression(), context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)); } - JetType type = facade.getType(tryBlock, context); + JetType type = facade.getType(tryBlock, context).getType(); if (type != null) { types.add(type); } if (types.isEmpty()) { - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } else { - return CommonSupertypes.commonSupertype(types); + return JetTypeInfo.create(CommonSupertypes.commonSupertype(types), context.dataFlowInfo); } } @Override - public JetType visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext context) { JetExpression thrownExpression = expression.getThrownExpression(); if (thrownExpression != null) { JetType throwableType = JetStandardLibrary.getInstance().getThrowable().getDefaultType(); facade.getType(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope)); } - return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context); + return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo); } @Override - public JetType visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext context) { JetElement element = context.labelResolver.resolveLabel(expression, context); JetExpression returnedExpression = expression.getReturnedExpression(); @@ -508,18 +508,18 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType)); } } - return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context); + return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo); } @Override - public JetType visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext context) { context.labelResolver.resolveLabel(expression, context); - return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context); + return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo); } @Override - public JetType visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext context) { context.labelResolver.resolveLabel(expression, context); - return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context); + return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index d2f9a040861..80c82d152f7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValue; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.types.JetTypeInfo; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; @@ -151,6 +152,11 @@ public class DataFlowUtils { return context.dataFlowInfo.and(result.get()); } + @NotNull + public static JetTypeInfo checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull DataFlowInfo dataFlowInfo) { + return JetTypeInfo.create(checkType(expressionType, expression, context), dataFlowInfo); + } + @Nullable public static JetType checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context) { if (expressionType == null || context.expectedType == null || context.expectedType == TypeUtils.NO_EXPECTED_TYPE || @@ -174,6 +180,11 @@ public class DataFlowUtils { return expressionType; } + @NotNull + public static JetTypeInfo checkStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull DataFlowInfo dataFlowInfo) { + return JetTypeInfo.create(checkStatementType(expression, context), dataFlowInfo); + } + @Nullable public static JetType checkStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context) { if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(context.expectedType)) { @@ -183,6 +194,11 @@ public class DataFlowUtils { return JetStandardClasses.getUnitType(); } + @NotNull + public static JetTypeInfo checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement, DataFlowInfo dataFlowInfo) { + return JetTypeInfo.create(checkImplicitCast(expressionType, expression, context, isStatement), dataFlowInfo); + } + @Nullable public static JetType checkImplicitCast(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context, boolean isStatement) { if (expressionType != null && context.expectedType == TypeUtils.NO_EXPECTED_TYPE && !isStatement && @@ -193,10 +209,10 @@ public class DataFlowUtils { return expressionType; } - @Nullable - public static JetType illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) { + @NotNull + public static JetTypeInfo illegalStatementType(@NotNull JetExpression expression, @NotNull ExpressionTypingContext context, @NotNull ExpressionTypingInternals facade) { facade.checkStatementType(expression, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)); context.trace.report(EXPRESSION_EXPECTED.on(expression, expression)); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java index e337c2781ee..9311190026a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java @@ -19,18 +19,18 @@ package org.jetbrains.jet.lang.types.expressions; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.JetTypeInfo; /** * @author abreslav */ public interface ExpressionTypingFacade { @NotNull - JetType safeGetType(@NotNull JetExpression expression, ExpressionTypingContext context); + JetTypeInfo safeGetType(@NotNull JetExpression expression, ExpressionTypingContext context); - @Nullable - JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context); + @NotNull + JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context); - @Nullable - JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement); + @NotNull + JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index da74017946c..3bf1540bee6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -37,6 +37,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.CommonSupertypes; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.JetTypeInfo; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lexer.JetTokens; @@ -119,13 +120,13 @@ public class ExpressionTypingServices { ExpressionTypingContext context = ExpressionTypingContext.newContext( this, trace, scope, dataFlowInfo, expectedType, false ); - return expressionTypingFacade.getType(expression, context); + return expressionTypingFacade.getType(expression, context).getType(); } public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull BindingTrace trace) { ExpressionTypingContext context = ExpressionTypingContext.newContext( this, trace, scope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, true); - return expressionTypingFacade.getType(expression, context); + return expressionTypingFacade.getType(expression, context).getType(); // return ((ExpressionTypingContext) ExpressionTyperVisitorWithNamespaces).INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE)); } @@ -174,8 +175,8 @@ public class ExpressionTypingServices { } } - @Nullable - public JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull JetBlockExpression expression, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) { + @NotNull + public JetTypeInfo getBlockReturnedType(@NotNull JetScope outerScope, @NotNull JetBlockExpression expression, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) { List block = expression.getStatements(); DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration(); @@ -190,9 +191,9 @@ public class ExpressionTypingServices { outerScope, containingDescriptor, new TraceBasedRedeclarationHandler(context.trace), "getBlockReturnedType"); scope.changeLockLevel(WritableScope.LockLevel.BOTH); - JetType r; + JetTypeInfo r; if (block.isEmpty()) { - r = DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, context); + r = DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, context, context.dataFlowInfo); } else { r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression, context, trace); @@ -262,15 +263,15 @@ public class ExpressionTypingServices { /*package*/ @SuppressWarnings("SuspiciousMethodCalls") - JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List block, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) { + JetTypeInfo getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List block, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) { if (block.isEmpty()) { - return JetStandardClasses.getUnitType(); + return JetTypeInfo.create(JetStandardClasses.getUnitType(), context.dataFlowInfo); } ExpressionTypingInternals blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(scope); ExpressionTypingContext newContext = createContext(context, trace, scope, context.dataFlowInfo, NO_EXPECTED_TYPE); - JetType result = null; + JetTypeInfo result = JetTypeInfo.create(null, context.dataFlowInfo); for (Iterator iterator = block.iterator(); iterator.hasNext(); ) { final JetElement statement = iterator.next(); trace.record(STATEMENT, statement); @@ -323,8 +324,8 @@ public class ExpressionTypingServices { } if (mightBeUnit) { // ExpressionTypingVisitorForStatements should return only null or Unit for declarations and assignments - assert result == null || JetStandardClasses.isUnit(result); - result = JetStandardClasses.getUnitType(); + assert result.getType() == null || JetStandardClasses.isUnit(result.getType()); + result = JetTypeInfo.create(JetStandardClasses.getUnitType(), newContext.dataFlowInfo); } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index e0c2c1386a9..ff35f88cf7b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -71,12 +71,12 @@ public class ExpressionTypingUtils { @Nullable protected static ExpressionReceiver getExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) { - return getExpressionReceiver(expression, facade.getType(expression, context)); + return getExpressionReceiver(expression, facade.getType(expression, context).getType()); } @NotNull protected static ExpressionReceiver safeGetExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) { - return new ExpressionReceiver(expression, facade.safeGetType(expression, context)); + return new ExpressionReceiver(expression, facade.safeGetType(expression, context).getType()); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitor.java index 35db609ede3..3591da4a02c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitor.java @@ -18,12 +18,12 @@ package org.jetbrains.jet.lang.types.expressions; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetVisitor; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.JetTypeInfo; /** * @author abreslav */ -/*package*/ abstract class ExpressionTypingVisitor extends JetVisitor { +/*package*/ abstract class ExpressionTypingVisitor extends JetVisitor { protected final ExpressionTypingInternals facade; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index 37281751222..d95f0d34bd7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.DeferredType; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.JetTypeInfo; import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException; import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM; @@ -34,10 +35,10 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO /** * @author abreslav */ -public class ExpressionTypingVisitorDispatcher extends JetVisitor implements ExpressionTypingInternals { +public class ExpressionTypingVisitorDispatcher extends JetVisitor implements ExpressionTypingInternals { @Override - public JetType visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext data) { + public JetTypeInfo visitIdeTemplateExpression(JetIdeTemplateExpression expression, ExpressionTypingContext data) { return basic.visitIdeTemplateExpression(expression, data); } @@ -91,22 +92,22 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor visitor) { + @NotNull + private JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor visitor) { if (context.trace.get(BindingContext.PROCESSED, expression)) { - return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression); + return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression), context.dataFlowInfo); } - JetType result; + JetTypeInfo result; try { result = expression.accept(visitor, context); // Some recursive definitions (object expressions) must put their types in the cache manually: if (context.trace.get(BindingContext.PROCESSED, expression)) { - return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression); + return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression), result.getDataFlowInfo()); } - if (result instanceof DeferredType) { - result = ((DeferredType) result).getActualType(); + if (result.getType() instanceof DeferredType) { + result = JetTypeInfo.create(((DeferredType) result.getType()).getActualType(), context.dataFlowInfo); } - if (result != null) { - context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result); + if (result.getType() != null) { + context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result.getType()); } } catch (ReenteringLazyValueComputationException e) { context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression)); - result = null; + result = JetTypeInfo.create(null, context.dataFlowInfo); } if (!context.trace.get(BindingContext.PROCESSED, expression) && !(expression instanceof JetReferenceExpression)) { @@ -159,78 +160,78 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor"))); - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java index 4dc1782cd92..216fe3d86de 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java @@ -52,27 +52,28 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { } @Override - public JetType visitIsExpression(JetIsExpression expression, ExpressionTypingContext contextWithExpectedType) { + public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext contextWithExpectedType) { ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); JetExpression leftHandSide = expression.getLeftHandSide(); - JetType knownType = facade.safeGetType(leftHandSide, context.replaceScope(context.scope)); + JetType knownType = facade.safeGetType(leftHandSide, context.replaceScope(context.scope)).getType(); JetPattern pattern = expression.getPattern(); + DataFlowInfo newDataFlowInfo = context.dataFlowInfo; if (pattern != null) { WritableScopeImpl scopeToExtend = newWritableScopeImpl(context, "Scope extended in 'is'"); DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(leftHandSide, knownType, context.trace.getBindingContext()); - DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, false, scopeToExtend, context, dataFlowValue); + newDataFlowInfo = checkPatternType(pattern, knownType, false, scopeToExtend, context, dataFlowValue); context.patternsToDataFlowInfo.put(pattern, newDataFlowInfo); context.patternsToBoundVariableLists.put(pattern, scopeToExtend.getDeclaredVariables()); } - return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getBooleanType(), expression, contextWithExpectedType); + return DataFlowUtils.checkType(JetStandardLibrary.getInstance().getBooleanType(), expression, contextWithExpectedType, newDataFlowInfo); } @Override - public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) { + public JetTypeInfo visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) { return visitWhenExpression(expression, context, false); } - public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { + public JetTypeInfo visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) { ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); // TODO :change scope according to the bound value in the when header final JetExpression subjectExpression = expression.getSubjectExpression(); @@ -122,7 +123,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { if (bodyExpression != null) { ExpressionTypingContext newContext = contextWithExpectedType.replaceScope(scopeToExtend).replaceDataFlowInfo(newDataFlowInfo); CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION; - JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace); + JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace).getType(); if (type != null) { expressionTypes.add(type); } @@ -130,9 +131,9 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { } if (!expressionTypes.isEmpty()) { - return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement); + return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement, context.dataFlowInfo); } - return null; + return JetTypeInfo.create(null, context.dataFlowInfo); } private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final boolean expectedCondition, final JetType subjectType, JetWhenCondition condition, final WritableScope scopeToExtend, final ExpressionTypingContext context, final DataFlowValue... subjectVariables) { @@ -245,7 +246,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { public void visitExpressionPattern(JetExpressionPattern pattern) { JetExpression expression = pattern.getExpression(); if (expression == null) return; - JetType type = facade.getType(expression, context.replaceScope(scopeToExtend)); + JetType type = facade.getType(expression, context.replaceScope(scopeToExtend)).getType(); if (conditionExpected) { JetType booleanType = JetStandardLibrary.getInstance().getBooleanType(); if (type != null && !JetTypeChecker.INSTANCE.equalTypes(booleanType, type)) { From 3e79d3c83454c57bbb85648dfbed496937702805 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 13 Jun 2012 17:19:26 +0400 Subject: [PATCH 02/11] getType -> getTypeInfo --- .../BasicExpressionTypingVisitor.java | 34 ++++++++++--------- .../ControlStructureTypingVisitor.java | 18 +++++----- .../expressions/ExpressionTypingFacade.java | 6 ++-- .../expressions/ExpressionTypingServices.java | 18 +++++----- .../expressions/ExpressionTypingUtils.java | 4 +-- .../ExpressionTypingVisitorDispatcher.java | 24 +++++++------ .../ExpressionTypingVisitorForStatements.java | 16 ++++----- .../PatternMatchingTypingVisitor.java | 6 ++-- 8 files changed, 66 insertions(+), 60 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index a8973e53394..32f3698bc8a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -146,7 +146,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (innerExpression == null) { return JetTypeInfo.create(null, context.dataFlowInfo); } - JetTypeInfo typeInfo = facade.getType(innerExpression, context.replaceScope(context.scope), isStatement); + JetTypeInfo typeInfo = facade.getTypeInfo(innerExpression, context.replaceScope(context.scope), isStatement); return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); } @@ -213,14 +213,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { result = operationType == JetTokens.AS_SAFE ? TypeUtils.makeNullable(targetType) : targetType; } else { - facade.getType(expression.getLeft(), context.replaceExpectedType(NO_EXPECTED_TYPE)); + facade.getTypeInfo(expression.getLeft(), context.replaceExpectedType(NO_EXPECTED_TYPE)); } return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); } private boolean checkBinaryWithTypeRHS(JetBinaryExpressionWithTypeRHS expression, ExpressionTypingContext context, @NotNull JetType targetType) { - JetType actualType = facade.getType(expression.getLeft(), context).getType(); + JetType actualType = facade.getTypeInfo(expression.getLeft(), context).getType(); if (actualType == null) return false; JetSimpleNameExpression operationSign = expression.getOperationSign(); @@ -532,7 +532,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression receiverExpression = expression.getReceiverExpression(); ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE); - JetTypeInfo receiverTypeInfo = facade.getType(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true)); + JetTypeInfo receiverTypeInfo = facade.getTypeInfo(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true)); JetType receiverType = receiverTypeInfo.getType(); if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo); if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText()); @@ -764,7 +764,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { referencedName = referencedName == null ? " " : referencedName; context.labelResolver.enterLabeledElement(new LabelName(referencedName.substring(1)), baseExpression); // TODO : Some processing for the label? - JetTypeInfo typeInfo = facade.getType(baseExpression, context, isStatement); + JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context, isStatement); context.labelResolver.exitLabeledElement(baseExpression); return DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo()); } @@ -772,7 +772,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { IElementType operationType = operationSign.getReferencedNameElementType(); // Type check the base expression - JetTypeInfo typeInfo = facade.getType(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE)); + JetTypeInfo typeInfo = facade.getTypeInfo(baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE)); JetType type = typeInfo.getType(); if (type == null) { return typeInfo; @@ -961,7 +961,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { result = booleanType; } else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) { - JetType leftType = facade.getType(left, context.replaceScope(context.scope)).getType(); + JetType leftType = facade.getTypeInfo(left, context.replaceScope(context.scope)).getType(); WritableScopeImpl leftScope = newWritableScopeImpl(context, "Left scope of && or ||"); DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope, context); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition WritableScopeImpl rightScope = operationType == JetTokens.ANDAND @@ -969,7 +969,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { : newWritableScopeImpl(context, "Right scope of && or ||"); JetType rightType = right == null ? null - : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType(); + : facade.getTypeInfo(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType(); if (leftType != null && !isBoolean(leftType)) { context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType)); } @@ -979,17 +979,19 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { result = booleanType; } else if (operationType == JetTokens.ELVIS) { - JetType leftType = facade.getType(left, context.replaceScope(context.scope)).getType(); + JetType leftType = facade.getTypeInfo(left, context.replaceScope(context.scope)).getType(); JetType rightType = right == null ? null - : facade.getType(right, contextWithExpectedType.replaceScope(context.scope)).getType(); + : facade.getTypeInfo(right, contextWithExpectedType.replaceScope(context.scope)).getType(); if (leftType != null) { if (!leftType.isNullable()) { context.trace.report(USELESS_ELVIS.on(left, leftType)); } if (rightType != null) { DataFlowUtils.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType); - return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified(CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable()), context.dataFlowInfo); + return JetTypeInfo.create(TypeUtils.makeNullableAsSpecified( + CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable()), + context.dataFlowInfo); } } } @@ -1018,9 +1020,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetExpression right = expression.getRight(); // TODO : duplicated effort for == and != - JetType leftType = facade.getType(left, context.replaceScope(context.scope)).getType(); + JetType leftType = facade.getTypeInfo(left, context.replaceScope(context.scope)).getType(); if (leftType != null && right != null) { - JetType rightType = facade.getType(right, context.replaceScope(context.scope)).getType(); + JetType rightType = facade.getTypeInfo(right, context.replaceScope(context.scope)).getType(); if (rightType != null) { if (TypeUtils.isIntersectionEmpty(leftType, rightType)) { @@ -1103,7 +1105,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { public void visitStringTemplateEntryWithExpression(JetStringTemplateEntryWithExpression entry) { JetExpression entryExpression = entry.getExpression(); if (entryExpression != null) { - facade.getType(entryExpression, context); + facade.getTypeInfo(entryExpression, context); } value[0] = CompileTimeConstantResolver.OUT_OF_RANGE; } @@ -1140,7 +1142,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { if (baseExpression == null) { return JetTypeInfo.create(null, data.dataFlowInfo); } - return facade.getType(baseExpression, data); + return facade.getTypeInfo(baseExpression, data); } @Override @@ -1165,7 +1167,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult, boolean isGet) { - JetType arrayType = facade.getType(arrayAccessExpression.getArrayExpression(), context).getType(); + JetType arrayType = facade.getTypeInfo(arrayAccessExpression.getArrayExpression(), context).getType(); if (arrayType == null) return null; ExpressionReceiver receiver = new ExpressionReceiver(arrayAccessExpression.getArrayExpression(), arrayType); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 9e302b454ee..f62506382e1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -65,7 +65,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) { if (condition != null) { - JetType conditionType = facade.getType(condition, context.replaceScope(scope)).getType(); + JetType conditionType = facade.getTypeInfo(condition, context.replaceScope(scope)).getType(); if (conditionType != null && !isBoolean(conditionType)) { context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType)); @@ -100,7 +100,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (type != null && JetStandardClasses.isNothing(type)) { facade.setResultingDataFlowInfo(elseInfo); } - return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, context.dataFlowInfo); + return DataFlowUtils.checkImplicitCast( + DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, + contextWithExpectedType, isStatement, context.dataFlowInfo); } return JetTypeInfo.create(null, context.dataFlowInfo); } @@ -205,7 +207,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { context.trace.record(BindingContext.BLOCK, function); } else { - facade.getType(body, context.replaceScope(context.scope)); + facade.getTypeInfo(body, context.replaceScope(context.scope)); } } else if (body != null) { @@ -419,7 +421,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (catchBody != null) { WritableScope catchScope = newWritableScopeImpl(context, "Catch scope"); catchScope.addVariableDescriptor(variableDescriptor); - JetType type = facade.getType(catchBody, context.replaceScope(catchScope)).getType(); + JetType type = facade.getTypeInfo(catchBody, context.replaceScope(catchScope)).getType(); if (type != null) { types.add(type); } @@ -427,9 +429,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } } if (finallyBlock != null) { - facade.getType(finallyBlock.getFinalExpression(), context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)); + facade.getTypeInfo(finallyBlock.getFinalExpression(), context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE)); } - JetType type = facade.getType(tryBlock, context).getType(); + JetType type = facade.getTypeInfo(tryBlock, context).getType(); if (type != null) { types.add(type); } @@ -446,7 +448,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { JetExpression thrownExpression = expression.getThrownExpression(); if (thrownExpression != null) { JetType throwableType = JetStandardLibrary.getInstance().getThrowable().getDefaultType(); - facade.getType(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope)); + facade.getTypeInfo(thrownExpression, context.replaceExpectedType(throwableType).replaceScope(context.scope)); } return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context, context.dataFlowInfo); } @@ -501,7 +503,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } } if (returnedExpression != null) { - facade.getType(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope)); + facade.getTypeInfo(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope)); } else { if (expectedType != TypeUtils.NO_EXPECTED_TYPE && expectedType != null && !JetStandardClasses.isUnit(expectedType)) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java index 9311190026a..68db9342cb4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingFacade.java @@ -26,11 +26,11 @@ import org.jetbrains.jet.lang.types.JetTypeInfo; */ public interface ExpressionTypingFacade { @NotNull - JetTypeInfo safeGetType(@NotNull JetExpression expression, ExpressionTypingContext context); + JetTypeInfo safeGetTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context); @NotNull - JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context); + JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context); @NotNull - JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement); + JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index 3bf1540bee6..4cee67c1b5a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -120,13 +120,13 @@ public class ExpressionTypingServices { ExpressionTypingContext context = ExpressionTypingContext.newContext( this, trace, scope, dataFlowInfo, expectedType, false ); - return expressionTypingFacade.getType(expression, context).getType(); + return expressionTypingFacade.getTypeInfo(expression, context).getType(); } public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull BindingTrace trace) { ExpressionTypingContext context = ExpressionTypingContext.newContext( this, trace, scope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, true); - return expressionTypingFacade.getType(expression, context).getType(); + return expressionTypingFacade.getTypeInfo(expression, context).getType(); // return ((ExpressionTypingContext) ExpressionTyperVisitorWithNamespaces).INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE)); } @@ -171,7 +171,7 @@ public class ExpressionTypingServices { getBlockReturnedType(newContext.scope, blockExpression, CoercionStrategy.COERCION_TO_UNIT, context, trace); } else { - expressionTypingFacade.getType(bodyExpression, newContext, !blockBody); + expressionTypingFacade.getTypeInfo(bodyExpression, newContext, !blockBody); } } @@ -215,7 +215,7 @@ public class ExpressionTypingServices { JetExpression bodyExpression = function.getBodyExpression(); assert bodyExpression != null; JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace); - expressionTypingFacade.getType(bodyExpression, ExpressionTypingContext.newContext( + expressionTypingFacade.getTypeInfo(bodyExpression, ExpressionTypingContext.newContext( this, trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, false), !function.hasBlockBody()); //todo function literals @@ -285,13 +285,13 @@ public class ExpressionTypingServices { final boolean[] mismatch = new boolean[1]; ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch); newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType); - result = blockLevelVisitor.getType(statementExpression, newContext, true); + result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true); if (mismatch[0]) { TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace); mismatch[0] = false; ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch); newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE); - result = blockLevelVisitor.getType(statementExpression, newContext, true); + result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true); if (mismatch[0]) { temporaryTraceExpectingUnit.commit(); } @@ -305,11 +305,11 @@ public class ExpressionTypingServices { } else { newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType); - result = blockLevelVisitor.getType(statementExpression, newContext, true); + result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true); } } else { - result = blockLevelVisitor.getType(statementExpression, newContext, true); + result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true); if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) { boolean mightBeUnit = false; if (statementExpression instanceof JetDeclaration) { @@ -331,7 +331,7 @@ public class ExpressionTypingServices { } } else { - result = blockLevelVisitor.getType(statementExpression, newContext, true); + result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true); } DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index ff35f88cf7b..519ac39f5d6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -71,12 +71,12 @@ public class ExpressionTypingUtils { @Nullable protected static ExpressionReceiver getExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) { - return getExpressionReceiver(expression, facade.getType(expression, context).getType()); + return getExpressionReceiver(expression, facade.getTypeInfo(expression, context).getType()); } @NotNull protected static ExpressionReceiver safeGetExpressionReceiver(@NotNull ExpressionTypingFacade facade, @NotNull JetExpression expression, ExpressionTypingContext context) { - return new ExpressionReceiver(expression, facade.safeGetType(expression, context).getType()); + return new ExpressionReceiver(expression, facade.safeGetTypeInfo(expression, context).getType()); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index d95f0d34bd7..b88a66b37e2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -92,8 +92,8 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor visitor) { + private JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor visitor) { if (context.trace.get(BindingContext.PROCESSED, expression)) { - return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression), context.dataFlowInfo); + return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression), + context.dataFlowInfo); } JetTypeInfo result; try { result = expression.accept(visitor, context); // Some recursive definitions (object expressions) must put their types in the cache manually: if (context.trace.get(BindingContext.PROCESSED, expression)) { - return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression), result.getDataFlowInfo()); + return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression), + result.getDataFlowInfo()); } if (result.getType() instanceof DeferredType) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index 88520c4a0ab..1e7a3a14883 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -112,7 +112,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito JetExpression initializer = property.getInitializer(); if (property.getPropertyTypeRef() != null && initializer != null) { JetType outType = propertyDescriptor.getType(); - JetType initializerType = facade.getType(initializer, context.replaceExpectedType(outType).replaceScope(scope)).getType(); + JetType initializerType = facade.getTypeInfo(initializer, context.replaceExpectedType(outType).replaceScope(scope)).getType(); } { @@ -169,7 +169,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito result = visitAssignmentOperation(expression, context); } else { - return facade.getType(expression, context); + return facade.getTypeInfo(expression, context); } return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo); } @@ -187,9 +187,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft()); if (left == null) return null; - JetType leftType = facade.getType(left, context).getType(); + JetType leftType = facade.getTypeInfo(left, context).getType(); if (leftType == null) { - facade.getType(right, context); + facade.getTypeInfo(right, context); context.trace.report(UNRESOLVED_REFERENCE.on(operationSign)); temporaryBindingTrace.commit(); return null; @@ -217,7 +217,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito for (ResolvedCall call : ambiguityResolutionResults.getResultingCalls()) { descriptors.add(call.getResultingDescriptor()); } - facade.getType(right, context); + facade.getTypeInfo(right, context); context.trace.record(AMBIGUOUS_REFERENCE_TARGET, operationSign, descriptors); } else if (assignmentOperationType != null) { @@ -250,9 +250,9 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito basic.checkLValue(context.trace, arrayAccessExpression); return checkAssignmentType(assignmentType, expression, contextWithExpectedType); } - JetType leftType = facade.getType(expression.getLeft(), context.replaceScope(scope)).getType(); + JetType leftType = facade.getTypeInfo(expression.getLeft(), context.replaceScope(scope)).getType(); if (right != null) { - JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope)).getType(); + JetType rightType = facade.getTypeInfo(right, context.replaceExpectedType(leftType).replaceScope(scope)).getType(); } if (leftType != null) { //if leftType == null, some another error has been generated basic.checkLValue(context.trace, expression.getLeft()); @@ -263,7 +263,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito @Override public JetTypeInfo visitExpression(JetExpression expression, ExpressionTypingContext context) { - return facade.getType(expression, context); + return facade.getTypeInfo(expression, context); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java index 216fe3d86de..b15315267ca 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java @@ -55,7 +55,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext contextWithExpectedType) { ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE); JetExpression leftHandSide = expression.getLeftHandSide(); - JetType knownType = facade.safeGetType(leftHandSide, context.replaceScope(context.scope)).getType(); + JetType knownType = facade.safeGetTypeInfo(leftHandSide, context.replaceScope(context.scope)).getType(); JetPattern pattern = expression.getPattern(); DataFlowInfo newDataFlowInfo = context.dataFlowInfo; if (pattern != null) { @@ -146,7 +146,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { if (rangeExpression == null) return; if (expectedCondition) { context.trace.report(EXPECTED_CONDITION.on(condition)); - facade.getType(rangeExpression, context); + facade.getTypeInfo(rangeExpression, context); return; } if (!facade.checkInExpression(condition, condition.getOperationReference(), subjectExpression, rangeExpression, context)) { @@ -246,7 +246,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { public void visitExpressionPattern(JetExpressionPattern pattern) { JetExpression expression = pattern.getExpression(); if (expression == null) return; - JetType type = facade.getType(expression, context.replaceScope(scopeToExtend)).getType(); + JetType type = facade.getTypeInfo(expression, context.replaceScope(scopeToExtend)).getType(); if (conditionExpected) { JetType booleanType = JetStandardLibrary.getInstance().getBooleanType(); if (type != null && !JetTypeChecker.INSTANCE.equalTypes(booleanType, type)) { From c3420e864e4986d2ef60ab79bcff109f01896e2f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 14 Jun 2012 14:16:42 +0400 Subject: [PATCH 03/11] get resulting DataFlowInfo from JetTypeInfo instead of facade --- .../jet/lang/types/expressions/ExpressionTypingServices.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index 4cee67c1b5a..dc68014f924 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -334,10 +334,7 @@ public class ExpressionTypingServices { result = blockLevelVisitor.getTypeInfo(statementExpression, newContext, true); } - DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo(); - if (newDataFlowInfo == null) { - newDataFlowInfo = context.dataFlowInfo; - } + DataFlowInfo newDataFlowInfo = result.getDataFlowInfo(); if (newDataFlowInfo != context.dataFlowInfo) { newContext = createContext(newContext, trace, scope, newDataFlowInfo, NO_EXPECTED_TYPE); } From efe70955dd3d345b902d9a6e9ca67049d1003801 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 14 Jun 2012 17:29:57 +0400 Subject: [PATCH 04/11] dataFlowInfoTraversal tests --- .../tests/dataFlowInfoTraversal/AndOr.jet | 12 ++++++++ .../dataFlowInfoTraversal/ArrayAccess.jet | 13 ++++++++ .../BinaryExpression.jet | 9 ++++++ .../tests/dataFlowInfoTraversal/DeepIf.jet | 30 +++++++++++++++++++ .../tests/dataFlowInfoTraversal/DoWhile.jet | 16 ++++++++++ .../tests/dataFlowInfoTraversal/Elvis.jet | 9 ++++++ .../tests/dataFlowInfoTraversal/ExclExcl.jet | 13 ++++++++ .../tests/dataFlowInfoTraversal/For.jet | 24 +++++++++++++++ .../dataFlowInfoTraversal/FunctionLiteral.jet | 9 ++++++ .../dataFlowInfoTraversal/IfThenElse.jet | 30 +++++++++++++++++++ .../IfThenElseBothInvalid.jet | 16 ++++++++++ .../ObjectExpression.jet | 10 +++++++ .../QualifiedExpression.jet | 13 ++++++++ .../tests/dataFlowInfoTraversal/Return.jet | 12 ++++++++ .../tests/dataFlowInfoTraversal/ThisSuper.jet | 21 +++++++++++++ .../tests/dataFlowInfoTraversal/Throw.jet | 10 +++++++ .../tests/dataFlowInfoTraversal/TryCatch.jet | 15 ++++++++++ .../dataFlowInfoTraversal/UnaryExpression.jet | 14 +++++++++ .../tests/dataFlowInfoTraversal/When.jet | 18 +++++++++++ .../tests/dataFlowInfoTraversal/While.jet | 22 ++++++++++++++ 20 files changed, 316 insertions(+) create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/AndOr.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ArrayAccess.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/BinaryExpression.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DeepIf.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DoWhile.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Elvis.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/For.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/FunctionLiteral.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElse.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElseBothInvalid.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ObjectExpression.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/QualifiedExpression.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ThisSuper.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/TryCatch.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/UnaryExpression.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/When.jet create mode 100644 compiler/testData/diagnostics/tests/dataFlowInfoTraversal/While.jet diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/AndOr.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/AndOr.jet new file mode 100644 index 00000000000..a2272cfd94c --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/AndOr.jet @@ -0,0 +1,12 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + if (x != null && bar(x) == 0) bar(bar(x)) + bar(x) + if (x == null || bar(x) == 0) bar(bar(x)) + bar(x) + if (x is Int && bar(x)*bar(x) == bar(x)) bar(x) + bar(x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ArrayAccess.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ArrayAccess.jet new file mode 100644 index 00000000000..3d178c3f5dd --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ArrayAccess.jet @@ -0,0 +1,13 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + val a = Array(3, {0}) + + if (x != null) bar(a[x]) else bar(a[x]) + bar(a[if (x == null) 0 else x]) + bar(a[x]) + + "123"[x]; + if (x != null) "123"[x]; +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/BinaryExpression.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/BinaryExpression.jet new file mode 100644 index 00000000000..e64572a063c --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/BinaryExpression.jet @@ -0,0 +1,9 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + bar(1 + (if (x == null) 0 else x)) + bar(if (x == null) x else x) + if (x != null) bar(x + x/(x-x*x)) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DeepIf.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DeepIf.jet new file mode 100644 index 00000000000..5373ed1f4d4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DeepIf.jet @@ -0,0 +1,30 @@ +fun bar(x: Int) = x + 1 + +fun foo() { + val x: Int? = null + + if (x != null) { + bar(x) + if (x != null) { + bar(x) + if (1 < 2) bar(x) + if (1 > 2) bar(x) + } + if (x == null) { + bar(x) + } + if (x == null) bar(x) else bar(x) + bar(bar(x)) + } else if (x == null) { + bar(x) + if (x != null) { + bar(x) + if (x == null) bar(x) + if (x == null) bar(x) else bar(x) + bar(bar(x) + bar(x)) + } else if (x == null) { + bar(x) + } + } + +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DoWhile.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DoWhile.jet new file mode 100644 index 00000000000..7117aeb2c1c --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/DoWhile.jet @@ -0,0 +1,16 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + do { + bar(x) + } while (x == null) + bar(x) + + val y: Int? = null + do { + bar(y) + } while (y != null) + bar(y) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Elvis.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Elvis.jet new file mode 100644 index 00000000000..fcfdbb7b7b7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Elvis.jet @@ -0,0 +1,9 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + bar(x ?: 0) + if (x != null) bar(x ?: x) + bar(x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet new file mode 100644 index 00000000000..94d44069aec --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.jet @@ -0,0 +1,13 @@ +fun bar(x: Int) = x + 1 + +fun foo() { + val x: Int? = null + + bar(x) + if (x != null) bar(x!!) + if (x == null) bar(x!!) + if (x != null) else bar(x!!) + if (x == null) else bar(x!!) + if (x != null) bar(x!!) else bar(x!!) + if (x == null) bar(x!!) else bar(x!!) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/For.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/For.jet new file mode 100644 index 00000000000..aa1ef31839c --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/For.jet @@ -0,0 +1,24 @@ +import java.util.HashMap + +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + val a = Array(3, {0}) + + for (p in a) { + bar(x) + if (x == null) continue + bar(x) + for (q in a) { + bar(x) + if (x == null) bar(x) + } + } + + for (p in a) { + bar(x) + if (x == null) break + bar(x) + } +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/FunctionLiteral.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/FunctionLiteral.jet new file mode 100644 index 00000000000..b78bfc8489f --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/FunctionLiteral.jet @@ -0,0 +1,9 @@ +fun bar(x: Int) = x + 1 + +fun foo() { + val x: Int? = null + + fun baz() = bar(x) + fun quux() = if (x != null) bar(x) else baz() + fun quuux() = bar(if (x == null) 0 else x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElse.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElse.jet new file mode 100644 index 00000000000..bc1e14b7dab --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElse.jet @@ -0,0 +1,30 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + bar(if (x == null) 0 else x) + + if (x == null) { + bar(x) + return + } else { + bar(x) + } + bar(x) + + val y: Int? = null + if (y is Int) { + bar(y) + } else { + bar(y) + return + } + bar(y) + + val z: Int? = null + if (z != null) bar(z) + bar(z) + bar(z!!) + if (z != null) bar(z!!) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElseBothInvalid.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElseBothInvalid.jet new file mode 100644 index 00000000000..37f20e95089 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/IfThenElseBothInvalid.jet @@ -0,0 +1,16 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + bar(x) + if (x != 2) { + if (x == null) return + 2+ + } + else { + if (x == null) return + 2+ + } + bar(x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ObjectExpression.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ObjectExpression.jet new file mode 100644 index 00000000000..74ed7fbbdc0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ObjectExpression.jet @@ -0,0 +1,10 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + val a = object { + fun baz() = bar(if (x == null) 0 else x) + fun quux(): Int = if (x == null) x else x + } +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/QualifiedExpression.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/QualifiedExpression.jet new file mode 100644 index 00000000000..94c36bb42c2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/QualifiedExpression.jet @@ -0,0 +1,13 @@ +fun baz(x: Int): Int = x + 1 + +class A { + fun bar(x: Int) = baz(x) +} + +fun foo() { + val x: Int? = null + + A().bar(x) + if (x == null) return + A().bar(x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.jet new file mode 100644 index 00000000000..23f0379d1a7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Return.jet @@ -0,0 +1,12 @@ +fun bar(x: Int): Int = x + 1 + +fun foo(): Int { + val x: Int? = null + + bar(x) + if (x != null) return x + if (x == null) return if (x != null) x else x + if (x == null) return x + if (x != null) return if (x == null) x else x + return x +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ThisSuper.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ThisSuper.jet new file mode 100644 index 00000000000..c2b4ee9fdd2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ThisSuper.jet @@ -0,0 +1,21 @@ +open class Base { + fun bar(x: Int): Int = x + 1 +} + +class Derived : Base() { + fun baz(x: Int): Int = x + 1 + + fun foo() { + val x: Int? = null + + super.bar(x) + this.baz(x) + if (x == null) return + super.bar(x) + this.baz(x) + + val y: Int? = null + if (y != null) super.bar(this.baz(y)) + else this.baz(super.bar(y)) + } +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.jet new file mode 100644 index 00000000000..e1e2ce8fd57 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/Throw.jet @@ -0,0 +1,10 @@ +fun bar(x: Int): RuntimeException = RuntimeException(x.toString()) + +fun foo() { + val x: Int? = null + + if (x == null || 1 < 2) throw bar(x) + if (x == null) return + throw bar(x) + throw bar(x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/TryCatch.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/TryCatch.jet new file mode 100644 index 00000000000..f3f8ce0347c --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/TryCatch.jet @@ -0,0 +1,15 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + bar(x) + if (x == null) return + try { + bar(x) + } + catch (e: Exception) { + bar(x) + } + bar(x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/UnaryExpression.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/UnaryExpression.jet new file mode 100644 index 00000000000..8803f8d30bf --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/UnaryExpression.jet @@ -0,0 +1,14 @@ +fun bar(x: Int): Int = x + 1 +fun baz(b: Boolean): Boolean = !b + +fun foo() { + val x: Int? = null + + bar(-x) + if (x != null) bar(-x) + bar(-x) + + val b: Boolean? = null + baz(!b) + if (b != null) baz(!b) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/When.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/When.jet new file mode 100644 index 00000000000..5582e7b2346 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/When.jet @@ -0,0 +1,18 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + + if (x != null) { + when (x) { + 0 -> bar(x) + else -> {} + } + } + + when (x) { + 0 -> { if (x == null) return } + else -> { if (x == null) return } + } + bar(x) +} diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/While.jet b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/While.jet new file mode 100644 index 00000000000..8cf3c7b7df3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/While.jet @@ -0,0 +1,22 @@ +fun bar(x: Int): Int = x + 1 + +fun foo() { + val x: Int? = null + while (x == null) { + bar(x) + } + bar(x) + + val y: Int? = null + while (y != null) { + bar(y) + } + bar(y) + + val z: Int? = null + while (z == null) { + bar(z) + break + } + bar(z) +} From f5bb00240a061fd524b169fb782362ad74a16d6b Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 14 Jun 2012 17:35:47 +0400 Subject: [PATCH 05/11] change dataFlowInfo after if-then-else construction --- .../ControlStructureTypingVisitor.java | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index f62506382e1..24dc308ff9d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -96,50 +96,56 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (elseBranch == null) { if (thenBranch != null) { - JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo), context.trace).getType(); + JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo), context.trace); + JetType type = typeInfo.getType(); + DataFlowInfo dataFlowInfo; if (type != null && JetStandardClasses.isNothing(type)) { - facade.setResultingDataFlowInfo(elseInfo); + dataFlowInfo = elseInfo; + } else { + dataFlowInfo = typeInfo.getDataFlowInfo().or(elseInfo); } - return DataFlowUtils.checkImplicitCast( - DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, - contextWithExpectedType, isStatement, context.dataFlowInfo); + return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, dataFlowInfo); } return JetTypeInfo.create(null, context.dataFlowInfo); } if (thenBranch == null) { - JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo), context.trace).getType(); + JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo), context.trace); + JetType type = typeInfo.getType(); + DataFlowInfo dataFlowInfo; if (type != null && JetStandardClasses.isNothing(type)) { - facade.setResultingDataFlowInfo(thenInfo); + dataFlowInfo = thenInfo; + } else { + dataFlowInfo = typeInfo.getDataFlowInfo().or(thenInfo); } - return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, context.dataFlowInfo); + return DataFlowUtils.checkImplicitCast(DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType), expression, contextWithExpectedType, isStatement, dataFlowInfo); } CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION; - JetType thenType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo), context.trace).getType(); - JetType elseType = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo), context.trace).getType(); - - JetType result; - if (thenType == null) { - result = elseType; - } - else if (elseType == null) { - result = thenType; - } - else { - result = CommonSupertypes.commonSupertype(Arrays.asList(thenType, elseType)); - } + JetTypeInfo thenTypeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(thenInfo), context.trace); + JetTypeInfo elseTypeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), coercionStrategy, contextWithExpectedType.replaceDataFlowInfo(elseInfo), context.trace); + JetType thenType = thenTypeInfo.getType(); + JetType elseType = elseTypeInfo.getType(); + DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo(); + DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo(); boolean jumpInThen = thenType != null && JetStandardClasses.isNothing(thenType); boolean jumpInElse = elseType != null && JetStandardClasses.isNothing(elseType); - if (jumpInThen && !jumpInElse) { - facade.setResultingDataFlowInfo(elseInfo); + JetTypeInfo result; + if (thenType == null && elseType == null) { + result = JetTypeInfo.create(null, thenDataFlowInfo.or(elseDataFlowInfo)); } - else if (jumpInElse && !jumpInThen) { - facade.setResultingDataFlowInfo(thenInfo); + else if (thenType == null || (jumpInThen && !jumpInElse)) { + result = elseTypeInfo; } - if (result == null) return JetTypeInfo.create(null, context.dataFlowInfo); - return DataFlowUtils.checkImplicitCast(result, expression, contextWithExpectedType, isStatement, context.dataFlowInfo); - } + else if (elseType == null || (jumpInElse && !jumpInThen)) { + result = thenTypeInfo; + } + else { + result = JetTypeInfo.create(CommonSupertypes.commonSupertype(Arrays.asList(thenType, elseType)), thenDataFlowInfo.or(elseDataFlowInfo)); + } + + return DataFlowUtils.checkImplicitCast(result.getType(), expression, contextWithExpectedType, isStatement, result.getDataFlowInfo()); + } @Override public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) { From b97d44c4804c4be91a97ee9c1cae2cbbe212389d Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 14 Jun 2012 18:35:51 +0400 Subject: [PATCH 06/11] change dataFlowInfo after while loop --- .../types/expressions/ControlStructureTypingVisitor.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 24dc308ff9d..5ceeca993b8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -164,10 +164,14 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context); context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo), context.trace); } + DataFlowInfo dataFlowInfo; if (!containsBreak(expression, context)) { - facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context)); + dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context); } - return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, context.dataFlowInfo); + else { + dataFlowInfo = context.dataFlowInfo; + } + return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, dataFlowInfo); } private boolean containsBreak(final JetLoopExpression loopExpression, final ExpressionTypingContext context) { From d377a7c070b0c08094d34a4f1ed9d9116d2465ac Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 14 Jun 2012 18:45:20 +0400 Subject: [PATCH 07/11] change dataFlowInfo after do-while loop --- .../types/expressions/ControlStructureTypingVisitor.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 5ceeca993b8..b0d4e8ecb63 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -234,10 +234,14 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } JetExpression condition = expression.getCondition(); checkCondition(conditionScope, condition, context); + DataFlowInfo dataFlowInfo; if (!containsBreak(expression, context)) { - facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context)); + dataFlowInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context); } - return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, context.dataFlowInfo); + else { + dataFlowInfo = context.dataFlowInfo; + } + return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType, dataFlowInfo); } @Override From 650cc4ce40aca10a6f687479b6ea7af03e8dffa7 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 14 Jun 2012 18:49:46 +0400 Subject: [PATCH 08/11] delete get/setResultingDataFlowInfo --- .../types/expressions/ExpressionTypingInternals.java | 5 ----- .../ExpressionTypingVisitorDispatcher.java | 12 ------------ 2 files changed, 17 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java index a88eef3e0ad..9348effa09c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingInternals.java @@ -31,11 +31,6 @@ import org.jetbrains.jet.lang.types.JetType; */ /*package*/ interface ExpressionTypingInternals extends ExpressionTypingFacade { - void setResultingDataFlowInfo(@NotNull DataFlowInfo dataFlowInfo); - - @Nullable - DataFlowInfo getResultingDataFlowInfo(); - @Nullable JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index b88a66b37e2..b101f9ccc02 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -57,7 +57,6 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor Date: Thu, 14 Jun 2012 21:51:52 +0400 Subject: [PATCH 09/11] calculate commonDataFlowInfo in visitWhenExpression --- .../PatternMatchingTypingVisitor.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java index b15315267ca..7ca1f094477 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java @@ -86,6 +86,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { // TODO : exhaustive patterns Set expressionTypes = Sets.newHashSet(); + DataFlowInfo commonDataFlowInfo = null; for (JetWhenEntry whenEntry : expression.getEntries()) { JetWhenCondition[] conditions = whenEntry.getConditions(); DataFlowInfo newDataFlowInfo; @@ -123,17 +124,28 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { if (bodyExpression != null) { ExpressionTypingContext newContext = contextWithExpectedType.replaceScope(scopeToExtend).replaceDataFlowInfo(newDataFlowInfo); CoercionStrategy coercionStrategy = isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION; - JetType type = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace).getType(); + JetTypeInfo typeInfo = context.expressionTypingServices.getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(bodyExpression), coercionStrategy, newContext, context.trace); + JetType type = typeInfo.getType(); if (type != null) { expressionTypes.add(type); } + if (commonDataFlowInfo == null) { + commonDataFlowInfo = typeInfo.getDataFlowInfo(); + } + else { + commonDataFlowInfo = commonDataFlowInfo.or(typeInfo.getDataFlowInfo()); + } } } - if (!expressionTypes.isEmpty()) { - return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement, context.dataFlowInfo); + if (commonDataFlowInfo == null) { + commonDataFlowInfo = context.dataFlowInfo; } - return JetTypeInfo.create(null, context.dataFlowInfo); + + if (!expressionTypes.isEmpty()) { + return DataFlowUtils.checkImplicitCast(CommonSupertypes.commonSupertype(expressionTypes), expression, contextWithExpectedType, isStatement, commonDataFlowInfo); + } + return JetTypeInfo.create(null, commonDataFlowInfo); } private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final boolean expectedCondition, final JetType subjectType, JetWhenCondition condition, final WritableScope scopeToExtend, final ExpressionTypingContext context, final DataFlowValue... subjectVariables) { From b2c42f4cc9703037c2524404e9f06e792618a1a1 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 15 Jun 2012 15:04:10 +0400 Subject: [PATCH 10/11] fix DataFlowInfo.or --- .../jet/lang/resolve/calls/autocasts/DataFlowInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java index ab56ec113ed..9e14dacf832 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java @@ -181,7 +181,7 @@ public class DataFlowInfo { ListMultimap newTypeInfo = Multimaps.newListMultimap(Maps.>newHashMap(), CommonSuppliers.getArrayListSupplier()); - Set keys = newTypeInfo.keySet(); + Set keys = typeInfo.keySet(); keys.retainAll(other.typeInfo.keySet()); for (DataFlowValue key : keys) { From 3660d51f34a13145d5a567e2e34de7526b082e4f Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 15 Jun 2012 15:24:28 +0400 Subject: [PATCH 11/11] fix DataFlowInfo.equate --- .../jet/lang/resolve/calls/autocasts/DataFlowInfo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java index 9e14dacf832..b74b1d2d044 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/autocasts/DataFlowInfo.java @@ -109,7 +109,7 @@ public class DataFlowInfo { boolean changed = false; changed |= putNullability(builder, a, nullabilityOfA.refine(nullabilityOfB)); - changed |= putNullability(builder, b, nullabilityOfA.refine(nullabilityOfA)); + changed |= putNullability(builder, b, nullabilityOfB.refine(nullabilityOfA)); return changed ? new DataFlowInfo(ImmutableMap.copyOf(builder), typeInfo) : this; }