[FIR] Implement CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION diagnostics, fix tests
This commit is contained in:
committed by
teamcityserver
parent
ca970f0a8b
commit
03e577bf98
@@ -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()
|
||||
|
||||
+3
@@ -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>()
|
||||
|
||||
+21
-15
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -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"
|
||||
|
||||
+4
-4
@@ -9,8 +9,8 @@ typealias OutAlias<T> = Out<T>
|
||||
typealias TestOutForIn<T> = In<<!CONFLICTING_PROJECTION!>out<!> T>
|
||||
typealias TestInForOut<T> = Out<<!CONFLICTING_PROJECTION!>in<!> T>
|
||||
|
||||
typealias TestOutForInWithinAlias<T> = InAlias<out T>
|
||||
typealias TestInForOutWithinAlias<T> = OutAlias<in T>
|
||||
typealias TestOutForInWithinAlias<T> = InAlias<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> T>
|
||||
typealias TestInForOutWithinAlias<T> = OutAlias<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> T>
|
||||
|
||||
fun <T> testOutForInWithinResolvedType(x: InAlias<out T>) {}
|
||||
fun <T> testInForOutWithinResolvedType(x: OutAlias<in T>) {}
|
||||
fun <T> testOutForInWithinResolvedType(x: InAlias<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> T>) {}
|
||||
fun <T> testInForOutWithinResolvedType(x: OutAlias<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> T>) {}
|
||||
|
||||
+10
-10
@@ -23,31 +23,31 @@ val inv1: Inv1<Int> = Inv<Int>()
|
||||
|
||||
fun inInv_Inv(x: In1<Int>) = x
|
||||
fun inInv_In(x: In1<in Int>) = x
|
||||
fun inInv_Out(x: In1<out Int>) = x
|
||||
fun inInv_Out(x: In1<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> Int>) = x
|
||||
fun inInv_Star(x: In1<*>) = x
|
||||
|
||||
fun inIn_Inv(x: In2<Int>) = x
|
||||
fun inIn_In(x: In2<in Int>) = x
|
||||
fun inIn_Out(x: In2<out Int>) = x
|
||||
fun inIn_Out(x: In2<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> Int>) = x
|
||||
fun inIn_Star(x: In2<*>) = x
|
||||
|
||||
fun inOut_Inv(x: In3<Int>) = x
|
||||
fun inOut_In(x: In3<in Int>) = x
|
||||
fun inOut_Out(x: In3<out Int>) = x
|
||||
fun inOut_In(x: In3<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> Int>) = x
|
||||
fun inOut_Out(x: In3<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> Int>) = x
|
||||
fun inOut_Star(x: In3<*>) = x
|
||||
|
||||
fun outInv_Inv(x: Out1<Int>) = x
|
||||
fun outInv_In(x: Out1<in Int>) = x
|
||||
fun outInv_In(x: Out1<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> Int>) = x
|
||||
fun outInv_Out(x: Out1<out Int>) = x
|
||||
fun outInv_Star(x: Out1<*>) = x
|
||||
|
||||
fun outIn_Inv(x: Out2<Int>) = x
|
||||
fun outIn_In(x: Out2<in Int>) = x
|
||||
fun outIn_Out(x: Out2<out Int>) = x
|
||||
fun outIn_In(x: Out2<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> Int>) = x
|
||||
fun outIn_Out(x: Out2<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> Int>) = x
|
||||
fun outIn_Star(x: Out2<*>) = x
|
||||
|
||||
fun outOut_Inv(x: Out3<Int>) = x
|
||||
fun outOut_In(x: Out3<in Int>) = x
|
||||
fun outOut_In(x: Out3<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> Int>) = x
|
||||
fun outOut_Out(x: Out3<out Int>) = x
|
||||
fun outOut_Star(x: Out3<*>) = x
|
||||
|
||||
@@ -58,10 +58,10 @@ fun invInv_Star(x: Inv1<*>) = x
|
||||
|
||||
fun invIn_Inv(x: Inv2<Int>) = x
|
||||
fun invIn_In(x: Inv2<in Int>) = x
|
||||
fun invIn_Out(x: Inv2<out Int>) = x
|
||||
fun invIn_Out(x: Inv2<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>out<!> Int>) = x
|
||||
fun invIn_Star(x: Inv2<*>) = x
|
||||
|
||||
fun invOut_Inv(x: Inv3<Int>) = x
|
||||
fun invOut_In(x: Inv3<in Int>) = x
|
||||
fun invOut_In(x: Inv3<<!CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION!>in<!> Int>) = x
|
||||
fun invOut_Out(x: Inv3<out Int>) = x
|
||||
fun invOut_Star(x: Inv3<*>) = x
|
||||
|
||||
+7
@@ -1193,6 +1193,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION) { firDiagnostic ->
|
||||
ConflictingProjectionInTypealiasExpansionImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED) { firDiagnostic ->
|
||||
VarianceOnTypeParameterNotAllowedImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
|
||||
+5
@@ -845,6 +845,11 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val type: KtType
|
||||
}
|
||||
|
||||
abstract class ConflictingProjectionInTypealiasExpansion : KtFirDiagnostic<KtTypeParameter>() {
|
||||
override val diagnosticClass get() = ConflictingProjectionInTypealiasExpansion::class
|
||||
abstract val type: KtType
|
||||
}
|
||||
|
||||
abstract class VarianceOnTypeParameterNotAllowed : KtFirDiagnostic<KtTypeParameter>() {
|
||||
override val diagnosticClass get() = VarianceOnTypeParameterNotAllowed::class
|
||||
}
|
||||
|
||||
+8
@@ -1362,6 +1362,14 @@ internal class ConflictingProjectionImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ConflictingProjectionInTypealiasExpansionImpl(
|
||||
override val type: KtType,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ConflictingProjectionInTypealiasExpansion(), KtAbstractFirDiagnostic<KtTypeParameter> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class VarianceOnTypeParameterNotAllowedImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
|
||||
Reference in New Issue
Block a user