[FIR] Implement UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION diagnostics, fix handling of UPPER_BOUND_VIOLATED
This commit is contained in:
committed by
teamcityserver
parent
5741374883
commit
66e2b44272
+1
-1
@@ -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
-2
@@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -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> {
|
||||
|
||||
+2
-1
@@ -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?)
|
||||
+4
-4
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
+4
-4
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+78
-33
@@ -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)
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -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
-4
@@ -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<!>>()
|
||||
|
||||
Vendored
-16
@@ -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
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
class TColl<T, C : Collection<T>>
|
||||
|
||||
+6
-6
@@ -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><!>>()
|
||||
|
||||
+8
-8
@@ -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><!>>
|
||||
|
||||
Vendored
+1
-1
@@ -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)
|
||||
|
||||
+9
@@ -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,
|
||||
)
|
||||
|
||||
+8
-1
@@ -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>() {
|
||||
|
||||
+11
-1
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user