diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderImpl.java index 2ac8b609e2c..68ecfaafd88 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderImpl.java @@ -25,12 +25,11 @@ public class SemanticWhitespaceAwarePsiBuilderImpl extends PsiBuilderAdapter imp @Override public boolean newlineBeforeCurrentToken() { - if (!newlinesEnabled.peek()) return false; if (eof()) return true; - // TODO: maybe, memorize this somehow? + // TODO: maybe, memoize this somehow? for (int i = 1; i <= getCurrentOffset(); i++) { IElementType previousToken = rawLookup(-i); @@ -51,8 +50,9 @@ public class SemanticWhitespaceAwarePsiBuilderImpl extends PsiBuilderAdapter imp assert previousTokenEnd < getOriginalText().length(); for (int j = previousTokenStart; j < previousTokenEnd; j++) { - if (getOriginalText().charAt(j) == '\n') + if (getOriginalText().charAt(j) == '\n') { return true; + } } } 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 720155d0206..1e95b4414b6 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 @@ -651,7 +651,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { return DataFlowUtils.checkType(result, expression, context); } - protected void checkLValue(BindingTrace trace, JetExpression expression) { + public void checkLValue(BindingTrace trace, JetExpression expression) { checkLValue(trace, expression, false); } @@ -685,8 +685,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } } else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) { - result = getTypeForBinaryCall(context.scope, OperatorConventions.BINARY_OPERATION_NAMES.get(operationType), context, expression); - } + result = getTypeForBinaryCall(context.scope, OperatorConventions.BINARY_OPERATION_NAMES.get(operationType), context, expression); +} else if (operationType == JetTokens.EQ) { result = visitAssignment(expression, contextWithExpectedType); } @@ -706,74 +706,77 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } } } - else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) { - String name = "equals"; - if (right != null) { - ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context.replaceScope(context.scope)); - OverloadResolutionResults resolutionResults = context.resolveExactSignature( - receiver, "equals", - Collections.singletonList(JetStandardClasses.getNullableAnyType())); - if (resolutionResults.isSuccess()) { - FunctionDescriptor equals = resolutionResults.getResult().getResultingDescriptor(); - context.trace.record(REFERENCE_TARGET, operationSign, equals); - if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) { - ensureNonemptyIntersectionOfOperandTypes(expression, context); - } - } - else { - if (resolutionResults.isAmbiguity()) { - context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResults())); + else { + JetType booleanType = context.semanticServices.getStandardLibrary().getBooleanType(); + if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) { + String name = "equals"; + if (right != null) { + ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context.replaceScope(context.scope)); + OverloadResolutionResults resolutionResults = context.resolveExactSignature( + receiver, "equals", + Collections.singletonList(JetStandardClasses.getNullableAnyType())); + if (resolutionResults.isSuccess()) { + FunctionDescriptor equals = resolutionResults.getResult().getResultingDescriptor(); + context.trace.record(REFERENCE_TARGET, operationSign, equals); + if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) { + ensureNonemptyIntersectionOfOperandTypes(expression, context); + } } else { - context.trace.report(EQUALS_MISSING.on(operationSign)); + if (resolutionResults.isAmbiguity()) { + context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResults())); + } + else { + context.trace.report(EQUALS_MISSING.on(operationSign)); + } + } + } + result = booleanType; + } + else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) { + ensureNonemptyIntersectionOfOperandTypes(expression, context); + + // TODO : Check comparison pointlessness + result = booleanType; + } + else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) { + if (right == null) { + result = ErrorUtils.createErrorType("No right argument"); // TODO + return null; + } + 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)); + WritableScopeImpl leftScope = newWritableScopeImpl(context).setDebugName("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 ? leftScope : newWritableScopeImpl(context).setDebugName("Right scope of && or ||"); + JetType rightType = right == null ? null : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)); + if (leftType != null && !isBoolean(context.semanticServices, leftType)) { + context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType)); + } + if (rightType != null && !isBoolean(context.semanticServices, rightType)) { + context.trace.report(TYPE_MISMATCH.on(right, booleanType, rightType)); + } + result = booleanType; + } + else if (operationType == JetTokens.ELVIS) { + JetType leftType = facade.getType(left, context.replaceScope(context.scope)); + JetType rightType = right == null ? null : facade.getType(right, contextWithExpectedType.replaceScope(context.scope)); + if (leftType != null) { + if (!leftType.isNullable()) { + context.trace.report(USELESS_ELVIS.on(expression, 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()); } } } - result = context.semanticServices.getStandardLibrary().getBooleanType(); - } - else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) { - ensureNonemptyIntersectionOfOperandTypes(expression, context); - - // TODO : Check comparison pointlessness - result = context.semanticServices.getStandardLibrary().getBooleanType(); - } - else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) { - if (right == null) { - result = ErrorUtils.createErrorType("No right argument"); // TODO - return null; + else { + context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation")); } - checkInExpression(expression, expression.getOperationReference(), expression.getLeft(), expression.getRight(), context); - result = context.semanticServices.getStandardLibrary().getBooleanType(); - } - else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) { - JetType leftType = facade.getType(left, context.replaceScope(context.scope)); - WritableScopeImpl leftScope = newWritableScopeImpl(context).setDebugName("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 ? leftScope : newWritableScopeImpl(context).setDebugName("Right scope of && or ||"); - JetType rightType = right == null ? null : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)); - if (leftType != null && !isBoolean(context.semanticServices, leftType)) { - context.trace.report(TYPE_MISMATCH.on(left, context.semanticServices.getStandardLibrary().getBooleanType(), leftType)); - } - if (rightType != null && !isBoolean(context.semanticServices, rightType)) { - context.trace.report(TYPE_MISMATCH.on(right, context.semanticServices.getStandardLibrary().getBooleanType(), rightType)); - } - result = context.semanticServices.getStandardLibrary().getBooleanType(); - } - else if (operationType == JetTokens.ELVIS) { - JetType leftType = facade.getType(left, context.replaceScope(context.scope)); - JetType rightType = right == null ? null : facade.getType(right, contextWithExpectedType.replaceScope(context.scope)); - if (leftType != null) { - if (!leftType.isNullable()) { - context.trace.report(USELESS_ELVIS.on(expression, 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()); - } - } - } - else { - context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation")); } return DataFlowUtils.checkType(result, expression, contextWithExpectedType); } @@ -842,7 +845,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } @Nullable - protected JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) { + public JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) { ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope)); FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenNameToDescriptor( CallMaker.makeCall(receiver, binaryExpression), 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 4db6dbe8df7..f573e39e79a 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 @@ -10,10 +10,11 @@ import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.TaskPrioritizers; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; -import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; +import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; @@ -21,7 +22,10 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver; import org.jetbrains.jet.lang.types.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.resolve.BindingContext.*; @@ -36,10 +40,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { super(facade); } - private JetType getTypeWithNewScopeAndDataFlowInfo(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull DataFlowInfo newDataFlowInfo, @NotNull ExpressionTypingContext context) { - return facade.getType(expression, context.replaceScope(scope).replaceDataFlowInfo(newDataFlowInfo)); - } - private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) { if (condition != null) { JetType conditionType = facade.getType(condition, context.replaceScope(scope)); @@ -63,30 +63,29 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { JetExpression thenBranch = expression.getThen(); WritableScopeImpl thenScope = newWritableScopeImpl(context).setDebugName("Then scope"); + WritableScopeImpl elseScope = newWritableScopeImpl(context).setDebugName("Else scope"); DataFlowInfo thenInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, thenScope, context); DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context); if (elseBranch == null) { if (thenBranch != null) { - JetType type = getTypeWithNewScopeAndDataFlowInfo(thenScope, thenBranch, thenInfo, context); + JetType type = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo)); if (type != null && JetStandardClasses.isNothing(type)) { facade.setResultingDataFlowInfo(elseInfo); -// resultScope = elseScope; } return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); } return null; } if (thenBranch == null) { - JetType type = getTypeWithNewScopeAndDataFlowInfo(context.scope, elseBranch, elseInfo, context); + JetType type = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo)); if (type != null && JetStandardClasses.isNothing(type)) { facade.setResultingDataFlowInfo(thenInfo); -// resultScope = thenScope; } return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); } - JetType thenType = getTypeWithNewScopeAndDataFlowInfo(thenScope, thenBranch, thenInfo, contextWithExpectedType); - JetType elseType = getTypeWithNewScopeAndDataFlowInfo(context.scope, elseBranch, elseInfo, contextWithExpectedType); + JetType thenType = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(thenInfo)); + JetType elseType = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(elseInfo)); JetType result; if (thenType == null) { @@ -120,7 +119,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { if (body != null) { WritableScopeImpl scopeToExtend = newWritableScopeImpl(context).setDebugName("Scope extended in while's condition"); DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context); - getTypeWithNewScopeAndDataFlowInfo(scopeToExtend, body, conditionInfo, context); + context.getServices().getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo)); } if (!containsBreak(expression, context)) { facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context)); @@ -229,8 +228,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { JetExpression body = expression.getBody(); if (body != null) { - ExpressionTypingInternals blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(loopScope); - blockLevelVisitor.getType(body, context.replaceScope(loopScope)); + context.getServices().getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context); } return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); 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 dcbdad0e6c9..cb51c922781 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 @@ -14,4 +14,7 @@ public interface ExpressionTypingFacade { @Nullable JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context); + + @Nullable + JetType getTypeForStatement(@NotNull JetExpression expression, ExpressionTypingContext context); } 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 108796a2d2b..db493f27c06 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 @@ -218,13 +218,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, context.expectedReturnType); - result = blockLevelVisitor.getType(statementExpression, newContext); + result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext); 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, context.expectedReturnType); - result = blockLevelVisitor.getType(statementExpression, newContext); + result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext); if (mismatch[0]) { temporaryTraceExpectingUnit.commit(); } @@ -238,11 +238,11 @@ public class ExpressionTypingServices { } else { newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType); - result = blockLevelVisitor.getType(statementExpression, newContext); + result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext); } } else { - result = blockLevelVisitor.getType(statementExpression, newContext); + result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext); if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) { boolean mightBeUnit = false; if (statementExpression instanceof JetDeclaration) { @@ -264,7 +264,7 @@ public class ExpressionTypingServices { } } else { - result = blockLevelVisitor.getType(statementExpression, newContext); + result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext); } DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo(); 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 12ad4d0e258..bdd82e73b85 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 @@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException; +import static org.jetbrains.jet.lang.diagnostics.Errors.ELSE_MISPLACED_IN_WHEN; import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM; /** @@ -21,36 +22,33 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO */ public class ExpressionTypingVisitorDispatcher extends JetVisitor implements ExpressionTypingInternals { - private static Function BASIC_FACTORY = new Function() { - @Override - public BasicExpressionTypingVisitor fun(ExpressionTypingInternals facade) { - return new BasicExpressionTypingVisitor(facade); - } - }; + private static ExpressionTypingVisitorDispatcher BASIC_DISPATCHER = new ExpressionTypingVisitorDispatcher(null); @NotNull public static ExpressionTypingFacade create() { - return new ExpressionTypingVisitorDispatcher(BASIC_FACTORY); + return BASIC_DISPATCHER; } @NotNull public static ExpressionTypingInternals createForBlock(final WritableScope writableScope) { - return new ExpressionTypingVisitorDispatcher(new Function() { - @Override - public BasicExpressionTypingVisitor fun(ExpressionTypingInternals facade) { - return new ExpressionTypingVisitorForStatements(facade, writableScope); - } - }); + return new ExpressionTypingVisitorDispatcher(writableScope); } private final BasicExpressionTypingVisitor basic; + private final ExpressionTypingVisitorForStatements statements; private final ClosureExpressionsTypingVisitor closures = new ClosureExpressionsTypingVisitor(this); private final ControlStructureTypingVisitor controlStructures = new ControlStructureTypingVisitor(this); private final PatternMatchingTypingVisitor patterns = new PatternMatchingTypingVisitor(this); protected DataFlowInfo resultDataFlowInfo; - private ExpressionTypingVisitorDispatcher(Function factoryForBasic) { - this.basic = factoryForBasic.fun(this); + private ExpressionTypingVisitorDispatcher(WritableScope writableScope) { + this.basic = new BasicExpressionTypingVisitor(this); + if (writableScope != null) { + this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic); + } + else { + this.statements = null; + } } @Override @@ -87,12 +85,23 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor visitor) { if (context.trace.get(BindingContext.PROCESSED, expression)) { return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression); } JetType result; try { - result = expression.accept(this, context); + 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); @@ -115,10 +124,10 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitorc.p = "yeah") +} + + +fun box2() : Boolean { + var c = A() + return (c.p = "yeah") && true +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 81687edd8c8..1ead89fcde2 100644 --- a/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/compiler/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -113,7 +113,7 @@ public class JetTypeCheckerTest extends JetLiteFixture { assertType("if (true) 1 else '1'", "Any"); assertType("if (true) else '1'", "Unit"); - assertType("if (true) else a = 0", "Unit"); + assertType("if (true) else { var a = 0; a = 1 }", "Unit"); } public void testWhen() throws Exception {