Relax requirements on function modifiers in multiplatform projects

Allow to implement header functions with external/tailrec/inline/infix/operator
functions
This commit is contained in:
Alexander Udalov
2016-12-14 21:17:09 +03:00
parent 64867409b7
commit a57455ce62
8 changed files with 65 additions and 75 deletions
@@ -178,7 +178,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
// Functions // Functions
object FunctionModifiers : Incompatible("modifiers are different (external, infix, inline, operator, suspend, tailrec)") object FunctionModifiersDifferent : Incompatible("modifiers are different (suspend)")
object FunctionModifiersNotSubset : Incompatible("some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec)")
// Properties // Properties
@@ -273,9 +274,13 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null)
} }
private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): Compatibility { private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): Compatibility {
if (!equalBy(a, b) { f -> if (!equalBy(a, b) { f -> f.isSuspend }) return Incompatible.FunctionModifiersDifferent
listOf(f.isExternal, f.isInfix, f.isInline, f.isOperator, f.isSuspend, f.isTailrec)
}) return Incompatible.FunctionModifiers if (a.isExternal && !b.isExternal ||
a.isInfix && !b.isInfix ||
a.isInline && !b.isInline ||
a.isOperator && !b.isOperator ||
a.isTailrec && !b.isTailrec) return Incompatible.FunctionModifiersNotSubset
return Compatible return Compatible
} }
@@ -0,0 +1,19 @@
// !LANGUAGE: +MultiPlatformProjects
// !DIAGNOSTICS: -NOTHING_TO_INLINE
// MODULE: m1-common
// FILE: common.kt
header fun external()
header fun tailrec()
header fun inline()
header fun String.unaryMinus(): String
header fun String.and(other: String): String
// MODULE: m2-jvm(m1-common)
// FILE: jvm.kt
impl external fun external()
impl tailrec fun tailrec(): Unit = if (true) Unit else tailrec()
impl inline fun inline() {}
impl operator fun String.unaryMinus(): String = this
impl infix fun String.and(other: String): String = this + other
@@ -0,0 +1,18 @@
// -- Module: <m1-common> --
package
public header fun external(): kotlin.Unit
public header fun inline(): kotlin.Unit
public header fun tailrec(): kotlin.Unit
public header fun kotlin.String.and(/*0*/ other: kotlin.String): kotlin.String
public header fun kotlin.String.unaryMinus(): kotlin.String
// -- Module: <m2-jvm> --
package
public external impl fun external(): kotlin.Unit
public inline impl fun inline(): kotlin.Unit
public tailrec impl fun tailrec(): kotlin.Unit
public infix impl fun kotlin.String.and(/*0*/ other: kotlin.String): kotlin.String
public operator impl fun kotlin.String.unaryMinus(): kotlin.String
@@ -15,4 +15,4 @@ impl fun nonInlineFun() { }
// FILE: js.kt // FILE: js.kt
impl <!NOTHING_TO_INLINE!>inline<!> fun inlineFun() { } impl <!NOTHING_TO_INLINE!>inline<!> fun inlineFun() { }
<!IMPLEMENTATION_WITHOUT_HEADER!>impl<!> <!NOTHING_TO_INLINE!>inline<!> fun nonInlineFun() { } impl <!NOTHING_TO_INLINE!>inline<!> fun nonInlineFun() { }
@@ -1,14 +1,9 @@
header infix fun Int.plus(s: CharSequence): Int header infix fun Int.plus(s: CharSequence): Int
header fun Int.minus(s: String): Int
header operator fun Double.times(x: CharArray) header operator fun Double.times(x: CharArray)
header fun Double.divide(x: ByteArray)
header external fun f1() header external fun f1()
header fun g1()
header inline fun f2() header inline fun f2()
header fun g2()
header tailrec fun f3() header tailrec fun f3()
header fun g3()
@@ -1,14 +1,9 @@
impl fun Int.plus(s: CharSequence): Int = 0 impl fun Int.plus(s: CharSequence): Int = 0
impl infix fun Int.minus(s: String): Int = 1
impl fun Double.times(x: CharArray) {} impl fun Double.times(x: CharArray) {}
impl operator fun Double.divide(x: ByteArray) {}
impl fun f1() {} impl fun f1() {}
impl external fun g1()
impl fun f2() {} impl fun f2() {}
impl inline fun g2() {}
impl fun f3() {} impl fun f3() {}
impl tailrec fun g3() {}
@@ -6,96 +6,48 @@ Output:
Exit code: COMPILATION_ERROR Exit code: COMPILATION_ERROR
Output: Output:
compiler/testData/multiplatform/incompatibleFunctions/common.kt:1:1: error: header declaration 'plus' has no implementation in module compiler/testData/multiplatform/incompatibleFunctions/common.kt:1:1: error: header declaration 'plus' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec):
public impl fun Int.plus(s: CharSequence): Int public impl fun Int.plus(s: CharSequence): Int
header infix fun Int.plus(s: CharSequence): Int header infix fun Int.plus(s: CharSequence): Int
^ ^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:2:1: error: header declaration 'minus' has no implementation in module compiler/testData/multiplatform/incompatibleFunctions/common.kt:3:1: error: header declaration 'times' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec):
public infix impl fun Int.minus(s: String): Int
header fun Int.minus(s: String): Int
^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:4:1: error: header declaration 'times' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec):
public impl fun Double.times(x: CharArray): Unit public impl fun Double.times(x: CharArray): Unit
header operator fun Double.times(x: CharArray) header operator fun Double.times(x: CharArray)
^ ^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:5:1: error: header declaration 'divide' has no implementation in module compiler/testData/multiplatform/incompatibleFunctions/common.kt:5:1: error: header declaration 'f1' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec):
public operator impl fun Double.divide(x: ByteArray): Unit
header fun Double.divide(x: ByteArray)
^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:7:1: error: header declaration 'f1' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec):
public impl fun f1(): Unit public impl fun f1(): Unit
header external fun f1() header external fun f1()
^ ^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:8:1: error: header declaration 'g1' has no implementation in module compiler/testData/multiplatform/incompatibleFunctions/common.kt:7:1: error: header declaration 'f2' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec):
public external impl fun g1(): Unit
header fun g1()
^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:10:1: error: header declaration 'f2' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec):
public impl fun f2(): Unit public impl fun f2(): Unit
header inline fun f2() header inline fun f2()
^ ^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:11:1: error: header declaration 'g2' has no implementation in module compiler/testData/multiplatform/incompatibleFunctions/common.kt:9:1: error: header declaration 'f3' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec): The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec):
public inline impl fun g2(): Unit
header fun g2()
^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:13:1: error: header declaration 'f3' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec):
public impl fun f3(): Unit public impl fun f3(): Unit
header tailrec fun f3() header tailrec fun f3()
^ ^
compiler/testData/multiplatform/incompatibleFunctions/common.kt:14:1: error: header declaration 'g3' has no implementation in module
The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, tailrec):
public tailrec impl fun g3(): Unit
header fun g3()
^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:1:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:1:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl fun Int.plus(s: CharSequence): Int = 0 impl fun Int.plus(s: CharSequence): Int = 0
^ ^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:2:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:3:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl infix fun Int.minus(s: String): Int = 1
^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:4:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl fun Double.times(x: CharArray) {} impl fun Double.times(x: CharArray) {}
^ ^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:5:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:5:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl operator fun Double.divide(x: ByteArray) {}
^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:5:6: error: 'operator' modifier is inapplicable on this function: illegal function name
impl operator fun Double.divide(x: ByteArray) {}
^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:7:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl fun f1() {} impl fun f1() {}
^ ^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:8:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:7:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl external fun g1()
^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:10:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl fun f2() {} impl fun f2() {}
^ ^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:11:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:9:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl inline fun g2() {}
^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:13:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl fun f3() {} impl fun f3() {}
^ ^
compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:14:1: error: modifier 'impl' is only applicable to members that are initially declared in platform-independent code
impl tailrec fun g3() {}
^
@@ -13149,6 +13149,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("functionModifiers.kt")
public void testFunctionModifiers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.kt");
doTest(fileName);
}
@TestMetadata("headerAndImplInDIfferentPackages.kt") @TestMetadata("headerAndImplInDIfferentPackages.kt")
public void testHeaderAndImplInDIfferentPackages() throws Exception { public void testHeaderAndImplInDIfferentPackages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/headerAndImplInDIfferentPackages.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/headerAndImplInDIfferentPackages.kt");