From aca21f78d59c575d1426d54f0206a98c028fc988 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Tue, 24 Dec 2013 21:24:37 +0400 Subject: [PATCH] check incomplete equality --- .../BasicExpressionTypingVisitor.java | 78 ++++++++++--------- .../tests/incompleteCode/incompleteEquals.kt | 3 + .../checkers/JetDiagnosticsTestGenerated.java | 5 ++ 3 files changed, 48 insertions(+), 38 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/incompleteCode/incompleteEquals.kt 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 b6f6a75f626..b9688367df3 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 @@ -871,54 +871,56 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { final JetExpression right ) { DataFlowInfo dataFlowInfo = context.dataFlowInfo; - if (right != null && left != null) { - ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context); + if (right == null || left == null) { + ExpressionTypingUtils.getTypeInfoOrNullType(right, context, facade); + ExpressionTypingUtils.getTypeInfoOrNullType(left, context, facade); + return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo); + } + ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context); - JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade); + JetTypeInfo leftTypeInfo = getTypeInfoOrNullType(left, context, facade); - dataFlowInfo = leftTypeInfo.getDataFlowInfo(); - ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo); + dataFlowInfo = leftTypeInfo.getDataFlowInfo(); + ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo); - TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create( - context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:" + right); - traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType()); - traceInterpretingRightAsNullableAny.record(PROCESSED, right); + TemporaryBindingTrace traceInterpretingRightAsNullableAny = TemporaryBindingTrace.create( + context.trace, "trace to resolve 'equals(Any?)' interpreting as of type Any? an expression:" + right); + traceInterpretingRightAsNullableAny.record(EXPRESSION_TYPE, right, KotlinBuiltIns.getInstance().getNullableAnyType()); + traceInterpretingRightAsNullableAny.record(PROCESSED, right); - Call call = CallMaker.makeCallWithExpressions(operationSign, receiver, null, operationSign, Collections.singletonList(right)); - ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny); - OverloadResolutionResults resolutionResults = - newContext.resolveCallWithGivenName(call, operationSign, OperatorConventions.EQUALS); + Call call = CallMaker.makeCallWithExpressions(operationSign, receiver, null, operationSign, Collections.singletonList(right)); + ExpressionTypingContext newContext = context.replaceBindingTrace(traceInterpretingRightAsNullableAny); + OverloadResolutionResults resolutionResults = + newContext.resolveCallWithGivenName(call, operationSign, OperatorConventions.EQUALS); - traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() { - @Override - public boolean accept(@Nullable WritableSlice slice, Object key) { + traceInterpretingRightAsNullableAny.commit(new TraceEntryFilter() { + @Override + public boolean accept(@Nullable WritableSlice slice, Object key) { + // the type of the right expression isn't 'Any?' actually + if (key == right && (slice == EXPRESSION_TYPE || slice == PROCESSED)) return false; - // the type of the right expression isn't 'Any?' actually - if (key == right && (slice == EXPRESSION_TYPE || slice == PROCESSED)) return false; + // a hack due to KT-678 + // without this line an autocast is reported on the receiver (if it was previously checked for not-null) + // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member + if (key == left && slice == AUTOCAST) return false; - // a hack due to KT-678 - // without this line an autocast is reported on the receiver (if it was previously checked for not-null) - // with not-null check the resolution result changes from 'fun Any?.equals' to 'equals' member - if (key == left && slice == AUTOCAST) return false; + return true; + } + }, true); + dataFlowInfo = facade.getTypeInfo(right, contextWithDataFlow).getDataFlowInfo(); - return true; - } - }, true); - dataFlowInfo = facade.getTypeInfo(right, contextWithDataFlow).getDataFlowInfo(); - - if (resolutionResults.isSuccess()) { - FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor(); - if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) { - ensureNonemptyIntersectionOfOperandTypes(expression, context); - } + if (resolutionResults.isSuccess()) { + FunctionDescriptor equals = resolutionResults.getResultingCall().getResultingDescriptor(); + if (ensureBooleanResult(operationSign, OperatorConventions.EQUALS, equals.getReturnType(), context)) { + ensureNonemptyIntersectionOfOperandTypes(expression, context); + } + } + else { + if (resolutionResults.isAmbiguity()) { + context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls())); } else { - if (resolutionResults.isAmbiguity()) { - context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResultingCalls())); - } - else { - context.trace.report(EQUALS_MISSING.on(operationSign)); - } + context.trace.report(EQUALS_MISSING.on(operationSign)); } } return JetTypeInfo.create(KotlinBuiltIns.getInstance().getBooleanType(), dataFlowInfo); diff --git a/compiler/testData/diagnostics/tests/incompleteCode/incompleteEquals.kt b/compiler/testData/diagnostics/tests/incompleteCode/incompleteEquals.kt new file mode 100644 index 00000000000..0c8f84176ae --- /dev/null +++ b/compiler/testData/diagnostics/tests/incompleteCode/incompleteEquals.kt @@ -0,0 +1,3 @@ +package a + +fun foo(a: Any) = a == \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 3df6192e1a7..66053c208c4 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -3326,6 +3326,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/incompleteCode/incompleteAssignment.kt"); } + @TestMetadata("incompleteEquals.kt") + public void testIncompleteEquals() throws Exception { + doTest("compiler/testData/diagnostics/tests/incompleteCode/incompleteEquals.kt"); + } + @TestMetadata("kt1955.kt") public void testKt1955() throws Exception { doTest("compiler/testData/diagnostics/tests/incompleteCode/kt1955.kt");