[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:
Roman Efremov
2023-09-11 13:24:29 +02:00
committed by Space Team
parent cb8529d65b
commit 423f4ca5f0
22 changed files with 314 additions and 41 deletions
@@ -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.ExpectActualMatchingContext
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.multiplatform.ExpectActualCompatibility
import org.jetbrains.kotlin.types.AbstractTypeChecker
@@ -177,9 +176,12 @@ internal abstract class IrExpectActualMatchingContext(
else -> shouldNotBeCalled()
}
override val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
override val RegularClassSymbolMarker.superTypes: List<IrType>
get() = asIr().superTypes
override val RegularClassSymbolMarker.superTypesRefs: List<TypeRefMarker>
get() = superTypes
override val RegularClassSymbolMarker.defaultType: KotlinTypeMarker
get() = asIr().defaultType
@@ -275,10 +277,13 @@ internal abstract class IrExpectActualMatchingContext(
override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
get() = (asIr().parent as? IrClass)?.defaultType
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
override val CallableSymbolMarker.extensionReceiverType: IrType?
get() = safeAsIr<IrFunction>()?.extensionReceiverParameter?.type
override val CallableSymbolMarker.returnType: KotlinTypeMarker
override val CallableSymbolMarker.extensionReceiverTypeRef: TypeRefMarker?
get() = extensionReceiverType
override val CallableSymbolMarker.returnType: IrType
get() = processIr(
onFunction = { it.returnType },
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 }
)
override val CallableSymbolMarker.returnTypeRef: TypeRefMarker
get() = returnType
override val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
get() = processIr(
onFunction = { it.typeParameters.map { parameter -> parameter.symbol } },
@@ -316,8 +325,10 @@ internal abstract class IrExpectActualMatchingContext(
return irConstructor.constructedClass.isAnnotationClass
}
override val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
override val TypeParameterSymbolMarker.bounds: List<IrType>
get() = asIr().superTypes
override val TypeParameterSymbolMarker.boundsTypeRefs: List<TypeRefMarker>
get() = bounds
override val TypeParameterSymbolMarker.variance: Variance
get() = asIr().variance
override val TypeParameterSymbolMarker.isReified: Boolean
@@ -529,4 +540,27 @@ internal abstract class IrExpectActualMatchingContext(
private object IrSourceElementStub : SourceElementMarker
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.IrTypeAliasSymbol
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.Variance
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