[FIR] Implement CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION diagnostics, fix tests

This commit is contained in:
Ivan Kochurkin
2021-06-01 16:22:02 +03:00
committed by teamcityserver
parent ca970f0a8b
commit 03e577bf98
10 changed files with 67 additions and 31 deletions
@@ -71,13 +71,13 @@ typealias Out1<X> = Out<X>
typealias Invariant1<X> = Invariant<X>
fun test_5(a: A, in1: In1<A>, in2: In1<in A>, in3: In1<out A>) {
fun test_5(a: A, in1: In1<A>, in2: In1<in A>, in3: In1<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> A>) {
in1.take(a)
in2.take(a)
in3.<!UNRESOLVED_REFERENCE!>take<!>(a)
}
fun test_6(a: A, out1: Out1<A>, out2: Out1<in A>, out3: Out1<out A>) {
fun test_6(a: A, out1: Out1<A>, out2: Out1<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> A>, out3: Out1<out A>) {
out1.value().foo()
out2.<!UNRESOLVED_REFERENCE!>value<!>().foo()
out3.value().foo()
@@ -383,6 +383,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val CONFLICTING_PROJECTION by error<KtTypeParameter>(PositioningStrategy.VARIANCE_MODIFIER) {
parameter<ConeKotlinType>("type")
}
val CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION by error<KtTypeParameter>(PositioningStrategy.VARIANCE_MODIFIER) {
parameter<ConeKotlinType>("type")
}
val VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED by error<KtTypeParameter>(PositioningStrategy.VARIANCE_MODIFIER)
val CATCH_PARAMETER_WITH_DEFAULT_VALUE by error<PsiElement>()
@@ -275,6 +275,7 @@ object FirErrors {
val ILLEGAL_PROJECTION_USAGE by error0<PsiElement>()
val TYPE_PARAMETERS_IN_ENUM by error0<PsiElement>()
val CONFLICTING_PROJECTION by error1<KtTypeParameter, ConeKotlinType>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
val CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION by error1<KtTypeParameter, ConeKotlinType>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
val VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED by error0<KtTypeParameter>(SourceElementPositioningStrategies.VARIANCE_MODIFIER)
val CATCH_PARAMETER_WITH_DEFAULT_VALUE by error0<PsiElement>()
val REIFIED_TYPE_IN_CATCH_CLAUSE by error0<PsiElement>()
@@ -5,13 +5,14 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -41,34 +42,39 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
}
}
private fun checkTypeRef(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
val declaration = typeRef.coneTypeSafe<ConeClassLikeType>()
?.lookupTag
?.toSymbol(context.session)
?.fir.safeAs<FirRegularClass>()
?: return
private fun checkTypeRef(
typeRef: FirTypeRef,
context: CheckerContext,
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 size = minOf(declaration.typeParameters.size, typeRef.coneType.typeArguments.size)
for (it in 0 until size) {
val proto = declaration.typeParameters[it]
val actual = typeRef.coneType.typeArguments[it]
val fullyExpandedProjection = fullyExpandedType.typeArguments[it]
val protoVariance = proto.safeAs<FirTypeParameterRef>()
?.symbol?.fir
?.variance
?: continue
if (protoVariance == Variance.INVARIANT) {
continue
}
if (
actual is ConeKotlinTypeProjectionIn && protoVariance == Variance.OUT_VARIANCE ||
actual is ConeKotlinTypeProjectionOut && protoVariance == Variance.IN_VARIANCE
(fullyExpandedProjection is ConeKotlinTypeConflictingProjection ||
actual is ConeKotlinTypeProjectionIn && protoVariance == Variance.OUT_VARIANCE ||
actual is ConeKotlinTypeProjectionOut && protoVariance == Variance.IN_VARIANCE) &&
typeRef.source?.kind !is FirFakeSourceElementKind
) {
val typeArgSource = extractTypeArgumentSource(typeRef, it)
reporter.reportOn(typeArgSource ?: typeRef.source, FirErrors.CONFLICTING_PROJECTION, typeRef.coneType, context)
reporter.reportOn(
typeArgSource ?: typeRef.source,
if (type != fullyExpandedType) FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION else FirErrors.CONFLICTING_PROJECTION,
fullyExpandedType,
context
)
}
}
}
@@ -70,6 +70,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTIO
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONDITION_TYPE_MISMATCH
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERLOADS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_UPPER_BOUNDS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONSTRUCTOR_IN_OBJECT
@@ -610,6 +611,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
"Projection is conflicting with variance of the corresponding type parameter of {0}. Remove the projection or replace it with ''*''",
RENDER_TYPE
)
map.put(
CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION,
"Conflicting projection in type alias expansion in intermediate type '{0}'",
RENDER_TYPE
)
map.put(
VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED,
"Variance annotations are only allowed for type parameters of classes and interfaces"