[FE, IR] Check compatibility of annotations set on type usages in expect and actual declarations
This includes checking of annotatins set on: - value parameter types - type parameter bound types - extension functions receiver types - function return types - class super types Fix in `defaultParams_inheritanceByDelegation_positive.kt` is needed because of problem in resolution of implicit return types (KT-62064), which leads to crash in annotation checker, because it expects resolved return type. MR: KT-MR-12245 ^KT-60671 Fixed
This commit is contained in:
committed by
Space Team
parent
cb8529d65b
commit
423f4ca5f0
+6
@@ -932,6 +932,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsage.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsage.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typeUsageTypealiasInSuper.kt")
|
||||||
|
public void testTypeUsageTypealiasInSuper() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsageTypealiasInSuper.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("typeUsageWithImplicitType.kt")
|
@TestMetadata("typeUsageWithImplicitType.kt")
|
||||||
public void testTypeUsageWithImplicitType() throws Exception {
|
public void testTypeUsageWithImplicitType() throws Exception {
|
||||||
|
|||||||
+6
@@ -932,6 +932,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsage.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsage.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typeUsageTypealiasInSuper.kt")
|
||||||
|
public void testTypeUsageTypealiasInSuper() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsageTypealiasInSuper.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("typeUsageWithImplicitType.kt")
|
@TestMetadata("typeUsageWithImplicitType.kt")
|
||||||
public void testTypeUsageWithImplicitType() throws Exception {
|
public void testTypeUsageWithImplicitType() throws Exception {
|
||||||
|
|||||||
+71
-1
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
|||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.getRetention
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
@@ -26,6 +25,7 @@ import org.jetbrains.kotlin.name.CallableId
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCompatibilityCheckStrategy
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCompatibilityCheckStrategy
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
|||||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||||
|
import org.jetbrains.kotlin.utils.zipIfSizesAreEqual
|
||||||
|
|
||||||
class FirExpectActualMatchingContextImpl private constructor(
|
class FirExpectActualMatchingContextImpl private constructor(
|
||||||
private val actualSession: FirSession,
|
private val actualSession: FirSession,
|
||||||
@@ -160,6 +161,9 @@ class FirExpectActualMatchingContextImpl private constructor(
|
|||||||
override val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
|
override val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
|
||||||
get() = asSymbol().resolvedSuperTypes
|
get() = asSymbol().resolvedSuperTypes
|
||||||
|
|
||||||
|
override val RegularClassSymbolMarker.superTypesRefs: List<TypeRefMarker>
|
||||||
|
get() = asSymbol().resolvedSuperTypeRefs
|
||||||
|
|
||||||
override val RegularClassSymbolMarker.defaultType: KotlinTypeMarker
|
override val RegularClassSymbolMarker.defaultType: KotlinTypeMarker
|
||||||
get() = asSymbol().defaultType()
|
get() = asSymbol().defaultType()
|
||||||
|
|
||||||
@@ -245,8 +249,12 @@ class FirExpectActualMatchingContextImpl private constructor(
|
|||||||
get() = asSymbol().dispatchReceiverType
|
get() = asSymbol().dispatchReceiverType
|
||||||
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
||||||
get() = asSymbol().resolvedReceiverTypeRef?.coneType
|
get() = asSymbol().resolvedReceiverTypeRef?.coneType
|
||||||
|
override val CallableSymbolMarker.extensionReceiverTypeRef: TypeRefMarker?
|
||||||
|
get() = asSymbol().resolvedReceiverTypeRef
|
||||||
override val CallableSymbolMarker.returnType: KotlinTypeMarker
|
override val CallableSymbolMarker.returnType: KotlinTypeMarker
|
||||||
get() = asSymbol().resolvedReturnType.type
|
get() = asSymbol().resolvedReturnType.type
|
||||||
|
override val CallableSymbolMarker.returnTypeRef: TypeRefMarker
|
||||||
|
get() = asSymbol().resolvedReturnTypeRef
|
||||||
override val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
override val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
||||||
get() = asSymbol().typeParameterSymbols
|
get() = asSymbol().typeParameterSymbols
|
||||||
|
|
||||||
@@ -286,6 +294,9 @@ class FirExpectActualMatchingContextImpl private constructor(
|
|||||||
override val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
|
override val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
|
||||||
get() = asSymbol().resolvedBounds.map { it.coneType }
|
get() = asSymbol().resolvedBounds.map { it.coneType }
|
||||||
|
|
||||||
|
override val TypeParameterSymbolMarker.boundsTypeRefs: List<TypeRefMarker>
|
||||||
|
get() = asSymbol().resolvedBounds
|
||||||
|
|
||||||
override val TypeParameterSymbolMarker.variance: Variance
|
override val TypeParameterSymbolMarker.variance: Variance
|
||||||
get() = asSymbol().variance
|
get() = asSymbol().variance
|
||||||
|
|
||||||
@@ -489,6 +500,65 @@ class FirExpectActualMatchingContextImpl private constructor(
|
|||||||
|
|
||||||
override fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker = FirSourceElement(asSymbol().source)
|
override fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker = FirSourceElement(asSymbol().source)
|
||||||
|
|
||||||
|
override fun TypeRefMarker.getClassId(): ClassId? = (this as FirResolvedTypeRef).type.fullyExpandedType(actualSession).classId
|
||||||
|
|
||||||
|
override fun checkAnnotationsOnTypeRefAndArguments(
|
||||||
|
expectTypeRef: TypeRefMarker,
|
||||||
|
actualTypeRef: TypeRefMarker,
|
||||||
|
checker: ExpectActualMatchingContext.AnnotationsCheckerCallback,
|
||||||
|
) {
|
||||||
|
check(expectTypeRef is FirResolvedTypeRef && actualTypeRef is FirResolvedTypeRef)
|
||||||
|
checkAnnotationsOnTypeRefAndArgumentsImpl(expectTypeRef, actualTypeRef, checker)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAnnotationsOnTypeRefAndArgumentsImpl(
|
||||||
|
expectTypeRef: FirTypeRef?,
|
||||||
|
actualTypeRef: FirTypeRef?,
|
||||||
|
checker: ExpectActualMatchingContext.AnnotationsCheckerCallback,
|
||||||
|
) {
|
||||||
|
fun FirAnnotationContainer.getAnnotations() = annotations.map(::AnnotationCallInfoImpl)
|
||||||
|
|
||||||
|
if (expectTypeRef == null || actualTypeRef == null) return
|
||||||
|
if (expectTypeRef is FirErrorTypeRef || actualTypeRef is FirErrorTypeRef) return
|
||||||
|
|
||||||
|
checker.check(expectTypeRef.getAnnotations(), actualTypeRef.getAnnotations(), FirSourceElement(actualTypeRef.source))
|
||||||
|
|
||||||
|
val expectDelegatedTypeRef = (expectTypeRef as? FirResolvedTypeRef)?.delegatedTypeRef ?: return
|
||||||
|
val actualDelegatedTypeRef = (actualTypeRef as? FirResolvedTypeRef?)?.delegatedTypeRef ?: return
|
||||||
|
|
||||||
|
when {
|
||||||
|
expectDelegatedTypeRef is FirUserTypeRef && actualDelegatedTypeRef is FirUserTypeRef -> {
|
||||||
|
val expectQualifier = expectDelegatedTypeRef.qualifier
|
||||||
|
val actualQualifier = actualDelegatedTypeRef.qualifier
|
||||||
|
for ((expectPart, actualPart) in expectQualifier.zipIfSizesAreEqual(actualQualifier).orEmpty()) {
|
||||||
|
val expectPartTypeArguments = expectPart.typeArgumentList.typeArguments
|
||||||
|
val actualPartTypeArguments = actualPart.typeArgumentList.typeArguments
|
||||||
|
val zippedArgs = expectPartTypeArguments.zipIfSizesAreEqual(actualPartTypeArguments).orEmpty()
|
||||||
|
for ((expectTypeArgument, actualTypeArgument) in zippedArgs) {
|
||||||
|
if (expectTypeArgument !is FirTypeProjectionWithVariance || actualTypeArgument !is FirTypeProjectionWithVariance) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
checkAnnotationsOnTypeRefAndArgumentsImpl(expectTypeArgument.typeRef, actualTypeArgument.typeRef, checker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expectDelegatedTypeRef is FirFunctionTypeRef && actualDelegatedTypeRef is FirFunctionTypeRef -> {
|
||||||
|
checkAnnotationsOnTypeRefAndArgumentsImpl(
|
||||||
|
expectDelegatedTypeRef.receiverTypeRef, actualDelegatedTypeRef.receiverTypeRef, checker,
|
||||||
|
)
|
||||||
|
checkAnnotationsOnTypeRefAndArgumentsImpl(
|
||||||
|
expectDelegatedTypeRef.returnTypeRef, actualDelegatedTypeRef.returnTypeRef, checker,
|
||||||
|
)
|
||||||
|
|
||||||
|
val expectParams = expectDelegatedTypeRef.parameters
|
||||||
|
val actualParams = actualDelegatedTypeRef.parameters
|
||||||
|
for ((expectParam, actualParam) in expectParams.zipIfSizesAreEqual(actualParams).orEmpty()) {
|
||||||
|
checkAnnotationsOnTypeRefAndArgumentsImpl(expectParam.returnTypeRef, actualParam.returnTypeRef, checker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object Factory : FirExpectActualMatchingContextFactory {
|
object Factory : FirExpectActualMatchingContextFactory {
|
||||||
override fun create(
|
override fun create(
|
||||||
session: FirSession, scopeSession: ScopeSession,
|
session: FirSession, scopeSession: ScopeSession,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.types
|
|||||||
import org.jetbrains.kotlin.KtSourceElement
|
import org.jetbrains.kotlin.KtSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.mpp.TypeRefMarker
|
||||||
import org.jetbrains.kotlin.fir.visitors.*
|
import org.jetbrains.kotlin.fir.visitors.*
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -15,7 +16,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
|||||||
* DO NOT MODIFY IT MANUALLY
|
* DO NOT MODIFY IT MANUALLY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
abstract class FirResolvedTypeRef : FirTypeRef() {
|
abstract class FirResolvedTypeRef : FirTypeRef(), TypeRefMarker {
|
||||||
abstract override val source: KtSourceElement?
|
abstract override val source: KtSourceElement?
|
||||||
abstract override val annotations: List<FirAnnotation>
|
abstract override val annotations: List<FirAnnotation>
|
||||||
abstract val type: ConeKotlinType
|
abstract val type: ConeKotlinType
|
||||||
|
|||||||
+1
-1
@@ -707,7 +707,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
|||||||
resolvedTypeRef.configure {
|
resolvedTypeRef.configure {
|
||||||
+field("type", coneKotlinTypeType)
|
+field("type", coneKotlinTypeType)
|
||||||
+field("delegatedTypeRef", typeRef, nullable = true)
|
+field("delegatedTypeRef", typeRef, nullable = true)
|
||||||
// TODO: add supertype in subsequent commits
|
element.additionalSupertypeInterfaces.add(typeRefMarkerType)
|
||||||
}
|
}
|
||||||
|
|
||||||
typeRefWithNullability.configure {
|
typeRefWithNullability.configure {
|
||||||
|
|||||||
@@ -108,3 +108,5 @@ val firPropertySymbolType = type("fir.symbols.impl", "FirPropertySymbol")
|
|||||||
val errorTypeRefImplType = type("fir.types.impl", "FirErrorTypeRefImpl")
|
val errorTypeRefImplType = type("fir.types.impl", "FirErrorTypeRefImpl")
|
||||||
|
|
||||||
val annotationResolvePhaseType = generatedType("expressions", "FirAnnotationResolvePhase")
|
val annotationResolvePhaseType = generatedType("expressions", "FirAnnotationResolvePhase")
|
||||||
|
|
||||||
|
val typeRefMarkerType = type("mpp", "TypeRefMarker")
|
||||||
|
|||||||
+39
-5
@@ -28,7 +28,6 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCompatibilityCheckStrategy
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCompatibilityCheckStrategy
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
||||||
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo
|
||||||
import org.jetbrains.kotlin.mpp.SourceElementMarker
|
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
@@ -177,9 +176,12 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
else -> shouldNotBeCalled()
|
else -> shouldNotBeCalled()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
|
override val RegularClassSymbolMarker.superTypes: List<IrType>
|
||||||
get() = asIr().superTypes
|
get() = asIr().superTypes
|
||||||
|
|
||||||
|
override val RegularClassSymbolMarker.superTypesRefs: List<TypeRefMarker>
|
||||||
|
get() = superTypes
|
||||||
|
|
||||||
override val RegularClassSymbolMarker.defaultType: KotlinTypeMarker
|
override val RegularClassSymbolMarker.defaultType: KotlinTypeMarker
|
||||||
get() = asIr().defaultType
|
get() = asIr().defaultType
|
||||||
|
|
||||||
@@ -275,10 +277,13 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
||||||
get() = (asIr().parent as? IrClass)?.defaultType
|
get() = (asIr().parent as? IrClass)?.defaultType
|
||||||
|
|
||||||
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
override val CallableSymbolMarker.extensionReceiverType: IrType?
|
||||||
get() = safeAsIr<IrFunction>()?.extensionReceiverParameter?.type
|
get() = safeAsIr<IrFunction>()?.extensionReceiverParameter?.type
|
||||||
|
|
||||||
override val CallableSymbolMarker.returnType: KotlinTypeMarker
|
override val CallableSymbolMarker.extensionReceiverTypeRef: TypeRefMarker?
|
||||||
|
get() = extensionReceiverType
|
||||||
|
|
||||||
|
override val CallableSymbolMarker.returnType: IrType
|
||||||
get() = processIr(
|
get() = processIr(
|
||||||
onFunction = { it.returnType },
|
onFunction = { it.returnType },
|
||||||
onProperty = { it.getter?.returnType ?: it.backingField?.type ?: error("No type for property: $it") },
|
onProperty = { it.getter?.returnType ?: it.backingField?.type ?: error("No type for property: $it") },
|
||||||
@@ -287,6 +292,10 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
onEnumEntry = { it.parentAsClass.defaultType }
|
onEnumEntry = { it.parentAsClass.defaultType }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val CallableSymbolMarker.returnTypeRef: TypeRefMarker
|
||||||
|
get() = returnType
|
||||||
|
|
||||||
|
|
||||||
override val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
override val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
||||||
get() = processIr(
|
get() = processIr(
|
||||||
onFunction = { it.typeParameters.map { parameter -> parameter.symbol } },
|
onFunction = { it.typeParameters.map { parameter -> parameter.symbol } },
|
||||||
@@ -316,8 +325,10 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
return irConstructor.constructedClass.isAnnotationClass
|
return irConstructor.constructedClass.isAnnotationClass
|
||||||
}
|
}
|
||||||
|
|
||||||
override val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
|
override val TypeParameterSymbolMarker.bounds: List<IrType>
|
||||||
get() = asIr().superTypes
|
get() = asIr().superTypes
|
||||||
|
override val TypeParameterSymbolMarker.boundsTypeRefs: List<TypeRefMarker>
|
||||||
|
get() = bounds
|
||||||
override val TypeParameterSymbolMarker.variance: Variance
|
override val TypeParameterSymbolMarker.variance: Variance
|
||||||
get() = asIr().variance
|
get() = asIr().variance
|
||||||
override val TypeParameterSymbolMarker.isReified: Boolean
|
override val TypeParameterSymbolMarker.isReified: Boolean
|
||||||
@@ -529,4 +540,27 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
private object IrSourceElementStub : SourceElementMarker
|
private object IrSourceElementStub : SourceElementMarker
|
||||||
|
|
||||||
override fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker = IrSourceElementStub
|
override fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker = IrSourceElementStub
|
||||||
|
|
||||||
|
override fun TypeRefMarker.getClassId(): ClassId? = (this as IrType).getClass()?.classId
|
||||||
|
|
||||||
|
override fun checkAnnotationsOnTypeRefAndArguments(
|
||||||
|
expectTypeRef: TypeRefMarker,
|
||||||
|
actualTypeRef: TypeRefMarker,
|
||||||
|
checker: ExpectActualMatchingContext.AnnotationsCheckerCallback
|
||||||
|
) {
|
||||||
|
check(expectTypeRef is IrType && actualTypeRef is IrType)
|
||||||
|
|
||||||
|
fun IrType.getAnnotations() = annotations.map(::AnnotationCallInfoImpl)
|
||||||
|
|
||||||
|
checker.check(expectTypeRef.getAnnotations(), actualTypeRef.getAnnotations(), IrSourceElementStub)
|
||||||
|
|
||||||
|
if (expectTypeRef !is IrSimpleType || actualTypeRef !is IrSimpleType) return
|
||||||
|
if (expectTypeRef.arguments.size != actualTypeRef.arguments.size) return
|
||||||
|
|
||||||
|
for ((expectArg, actualArg) in expectTypeRef.arguments.zip(actualTypeRef.arguments)) {
|
||||||
|
val expectArgType = expectArg.typeOrNull ?: continue
|
||||||
|
val actualArgType = actualArg.typeOrNull ?: continue
|
||||||
|
checkAnnotationsOnTypeRefAndArguments(expectArgType, actualArgType, checker)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrTypeAliasSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrTypeBase
|
import org.jetbrains.kotlin.ir.types.impl.IrTypeBase
|
||||||
|
import org.jetbrains.kotlin.mpp.TypeRefMarker
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.model.*
|
import org.jetbrains.kotlin.types.model.*
|
||||||
|
|
||||||
abstract class IrType : KotlinTypeMarker, IrAnnotationContainer {
|
abstract class IrType : KotlinTypeMarker, TypeRefMarker, IrAnnotationContainer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this type is equal to [other] symbolically. Note that this is NOT EQUIVALENT to the full type checking algorithm
|
* @return true if this type is equal to [other] symbolically. Note that this is NOT EQUIVALENT to the full type checking algorithm
|
||||||
|
|||||||
+63
-6
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
|
import org.jetbrains.kotlin.utils.zipIfSizesAreEqual
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType as IncompatibilityType
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType as IncompatibilityType
|
||||||
|
|
||||||
object AbstractExpectActualAnnotationMatchChecker {
|
object AbstractExpectActualAnnotationMatchChecker {
|
||||||
@@ -84,6 +85,13 @@ object AbstractExpectActualAnnotationMatchChecker {
|
|||||||
arePropertyGetterAndSetterAnnotationsCompatible(expectSymbol, actualSymbol)?.let { return it }
|
arePropertyGetterAndSetterAnnotationsCompatible(expectSymbol, actualSymbol)?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
areAnnotationsSetOnTypesCompatible(
|
||||||
|
expectSymbol, actualSymbol, expectSymbol.extensionReceiverTypeRef, actualSymbol.extensionReceiverTypeRef
|
||||||
|
)?.let { return it }
|
||||||
|
|
||||||
|
areAnnotationsSetOnTypesCompatible(expectSymbol, actualSymbol, expectSymbol.returnTypeRef, actualSymbol.returnTypeRef)
|
||||||
|
?.let { return it }
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +134,16 @@ object AbstractExpectActualAnnotationMatchChecker {
|
|||||||
checkAnnotationsOnEnumEntries(expectSymbol, actualSymbol)?.let { return it }
|
checkAnnotationsOnEnumEntries(expectSymbol, actualSymbol)?.let { return it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// actual may have more super types, that's why we can't just zip them.
|
||||||
|
// Identifying super type with ClassId (without type parameters) is enough because same type can't be extended twice.
|
||||||
|
val actualSuperTypes = actualSymbol.superTypesRefs.groupBy { it.getClassId() }
|
||||||
|
for (expectSuperType in expectSymbol.superTypesRefs) {
|
||||||
|
val expectClassId = expectSuperType.getClassId() ?: continue
|
||||||
|
val actualSuperType = actualSuperTypes[expectClassId]?.singleOrNull() ?: continue
|
||||||
|
areAnnotationsSetOnTypesCompatible(expectSymbol, actualSymbol, expectSuperType, actualSuperType)
|
||||||
|
?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,13 +166,12 @@ object AbstractExpectActualAnnotationMatchChecker {
|
|||||||
val expectParams = expectSymbol.valueParameters
|
val expectParams = expectSymbol.valueParameters
|
||||||
val actualParams = actualSymbol.valueParameters
|
val actualParams = actualSymbol.valueParameters
|
||||||
|
|
||||||
if (expectParams.size != actualParams.size) return null
|
return expectParams.zipIfSizesAreEqual(actualParams)?.firstNotNullOfOrNull { (expectParam, actualParam) ->
|
||||||
|
|
||||||
return expectParams.zip(actualParams).firstNotNullOfOrNull { (expectParam, actualParam) ->
|
|
||||||
areAnnotationsSetOnDeclarationsCompatible(expectParam, actualParam)?.let {
|
areAnnotationsSetOnDeclarationsCompatible(expectParam, actualParam)?.let {
|
||||||
// Write containing declarations into diagnostic
|
// Write containing declarations into diagnostic
|
||||||
Incompatibility(expectSymbol, actualSymbol, actualParam.getSourceElement(), it.type)
|
Incompatibility(expectSymbol, actualSymbol, actualParam.getSourceElement(), it.type)
|
||||||
}
|
}
|
||||||
|
?: areAnnotationsSetOnTypesCompatible(expectSymbol, actualSymbol, expectParam.returnTypeRef, actualParam.returnTypeRef)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,16 +190,57 @@ object AbstractExpectActualAnnotationMatchChecker {
|
|||||||
|
|
||||||
val expectParams = expectSymbol.getTypeParameters() ?: return null
|
val expectParams = expectSymbol.getTypeParameters() ?: return null
|
||||||
val actualParams = actualSymbol.getTypeParameters() ?: return null
|
val actualParams = actualSymbol.getTypeParameters() ?: return null
|
||||||
if (expectParams.size != actualParams.size) return null
|
|
||||||
|
|
||||||
return expectParams.zip(actualParams).firstNotNullOfOrNull { (expectParam, actualParam) ->
|
return expectParams.zipIfSizesAreEqual(actualParams)?.firstNotNullOfOrNull { (expectParam, actualParam) ->
|
||||||
areAnnotationsSetOnDeclarationsCompatible(expectParam, actualParam)?.let {
|
areAnnotationsSetOnDeclarationsCompatible(expectParam, actualParam)?.let {
|
||||||
// Write containing declarations into diagnostic
|
// Write containing declarations into diagnostic
|
||||||
Incompatibility(expectSymbol, actualSymbol, actualParam.getSourceElement(), it.type)
|
Incompatibility(expectSymbol, actualSymbol, actualParam.getSourceElement(), it.type)
|
||||||
}
|
}
|
||||||
|
?: areAnnotationsOnTypeParameterBoundsCompatible(expectSymbol, actualSymbol, expectParam, actualParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context (ExpectActualMatchingContext<*>)
|
||||||
|
private fun areAnnotationsOnTypeParameterBoundsCompatible(
|
||||||
|
expectDeclarationSymbol: DeclarationSymbolMarker,
|
||||||
|
actualDeclarationSymbol: DeclarationSymbolMarker,
|
||||||
|
expectParam: TypeParameterSymbolMarker,
|
||||||
|
actualParam: TypeParameterSymbolMarker,
|
||||||
|
): Incompatibility? {
|
||||||
|
val expectBounds = expectParam.boundsTypeRefs
|
||||||
|
val actualBounds = actualParam.boundsTypeRefs
|
||||||
|
|
||||||
|
return expectBounds.zipIfSizesAreEqual(actualBounds)?.firstNotNullOfOrNull { (expectType, actualType) ->
|
||||||
|
// Identifying bounds by ClassId (without type parameters) is enough because type can't have two bounds of same type.
|
||||||
|
if (expectType.getClassId() != actualType.getClassId()) {
|
||||||
|
// Expect and actual type bounds must be same and have same order, otherwise expect-actual compatibility checker
|
||||||
|
// reports error. So, skip in case of incompatibility to not report extra warning.
|
||||||
|
return@firstNotNullOfOrNull null
|
||||||
|
}
|
||||||
|
areAnnotationsSetOnTypesCompatible(expectDeclarationSymbol, actualDeclarationSymbol, expectType, actualType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context (ExpectActualMatchingContext<*>)
|
||||||
|
private fun areAnnotationsSetOnTypesCompatible(
|
||||||
|
expectDeclarationSymbol: DeclarationSymbolMarker,
|
||||||
|
actualDeclarationSymbol: DeclarationSymbolMarker,
|
||||||
|
expectTypeRef: TypeRefMarker?,
|
||||||
|
actualTypeRef: TypeRefMarker?,
|
||||||
|
): Incompatibility? {
|
||||||
|
if (expectTypeRef == null || actualTypeRef == null) return null
|
||||||
|
|
||||||
|
var firstIncompatibility: Incompatibility? = null
|
||||||
|
|
||||||
|
checkAnnotationsOnTypeRefAndArguments(expectTypeRef, actualTypeRef) { expectAnnotations, actualAnnotations, actualTypeRefSource ->
|
||||||
|
if (firstIncompatibility == null) {
|
||||||
|
firstIncompatibility = areAnnotationListsCompatible(expectAnnotations, actualAnnotations, actualDeclarationSymbol)
|
||||||
|
?.let { Incompatibility(expectDeclarationSymbol, actualDeclarationSymbol, actualTypeRefSource, type = it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return firstIncompatibility
|
||||||
|
}
|
||||||
|
|
||||||
context (ExpectActualMatchingContext<*>)
|
context (ExpectActualMatchingContext<*>)
|
||||||
private fun areAnnotationsSetOnDeclarationsCompatible(
|
private fun areAnnotationsSetOnDeclarationsCompatible(
|
||||||
expectSymbol: DeclarationSymbolMarker,
|
expectSymbol: DeclarationSymbolMarker,
|
||||||
@@ -198,7 +256,6 @@ object AbstractExpectActualAnnotationMatchChecker {
|
|||||||
actualAnnotations: List<ExpectActualMatchingContext.AnnotationCallInfo>,
|
actualAnnotations: List<ExpectActualMatchingContext.AnnotationCallInfo>,
|
||||||
actualContainerSymbol: DeclarationSymbolMarker,
|
actualContainerSymbol: DeclarationSymbolMarker,
|
||||||
): IncompatibilityType<ExpectActualMatchingContext.AnnotationCallInfo>? {
|
): IncompatibilityType<ExpectActualMatchingContext.AnnotationCallInfo>? {
|
||||||
// TODO(Roman.Efremov, KT-60671): check annotations set on types
|
|
||||||
val skipSourceAnnotations = actualContainerSymbol.hasSourceAnnotationsErased
|
val skipSourceAnnotations = actualContainerSymbol.hasSourceAnnotationsErased
|
||||||
val actualAnnotationsByName = actualAnnotations.groupBy { it.classId }
|
val actualAnnotationsByName = actualAnnotations.groupBy { it.classId }
|
||||||
|
|
||||||
|
|||||||
+35
@@ -85,6 +85,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
|||||||
val CallableSymbolMarker.visibility: Visibility
|
val CallableSymbolMarker.visibility: Visibility
|
||||||
|
|
||||||
val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
|
val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
|
||||||
|
val RegularClassSymbolMarker.superTypesRefs: List<TypeRefMarker>
|
||||||
val RegularClassSymbolMarker.defaultType: KotlinTypeMarker
|
val RegularClassSymbolMarker.defaultType: KotlinTypeMarker
|
||||||
|
|
||||||
val CallableSymbolMarker.isExpect: Boolean
|
val CallableSymbolMarker.isExpect: Boolean
|
||||||
@@ -115,7 +116,9 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
|||||||
|
|
||||||
val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
||||||
val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
||||||
|
val CallableSymbolMarker.extensionReceiverTypeRef: TypeRefMarker?
|
||||||
val CallableSymbolMarker.returnType: KotlinTypeMarker
|
val CallableSymbolMarker.returnType: KotlinTypeMarker
|
||||||
|
val CallableSymbolMarker.returnTypeRef: TypeRefMarker
|
||||||
val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
||||||
val FunctionSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
|
val FunctionSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
|
||||||
|
|
||||||
@@ -135,6 +138,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
|||||||
fun CallableSymbolMarker.isAnnotationConstructor(): Boolean
|
fun CallableSymbolMarker.isAnnotationConstructor(): Boolean
|
||||||
|
|
||||||
val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
|
val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
|
||||||
|
val TypeParameterSymbolMarker.boundsTypeRefs: List<TypeRefMarker>
|
||||||
val TypeParameterSymbolMarker.variance: Variance
|
val TypeParameterSymbolMarker.variance: Variance
|
||||||
val TypeParameterSymbolMarker.isReified: Boolean
|
val TypeParameterSymbolMarker.isReified: Boolean
|
||||||
|
|
||||||
@@ -215,4 +219,35 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
|||||||
): Map<out DeclarationSymbolMarker, ExpectActualCompatibility<*>>
|
): Map<out DeclarationSymbolMarker, ExpectActualCompatibility<*>>
|
||||||
|
|
||||||
fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker
|
fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker
|
||||||
|
|
||||||
|
fun TypeRefMarker.getClassId(): ClassId?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback interface to be implemented by caller of [checkAnnotationsOnTypeRefAndArguments].
|
||||||
|
*/
|
||||||
|
fun interface AnnotationsCheckerCallback {
|
||||||
|
/**
|
||||||
|
* Implementation must check `expect` and `actual` annotations and report diagnostic in case of incompatibility.
|
||||||
|
* [actualTypeRefSource] is needed in order to know where on the `actual` declaration to insert the missing annotation
|
||||||
|
* from the `expect` declaration (see [AbstractExpectActualAnnotationMatchChecker.Incompatibility.actualAnnotationTargetElement]).
|
||||||
|
*/
|
||||||
|
fun check(
|
||||||
|
expectAnnotations: List<AnnotationCallInfo>, actualAnnotations: List<AnnotationCallInfo>,
|
||||||
|
actualTypeRefSource: SourceElementMarker,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds pairs of matching expect and actual types, on which annotations must be checked by [AbstractExpectActualAnnotationMatchChecker].
|
||||||
|
*
|
||||||
|
* This is done by recursively traversing [expectTypeRef] and [actualTypeRef] and their arguments, which is needed in case of
|
||||||
|
* complex types like `T1<T2<@Ann T3>>`. Founded expect and actual annotations are passed to [checker] callback.
|
||||||
|
* For functional types (e.g. `ReceiverType.(Arg1Type) -> ReturnType`) receiver, argument and return types and their arguments
|
||||||
|
* are checked.
|
||||||
|
*
|
||||||
|
* **Example**: for type `@Ann1 List<@Ann2 Map<@Ann3 Int, @Ann4 String>>`, there are 4 types to check in [checker].
|
||||||
|
*/
|
||||||
|
fun checkAnnotationsOnTypeRefAndArguments(
|
||||||
|
expectTypeRef: TypeRefMarker, actualTypeRef: TypeRefMarker, checker: AnnotationsCheckerCallback,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
-2
@@ -179,8 +179,6 @@ object K1AbstractExpectActualAnnotationMatchChecker {
|
|||||||
expectSymbol: DeclarationSymbolMarker,
|
expectSymbol: DeclarationSymbolMarker,
|
||||||
actualSymbol: DeclarationSymbolMarker,
|
actualSymbol: DeclarationSymbolMarker,
|
||||||
): Incompatibility? {
|
): Incompatibility? {
|
||||||
// TODO(Roman.Efremov, KT-60671): check annotations set on types
|
|
||||||
|
|
||||||
val skipSourceAnnotations = actualSymbol.hasSourceAnnotationsErased
|
val skipSourceAnnotations = actualSymbol.hasSourceAnnotationsErased
|
||||||
val actualAnnotationsByName = actualSymbol.annotations.groupBy { it.classId }
|
val actualAnnotationsByName = actualSymbol.annotations.groupBy { it.classId }
|
||||||
|
|
||||||
|
|||||||
+3
@@ -21,3 +21,6 @@ All annotations from expect 'fun <T> inTypeParam(): Unit' must be present with t
|
|||||||
|
|
||||||
/jvm.kt:(513,521): warning: Annotation `@PROPERTY_GETTER:Ann()` is missing on actual declaration.
|
/jvm.kt:(513,521): warning: Annotation `@PROPERTY_GETTER:Ann()` is missing on actual declaration.
|
||||||
All annotations from expect 'val onGetter: String get(): String' must be present with the same arguments on actual 'val onGetter: String get(): String', otherwise they might behave incorrectly.
|
All annotations from expect 'val onGetter: String get(): String' must be present with the same arguments on actual 'val onGetter: String get(): String', otherwise they might behave incorrectly.
|
||||||
|
|
||||||
|
/jvm.kt:(547,553): warning: Annotation `@Ann()` is missing on actual declaration.
|
||||||
|
All annotations from expect 'fun onType(param: @R|Ann|() Any): Unit' must be present with the same arguments on actual 'fun onType(param: Any): Unit', otherwise they might behave incorrectly.
|
||||||
|
|||||||
Vendored
+1
-1
@@ -68,4 +68,4 @@ actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>withDifferentArg<!>() {}<!>
|
|||||||
|
|
||||||
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetter<!>: String = ""<!>
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual val <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onGetter<!>: String = ""<!>
|
||||||
|
|
||||||
actual fun onType(param: Any) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onType<!>(param: Any) {}<!>
|
||||||
|
|||||||
+17
-17
@@ -61,46 +61,46 @@ expect fun funcTypeArgType(arg: (arg: @Ann Any) -> Unit)
|
|||||||
|
|
||||||
// MODULE: m1-jvm()()(m1-common)
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
actual fun valueParameterType(arg: String) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>valueParameterType<!>(arg: String) {}<!>
|
||||||
|
|
||||||
actual fun returnType(): String = ""
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>returnType<!>(): String = ""<!>
|
||||||
|
|
||||||
actual fun <T : Any> methodTypeParamBound() {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <T : Any> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>methodTypeParamBound<!>() {}<!>
|
||||||
|
|
||||||
actual class OnClassTypeParamBound<T : Any>
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClassTypeParamBound<!><T : Any><!>
|
||||||
|
|
||||||
actual fun <T> typeParamBoundInWhere() where T : Any {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <T> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>typeParamBoundInWhere<!>() where T : Any {}<!>
|
||||||
|
|
||||||
actual fun <T> severalBounds() where T : I1, T : I2 {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <T> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>severalBounds<!>() where T : I1, T : I2 {}<!>
|
||||||
|
|
||||||
actual fun <T> <!ACTUAL_WITHOUT_EXPECT!>severalBoundsDifferentOrder<!>() where T : @Ann I1, T : I2 {}
|
actual fun <T> <!ACTUAL_WITHOUT_EXPECT!>severalBoundsDifferentOrder<!>() where T : @Ann I1, T : I2 {}
|
||||||
|
|
||||||
actual fun <T> <!ACTUAL_WITHOUT_EXPECT!>lessTypeParamBoundsOnActual<!>() where T : @Ann I2 {}
|
actual fun <T> <!ACTUAL_WITHOUT_EXPECT!>lessTypeParamBoundsOnActual<!>() where T : @Ann I2 {}
|
||||||
|
|
||||||
actual fun Any.onReceiver() {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun Any.<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>onReceiver<!>() {}<!>
|
||||||
|
|
||||||
actual class OnClassSuper : I1
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClassSuper<!> : I1<!>
|
||||||
|
|
||||||
actual class OnClassSuperDifferentOrder : @Ann I2, I1
|
actual class OnClassSuperDifferentOrder : @Ann I2, I1
|
||||||
|
|
||||||
actual class OnClassSuperMoreOnActual : I1, I2
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClassSuperMoreOnActual<!> : I1, I2<!>
|
||||||
|
|
||||||
actual class OnClassSuperTypeParams<T> : I3<T>
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>OnClassSuperTypeParams<!><T> : I3<T><!>
|
||||||
|
|
||||||
actual fun deepInParamsTypes(arg: I3<I3<Any>>) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>deepInParamsTypes<!>(arg: I3<I3<Any>>) {}<!>
|
||||||
|
|
||||||
actual fun starProjection(arg: I4<*, Any>) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>starProjection<!>(arg: I4<*, Any>) {}<!>
|
||||||
|
|
||||||
actual fun <T> typeArgWithVariance(t: I3<out T>) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <T> <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>typeArgWithVariance<!>(t: I3<out T>) {}<!>
|
||||||
|
|
||||||
actual fun qualifierPartsMatching(arg: WithNested<String>.Nested<@Ann String>) {}
|
actual fun qualifierPartsMatching(arg: WithNested<String>.Nested<@Ann String>) {}
|
||||||
|
|
||||||
actual fun qualifierPartsNonMatching(arg: WithNested<@Ann String>.Nested<String>) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>qualifierPartsNonMatching<!>(arg: WithNested<@Ann String>.Nested<String>) {}<!>
|
||||||
|
|
||||||
actual fun <!ACTUAL_WITHOUT_EXPECT!>funTypeVsUserType<!>(arg: kotlin.jvm.functions.Function0<String>) {}
|
actual fun <!ACTUAL_WITHOUT_EXPECT!>funTypeVsUserType<!>(arg: kotlin.jvm.functions.Function0<String>) {}
|
||||||
|
|
||||||
actual fun funcTypeReturnType(arg: () -> Any) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>funcTypeReturnType<!>(arg: () -> Any) {}<!>
|
||||||
|
|
||||||
actual fun funcTypeReceiverType(arg: Any.() -> Unit) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>funcTypeReceiverType<!>(arg: Any.() -> Unit) {}<!>
|
||||||
|
|
||||||
actual fun funcTypeArgType(arg: (arg: Any) -> Unit) {}
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>funcTypeArgType<!>(arg: (arg: Any) -> Unit) {}<!>
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
interface I
|
||||||
|
|
||||||
|
expect class Foo: @Ann I
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
typealias ITypealias = I
|
||||||
|
|
||||||
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>Foo<!> : ITypealias<!>
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
interface I
|
||||||
|
|
||||||
|
expect class Foo: @Ann I
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
typealias ITypealias = I
|
||||||
|
|
||||||
|
actual class Foo : ITypealias
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
expect fun foo(): @Ann Int
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>actual fun <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>foo<!>() = 1<!>
|
||||||
Vendored
-1
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
|||||||
Vendored
+1
-1
@@ -12,7 +12,7 @@ expect class E2 {
|
|||||||
// MODULE: m2-jvm()()(m1-common)
|
// MODULE: m2-jvm()()(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
interface I {
|
interface I {
|
||||||
fun f(x: Int = 5) = x
|
fun f(x: Int = 5): Int = x
|
||||||
}
|
}
|
||||||
|
|
||||||
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E<!>(i: I) : I by i
|
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>E<!>(i: I) : I by i
|
||||||
|
|||||||
+4
-4
@@ -23,11 +23,11 @@ expect class FastArrayList<E> : MutableListEx<E>, RandomAccess {
|
|||||||
fun ensureCapacity(minCapacity: Int)
|
fun ensureCapacity(minCapacity: Int)
|
||||||
override val size: Int
|
override val size: Int
|
||||||
override fun isEmpty(): Boolean
|
override fun isEmpty(): Boolean
|
||||||
override fun contains(element: @UnsafeVariance E): Boolean
|
override fun contains(element: E): Boolean
|
||||||
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
|
override fun containsAll(elements: Collection<E>): Boolean
|
||||||
override operator fun get(index: Int): E
|
override operator fun get(index: Int): E
|
||||||
override fun indexOf(element: @UnsafeVariance E): Int
|
override fun indexOf(element: E): Int
|
||||||
override fun lastIndexOf(element: @UnsafeVariance E): Int
|
override fun lastIndexOf(element: E): Int
|
||||||
override fun iterator(): MutableIterator<E>
|
override fun iterator(): MutableIterator<E>
|
||||||
override fun add(element: E): Boolean
|
override fun add(element: E): Boolean
|
||||||
override fun remove(element: E): Boolean
|
override fun remove(element: E): Boolean
|
||||||
|
|||||||
Generated
+6
@@ -24107,6 +24107,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsage.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsage.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("typeUsageTypealiasInSuper.kt")
|
||||||
|
public void testTypeUsageTypealiasInSuper() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/typeUsageTypealiasInSuper.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("typeUsageWithImplicitType.kt")
|
@TestMetadata("typeUsageWithImplicitType.kt")
|
||||||
public void testTypeUsageWithImplicitType() throws Exception {
|
public void testTypeUsageWithImplicitType() throws Exception {
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* 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.mpp
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common interface for type references to be used in abstract checker.
|
||||||
|
* The idea is similar to [org.jetbrains.kotlin.types.model.KotlinTypeMarker],
|
||||||
|
* but type reference, unlike a type, has source element.
|
||||||
|
*
|
||||||
|
* Used in [org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker].
|
||||||
|
*/
|
||||||
|
interface TypeRefMarker
|
||||||
Reference in New Issue
Block a user