[FIR] Fix processing of nested type arguments, extract extractTypeRefAndSourceFromTypeArgument method to FirHelpers and use it from FirClassVarianceChecker and FirConflictingProjectionChecker

This commit is contained in:
Ivan Kochurkin
2021-06-01 21:43:17 +03:00
committed by teamcityserver
parent f081a6b4fa
commit 0b0a96a1d3
7 changed files with 60 additions and 29 deletions
@@ -578,3 +578,41 @@ internal fun checkCondition(condition: FirExpression, context: CheckerContext, r
reporter.reportOn(condition.source, FirErrors.CONDITION_TYPE_MISMATCH, coneType, context)
}
}
fun extractTypeRefAndSourceFromTypeArgument(typeRef: FirTypeRef?, index: Int): Pair<FirTypeRef, FirSourceElement?>? {
if (typeRef is FirResolvedTypeRef) {
val delegatedTypeRef = typeRef.delegatedTypeRef
if (delegatedTypeRef is FirUserTypeRef) {
var currentTypeArguments: List<FirTypeProjection>? = null
var currentIndex = index
val qualifier = delegatedTypeRef.qualifier
for (i in qualifier.size - 1 downTo 0) {
val typeArguments = qualifier[i].typeArgumentList.typeArguments
if (currentIndex < typeArguments.size) {
currentTypeArguments = typeArguments
break
} else {
currentIndex -= typeArguments.size
}
}
val typeArgument = currentTypeArguments?.elementAtOrNull(currentIndex)
if (typeArgument is FirTypeProjectionWithVariance) {
return Pair(typeArgument.typeRef, typeArgument.source)
}
} else if (delegatedTypeRef is FirFunctionTypeRef) {
val valueParameters = delegatedTypeRef.valueParameters
if (index < valueParameters.size) {
val valueParamTypeRef = valueParameters.elementAt(index).returnTypeRef
return Pair(valueParamTypeRef, valueParamTypeRef.source)
}
if (index == valueParameters.size) {
val returnTypeRef = delegatedTypeRef.returnTypeRef
return Pair(returnTypeRef, returnTypeRef.source)
}
}
}
return null
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.extractTypeRefAndSourceFromTypeArgument
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
@@ -154,11 +155,11 @@ object FirClassVarianceChecker : FirClassChecker() {
}
if (newVariance != null) {
val subTypeRef = extractTypeArgumentTypeRef(typeRef, index)
val subTypeRefAndSource = extractTypeRefAndSourceFromTypeArgument(typeRef, index)
checkVarianceConflict(
typeArgumentType, newVariance, subTypeRef, containingType,
context, reporter,subTypeRef?.source ?: source,
typeArgumentType, newVariance, subTypeRefAndSource?.first, containingType,
context, reporter, subTypeRefAndSource?.first?.source ?: source,
fullyExpandedType != type
)
}
@@ -166,25 +167,4 @@ object FirClassVarianceChecker : FirClassChecker() {
}
}
}
private fun extractTypeArgumentTypeRef(typeRef: FirTypeRef?, index: Int): FirTypeRef? {
if (typeRef is FirResolvedTypeRef) {
val delegatedTypeRef = typeRef.delegatedTypeRef
if (delegatedTypeRef is FirUserTypeRef) {
val typeArgument = delegatedTypeRef.qualifier[0].typeArgumentList.typeArguments.elementAtOrNull(index)
if (typeArgument is FirTypeProjectionWithVariance) {
return typeArgument.typeRef
}
} else if (delegatedTypeRef is FirFunctionTypeRef) {
if (index < delegatedTypeRef.valueParameters.size) {
return delegatedTypeRef.valueParameters.elementAt(index).returnTypeRef
}
if (index == delegatedTypeRef.valueParameters.size) {
return delegatedTypeRef.returnTypeRef
}
}
}
return null
}
}
@@ -45,17 +45,19 @@ object FirProjectionRelationChecker : FirBasicDeclarationChecker() {
private fun checkTypeRef(
typeRef: FirTypeRef,
context: CheckerContext,
reporter: DiagnosticReporter,
reporter: DiagnosticReporter
) {
val type = typeRef.coneTypeSafe<ConeClassLikeType>()
val fullyExpandedType = type?.fullyExpandedType(context.session) ?: return
val declaration = fullyExpandedType.toSymbol(context.session)?.fir.safeAs<FirRegularClass>() ?: return
val typeParameters = declaration.typeParameters
val typeArguments = type.typeArguments
val size = minOf(declaration.typeParameters.size, typeRef.coneType.typeArguments.size)
val size = minOf(typeParameters.size, typeArguments.size)
for (it in 0 until size) {
val proto = declaration.typeParameters[it]
val actual = typeRef.coneType.typeArguments[it]
val proto = typeParameters[it]
val actual = typeArguments[it]
val fullyExpandedProjection = fullyExpandedType.typeArguments[it]
val protoVariance = proto.safeAs<FirTypeParameterRef>()
@@ -88,6 +90,8 @@ object FirProjectionRelationChecker : FirBasicDeclarationChecker() {
context
)
}
checkTypeRef(typeArgTypeRef, context, reporter)
}
}