diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 3f7684d78b9..59ee863edbc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -22,7 +22,6 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.psi.PsiElement; -import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -51,7 +50,6 @@ import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.expressions.DataFlowUtils; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils; -import org.jetbrains.jet.lang.types.expressions.OperatorConventions; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import javax.inject.Inject; @@ -417,21 +415,9 @@ public class CandidateResolver { return expression; } - @SuppressWarnings("SuspiciousMethodCalls") @Override public JetExpression visitBinaryExpression(JetBinaryExpression expression, Void data) { - IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); - if (OperatorConventions.COMPARISON_OPERATIONS.contains(operationType)) { - //Result type of comparison doesn't depend on expected type: - //it's 'Boolean', but 'compareTo' should return 'Int'. - //So we shouldn't check result type of such a call('Int') at completion phase. - return null; - } - if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) { - //the same, result type is always 'Unit' - return null; - } - return super.visitBinaryExpression(expression, data); + return ExpressionTypingUtils.isBinaryExpressionDependentOnExpectedType(expression) ? expression : null; } }; return expression.accept(selectorExpressionFinder, null); 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 012742db49f..1eaf5cf1162 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 @@ -881,9 +881,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { @Override public JetTypeInfo visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) { - ExpressionTypingContext context = contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE); - JetSimpleNameExpression operationSign = expression.getOperationReference(); + ExpressionTypingContext context = isBinaryExpressionDependentOnExpectedType(expression) + ? contextWithExpectedType + : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE); + JetSimpleNameExpression operationSign = expression.getOperationReference(); JetExpression left = expression.getLeft(); JetExpression right = expression.getRight(); IElementType operationType = operationSign.getReferencedNameElementType(); @@ -893,15 +895,15 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { //Expressions that can depend on expected type if (operationType == JetTokens.IDENTIFIER) { Name referencedName = operationSign.getReferencedNameAsName(); - result = getTypeInfoForBinaryCall(referencedName, contextWithExpectedType, expression); + result = getTypeInfoForBinaryCall(referencedName, context, expression); } else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) { Name referencedName = OperatorConventions.BINARY_OPERATION_NAMES.get(operationType); - result = getTypeInfoForBinaryCall(referencedName, contextWithExpectedType, expression); + result = getTypeInfoForBinaryCall(referencedName, context, expression); } else if (operationType == JetTokens.ELVIS) { - //base expression of elvis operator (not the whole expression) is checked for 'type mismatch' - return visitElvisExpression(expression, contextWithExpectedType); + //base expression of elvis operator is checked for 'type mismatch', so the whole expression shouldn't be checked + return visitElvisExpression(expression, context); } //Expressions that don't depend on expected type diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index a6072d97e10..201daeb3aa1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -51,6 +51,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.slicedmap.WritableSlice; import java.util.*; @@ -484,4 +485,11 @@ public class ExpressionTypingUtils { ? facade.getTypeInfo(expression, context) : JetTypeInfo.create(null, context.dataFlowInfo); } + + @SuppressWarnings("SuspiciousMethodCalls") + public static boolean isBinaryExpressionDependentOnExpectedType(@NotNull JetBinaryExpression expression) { + IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); + return (operationType == JetTokens.IDENTIFIER || OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType) + || operationType == JetTokens.ELVIS); + } }