From 38820d3e41479a03a71b137d85983f82e15bda1f Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Tue, 17 Aug 2021 22:23:49 +0300 Subject: [PATCH] [FIR] Implement WRONG_NUMBER_OF_TYPE_ARGUMENTS for top level type aliases --- .../diagnostics/KtFirDataClassConverters.kt | 6 +- .../diagnostics/FirDiagnosticsList.kt | 4 +- .../fir/analysis/diagnostics/FirErrors.kt | 4 +- .../kotlin/fir/resolve/ResolveUtils.kt | 6 +- .../providers/impl/FirTypeResolverImpl.kt | 83 ++++++++++++++----- .../resolve/diagnostics/ConeDiagnostics.kt | 4 +- .../typealias/innerTypeAliasAsType.fir.kt | 14 ++-- .../typealias/innerTypeAliasAsType2.fir.kt | 24 ++++++ .../tests/typealias/innerTypeAliasAsType2.kt | 1 - .../tests/typealias/kt14518.fir.kt | 4 +- ...onstructorInferenceInSupertypesList.fir.kt | 7 -- ...iasConstructorInferenceInSupertypesList.kt | 1 + 12 files changed, 109 insertions(+), 49 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.fir.kt diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index cf02ff69ba3..d3f9a94942e 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -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) } diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index b1cbaef10f1..a8bf1c8efd8 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -534,14 +534,14 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val TYPE_ARGUMENTS_NOT_ALLOWED by error() val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error { parameter("expectedCount") - parameter("classifier") + parameter>("classifier") } val NO_TYPE_ARGUMENTS_ON_RHS by error { parameter("expectedCount") parameter>("classifier") } val OUTER_CLASS_ARGUMENTS_REQUIRED by error { - parameter("outer") + parameter>("outer") } val TYPE_PARAMETERS_IN_OBJECT by error(PositioningStrategy.TYPE_PARAMETERS_LIST) val TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT by error(PositioningStrategy.TYPE_PARAMETERS_LIST) diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index ec02884b4e1..c15ad1123a5 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -353,9 +353,9 @@ object FirErrors { val UPPER_BOUND_VIOLATED by error2() val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION by error2() val TYPE_ARGUMENTS_NOT_ALLOWED by error0() - val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error2() + val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error2>() val NO_TYPE_ARGUMENTS_ON_RHS by error2>() - val OUTER_CLASS_ARGUMENTS_REQUIRED by error1() + val OUTER_CLASS_ARGUMENTS_REQUIRED by error1>() val TYPE_PARAMETERS_IN_OBJECT by error0(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST) val TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT by error0(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST) val ILLEGAL_PROJECTION_USAGE by error0() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index e7295951584..38f2c98275f 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -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 } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt index 38f6dc26275..bdfdb7b511a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt @@ -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 { + return if (symbol is FirTypeAliasSymbol) { + val typeAliasFir = symbol.fir + val typeAliasTypeParameters = typeAliasFir.typeParameters.toMutableList() + val fullyExpandedClass = typeAliasFir.fullyExpandedClass(session) + val newTypeParameters: MutableList + + 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, session: FirSession ): ParametersMapAndOuterClasses { - var currentClass: FirRegularClass? = null - val outerClasses = mutableListOf() + var currentClassLikeDeclaration: FirClassLikeDeclaration? = null + val outerDeclarations = mutableListOf() // 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() 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, - val outerClasses: List + val outerClasses: List ) 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? { diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt index 91a120b7e92..58bea198c13 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/diagnostics/ConeDiagnostics.kt @@ -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" } diff --git a/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType.fir.kt b/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType.fir.kt index cc100a53247..b0586ac0586 100644 --- a/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType.fir.kt @@ -18,17 +18,17 @@ class Outer { fun test5(x: GenericInnerAlias) = x fun test6(x: GenericInnerAlias) = x } -fun test1(x: Outer.NestedAlias) = x -fun test2(x: Outer.NestedAlias) = x +fun test1(x: Outer.NestedAlias) = x +fun test2(x: Outer.NestedAlias) = x fun test3(x: Outer.NestedAlias) = x -fun test4(x: Outer.GenericNestedAlias) = x -fun test5(x: Outer.GenericNestedAlias) = x -fun test6(x: Outer.GenericNestedAlias) = x +fun test4(x: Outer.GenericNestedAlias) = x +fun test5(x: Outer.GenericNestedAlias) = x +fun test6(x: Outer.GenericNestedAlias) = x fun test7(x: Outer.GenericNestedAlias) = x fun test8(x: Outer.GenericNestedAlias) = x -fun test9(x: Outer.InnerAlias) = x +fun test9(x: Outer.InnerAlias) = x fun test10(x: Outer.InnerAlias) = x fun test11(x: Outer.InnerAlias) = x -fun test12(x: Outer.GenericInnerAlias) = x +fun test12(x: Outer.GenericInnerAlias) = x fun test13(x: Outer.GenericInnerAlias) = x fun test14(x: Outer.GenericInnerAlias) = x diff --git a/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.fir.kt b/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.fir.kt new file mode 100644 index 00000000000..b891a7ddb0b --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.fir.kt @@ -0,0 +1,24 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY + +class C { + inner class D + + typealias DA = D + typealias SDA = C.D + typealias TSDA = C.D + typealias TC = C + typealias SSDA = C<*>.D + typealias SSC = C<*> +} + +fun test1(x: C.DA) = x +fun test2(x: C.SDA) = x +fun test3(x: C.TSDA) = x +fun test4(x: C.TC) = x + +fun test5(x: C<*>.DA) = x +fun test6(x: C<*>.TSDA) = x +fun test7(x: C<*>.TC) = x + +fun test8(x: C.SSDA) = x +fun test9(x: C.SSC) = x diff --git a/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.kt b/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.kt index b395df6be23..f1a2018e98d 100644 --- a/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.kt +++ b/compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY class C { diff --git a/compiler/testData/diagnostics/tests/typealias/kt14518.fir.kt b/compiler/testData/diagnostics/tests/typealias/kt14518.fir.kt index dac0393b6ed..046f7dd03cb 100644 --- a/compiler/testData/diagnostics/tests/typealias/kt14518.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/kt14518.fir.kt @@ -6,5 +6,5 @@ class OuterClass { } typealias ON1 = OuterClass.NestedClass -typealias ON2 = OuterClass.NestedType -typealias ON3 = OuterClass.NestedType +typealias ON2 = OuterClass.NestedType +typealias ON3 = OuterClass.NestedType diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.fir.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.fir.kt deleted file mode 100644 index 9633af61203..00000000000 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.fir.kt +++ /dev/null @@ -1,7 +0,0 @@ -open class Ref(var x: T) - -typealias R = Ref - -// Type inference SHOULD NOT work for type alias constructor in supertypes list -class Test1 : R(0) -class Test2 : R(0) diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.kt index 955d07623f5..1f19a670ebf 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorInferenceInSupertypesList.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open class Ref(var x: T) typealias R = Ref