diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt index fec9cf32aa8..f530a57b4e7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt @@ -178,7 +178,8 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) // 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 @@ -273,9 +274,13 @@ class HeaderImplDeclarationChecker(val moduleToCheck: ModuleDescriptor? = null) } private fun areCompatibleFunctions(a: FunctionDescriptor, b: FunctionDescriptor): Compatibility { - if (!equalBy(a, b) { f -> - listOf(f.isExternal, f.isInfix, f.isInline, f.isOperator, f.isSuspend, f.isTailrec) - }) return Incompatible.FunctionModifiers + if (!equalBy(a, b) { f -> f.isSuspend }) return Incompatible.FunctionModifiersDifferent + + 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 } diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.kt new file mode 100644 index 00000000000..c0d1607e396 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.kt @@ -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 diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.txt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.txt new file mode 100644 index 00000000000..7f51343aa68 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/functionModifiers.txt @@ -0,0 +1,18 @@ +// -- Module: -- +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: -- +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 diff --git a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt index 75ba5595b4c..653501edd08 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/topLevelFun/inlineFun.kt @@ -15,4 +15,4 @@ impl fun nonInlineFun() { } // FILE: js.kt impl inline fun inlineFun() { } -impl inline fun nonInlineFun() { } +impl inline fun nonInlineFun() { } diff --git a/compiler/testData/multiplatform/incompatibleFunctions/common.kt b/compiler/testData/multiplatform/incompatibleFunctions/common.kt index 033190851c9..2d7f3e82781 100644 --- a/compiler/testData/multiplatform/incompatibleFunctions/common.kt +++ b/compiler/testData/multiplatform/incompatibleFunctions/common.kt @@ -1,14 +1,9 @@ header infix fun Int.plus(s: CharSequence): Int -header fun Int.minus(s: String): Int header operator fun Double.times(x: CharArray) -header fun Double.divide(x: ByteArray) header external fun f1() -header fun g1() header inline fun f2() -header fun g2() header tailrec fun f3() -header fun g3() diff --git a/compiler/testData/multiplatform/incompatibleFunctions/jvm.kt b/compiler/testData/multiplatform/incompatibleFunctions/jvm.kt index 64d18ddacef..51cab42fe40 100644 --- a/compiler/testData/multiplatform/incompatibleFunctions/jvm.kt +++ b/compiler/testData/multiplatform/incompatibleFunctions/jvm.kt @@ -1,14 +1,9 @@ impl fun Int.plus(s: CharSequence): Int = 0 -impl infix fun Int.minus(s: String): Int = 1 impl fun Double.times(x: CharArray) {} -impl operator fun Double.divide(x: ByteArray) {} impl fun f1() {} -impl external fun g1() impl fun f2() {} -impl inline fun g2() {} impl fun f3() {} -impl tailrec fun g3() {} diff --git a/compiler/testData/multiplatform/incompatibleFunctions/output.txt b/compiler/testData/multiplatform/incompatibleFunctions/output.txt index 81ee8b739c4..80b500255d9 100644 --- a/compiler/testData/multiplatform/incompatibleFunctions/output.txt +++ b/compiler/testData/multiplatform/incompatibleFunctions/output.txt @@ -6,96 +6,48 @@ Output: Exit code: COMPILATION_ERROR Output: 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 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 -The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, 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): +compiler/testData/multiplatform/incompatibleFunctions/common.kt:3:1: error: header declaration 'times' has no implementation in module +The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec): public impl fun Double.times(x: CharArray): Unit header operator fun Double.times(x: CharArray) ^ -compiler/testData/multiplatform/incompatibleFunctions/common.kt:5:1: error: header declaration 'divide' has no implementation in module -The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, 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): +compiler/testData/multiplatform/incompatibleFunctions/common.kt:5:1: error: header declaration 'f1' has no implementation in module +The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec): public impl fun f1(): Unit header external fun f1() ^ -compiler/testData/multiplatform/incompatibleFunctions/common.kt:8:1: error: header declaration 'g1' has no implementation in module -The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, 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): +compiler/testData/multiplatform/incompatibleFunctions/common.kt:7:1: error: header declaration 'f2' has no implementation in module +The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec): public impl fun f2(): Unit header inline fun f2() ^ -compiler/testData/multiplatform/incompatibleFunctions/common.kt:11:1: error: header declaration 'g2' has no implementation in module -The following declaration is incompatible because modifiers are different (external, infix, inline, operator, suspend, 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): +compiler/testData/multiplatform/incompatibleFunctions/common.kt:9:1: error: header declaration 'f3' has no implementation in module +The following declaration is incompatible because some modifiers on header declaration are missing on the implementation (external, infix, inline, operator, tailrec): public impl fun f3(): Unit 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 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 -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 +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 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 -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() {} ^ -compiler/testData/multiplatform/incompatibleFunctions/jvm.kt:8: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 +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 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 -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 +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 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() {} -^ diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 3682bbf8707..ec67739ea9c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -13149,6 +13149,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { 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") public void testHeaderAndImplInDIfferentPackages() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/topLevelFun/headerAndImplInDIfferentPackages.kt");