[FIR] Implement WRONG_NUMBER_OF_TYPE_ARGUMENTS for top level type aliases

This commit is contained in:
Ivan Kochurkin
2021-08-17 22:23:49 +03:00
committed by TeamCityServer
parent 09510633c7
commit 38820d3e41
12 changed files with 109 additions and 49 deletions
@@ -2771,7 +2771,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
firDiagnostic.b,
firDiagnostic.c.mapKeys { (incompatible, _) ->
incompatible
}.mapValues { (_, collection) ->
}.mapValues { (_, collection) ->
collection.map { firBasedSymbol ->
firSymbolBuilder.buildSymbol(firBasedSymbol.fir)
}
@@ -2785,7 +2785,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
firDiagnostic.b.mapKeys { (incompatible, _) ->
incompatible
}.mapValues { (_, collection) ->
}.mapValues { (_, collection) ->
collection.map { firBasedSymbol ->
firSymbolBuilder.buildSymbol(firBasedSymbol.fir)
}
@@ -2820,7 +2820,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
firDiagnostic.b.map { pair ->
firSymbolBuilder.buildSymbol(pair.first.fir) to pair.second.mapKeys { (incompatible, _) ->
incompatible
}.mapValues { (_, collection) ->
}.mapValues { (_, collection) ->
collection.map { firBasedSymbol ->
firSymbolBuilder.buildSymbol(firBasedSymbol.fir)
}
@@ -534,14 +534,14 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val TYPE_ARGUMENTS_NOT_ALLOWED by error<PsiElement>()
val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error<PsiElement> {
parameter<Int>("expectedCount")
parameter<FirRegularClassSymbol>("classifier")
parameter<FirClassLikeSymbol<*>>("classifier")
}
val NO_TYPE_ARGUMENTS_ON_RHS by error<PsiElement> {
parameter<Int>("expectedCount")
parameter<FirClassLikeSymbol<*>>("classifier")
}
val OUTER_CLASS_ARGUMENTS_REQUIRED by error<PsiElement> {
parameter<FirRegularClassSymbol>("outer")
parameter<FirClassLikeSymbol<*>>("outer")
}
val TYPE_PARAMETERS_IN_OBJECT by error<PsiElement>(PositioningStrategy.TYPE_PARAMETERS_LIST)
val TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT by error<PsiElement>(PositioningStrategy.TYPE_PARAMETERS_LIST)
@@ -353,9 +353,9 @@ object FirErrors {
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, FirRegularClassSymbol>()
val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
val NO_TYPE_ARGUMENTS_ON_RHS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
val OUTER_CLASS_ARGUMENTS_REQUIRED by error1<PsiElement, FirRegularClassSymbol>()
val OUTER_CLASS_ARGUMENTS_REQUIRED by error1<PsiElement, FirClassLikeSymbol<*>>()
val TYPE_PARAMETERS_IN_OBJECT by error0<PsiElement>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
val TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT by error0<PsiElement>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
val ILLEGAL_PROJECTION_USAGE by error0<PsiElement>()
@@ -469,10 +469,10 @@ fun FirFunction.getHasStableParameterNames(session: FirSession): Boolean = getAs
fun FirRegularClass.getActualTypeParametersCount(session: FirSession): Int {
var result = typeParameters.size
fun FirClassLikeDeclaration.getActualTypeParametersCount(session: FirSession): Int {
var result = (if (this is FirTypeAlias) this.typeParameters else (this as FirClass).typeParameters).size
if (!isInner) {
if (this is FirRegularClass && !isInner) {
return result
}
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.fullyExpandedClass
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOuterClassArgumentsRequired
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedQualifierError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedDynamicType
@@ -234,11 +235,12 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
}
}
if (symbol is FirRegularClassSymbol) {
if (symbol is FirClassLikeSymbol<*>) {
val isPossibleBareType = areBareTypesAllowed && allTypeArguments.isEmpty()
if (!isPossibleBareType) {
val actualSubstitutor = substitutor ?: ConeSubstitutor.Empty
val typeParameters = symbol.fir.typeParameters
val typeParameters = calculateTypeParameters(symbol)
val (typeParametersAlignedToQualifierParts, outerClasses) = getClassesAlignedToQualifierParts(symbol, qualifier, session)
@@ -302,41 +304,82 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
}
}
private fun calculateTypeParameters(symbol: FirClassLikeSymbol<*>): List<FirTypeParameterRef> {
return if (symbol is FirTypeAliasSymbol) {
val typeAliasFir = symbol.fir
val typeAliasTypeParameters = typeAliasFir.typeParameters.toMutableList()
val fullyExpandedClass = typeAliasFir.fullyExpandedClass(session)
val newTypeParameters: MutableList<FirTypeParameterRef>
if (fullyExpandedClass != null) { // TODO: Should not be null, move to resolver?
val expandedTypeRef = typeAliasFir.expandedTypeRef
fun checkTypeArguments(typeArgument: ConeTypeProjection) {
when (typeArgument) {
is ConeTypeParameterType -> typeAliasTypeParameters.removeIf { it.symbol == typeArgument.lookupTag.symbol }
is ConeClassLikeType -> {
for (subTypeArgument in typeArgument.typeArguments) {
checkTypeArguments(subTypeArgument)
}
}
is ConeKotlinTypeProjection -> checkTypeArguments(typeArgument.type)
else -> {
}
}
}
checkTypeArguments(expandedTypeRef.coneType)
newTypeParameters = fullyExpandedClass.typeParameters.toMutableList()
} else {
newTypeParameters = mutableListOf()
}
for (typeParameter in typeAliasTypeParameters) {
newTypeParameters.add(typeParameter)
}
newTypeParameters
} else {
(symbol as FirClassSymbol<*>).fir.typeParameters
}
}
@OptIn(SymbolInternals::class)
private fun getClassesAlignedToQualifierParts(
symbol: FirRegularClassSymbol,
symbol: FirClassLikeSymbol<*>,
qualifier: List<FirQualifierPart>,
session: FirSession
): ParametersMapAndOuterClasses {
var currentClass: FirRegularClass? = null
val outerClasses = mutableListOf<FirRegularClass?>()
var currentClassLikeDeclaration: FirClassLikeDeclaration? = null
val outerDeclarations = mutableListOf<FirClassLikeDeclaration?>()
// Try to get at least qualifier.size classes that match qualifier parts
var qualifierPartIndex = 0
while (qualifierPartIndex < qualifier.size || currentClass != null) {
while (qualifierPartIndex < qualifier.size || currentClassLikeDeclaration != null) {
if (qualifierPartIndex == 0) {
currentClass = symbol.fir
currentClassLikeDeclaration = symbol.fir
} else {
if (currentClass != null) {
currentClass = currentClass.getContainingDeclaration(session) as? FirRegularClass
if (currentClassLikeDeclaration != null) {
currentClassLikeDeclaration = currentClassLikeDeclaration.getContainingDeclaration(session)
}
}
outerClasses.add(currentClass)
outerDeclarations.add(currentClassLikeDeclaration)
qualifierPartIndex++
}
val outerArgumentsCount = outerClasses.size - qualifier.size
val reversedOuterClasses = outerClasses.asReversed()
val outerArgumentsCount = outerDeclarations.size - qualifier.size
val reversedOuterClasses = outerDeclarations.asReversed()
val result = mutableMapOf<FirTypeParameterSymbol, ClassWithQualifierPartIndex>()
for (index in reversedOuterClasses.indices) {
currentClass = reversedOuterClasses[index]
if (currentClass != null) {
for (typeParameter in currentClass.typeParameters) {
currentClassLikeDeclaration = reversedOuterClasses[index]
val typeParameters = if (currentClassLikeDeclaration is FirTypeAlias) currentClassLikeDeclaration.typeParameters else
(currentClassLikeDeclaration as? FirClass)?.typeParameters
if (currentClassLikeDeclaration != null && typeParameters != null) {
for (typeParameter in typeParameters) {
val typeParameterSymbol = typeParameter.symbol
if (!result.containsKey(typeParameterSymbol)) {
result[typeParameterSymbol] = ClassWithQualifierPartIndex(currentClass, index - outerArgumentsCount)
result[typeParameterSymbol] = ClassWithQualifierPartIndex(currentClassLikeDeclaration, index - outerArgumentsCount)
}
}
}
@@ -347,19 +390,19 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
private data class ParametersMapAndOuterClasses(
val parameters: Map<FirTypeParameterSymbol, ClassWithQualifierPartIndex>,
val outerClasses: List<FirRegularClass?>
val outerClasses: List<FirClassLikeDeclaration?>
)
private data class ClassWithQualifierPartIndex(
val klass: FirRegularClass,
val klass: FirClassLikeDeclaration,
val index: Int
)
@OptIn(SymbolInternals::class)
private fun createDiagnosticsIfExists(
parameterClass: FirRegularClass?,
parameterClass: FirClassLikeDeclaration?,
qualifierPartIndex: Int,
symbol: FirRegularClassSymbol,
symbol: FirClassLikeSymbol<*>,
userTypeRef: FirUserTypeRef,
qualifierPartArgumentsCount: Int? = null
): ConeClassErrorType? {
@@ -152,7 +152,7 @@ interface ConeUnmatchedTypeArgumentsError : ConeDiagnosticWithSingleCandidate {
class ConeWrongNumberOfTypeArgumentsError(
override val desiredCount: Int,
override val candidateSymbol: FirRegularClassSymbol,
override val candidateSymbol: FirClassLikeSymbol<*>,
source: KtSourceElement
) : ConeDiagnosticWithSource(source), ConeUnmatchedTypeArgumentsError {
override val reason: String get() = "Wrong number of type arguments"
@@ -166,7 +166,7 @@ class ConeNoTypeArgumentsOnRhsError(
}
class ConeOuterClassArgumentsRequired(
val symbol: FirRegularClassSymbol,
val symbol: FirClassLikeSymbol<*>,
) : ConeDiagnostic {
override val reason: String = "Type arguments should be specified for an outer class"
}
@@ -18,17 +18,17 @@ class Outer<T> {
fun test5(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<Int><!>) = x
fun <T> test6(x: <!UNRESOLVED_REFERENCE!>GenericInnerAlias<T><!>) = x
}
fun test1(x: Outer<Int>.NestedAlias) = x
fun <T> test2(x: Outer<T>.NestedAlias) = x
fun test1(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.NestedAlias) = x
fun <T> test2(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T><!>.NestedAlias) = x
fun test3(x: Outer.NestedAlias) = x
fun test4(x: Outer<Int>.GenericNestedAlias<Int>) = x
fun <T> test5(x: Outer<T>.GenericNestedAlias<Int>) = x
fun <T> test6(x: Outer<Int>.GenericNestedAlias<T>) = x
fun test4(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.GenericNestedAlias<Int>) = x
fun <T> test5(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T><!>.GenericNestedAlias<Int>) = x
fun <T> test6(x: Outer<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>.GenericNestedAlias<T>) = x
fun test7(x: Outer.GenericNestedAlias<Int>) = x
fun <T> test8(x: Outer.GenericNestedAlias<T>) = x
fun test9(x: Outer.InnerAlias) = x
fun test9(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Outer<!>.InnerAlias) = x
fun test10(x: Outer<Int>.InnerAlias) = x
fun <T> test11(x: Outer<T>.InnerAlias) = x
fun test12(x: Outer.GenericInnerAlias<Int>) = x
fun test12(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Outer<!>.GenericInnerAlias<Int>) = x
fun test13(x: Outer<Int>.GenericInnerAlias<Int>) = x
fun <T> test14(x: Outer<T>.GenericInnerAlias<Int>) = x
@@ -0,0 +1,24 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
class C<T> {
inner class D
typealias DA = D
typealias SDA = C<Int>.D
typealias TSDA = C<T>.D
typealias TC = C<T>
typealias SSDA = C<*>.D
typealias SSC = C<*>
}
fun test1(x: C<Int>.DA) = x
fun test2(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>C<!>.SDA) = x
fun test3(x: C<Int>.TSDA) = x
fun test4(x: C<Int>.TC) = x
fun test5(x: C<*>.DA) = x
fun test6(x: C<*>.TSDA) = x
fun test7(x: C<*>.TC) = x
fun test8(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>C<!>.SSDA) = x
fun test9(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>C<!>.SSC) = x
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
class C<T> {
@@ -6,5 +6,5 @@ class OuterClass<T1> {
}
typealias ON1<T1, T2> = OuterClass<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T1><!>.NestedClass<T2>
typealias ON2<T1, T2> = OuterClass<T1>.NestedType<T2>
typealias ON3<T2> = OuterClass.NestedType<T2>
typealias ON2<T1, T2> = OuterClass<T1>.NestedType<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T2><!>
typealias ON3<T2> = OuterClass.NestedType<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T2><!>
@@ -1,7 +0,0 @@
open class Ref<T>(var x: T)
typealias R<T> = Ref<T>
// Type inference SHOULD NOT work for type alias constructor in supertypes list
class Test1 : R(0)
class Test2 : R<Int>(0)
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
open class Ref<T>(var x: T)
typealias R<T> = Ref<T>