visitor methods return JetTypeInfo instead of JetType

This commit is contained in:
Alexander Udalov
2012-06-13 17:14:37 +04:00
parent bdd83d86f6
commit 38e7dde8f6
13 changed files with 283 additions and 209 deletions
@@ -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");
}
@@ -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;
}
}
@@ -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<JetExpression> entries = expression.getEntries();
List<JetType> types = new ArrayList<JetType>();
for (JetExpression entry : entries) {
@@ -354,11 +355,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (context.expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isTupleType(context.expectedType)) {
List<JetType> 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(), "<no name>")));
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);
@@ -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<WritableSlice>() {
@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.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context);
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, JetStandardClasses.getUnitType()), expression, context, context.dataFlowInfo);
}
}
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, safeReturnType), expression, context);
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), receiver, parameterTypes, safeReturnType), expression, context, context.dataFlowInfo);
}
private SimpleFunctionDescriptorImpl createFunctionDescriptor(JetFunctionLiteralExpression expression, ExpressionTypingContext context, boolean functionTypeExpected) {
@@ -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<JetCatchClause> 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);
}
}
@@ -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);
}
}
@@ -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);
}
@@ -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<JetElement> 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<? extends JetElement> block, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context, BindingTrace trace) {
JetTypeInfo getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> 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<? extends JetElement> 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);
}
}
}
@@ -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
@@ -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<JetType, ExpressionTypingContext> {
/*package*/ abstract class ExpressionTypingVisitor extends JetVisitor<JetTypeInfo, ExpressionTypingContext> {
protected final ExpressionTypingInternals facade;
@@ -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<JetType, ExpressionTypingContext> implements ExpressionTypingInternals {
public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, ExpressionTypingContext> 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<JetType, Expre
@Override
@NotNull
public final JetType safeGetType(@NotNull JetExpression expression, ExpressionTypingContext context) {
JetType type = getType(expression, context);
if (type != null) {
return type;
public final JetTypeInfo safeGetType(@NotNull JetExpression expression, ExpressionTypingContext context) {
JetTypeInfo typeInfo = getType(expression, context);
if (typeInfo.getType() != null) {
return typeInfo;
}
return ErrorUtils.createErrorType("Type for " + expression.getText());
return JetTypeInfo.create(ErrorUtils.createErrorType("Type for " + expression.getText()), context.dataFlowInfo);
}
@Override
@Nullable
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context) {
@NotNull
public final JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context) {
return getType(expression, context, this);
}
@Nullable
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
@NotNull
public final JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
if (!isStatement) return getType(expression, context);
if (statements != null) {
return getType(expression, context, statements);
@@ -123,30 +124,30 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
expression.accept(createStatementVisitor(context), context);
}
@Nullable
private JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetType, ExpressionTypingContext> visitor) {
@NotNull
private JetTypeInfo getType(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetTypeInfo, ExpressionTypingContext> 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<JetType, Expre
//////////////////////////////////////////////////////////////////////////////////////////////
@Override
public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
return expression.accept(closures, data);
}
@Override
public JetType visitObjectLiteralExpression(JetObjectLiteralExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitObjectLiteralExpression(JetObjectLiteralExpression expression, ExpressionTypingContext data) {
return expression.accept(closures, data);
}
//////////////////////////////////////////////////////////////////////////////////////////////
@Override
public JetType visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitTryExpression(JetTryExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
@Override
public JetType visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext data) {
return expression.accept(controlStructures, data);
}
//////////////////////////////////////////////////////////////////////////////////////////////
@Override
public JetType visitIsExpression(JetIsExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext data) {
return expression.accept(patterns, data);
}
@Override
public JetType visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext data) {
public JetTypeInfo visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext data) {
return expression.accept(patterns, data);
}
//////////////////////////////////////////////////////////////////////////////////////////////
@Override
public JetType visitJetElement(JetElement element, ExpressionTypingContext data) {
public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext data) {
return element.accept(basic, data);
}
}
@@ -33,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
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;
@@ -78,7 +79,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
}
@Override
public JetType visitObjectDeclaration(JetObjectDeclaration declaration, ExpressionTypingContext context) {
public JetTypeInfo visitObjectDeclaration(JetObjectDeclaration declaration, ExpressionTypingContext context) {
TopDownAnalyzer.processClassOrObject(context.expressionTypingServices.getProject(), context.trace, scope,
scope.getContainingDeclaration(), declaration);
ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, declaration);
@@ -87,11 +88,11 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
.resolveObjectDeclaration(scope.getContainingDeclaration(), declaration, classDescriptor, context.trace);
scope.addVariableDescriptor(variableDescriptor);
}
return DataFlowUtils.checkStatementType(declaration, context);
return DataFlowUtils.checkStatementType(declaration, context, context.dataFlowInfo);
}
@Override
public JetType visitProperty(JetProperty property, ExpressionTypingContext context) {
public JetTypeInfo visitProperty(JetProperty property, ExpressionTypingContext context) {
JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
if (receiverTypeRef != null) {
context.trace.report(LOCAL_EXTENSION_PROPERTY.on(receiverTypeRef));
@@ -111,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));
JetType initializerType = facade.getType(initializer, context.replaceExpectedType(outType).replaceScope(scope)).getType();
}
{
@@ -123,41 +124,41 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
}
scope.addVariableDescriptor(propertyDescriptor);
return DataFlowUtils.checkStatementType(property, context);
return DataFlowUtils.checkStatementType(property, context, context.dataFlowInfo);
}
@Override
public JetType visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
public JetTypeInfo visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
SimpleFunctionDescriptor functionDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function, context.trace);
scope.addFunctionDescriptor(functionDescriptor);
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
context.expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace);
return DataFlowUtils.checkStatementType(function, context);
return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo);
}
@Override
public JetType visitClass(JetClass klass, ExpressionTypingContext context) {
public JetTypeInfo visitClass(JetClass klass, ExpressionTypingContext context) {
TopDownAnalyzer.processClassOrObject(context.expressionTypingServices.getProject(), context.trace, scope,
scope.getContainingDeclaration(), klass);
ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, klass);
if (classDescriptor != null) {
scope.addClassifierDescriptor(classDescriptor);
}
return DataFlowUtils.checkStatementType(klass, context);
return DataFlowUtils.checkStatementType(klass, context, context.dataFlowInfo);
}
@Override
public JetType visitTypedef(JetTypedef typedef, ExpressionTypingContext context) {
public JetTypeInfo visitTypedef(JetTypedef typedef, ExpressionTypingContext context) {
return super.visitTypedef(typedef, context); // TODO
}
@Override
public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
return DataFlowUtils.checkStatementType(dcl, context);
public JetTypeInfo visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
return DataFlowUtils.checkStatementType(dcl, context, context.dataFlowInfo);
}
@Override
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext context) {
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
JetType result;
@@ -170,7 +171,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
else {
return facade.getType(expression, context);
}
return DataFlowUtils.checkType(result, expression, context);
return DataFlowUtils.checkType(result, expression, context, context.dataFlowInfo);
}
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
@@ -186,7 +187,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (left == null) return null;
JetType leftType = facade.getType(left, context);
JetType leftType = facade.getType(left, context).getType();
if (leftType == null) {
facade.getType(right, context);
context.trace.report(UNRESOLVED_REFERENCE.on(operationSign));
@@ -249,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));
JetType leftType = facade.getType(expression.getLeft(), context.replaceScope(scope)).getType();
if (right != null) {
JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
JetType rightType = facade.getType(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());
@@ -261,59 +262,59 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
@Override
public JetType visitExpression(JetExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitExpression(JetExpression expression, ExpressionTypingContext context) {
return facade.getType(expression, context);
}
@Override
public JetType visitJetElement(JetElement element, ExpressionTypingContext context) {
public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext context) {
context.trace.report(UNSUPPORTED.on(element, "in a block"));
return null;
return JetTypeInfo.create(null, context.dataFlowInfo);
}
@Override
public JetType visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext context) {
return controlStructures.visitWhileExpression(expression, context, true);
}
@Override
public JetType visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext context) {
return controlStructures.visitDoWhileExpression(expression, context, true);
}
@Override
public JetType visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext context) {
return controlStructures.visitForExpression(expression, context, true);
}
@Override
public JetType visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext context) {
return controlStructures.visitIfExpression(expression, context, true);
}
@Override
public JetType visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitWhenExpression(final JetWhenExpression expression, ExpressionTypingContext context) {
return patterns.visitWhenExpression(expression, context, true);
}
@Override
public JetType visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitBlockExpression(JetBlockExpression expression, ExpressionTypingContext context) {
return basic.visitBlockExpression(expression, context, true);
}
@Override
public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitParenthesizedExpression(JetParenthesizedExpression expression, ExpressionTypingContext context) {
return basic.visitParenthesizedExpression(expression, context, true);
}
@Override
public JetType visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
public JetTypeInfo visitUnaryExpression(JetUnaryExpression expression, ExpressionTypingContext context) {
return basic.visitUnaryExpression(expression, context, true);
}
@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(), "<no name>")));
return null;
return JetTypeInfo.create(null, context.dataFlowInfo);
}
}
@@ -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)) {