From e2d6e0cbab601b82b25239dff19e330f2a5b417e Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 30 May 2016 13:35:00 +0300 Subject: [PATCH] Propagate control flow to bound double colon expressions "Unused expression" should be reported on unused double colon expressions, this is postponed #KT-12551 Open --- .../kotlin/cfg/ControlFlowProcessor.kt | 12 +++++++++- .../eval/operationInstructions.kt | 3 ++- .../callableReferences.instructions | 10 ++++---- .../cfg/expressions/callableReferences.values | 2 +- .../callableReference/bound/controlFlow.kt | 23 +++++++++++++++++++ .../callableReference/bound/controlFlow.txt | 6 +++++ .../ea81649_errorPropertyLHS.kt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 6 +++++ 8 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.kt create mode 100644 compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt index 775b1cd287d..5235b9705bf 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowProcessor.kt @@ -53,6 +53,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver +import org.jetbrains.kotlin.types.expressions.DoubleColonLHS import org.jetbrains.kotlin.types.expressions.OperatorConventions import java.util.* @@ -1349,7 +1350,16 @@ class ControlFlowProcessor(private val trace: BindingTrace) { override fun visitDoubleColonExpression(expression: KtDoubleColonExpression) { mark(expression) - createNonSyntheticValue(expression, MagicKind.CALLABLE_REFERENCE) + val receiverExpression = expression.receiverExpression + if (receiverExpression != null && + trace.bindingContext.get(BindingContext.DOUBLE_COLON_LHS, receiverExpression) is DoubleColonLHS.Expression) { + // TODO: UNUSED_EXPRESSION is not reported on the whole expression, see KT-12551 + generateInstructions(receiverExpression) + createSyntheticValue(expression, MagicKind.BOUND_CALLABLE_REFERENCE, receiverExpression) + } + else { + createNonSyntheticValue(expression, MagicKind.UNBOUND_CALLABLE_REFERENCE) + } } override fun visitKtElement(element: KtElement) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/instructions/eval/operationInstructions.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/instructions/eval/operationInstructions.kt index 1171ce4a639..4e909d9d555 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/instructions/eval/operationInstructions.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/instructions/eval/operationInstructions.kt @@ -133,7 +133,8 @@ enum class MagicKind(val sideEffectFree: Boolean = false) { EQUALS_IN_WHEN_CONDITION(), IS(), CAST(), - CALLABLE_REFERENCE(true), + UNBOUND_CALLABLE_REFERENCE(true), + BOUND_CALLABLE_REFERENCE(), // implicit operations LOOP_RANGE_ITERATION(), IMPLICIT_RECEIVER(), diff --git a/compiler/testData/cfg/expressions/callableReferences.instructions b/compiler/testData/cfg/expressions/callableReferences.instructions index eb8a426ed25..d7729e95840 100644 --- a/compiler/testData/cfg/expressions/callableReferences.instructions +++ b/compiler/testData/cfg/expressions/callableReferences.instructions @@ -18,12 +18,12 @@ fun foo(): Any = ::bar L0: 1 mark(::bar) - magic[CALLABLE_REFERENCE](::bar) -> + magic[UNBOUND_CALLABLE_REFERENCE](::bar) -> ret(*|) L1 L1: - NEXT:[] + NEXT:[] error: - PREV:[] + PREV:[] sink: - PREV:[, ] -===================== \ No newline at end of file + PREV:[, ] +===================== diff --git a/compiler/testData/cfg/expressions/callableReferences.values b/compiler/testData/cfg/expressions/callableReferences.values index 0d8e5c606cc..c24e4f4c8a1 100644 --- a/compiler/testData/cfg/expressions/callableReferences.values +++ b/compiler/testData/cfg/expressions/callableReferences.values @@ -6,5 +6,5 @@ fun bar(): Int = 1 == foo == fun foo(): Any = ::bar --------------------- -::bar : {<: Any} NEW: magic[CALLABLE_REFERENCE](::bar) -> +::bar : {<: Any} NEW: magic[UNBOUND_CALLABLE_REFERENCE](::bar) -> ===================== diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.kt b/compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.kt new file mode 100644 index 00000000000..03620a34f60 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.kt @@ -0,0 +1,23 @@ +fun unusedExpression(s: String) { + // TODO: report UNUSED_EXPRESSION (KT-12551) + s::hashCode + s::class +} + +fun noUnusedParameter(s: String): Int { + val f = s::hashCode + return f() +} + +fun unreachableCode(): Int { + (if (true) return 1 else return 0)::toString + return 0 +} + +fun unreachableCodeInLoop(): Int { + while (true) { + (break)::toString + return 1 + } + return 2 +} diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.txt b/compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.txt new file mode 100644 index 00000000000..0b5028e1239 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.txt @@ -0,0 +1,6 @@ +package + +public fun noUnusedParameter(/*0*/ s: kotlin.String): kotlin.Int +public fun unreachableCode(): kotlin.Int +public fun unreachableCodeInLoop(): kotlin.Int +public fun unusedExpression(/*0*/ s: kotlin.String): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/callableReference/ea81649_errorPropertyLHS.kt b/compiler/testData/diagnostics/tests/callableReference/ea81649_errorPropertyLHS.kt index 16b4f2a174e..49bbc029531 100644 --- a/compiler/testData/diagnostics/tests/callableReference/ea81649_errorPropertyLHS.kt +++ b/compiler/testData/diagnostics/tests/callableReference/ea81649_errorPropertyLHS.kt @@ -15,6 +15,6 @@ data class User(val surname: String) fun foo() { bar { - User::surname + User::surname } } diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 4f21098d6e0..0abcfe215c4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -1733,6 +1733,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("controlFlow.kt") + public void testControlFlow() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/controlFlow.kt"); + doTest(fileName); + } + @TestMetadata("functionCallWithoutArguments.kt") public void testFunctionCallWithoutArguments() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/functionCallWithoutArguments.kt");