[IR] Implement IR checker for expect actual annotations matching

^KT-58551
This commit is contained in:
Roman Efremov
2023-06-22 12:30:52 +02:00
committed by Space Team
parent b6cae1adcc
commit 2980179bd7
26 changed files with 324 additions and 44 deletions
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.cast
import java.io.File
class ExpectedActualDeclarationChecker(
@@ -7,9 +7,10 @@ package org.jetbrains.kotlin.backend.common
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.INCOMPATIBILITY
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.SYMBOL_OWNER_DECLARATION_FQ_NAME
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.error0
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies.ACTUAL_DECLARATION_NAME
import org.jetbrains.kotlin.diagnostics.error2
import org.jetbrains.kotlin.diagnostics.error3
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
@@ -17,6 +18,10 @@ import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.MODULE_WITH_PLATFORM
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.warning2
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
object CommonBackendErrors {
@@ -24,6 +29,7 @@ object CommonBackendErrors {
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error2<PsiElement, String, String>()
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error2<PsiElement, String, String>()
val INCOMPATIBLE_MATCHING by error3<PsiElement, String, String, ExpectActualCompatibility.Incompatible<*>>()
val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning2<PsiElement, IrSymbol, IrSymbol>()
init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultCommonBackendErrorMessages)
@@ -57,6 +63,12 @@ object KtDefaultCommonBackendErrorMessages : BaseDiagnosticRendererFactory() {
STRING,
INCOMPATIBILITY
)
map.put(
CommonBackendErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
"All annotations from expect declaration `{0}` must be present with the same arguments on actual declaration `{1}` otherwise they have no effect",
SYMBOL_OWNER_DECLARATION_FQ_NAME,
SYMBOL_OWNER_DECLARATION_FQ_NAME,
)
}
}
@@ -64,4 +76,7 @@ object BackendDiagnosticRenderers {
val INCOMPATIBILITY = Renderer<ExpectActualCompatibility.Incompatible<*>> {
it.reason ?: "<unknown>"
}
val SYMBOL_OWNER_DECLARATION_FQ_NAME = Renderer<IrSymbol> {
(it.owner as? IrDeclarationWithName)?.fqNameWhenAvailable?.asString() ?: "unknown name"
}
}
@@ -33,6 +33,7 @@ object IrActualizer {
typeSystemContext,
ktDiagnosticReporter
).collect()
IrExpectActualAnnotationMatchingChecker(expectActualMap, actualDeclarations, typeSystemContext, ktDiagnosticReporter).check()
// 2. Remove top-only expect declarations since they are not needed anymore and should not be presented in the final IrFragment
// Expect fake-overrides from non-expect classes remain untouched since they will be actualized in the next phase.
@@ -122,6 +122,18 @@ internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportIncompatibleEx
)
}
internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportActualAnnotationsNotMatchExpect(
expectSymbol: IrSymbol,
actualSymbol: IrSymbol,
reportOn: IrSymbol,
) {
at(reportOn.owner as IrDeclaration).report(
CommonBackendErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT,
expectSymbol,
actualSymbol,
)
}
internal fun IrElement.containsOptionalExpectation(): Boolean {
return this is IrClass &&
this.kind == ClassKind.ANNOTATION_CLASS &&
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.util.classIdOrFail
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker
internal class IrExpectActualAnnotationMatchingChecker(
private val matchedExpectToActual: Map<IrSymbol, IrSymbol>,
private val classActualizationInfo: ClassActualizationInfo,
typeSystemContext: IrTypeSystemContext,
private val diagnosticsReporter: KtDiagnosticReporterWithImplicitIrBasedContext,
) {
private val context = object : IrExpectActualMatchingContext(typeSystemContext, classActualizationInfo.actualClasses) {
override fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol) {
error("Must not be called")
}
override fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol) {
error("Must not be called")
}
}
fun check() {
for ((expectSymbol, actualSymbol) in matchedExpectToActual.entries) {
val incompatibility =
AbstractExpectActualAnnotationMatchChecker.areAnnotationsCompatible(expectSymbol, actualSymbol, context) ?: continue
val reportOn = getTypealiasSymbolIfActualizedViaTypealias(expectSymbol) ?: actualSymbol
diagnosticsReporter.reportActualAnnotationsNotMatchExpect(
incompatibility.expectSymbol as IrSymbol,
incompatibility.actualSymbol as IrSymbol,
reportOn,
)
}
}
private fun getTypealiasSymbolIfActualizedViaTypealias(expectSymbol: IrSymbol): IrTypeAliasSymbol? {
val expectDeclaration = expectSymbol.owner as IrDeclaration
val topLevelExpectClass = expectDeclaration.parentsWithSelf.filterIsInstance<IrClass>().lastOrNull() ?: return null
val classId = topLevelExpectClass.classIdOrFail
return classActualizationInfo.actualTypeAliases[classId]
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.TypeCheckerState
import org.jetbrains.kotlin.types.Variance
@@ -446,12 +448,21 @@ internal abstract class IrExpectActualMatchingContext(
abstract fun onMatchedClasses(expectClassSymbol: IrClassSymbol, actualClassSymbol: IrClassSymbol)
abstract fun onMatchedCallables(expectSymbol: IrSymbol, actualSymbol: IrSymbol)
override val DeclarationSymbolMarker.annotations: List<ExpectActualMatchingContext.AnnotationCallInfo>
// TODO(Roman.Efremov): implement in subsequent commits
get() = emptyList()
override val DeclarationSymbolMarker.annotations: List<AnnotationCallInfo>
get() = asIr().annotations.map(::AnnotationCallInfoImpl)
override fun areAnnotationArgumentsEqual(annotation1: ExpectActualMatchingContext.AnnotationCallInfo, annotation2: ExpectActualMatchingContext.AnnotationCallInfo): Boolean {
// TODO(Roman.Efremov): implement in subsequent commits
return true
override fun areAnnotationArgumentsEqual(annotation1: AnnotationCallInfo, annotation2: AnnotationCallInfo): Boolean {
fun AnnotationCallInfo.getIrElement(): IrConstructorCall = (this as AnnotationCallInfoImpl).irElement
return areIrExpressionConstValuesEqual(annotation1.getIrElement(), annotation2.getIrElement())
}
internal fun getClassIdAfterActualization(classId: ClassId): ClassId {
return expectToActualClassMap[classId]?.classId ?: classId
}
private class AnnotationCallInfoImpl(val irElement: IrConstructorCall) : AnnotationCallInfo {
override val classId: ClassId?
get() = irElement.type.getClass()?.classId
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.actualizer
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.classOrFail
internal fun IrExpectActualMatchingContext.areIrExpressionConstValuesEqual(a: IrElement?, b: IrElement?): Boolean {
return when {
a == null || b == null -> (a == null) == (b == null)
a::class != b::class -> false
a is IrConst<*> && b is IrConst<*> -> a.value == b.value
a is IrClassReference && b is IrClassReference -> equalBy(a, b) {
val classId = it.classType.classOrFail.classId
getClassIdAfterActualization(classId)
}
a is IrGetEnumValue && b is IrGetEnumValue -> equalBy(a, b) { it.symbol.signature?.toString() }
a is IrVararg && b is IrVararg -> {
equalBy(a, b) { it.elements.size } &&
a.elements.zip(b.elements).all { (f, s) -> areIrExpressionConstValuesEqual(f, s) }
}
a is IrConstructorCall && b is IrConstructorCall -> {
equalBy(a, b) { it.valueArgumentsCount } &&
areCompatibleExpectActualTypes(a.type, b.type) &&
(0..<a.valueArgumentsCount).all { i ->
areIrExpressionConstValuesEqual(a.getValueArgument(i), b.getValueArgument(i))
}
}
else -> error("Not handled expression types $a $b")
}
}
private inline fun <T : Any> equalBy(first: T, second: T, selector: (T) -> Any?): Boolean =
selector(first) == selector(second)
@@ -87,8 +87,8 @@ package test
@ClassArgAnn(ClassForReference::class)
actual fun getClassExpression() {}
@ClassArgAnn(ClassForReference::class)
actual fun differentClassesWithSameName() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@ClassArgAnn(ClassForReference::class)
actual fun differentClassesWithSameName() {}<!>
@StringArgAnn("1.9")
actual fun stringConstant() {}
@@ -114,8 +114,8 @@ actual fun varargInAnnotationWithArraySpread() {}
@ArrayArgAnn(arrayOf("foo", "bar"))
actual fun arrayInAnnotation() {}
@ArrayArgAnn(["foo"])
actual fun arrayInAnnotationNotMatch() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@ArrayArgAnn(["foo"])
actual fun arrayInAnnotationNotMatch() {}<!>
@NestedAnnArg(
text = "root",
@@ -127,7 +127,7 @@ actual fun arrayInAnnotationNotMatch() {}
)
actual fun complexNestedAnnotations() {}
@NestedAnnArg(
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@NestedAnnArg(
text = "root",
NestedAnnArg("1"),
NestedAnnArg("2",
@@ -135,4 +135,4 @@ actual fun complexNestedAnnotations() {}
NestedAnnArg("DIFFERENT")
)
)
actual fun complexNestedAnnotationsNotMatch() {}
actual fun complexNestedAnnotationsNotMatch() {}<!>
@@ -0,0 +1,11 @@
// MODULE: m1-common
// FILE: common.kt
annotation class Ann(val p: String = "")
@Ann("")
expect fun explicitDefaultArgument()
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
// No special handling for this case
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>explicitDefaultArgument<!>() {}<!>
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
annotation class Ann(val p: String = "")
@@ -62,26 +62,26 @@ expect fun explicitVsInfered()
@Ann<A>
actual fun sameTypeParam() {}
@Ann<A>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentTypeParam<!>() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann<A>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentTypeParam<!>() {}<!>
@Ann<A>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentWithSameName<!>() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann<A>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentWithSameName<!>() {}<!>
@Ann<A>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>nonNullvsNull<!>() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann<A>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>nonNullvsNull<!>() {}<!>
@Ann<Ann<out A>>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentVariance<!>() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann<Ann<out A>>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>differentVariance<!>() {}<!>
@Ann<Ann<A>>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>varianceVsNoVariance<!>() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann<Ann<A>>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>varianceVsNoVariance<!>() {}<!>
@Ann<Ann<in A>>
actual fun sameVariance() {}
@Ann<Ann<Any>>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>startProjection<!>() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann<Ann<Any>>
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>startProjection<!>() {}<!>
@ComplexNested<A>(
ComplexNested<A>(),
@@ -89,11 +89,11 @@ actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_E
)
actual fun complexSame() {}
@ComplexNested<A>(
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@ComplexNested<A>(
ComplexNested<A>(),
ComplexNested<A>(),
)
actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>complexDiffer<!>() {}
actual fun complexDiffer() {}<!>
@NestedWithSameTypeArgument<A>(
NestedWithSameTypeArgument<A>()
@@ -0,0 +1,41 @@
// MODULE: m1-common
// FILE: common.kt
annotation class Ann
@Ann
expect class AnnotationMatching
@Ann
expect class AnnotationOnExpectOnly
expect class AnnotationOnActualOnly
expect class AnnotationInside {
@Ann
fun matches()
@Ann
fun onlyOnExpect()
fun onlyOnActual()
}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
@Ann
actual class AnnotationMatching
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>AnnotationOnExpectOnly<!><!>
@Ann
actual class AnnotationOnActualOnly
actual class AnnotationInside {
@Ann
actual fun matches() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onlyOnExpect<!>() {}<!>
@Ann
actual fun onlyOnActual() {}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
annotation class Ann
@@ -1,17 +1,17 @@
// -- Module: <m1-common> --
// -- Module: <m1-jvm> --
/jvm.kt:24:14: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
/jvm.kt:23:14: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
Expected: @Ann public final expect class OnClass defined in root package in file common.kt
Actual: public final actual class OnClass defined in root package in file jvm.kt
actual class OnClass
^
/jvm.kt:27:16: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
/jvm.kt:26:16: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
Expected: @Ann public final expect fun onMember(): Unit defined in OnMember
Actual: public final actual fun onMember(): Unit defined in OnMember
actual fun onMember() {}
^
/jvm.kt:34:18: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
/jvm.kt:33:18: warning: all annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
Expected: @Ann public final expect class ViaTypealias defined in root package in file common.kt
Actual: public final class ViaTypealiasImpl defined in root package in file jvm.kt
actual typealias ViaTypealias = ViaTypealiasImpl
@@ -1,11 +1,11 @@
/jvm.kt:(83,90): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
/jvm.kt:(82,89): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
Expected: @Ann() public final expect class OnClass : Any
Actual: public final actual class OnClass : Any
/jvm.kt:(131,139): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
/jvm.kt:(130,138): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
Expected: @Ann() public final expect fun onMember(): Unit
Actual: public final actual fun onMember(): Unit
/jvm.kt:(210,222): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
/jvm.kt:(209,221): warning: All annotations from `expect` must be presented with same arguments on `actual`, otherwise they have no effect.
Expected: @Ann() public final expect class ViaTypealias : Any
Actual: public final class ViaTypealiasImpl : Any
@@ -0,0 +1,33 @@
// RENDER_DIAGNOSTICS_FULL_TEXT
// MODULE: m1-common
// FILE: common.kt
annotation class Ann
@Ann
expect class OnClass
expect class OnMember {
@Ann
fun onMember()
}
@Ann
expect class ViaTypealias {
@Ann
fun foo()
}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClass<!><!>
actual class OnMember {
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onMember<!>() {}<!>
}
class ViaTypealiasImpl {
fun foo() {}
}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>ViaTypealias<!> = ViaTypealiasImpl<!>
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// RENDER_DIAGNOSTICS_FULL_TEXT
// MODULE: m1-common
// FILE: common.kt
@@ -0,0 +1,18 @@
// MODULE: m1-common
// FILE: common.kt
annotation class Ann
expect class CompatibleOverrides {
fun foo()
@Ann
fun foo(withArg: Any)
}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual class CompatibleOverrides {
actual fun foo() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>foo<!>(withArg: Any) {}<!>
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// MODULE: m1-common
// FILE: common.kt
annotation class Ann
@@ -24,8 +24,8 @@ expect fun differentArgumentsOrder()
@Ann1
actual class AnnotationOrder
@Ann3(2, 1)
actual class ValuesOrderInsideAnnotationArgument
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann3(2, 1)
actual class ValuesOrderInsideAnnotationArgument<!>
@Ann4(arg2 = "2", arg1 = "1")
actual fun differentArgumentsOrder() {}
@@ -7,5 +7,5 @@ expect fun floatNumbersComparison()
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
@Ann(0.1 + 0.1 + 0.1)
actual fun floatNumbersComparison() {}
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann(0.1 + 0.1 + 0.1)
actual fun floatNumbersComparison() {}<!>
@@ -0,0 +1,22 @@
// WITH_STDLIB
// MODULE: m1-common
// FILE: common.kt
@Target(AnnotationTarget.TYPEALIAS, AnnotationTarget.CLASS)
annotation class Ann
@Ann
expect class KtTypealiasNotMatch
@Ann
expect class AnnotationsNotConsideredOnTypealias
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
class KtTypealiasNotMatchImpl
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>KtTypealiasNotMatch<!> = KtTypealiasNotMatchImpl<!>
class AnnotationsNotConsideredOnTypealiasImpl
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>@Ann
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>AnnotationsNotConsideredOnTypealias<!> = AnnotationsNotConsideredOnTypealiasImpl<!>
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// WITH_STDLIB
// MODULE: m1-common
// FILE: common.kt
@@ -9,6 +9,6 @@ expect annotation class MyDeprecatedMatch
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias MyDeprecatedNotMatch = java.lang.Deprecated
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias MyDeprecatedNotMatch = java.lang.Deprecated<!>
actual typealias MyDeprecatedMatch = java.lang.Deprecated
@@ -1,4 +1,5 @@
// WITH_STDLIB
// DIAGNOSTICS: -ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION
// MODULE: m1-common
// FILE: common.kt
@Target(
@@ -25,8 +26,17 @@ expect annotation class MyDeprecatedNotMatch
)
expect annotation class MyDeprecatedMatch
annotation class Ann(val s: String)
expect abstract class MyAbstractIterator<T> {
@Ann("something" + "complex")
fun hasNext(): Boolean
}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias MyDeprecatedNotMatch = kotlin.Deprecated
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias MyDeprecatedNotMatch = kotlin.Deprecated<!>
actual typealias MyDeprecatedMatch = kotlin.Deprecated
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual typealias MyAbstractIterator<T> = AbstractIterator<T><!>
@@ -1,4 +1,5 @@
// WITH_STDLIB
// DIAGNOSTICS: -ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION
// MODULE: m1-common
// FILE: common.kt
@Target(
@@ -25,8 +26,17 @@ expect annotation class MyDeprecatedNotMatch
)
expect annotation class MyDeprecatedMatch
annotation class Ann(val s: String)
expect abstract class MyAbstractIterator<T> {
@Ann("something" + "complex")
fun hasNext(): Boolean
}
// MODULE: m1-jvm()()(m1-common)
// FILE: jvm.kt
actual typealias <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>MyDeprecatedNotMatch<!> = kotlin.Deprecated
actual typealias MyDeprecatedMatch = kotlin.Deprecated
actual typealias MyAbstractIterator<T> = AbstractIterator<T>