Propagate control flow to bound double colon expressions
"Unused expression" should be reported on unused double colon expressions, this is postponed #KT-12551 Open
This commit is contained in:
@@ -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) {
|
||||
|
||||
+2
-1
@@ -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(),
|
||||
|
||||
@@ -18,12 +18,12 @@ fun foo(): Any = ::bar
|
||||
L0:
|
||||
1 <START>
|
||||
mark(::bar)
|
||||
magic[CALLABLE_REFERENCE](::bar) -> <v0>
|
||||
magic[UNBOUND_CALLABLE_REFERENCE](::bar) -> <v0>
|
||||
ret(*|<v0>) L1
|
||||
L1:
|
||||
<END> NEXT:[<SINK>]
|
||||
<END> NEXT:[<SINK>]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -6,5 +6,5 @@ fun bar(): Int = 1
|
||||
== foo ==
|
||||
fun foo(): Any = ::bar
|
||||
---------------------
|
||||
::bar <v0>: {<: Any} NEW: magic[CALLABLE_REFERENCE](::bar) -> <v0>
|
||||
::bar <v0>: {<: Any} NEW: magic[UNBOUND_CALLABLE_REFERENCE](::bar) -> <v0>
|
||||
=====================
|
||||
|
||||
@@ -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
|
||||
<!UNREACHABLE_CODE!>return 0<!>
|
||||
}
|
||||
|
||||
fun unreachableCodeInLoop(): Int {
|
||||
while (true) {
|
||||
(break)::toString
|
||||
<!UNREACHABLE_CODE!>return 1<!>
|
||||
}
|
||||
return 2
|
||||
}
|
||||
@@ -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
|
||||
+1
-1
@@ -15,6 +15,6 @@ data class User(val surname: String)
|
||||
|
||||
fun foo() {
|
||||
bar<String> {
|
||||
<!UNUSED_EXPRESSION!><!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>User<!>::<!OVERLOAD_RESOLUTION_AMBIGUITY!>surname<!><!>
|
||||
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>User<!>::<!OVERLOAD_RESOLUTION_AMBIGUITY!>surname<!>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user