[FE, IR] Check annotations compatibility on expect and actual type parameters

^KT-60671
This commit is contained in:
Roman Efremov
2023-08-02 15:18:58 +02:00
committed by Space Team
parent 420dceb7d8
commit 8fb2935ef6
10 changed files with 151 additions and 12 deletions
@@ -908,6 +908,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/twoActualTypealiasesToSameClass.kt");
}
@Test
@TestMetadata("typeParameters.kt")
public void testTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeParameters.kt");
}
@Test
@TestMetadata("typealias.kt")
public void testTypealias() throws Exception {
@@ -908,6 +908,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/twoActualTypealiasesToSameClass.kt");
}
@Test
@TestMetadata("typeParameters.kt")
public void testTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeParameters.kt");
}
@Test
@TestMetadata("typealias.kt")
public void testTypealias() throws Exception {
@@ -112,6 +112,7 @@ object AbstractExpectActualAnnotationMatchChecker {
actualSymbol: DeclarationSymbolMarker,
): Incompatibility? {
areAnnotationsSetOnDeclarationsCompatible(expectSymbol, actualSymbol)?.let { return it }
areAnnotationsOnTypeParametersCompatible(expectSymbol, actualSymbol)?.let { return it }
return null
}
@@ -134,6 +135,31 @@ object AbstractExpectActualAnnotationMatchChecker {
}
}
context (ExpectActualMatchingContext<*>)
private fun areAnnotationsOnTypeParametersCompatible(
expectSymbol: DeclarationSymbolMarker,
actualSymbol: DeclarationSymbolMarker,
): Incompatibility? {
fun DeclarationSymbolMarker.getTypeParameters(): List<TypeParameterSymbolMarker>? {
return when (this) {
is FunctionSymbolMarker -> typeParameters
is RegularClassSymbolMarker -> typeParameters
else -> null
}
}
val expectParams = expectSymbol.getTypeParameters() ?: return null
val actualParams = actualSymbol.getTypeParameters() ?: return null
if (expectParams.size != actualParams.size) return null
return expectParams.zip(actualParams).firstNotNullOfOrNull { (expectParam, actualParam) ->
areAnnotationsSetOnDeclarationsCompatible(expectParam, actualParam)?.let {
// Write containing declarations into diagnostic
Incompatibility(expectSymbol, actualSymbol, actualParam.getSourceElement(), it.type)
}
}
}
context (ExpectActualMatchingContext<*>)
private fun areAnnotationsSetOnDeclarationsCompatible(
expectSymbol: DeclarationSymbolMarker,
@@ -1,28 +1,32 @@
// -- Module: <m1-common> --
// -- Module: <m1-jvm> --
/jvm.kt:31:14: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:39:14: warning: annotation `@Ann` is missing on actual declaration.
All annotations from expect `class OnClass defined in root package in file common.kt` must be present with the same arguments on actual `class OnClass defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
actual class OnClass
^
/jvm.kt:34:16: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:42:16: warning: annotation `@Ann` is missing on actual declaration.
All annotations from expect `fun onMember(): Unit defined in OnMember` must be present with the same arguments on actual `fun onMember(): Unit defined in OnMember`, otherwise they might behave incorrectly.
actual fun onMember() {}
^
/jvm.kt:39:18: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:47:18: warning: annotation `@Ann` is missing on actual declaration.
All annotations from expect `class ViaTypealias defined in root package in file common.kt` must be present with the same arguments on actual `class ViaTypealiasImpl defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
actual typealias ViaTypealias = ViaTypealiasImpl
^
/jvm.kt:44:18: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:52:18: warning: annotation `@Ann` is missing on actual declaration.
All annotations from expect `fun foo(): Unit defined in MemberScopeViaTypealias` must be present with the same arguments on actual `fun foo(): Unit defined in MemberScopeViaTypealiasImpl`, otherwise they might behave incorrectly.
actual typealias MemberScopeViaTypealias = MemberScopeViaTypealiasImpl
^
/jvm.kt:47:12: warning: annotation `@WithArg(s = "str")` has different arguments on actual declaration: `@WithArg(s = "other str")`.
/jvm.kt:55:12: warning: annotation `@WithArg(s = "str")` has different arguments on actual declaration: `@WithArg(s = "other str")`.
All annotations from expect `fun withDifferentArg(): Unit defined in root package in file common.kt` must be present with the same arguments on actual `fun withDifferentArg(): Unit defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
actual fun withDifferentArg() {}
^
/jvm.kt:49:12: warning: annotation `@Ann` is missing on actual declaration.
/jvm.kt:57:12: warning: annotation `@Ann` is missing on actual declaration.
All annotations from expect `fun inValueParam(arg: String): Unit defined in root package in file common.kt` must be present with the same arguments on actual `fun inValueParam(arg: String): Unit defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
actual fun inValueParam(arg: String) {}
^
/jvm.kt:59:16: warning: annotation `@Ann` is missing on actual declaration.
All annotations from expect `fun <T> inTypeParam(): Unit defined in root package in file common.kt` must be present with the same arguments on actual `fun <T> inTypeParam(): Unit defined in root package in file jvm.kt`, otherwise they might behave incorrectly.
actual fun <T> inTypeParam() {}
^
@@ -1,17 +1,20 @@
/jvm.kt:(90,97): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(98,105): warning: Annotation `@Ann()` is missing on actual declaration.
All annotations from expect 'class OnClass : Any' must be present with the same arguments on actual 'class OnClass : Any', otherwise they might behave incorrectly.
/jvm.kt:(138,146): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(146,154): warning: Annotation `@Ann()` is missing on actual declaration.
All annotations from expect 'fun onMember(): Unit' must be present with the same arguments on actual 'fun onMember(): Unit', otherwise they might behave incorrectly.
/jvm.kt:(196,208): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(204,216): warning: Annotation `@Ann()` is missing on actual declaration.
All annotations from expect 'class ViaTypealias : Any' must be present with the same arguments on actual 'class ViaTypealiasImpl : Any', otherwise they might behave incorrectly.
/jvm.kt:(301,324): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(309,332): warning: Annotation `@Ann()` is missing on actual declaration.
All annotations from expect 'fun foo(): Unit' must be present with the same arguments on actual 'fun foo(): Unit', otherwise they might behave incorrectly.
/jvm.kt:(389,405): warning: Annotation `@WithArg(s = String(str))` has different arguments on actual declaration: `@WithArg(s = String(other str))`.
/jvm.kt:(397,413): warning: Annotation `@WithArg(s = String(str))` has different arguments on actual declaration: `@WithArg(s = String(other str))`.
All annotations from expect 'fun withDifferentArg(): Unit' must be present with the same arguments on actual 'fun withDifferentArg(): Unit', otherwise they might behave incorrectly.
/jvm.kt:(423,435): warning: Annotation `@Ann()` is missing on actual declaration.
/jvm.kt:(431,443): warning: Annotation `@Ann()` is missing on actual declaration.
All annotations from expect 'fun inValueParam(arg: String): Unit' must be present with the same arguments on actual 'fun inValueParam(arg: String): Unit', otherwise they might behave incorrectly.
/jvm.kt:(476,487): warning: Annotation `@Ann()` is missing on actual declaration.
All annotations from expect 'fun <T> inTypeParam(): Unit' must be present with the same arguments on actual 'fun <T> inTypeParam(): Unit', otherwise they might behave incorrectly.
@@ -1,6 +1,12 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
// MODULE: m1-common
// FILE: common.kt
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.CLASS,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.TYPE_PARAMETER,
)
annotation class Ann
@Ann
@@ -26,6 +32,8 @@ expect fun withDifferentArg()
expect fun inValueParam(@Ann arg: String)
expect fun <@Ann T> inTypeParam()
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!><!>
@@ -47,3 +55,5 @@ class MemberScopeViaTypealiasImpl {
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}<!>
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inValueParam<!>(arg: String) {}<!>
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <T> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inTypeParam<!>() {}<!>
@@ -1,6 +1,12 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
// MODULE: m1-common
// FILE: common.kt
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.CLASS,
AnnotationTarget.VALUE_PARAMETER,
AnnotationTarget.TYPE_PARAMETER,
)
annotation class Ann
@Ann
@@ -26,6 +32,8 @@ expect fun withDifferentArg()
expect fun inValueParam(@Ann arg: String)
expect fun <@Ann T> inTypeParam()
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!>
@@ -47,3 +55,5 @@ actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>MemberScopeViaTypealias<
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inValueParam<!>(arg: String) {}
actual fun <T> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inTypeParam<!>() {}
@@ -0,0 +1,34 @@
// MODULE: m1-common
// FILE: common.kt
@Target(AnnotationTarget.TYPE_PARAMETER)
annotation class Ann
expect fun <@Ann A> inMethod()
expect fun <A, @Ann B> inMethodTwoParams()
expect class InClass<@Ann A>
expect class ViaTypealias<@Ann A>
expect class TypealiasParamNotAccepted<@Ann A>
<!INCOMPATIBLE_MATCHING{JVM}!>expect fun <@Ann A, @Ann B> withIncompatibility()<!>
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <A> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inMethod<!>() {}<!>
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <@Ann A, B> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inMethodTwoParams<!>() {}<!>
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>InClass<!><A><!>
class ViaTypealiasImpl<@Ann A>
actual typealias ViaTypealias<A> = ViaTypealiasImpl<A>
class TypealiasParamNotAcceptedImpl<A>
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>TypealiasParamNotAccepted<!><@Ann A> = TypealiasParamNotAcceptedImpl<A><!>
actual fun <A> <!ACTUAL_WITHOUT_EXPECT!>withIncompatibility<!>() {}
@@ -0,0 +1,34 @@
// MODULE: m1-common
// FILE: common.kt
@Target(AnnotationTarget.TYPE_PARAMETER)
annotation class Ann
expect fun <@Ann A> inMethod()
expect fun <A, @Ann B> inMethodTwoParams()
expect class InClass<@Ann A>
expect class ViaTypealias<@Ann A>
expect class TypealiasParamNotAccepted<@Ann A>
expect fun <!NO_ACTUAL_FOR_EXPECT{JVM}!><@Ann A, @Ann B><!> withIncompatibility()
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual fun <A> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inMethod<!>() {}
actual fun <@Ann A, B> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>inMethodTwoParams<!>() {}
actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>InClass<!><A>
class ViaTypealiasImpl<@Ann A>
actual typealias ViaTypealias<A> = ViaTypealiasImpl<A>
class TypealiasParamNotAcceptedImpl<A>
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>TypealiasParamNotAccepted<!><@Ann A> = TypealiasParamNotAcceptedImpl<A>
actual fun <!ACTUAL_WITHOUT_EXPECT!><A><!> withIncompatibility() {}
@@ -23903,6 +23903,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/twoActualTypealiasesToSameClass.kt");
}
@Test
@TestMetadata("typeParameters.kt")
public void testTypeParameters() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeParameters.kt");
}
@Test
@TestMetadata("typealias.kt")
public void testTypealias() throws Exception {