Prohibit callable references to suspend functions

#KT-15662 Fixed
This commit is contained in:
Denis Zharkov
2017-01-12 10:39:48 +03:00
parent 695b6d9e67
commit f12409504f
4 changed files with 62 additions and 0 deletions
@@ -50,6 +50,7 @@ import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.lang.UnsupportedOperationException
import java.util.*
import javax.inject.Inject
@@ -574,9 +575,22 @@ class DoubleColonExpressionResolver(
val resolutionResults =
resolveCallableReferenceRHS(expression, lhsResult, context, resolveArgumentsMode)
reportUnsupportedReferenceToSuspendFunction(resolutionResults, expression, context)
return lhsResult to resolutionResults
}
private fun reportUnsupportedReferenceToSuspendFunction(
resolutionResults: OverloadResolutionResults<CallableDescriptor>?,
expression: KtCallableReferenceExpression,
context: ExpressionTypingContext
) {
if (resolutionResults?.isSingleResult == true &&
resolutionResults.resultingDescriptor.safeAs<FunctionDescriptor>()?.isSuspend == true) {
context.trace.report(UNSUPPORTED.on(expression.callableReference, "Callable references to suspend functions"))
}
}
private fun tryResolveRHSWithReceiver(
traceTitle: String,
receiver: Receiver?,
@@ -0,0 +1,28 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
suspend fun foo() {}
class A {
suspend fun member() {}
}
suspend fun A.ext() {}
fun test1(a: A) {
val x = ::<!ILLEGAL_SUSPEND_FUNCTION_CALL, UNSUPPORTED!>foo<!>
val y1 = a::<!ILLEGAL_SUSPEND_FUNCTION_CALL, UNSUPPORTED!>member<!>
val y2 = A::<!ILLEGAL_SUSPEND_FUNCTION_CALL, UNSUPPORTED!>member<!>
val z1 = a::<!ILLEGAL_SUSPEND_FUNCTION_CALL, UNSUPPORTED!>ext<!>
val z2 = A::<!ILLEGAL_SUSPEND_FUNCTION_CALL, UNSUPPORTED!>ext<!>
}
suspend fun test2(a: A) {
val x = ::<!UNSUPPORTED!>foo<!>
val y1 = a::<!UNSUPPORTED!>member<!>
val y2 = A::<!UNSUPPORTED!>member<!>
val z1 = a::<!UNSUPPORTED!>ext<!>
val z2 = A::<!UNSUPPORTED!>ext<!>
}
@@ -0,0 +1,14 @@
package
public suspend fun foo(): kotlin.Unit
public fun test1(/*0*/ a: A): kotlin.Unit
public suspend fun test2(/*0*/ a: A): kotlin.Unit
public suspend fun A.ext(): kotlin.Unit
public final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final suspend fun member(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -4282,6 +4282,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/coroutines"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("callableReferences.kt")
public void testCallableReferences() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/callableReferences.kt");
doTest(fileName);
}
@TestMetadata("coroutinesDisabled.kt")
public void testCoroutinesDisabled() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/coroutinesDisabled.kt");