Fix overridability rules for suspend functions

Treat suspend and non-suspend functions as conflicting

 #KT-15413 Fixed
This commit is contained in:
Denis Zharkov
2017-01-12 11:25:37 +03:00
parent 978f53414f
commit de9c41c412
8 changed files with 165 additions and 0 deletions
@@ -0,0 +1,6 @@
interface AsyncVal { suspend fun getVal(): Int = 1}
interface SyncVal { fun getVal(): Int = 1 }
<!CONFLICTING_INHERITED_MEMBERS!>class MixSuspend<!> : AsyncVal, SyncVal {
}
@@ -0,0 +1,23 @@
package
public interface AsyncVal {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open suspend fun getVal(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class MixSuspend : AsyncVal, SyncVal {
public constructor MixSuspend()
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open suspend override /*1*/ /*fake_override*/ fun getVal(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface SyncVal {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun getVal(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,15 @@
// FILE: main.kt
interface A {
<!CONFLICTING_OVERLOADS!>suspend fun foo()<!>
<!CONFLICTING_OVERLOADS!>fun foo()<!>
}
interface B : A {
<!CONFLICTING_OVERLOADS, CONFLICTING_OVERLOADS!>suspend override fun foo()<!> {
}
<!CONFLICTING_OVERLOADS, CONFLICTING_OVERLOADS!>override fun foo()<!> {
}
}
@@ -0,0 +1,17 @@
package
public interface A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(): kotlin.Unit
public abstract suspend fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B : A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ fun foo(): kotlin.Unit
public open suspend override /*1*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,37 @@
// FILE: main.kt
interface A {
suspend fun foo()
fun bar()
}
interface B : A {
<!CONFLICTING_OVERLOADS!><!NOTHING_TO_OVERRIDE!>override<!> fun foo()<!> {
}
<!CONFLICTING_OVERLOADS!><!NOTHING_TO_OVERRIDE!>override<!> suspend fun bar()<!> {
}
}
interface C : A {
suspend override fun foo() {
}
override fun bar() {
}
}
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class D<!> : J {
suspend override fun foo() {
}
}
// FILE: J.java
public interface J extends A {
Object foo(kotlin.coroutines.Continuation<kotlin.Unit> y);
}
@@ -0,0 +1,44 @@
package
public interface A {
public abstract fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract suspend fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B : A {
public open suspend fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A {
public open override /*1*/ fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open suspend override /*1*/ fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class D : J {
public constructor D()
public abstract override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open suspend override /*1*/ fun foo(): kotlin.Unit
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ y: kotlin.coroutines.Continuation!): kotlin.Any!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface J : A {
public abstract override /*1*/ /*fake_override*/ fun bar(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract suspend override /*1*/ /*fake_override*/ fun foo(): kotlin.Unit
public abstract fun foo(/*0*/ y: kotlin.coroutines.Continuation!): kotlin.Any!
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -4318,6 +4318,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("mixingSuspendability.kt")
public void testMixingSuspendability() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/mixingSuspendability.kt");
doTest(fileName);
}
@TestMetadata("noDefaultCoroutineImports.kt")
public void testNoDefaultCoroutineImports() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/noDefaultCoroutineImports.kt");
@@ -4336,6 +4342,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("suspendConflictsWithNoSuspend.kt")
public void testSuspendConflictsWithNoSuspend() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/suspendConflictsWithNoSuspend.kt");
doTest(fileName);
}
@TestMetadata("suspendCoroutineOrReturn.kt")
public void testSuspendCoroutineOrReturn() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/suspendCoroutineOrReturn.kt");
@@ -4354,6 +4366,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("suspendOverridability.kt")
public void testSuspendOverridability() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/suspendOverridability.kt");
doTest(fileName);
}
@TestMetadata("tryCatchLambda.kt")
public void testTryCatchLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/coroutines/tryCatchLambda.kt");
@@ -260,6 +260,11 @@ public class OverridingUtil {
}
}
if (superDescriptor instanceof FunctionDescriptor && subDescriptor instanceof FunctionDescriptor &&
((FunctionDescriptor) superDescriptor).isSuspend() != ((FunctionDescriptor) subDescriptor).isSuspend()) {
return OverrideCompatibilityInfo.conflict("Incompatible suspendability");
}
if (checkReturnType) {
KotlinType superReturnType = superDescriptor.getReturnType();
KotlinType subReturnType = subDescriptor.getReturnType();