[FIR] Implement UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION diagnostics, fix handling of UPPER_BOUND_VIOLATED

This commit is contained in:
Ivan Kochurkin
2021-06-14 16:19:21 +03:00
committed by teamcityserver
parent 5741374883
commit 66e2b44272
20 changed files with 162 additions and 89 deletions
@@ -45,7 +45,7 @@ fun <K, L : K> rest() {
class NumColl<T : Collection<Number>>
typealias NL<K> = NumColl<List<K>>
val test7 = NL<Int>()<!UNRESOLVED_REFERENCE!>NumberPhile<!><!SYNTAX!><!>
val test8 = NL<String>()
val test8 = NL<<!UPPER_BOUND_VIOLATED!>String<!>>()
class NumberPhile<T: Number>(x: T)
val np1 = NumberPhile(10)
@@ -2,8 +2,8 @@
import java.util.EnumMap
typealias SomeEnumMap = EnumMap<String, String?>
typealias SomeEnumMap = EnumMap<<!UPPER_BOUND_VIOLATED!>String<!>, String?>
fun test(map: SomeEnumMap, qualifier: String?) {
val result = map[qualifier]
}
}
@@ -402,7 +402,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val INFERENCE_ERROR by error<PsiElement>()
val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error<PsiElement>()
val UPPER_BOUND_VIOLATED by error<PsiElement> {
parameter<ConeKotlinType>("upperBound")
parameter<ConeKotlinType>("expectedUpperBound")
parameter<ConeKotlinType>("actualUpperBound")
}
val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION by error<PsiElement> {
parameter<ConeKotlinType>("expectedUpperBound")
parameter<ConeKotlinType>("actualUpperBound")
}
val TYPE_ARGUMENTS_NOT_ALLOWED by error<PsiElement>()
val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error<PsiElement> {
@@ -282,7 +282,8 @@ object FirErrors {
val RECURSION_IN_IMPLICIT_TYPES by error0<PsiElement>()
val INFERENCE_ERROR by error0<PsiElement>()
val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error0<PsiElement>()
val UPPER_BOUND_VIOLATED by error1<PsiElement, ConeKotlinType>()
val UPPER_BOUND_VIOLATED by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION by error2<PsiElement, ConeKotlinType, ConeKotlinType>()
val TYPE_ARGUMENTS_NOT_ALLOWED by error0<PsiElement>()
val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
val NO_TYPE_ARGUMENTS_ON_RHS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
@@ -581,7 +581,7 @@ internal fun checkCondition(condition: FirExpression, context: CheckerContext, r
}
}
fun extractTypeRefAndSourceFromTypeArgument(typeRef: FirTypeRef?, index: Int): Pair<FirTypeRef, FirSourceElement?>? {
fun extractArgumentTypeRefAndSource(typeRef: FirTypeRef?, index: Int): FirTypeRefSource? {
if (typeRef is FirResolvedTypeRef) {
val delegatedTypeRef = typeRef.delegatedTypeRef
if (delegatedTypeRef is FirUserTypeRef) {
@@ -601,20 +601,22 @@ fun extractTypeRefAndSourceFromTypeArgument(typeRef: FirTypeRef?, index: Int): P
val typeArgument = currentTypeArguments?.elementAtOrNull(currentIndex)
if (typeArgument is FirTypeProjectionWithVariance) {
return Pair(typeArgument.typeRef, typeArgument.source)
return FirTypeRefSource(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)
return FirTypeRefSource(valueParamTypeRef, valueParamTypeRef.source)
}
if (index == valueParameters.size) {
val returnTypeRef = delegatedTypeRef.returnTypeRef
return Pair(returnTypeRef, returnTypeRef.source)
return FirTypeRefSource(returnTypeRef, returnTypeRef.source)
}
}
}
return null
}
data class FirTypeRefSource(val typeRef: FirTypeRef?, val source: FirSourceElement?)
@@ -8,7 +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.checkers.extractArgumentTypeRefAndSource
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
@@ -155,11 +155,11 @@ object FirClassVarianceChecker : FirClassChecker() {
}
if (newVariance != null) {
val subTypeRefAndSource = extractTypeRefAndSourceFromTypeArgument(typeRef, index)
val subTypeRefAndSource = extractArgumentTypeRefAndSource(typeRef, index)
checkVarianceConflict(
typeArgumentType, newVariance, subTypeRefAndSource?.first, containingType,
context, reporter, subTypeRefAndSource?.first?.source ?: source,
typeArgumentType, newVariance, subTypeRefAndSource?.typeRef, containingType,
context, reporter, subTypeRefAndSource?.typeRef?.source ?: source,
fullyExpandedType != type
)
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.extractTypeRefAndSourceFromTypeArgument
import org.jetbrains.kotlin.fir.analysis.checkers.extractArgumentTypeRefAndSource
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
@@ -77,11 +77,11 @@ object FirProjectionRelationChecker : FirBasicDeclarationChecker() {
ProjectionRelation.None
}
val (typeArgTypeRef, typeArgSource) = extractTypeRefAndSourceFromTypeArgument(typeRef, it) ?: continue
val argTypeRefSource = extractArgumentTypeRefAndSource(typeRef, it) ?: continue
if (projectionRelation != ProjectionRelation.None && typeRef.source?.kind !is FirFakeSourceElementKind) {
reporter.reportOn(
typeArgSource ?: typeArgTypeRef.source,
argTypeRefSource.source ?: argTypeRefSource.typeRef?.source,
if (projectionRelation == ProjectionRelation.Conflicting)
if (type != fullyExpandedType) FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION else FirErrors.CONFLICTING_PROJECTION
else
@@ -91,7 +91,7 @@ object FirProjectionRelationChecker : FirBasicDeclarationChecker() {
)
}
checkTypeRef(typeArgTypeRef, context, reporter)
argTypeRefSource.typeRef?.let { checkTypeRef(it, context, reporter) }
}
}
@@ -5,10 +5,12 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.FirTypeRefSource
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
import org.jetbrains.kotlin.fir.analysis.checkers.extractTypeRefAndSourceFromTypeArgument
import org.jetbrains.kotlin.fir.analysis.checkers.extractArgumentTypeRefAndSource
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
@@ -17,7 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableCandidateError
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
@@ -33,16 +35,20 @@ object FirUpperBoundViolatedClassChecker : FirBasicDeclarationChecker() {
for (typeParameter in declaration.typeParameters) {
if (typeParameter is FirTypeParameter) {
for (bound in typeParameter.bounds) {
analyzeTypeParameters(bound, context, reporter)
checkUpperBoundViolated(bound, context, reporter)
}
}
}
for (superTypeRef in declaration.superTypeRefs) {
analyzeTypeParameters(superTypeRef, context, reporter)
checkUpperBoundViolated(superTypeRef, context, reporter)
}
} else if (declaration is FirTypeAlias) {
checkUpperBoundViolated(declaration.expandedTypeRef, context, reporter, isIgnoreTypeParameters = true)
} else if (declaration is FirCallableDeclaration<*>) {
analyzeTypeParameters(declaration.returnTypeRef, context, reporter)
if (declaration.returnTypeRef.source?.kind !is FirFakeSourceElementKind) {
checkUpperBoundViolated(declaration.returnTypeRef, context, reporter)
}
}
}
}
@@ -67,12 +73,25 @@ object FirUpperBoundViolatedExpressionChecker : FirQualifiedAccessExpressionChec
calleeFir = calleReference.candidateSymbol?.fir.safeAs()
}
analyzeTypeParameters(
var typeArguments: List<Any>? = null
var typeArgumentRefsAndSources: List<FirTypeRefSource?>? = null
val typeParameters = if (calleeFir is FirConstructor) {
typeArgumentRefsAndSources =
expression.typeArguments.map { FirTypeRefSource((it as? FirTypeProjectionWithVariance)?.typeRef, it.source) }
val prototypeClass = calleeFir.dispatchReceiverType?.toSymbol(context.session)?.fir.safeAs<FirRegularClass>()
prototypeClass?.typeParameters?.map { it.symbol }
} else {
typeArguments = expression.typeArguments
calleeFir?.typeParameters?.map { it.symbol }
}
checkUpperBoundViolated(
expression.typeRef,
context,
reporter,
calleeFir?.typeParameters?.map { it.symbol },
expression.typeArguments
typeParameters,
typeArguments,
typeArgumentRefsAndSources
)
}
}
@@ -81,12 +100,15 @@ object FirUpperBoundViolatedExpressionChecker : FirQualifiedAccessExpressionChec
* Recursively analyzes type parameters and reports the diagnostic on the given source calculated using typeRef
* Returns true if an error occurred
*/
private fun analyzeTypeParameters(
private fun checkUpperBoundViolated(
typeRef: FirTypeRef?,
context: CheckerContext,
reporter: DiagnosticReporter,
typeParameters: List<FirTypeParameterSymbol>? = null,
typeArguments: List<FirTypeProjection>? = null
typeArguments: List<Any>? = null,
typeArgumentRefsAndSources: List<FirTypeRefSource?>? = null,
isTypeAlias: Boolean = false,
isIgnoreTypeParameters: Boolean = false
) {
val type = when (typeRef) {
is ConeKotlinType -> typeRef
@@ -101,10 +123,26 @@ private fun analyzeTypeParameters(
val typeParameterSymbols = typeParameters
?: if (type is ConeClassLikeType) {
val prototypeClass = type.lookupTag.toSymbol(context.session)
val fullyExpandedType = type.fullyExpandedType(context.session)
val prototypeClass = fullyExpandedType.lookupTag.toSymbol(context.session)
?.fir.safeAs<FirRegularClass>()
?: return
if (type != fullyExpandedType) {
// special check for type aliases
checkUpperBoundViolated(
typeRef,
context,
reporter,
prototypeClass.typeParameters.map { it.symbol },
fullyExpandedType.typeArguments.toList(),
null,
isTypeAlias = true,
isIgnoreTypeParameters = isIgnoreTypeParameters
)
return
}
prototypeClass.typeParameters.map { it.symbol }
} else {
listOf()
@@ -142,36 +180,43 @@ private fun analyzeTypeParameters(
typeArgumentTypeRef = localTypeArgument.typeRef
typeArgument = typeArgumentTypeRef.coneType
typeArgumentSource = localTypeArgument.source
} else if (localTypeArgument is ConeKotlinType) {
// Typealias case
typeArgument = localTypeArgument
typeArgumentSource = typeRef.source
}
} else {
typeArgument = type.typeArguments[index] as? ConeKotlinType
val argTypeRefSource = extractTypeRefAndSourceFromTypeArgument(typeRef, index)
if (argTypeRefSource != null) {
typeArgumentTypeRef = argTypeRefSource.first
typeArgumentSource = argTypeRefSource.second
val typeArgumentRefAndSource = typeArgumentRefsAndSources?.elementAtOrNull(index)
if (typeArgumentRefAndSource != null) {
typeArgumentTypeRef = typeArgumentRefAndSource.typeRef
typeArgumentSource = typeArgumentRefAndSource.source
} else {
val extractedTypeArgumentRefAndSource = extractArgumentTypeRefAndSource(typeRef, index)
if (extractedTypeArgumentRefAndSource != null) {
typeArgumentTypeRef = extractedTypeArgumentRefAndSource.typeRef
typeArgumentSource = extractedTypeArgumentRefAndSource.source
}
}
}
if (typeArgument != null && typeArgumentSource != null) {
val upperBound = getSubstitutedUpperBound(typeParameterSymbols[index], substitutor, typeSystemContext)
if (upperBound != null && !satisfiesBounds(upperBound, typeArgument.type, typeSystemContext)) {
reporter.reportOn(typeArgumentSource, FirErrors.UPPER_BOUND_VIOLATED, upperBound, context)
if (!isIgnoreTypeParameters || (typeArgument.typeArguments.isEmpty() && typeArgument !is ConeTypeParameterType)) {
val intersection = typeSystemContext.intersectTypes(typeParameterSymbols[index].fir.bounds.map { it.coneType }) as? ConeKotlinType
if (intersection != null) {
val upperBound = substitutor.substituteOrSelf(intersection)
if (!AbstractTypeChecker.isSubtypeOf(typeSystemContext, typeArgument.type, upperBound, stubTypesEqualToAnything = false)) {
val factory =
if (isTypeAlias) FirErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION else FirErrors.UPPER_BOUND_VIOLATED
reporter.reportOn(typeArgumentSource, factory, upperBound, typeArgument.type, context)
if (isTypeAlias) {
return
}
}
}
}
analyzeTypeParameters(typeArgumentTypeRef, context, reporter)
checkUpperBoundViolated(typeArgumentTypeRef, context, reporter, isIgnoreTypeParameters = isIgnoreTypeParameters)
}
}
}
private fun getSubstitutedUpperBound(
prototypeSymbol: FirTypeParameterSymbol,
substitutor: ConeSubstitutor,
typeSystemContext: ConeTypeContext
): ConeKotlinType? {
val intersection = typeSystemContext.intersectTypes(prototypeSymbol.fir.bounds.map { it.coneType }) as? ConeKotlinType ?: return null
return substitutor.substituteOrSelf(intersection)
}
private fun satisfiesBounds(upperBound: ConeKotlinType, target: ConeKotlinType, typeSystemContext: ConeTypeContext): Boolean {
return AbstractTypeChecker.isSubtypeOf(typeSystemContext, target, upperBound, stubTypesEqualToAnything = false)
}
}
@@ -340,6 +340,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATU
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USAGE_IS_NOT_INLINABLE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_CAST
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS
@@ -649,7 +650,14 @@ class FirDefaultErrorMessages {
map.put(RECURSION_IN_IMPLICIT_TYPES, "Recursion in implicit types")
map.put(INFERENCE_ERROR, "Inference error")
map.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties")
map.put(UPPER_BOUND_VIOLATED, "Type argument is not within its bounds: should be subtype of ''{0}''", RENDER_TYPE)
map.put(UPPER_BOUND_VIOLATED, "Type argument is not within its bounds: should be subtype of ''{0}''", RENDER_TYPE, RENDER_TYPE)
map.put(
UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION,
"Type argument is not within its bounds: should be subtype of ''{0}''",
RENDER_TYPE,
RENDER_TYPE
)
map.put(TYPE_ARGUMENTS_NOT_ALLOWED, "Type arguments are not allowed for type parameters") // *
map.put(
WRONG_NUMBER_OF_TYPE_ARGUMENTS,
@@ -22,6 +22,7 @@ abstract class AbstractConeSubstitutor(private val typeContext: ConeTypeContext)
is ConeStarProjection -> old
is ConeKotlinTypeProjectionIn -> ConeKotlinTypeProjectionIn(newType)
is ConeKotlinTypeProjectionOut -> ConeKotlinTypeProjectionOut(newType)
is ConeKotlinTypeConflictingProjection -> ConeKotlinTypeConflictingProjection(newType)
is ConeKotlinType -> newType
else -> old
}
@@ -4,8 +4,8 @@ typealias N<T> = Num<T>
typealias N2<T> = N<T>
val x1 = Num<<!UPPER_BOUND_VIOLATED!>String<!>>(<!ARGUMENT_TYPE_MISMATCH!>""<!>)
val x2 = N<String>("")
val x3 = N2<String>("")
val x2 = N<<!UPPER_BOUND_VIOLATED!>String<!>>("")
val x3 = N2<<!UPPER_BOUND_VIOLATED!>String<!>>("")
class TColl<T, C : Collection<T>>
@@ -13,5 +13,5 @@ typealias TC<T, C> = TColl<T, C>
typealias TC2<T, C> = TC<T, C>
val y1 = TColl<Any, <!UPPER_BOUND_VIOLATED!>Any<!>>()
val y2 = TC<Any, Any>()
val y3 = TC2<Any, Any>()
val y2 = TC<Any, <!UPPER_BOUND_VIOLATED!>Any<!>>()
val y3 = TC2<Any, <!UPPER_BOUND_VIOLATED!>Any<!>>()
@@ -1,16 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
class TColl<T, C : Collection<T>>
typealias TC<T1, T2> = TColl<T1, T2>
typealias TC2<T1, T2> = TC<T1, T2>
fun test1(x: TC2<Number, Collection<Number>>) {}
fun test2(x: TC2<Number, Collection<Int>>) {}
fun test3(x: TC2<Number, List<Int>>) {}
fun test4(x: TC2<Number, List<Any>>) {}
val test5 = TC2<Number, Collection<Number>>()
val test6 = TC2<Number, Collection<Int>>()
val test7 = TC2<Number, List<Int>>()
val test8 = TC2<Number, List<Any>>()
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
class TColl<T, C : Collection<T>>
@@ -10,22 +10,22 @@ typealias MMMM<A3> = NL<A3>
typealias TC<T1, T2> = TColl<T1, T2>
fun test1(x: NA<Int>) {}
fun test2(x: NA<Any>) {}
fun test2(x: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>NA<Any><!>) {}
fun test3(x: NL<Int>) {}
fun test4(x: NL<Any>) {}
fun test4(x: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>NL<Any><!>) {}
val test5 = NA<Int>()
val test6 = NA<Any>()
val test6 = NA<<!UPPER_BOUND_VIOLATED!>Any<!>>()
val test7 = NL<Int>()
val test8 = MMMM<Int>()
val test9dwd = NL<Any>()
val test9dwd = NL<<!UPPER_BOUND_VIOLATED!>Any<!>>()
fun test9(x: TC<Number, Collection<Number>>) {}
fun test10(x: TC<Number, Collection<Int>>) {}
fun test11(x: TC<Number, List<Int>>) {}
fun test12(x: TC<Number, List<Any>>) {}
fun test12(x: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>TC<Number, List<Any>><!>) {}
val test13 = TC<Number, Collection<Number>>()
val test14 = TC<Number, Collection<Int>>()
val test15 = TC<Number, List<Int>>()
val test16 = TC<Number, List<Any>>()
val test16 = TC<Number, <!UPPER_BOUND_VIOLATED!>List<Any><!>>()
@@ -3,18 +3,18 @@
class TC<T, C : Collection<T>>
typealias TCAlias<T, C> = TC<T, C>
typealias TCAliasT<T> = TC<T, Any>
typealias TCAliasT<T> = TC<T, <!UPPER_BOUND_VIOLATED!>Any<!>>
typealias TCAliasC<C> = TC<Any, C>
typealias TCAliasT1<T> = TCAlias<T, Any>
typealias TCAliasT1<T> = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>TCAlias<T, Any><!>
typealias TCAliasC1<C> = TCAlias<Any, C>
typealias Test1 = TC<Any, Any>
typealias Test1 = TC<Any, <!UPPER_BOUND_VIOLATED!>Any<!>>
typealias Test2 = TC<Any, Collection<Any>>
typealias Test3 = TCAlias<Any, Any>
typealias Test3 = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>TCAlias<Any, Any><!>
typealias Test4 = TCAlias<Any, Collection<Any>>
typealias Test5 = TCAliasT<Any>
typealias Test6 = TCAliasC<Any>
typealias Test5 = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>TCAliasT<Any><!>
typealias Test6 = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>TCAliasC<Any><!>
typealias Test7 = TCAliasC<Collection<Any>>
typealias Test8 = TCAliasT1<Any>
typealias Test9 = TCAliasC1<Any>
typealias Test8 = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>TCAliasT1<Any><!>
typealias Test9 = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>TCAliasC1<Any><!>
typealias Test10 = TCAliasC1<Collection<Any>>
@@ -8,4 +8,4 @@ interface Num<T : Number>
typealias N<T> = Num<T>
class Test2<T : N<String>>
class Test2<T : <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>N<String><!>>
@@ -30,7 +30,7 @@ typealias N<T> = Num<T>
val testN0 = N("")
val testN1 = N<Int>(1)
val testN1a = N<String>("")
val testN1a = N<<!UPPER_BOUND_VIOLATED!>String<!>>("")
val testN2 = <!INAPPLICABLE_CANDIDATE!>N<!><Int, Int>(1)
class MyPair<T1 : CharSequence, T2 : Number>(val string: T1, val number: T2)
@@ -1230,6 +1230,15 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
add(FirErrors.UPPER_BOUND_VIOLATED) { firDiagnostic ->
UpperBoundViolatedImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION) { firDiagnostic ->
UpperBoundViolatedInTypealiasExpansionImpl(
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.b),
firDiagnostic as FirPsiDiagnostic,
token,
)
@@ -872,7 +872,14 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract class UpperBoundViolated : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = UpperBoundViolated::class
abstract val upperBound: KtType
abstract val expectedUpperBound: KtType
abstract val actualUpperBound: KtType
}
abstract class UpperBoundViolatedInTypealiasExpansion : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = UpperBoundViolatedInTypealiasExpansion::class
abstract val expectedUpperBound: KtType
abstract val actualUpperBound: KtType
}
abstract class TypeArgumentsNotAllowed : KtFirDiagnostic<PsiElement>() {
@@ -1403,13 +1403,23 @@ internal class ProjectionOnNonClassTypeArgumentImpl(
}
internal class UpperBoundViolatedImpl(
override val upperBound: KtType,
override val expectedUpperBound: KtType,
override val actualUpperBound: KtType,
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.UpperBoundViolated(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class UpperBoundViolatedInTypealiasExpansionImpl(
override val expectedUpperBound: KtType,
override val actualUpperBound: KtType,
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.UpperBoundViolatedInTypealiasExpansion(), KtAbstractFirDiagnostic<PsiElement> {
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
}
internal class TypeArgumentsNotAllowedImpl(
firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,