From 66e2b4427276a50fec65967e87e01e92b20de988 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Mon, 14 Jun 2021 16:19:21 +0300 Subject: [PATCH] [FIR] Implement UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION diagnostics, fix handling of UPPER_BOUND_VIOLATED --- .../resolve/diagnostics/upperBoundViolated.kt | 2 +- .../resolveWithStdlib/problems/EnumMapGet.kt | 4 +- .../diagnostics/FirDiagnosticsList.kt | 7 +- .../fir/analysis/diagnostics/FirErrors.kt | 3 +- .../fir/analysis/checkers/FirHelpers.kt | 10 +- .../declaration/FirClassVarianceChecker.kt | 8 +- .../FirProjectionRelationChecker.kt | 8 +- .../FirUpperBoundViolatedChecker.kt | 111 ++++++++++++------ .../diagnostics/FirDefaultErrorMessages.kt | 10 +- .../fir/resolve/substitution/Substitutors.kt | 1 + ...oundViolationInTypeAliasConstructor.fir.kt | 8 +- ...dsViolationInDeepTypeAliasExpansion.fir.kt | 16 --- ...boundsViolationInDeepTypeAliasExpansion.kt | 1 + ...boundsViolationInTypeAliasExpansion.fir.kt | 12 +- .../boundsViolationInTypeAliasRHS.fir.kt | 16 +-- .../tests/typealias/kt19601.fir.kt | 2 +- ...erOfArgumentsInTypeAliasConstructor.fir.kt | 2 +- .../diagnostics/KtFirDataClassConverters.kt | 9 ++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 9 +- .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 12 +- 20 files changed, 162 insertions(+), 89 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/upperBoundViolated.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/upperBoundViolated.kt index 3175b732681..d1904da748e 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/upperBoundViolated.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/upperBoundViolated.kt @@ -45,7 +45,7 @@ fun rest() { class NumColl> typealias NL = NumColl> val test7 = NL()NumberPhile -val test8 = NL() +val test8 = NL<String>() class NumberPhile(x: T) val np1 = NumberPhile(10) diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/EnumMapGet.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/EnumMapGet.kt index 37dab26554f..9337e96fe1c 100644 --- a/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/EnumMapGet.kt +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/EnumMapGet.kt @@ -2,8 +2,8 @@ import java.util.EnumMap -typealias SomeEnumMap = EnumMap +typealias SomeEnumMap = EnumMap<String, String?> fun test(map: SomeEnumMap, qualifier: String?) { val result = map[qualifier] -} \ No newline at end of file +} 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 8a561cd8409..4d4d13f2729 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 @@ -402,7 +402,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val INFERENCE_ERROR by error() val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error() val UPPER_BOUND_VIOLATED by error { - parameter("upperBound") + parameter("expectedUpperBound") + parameter("actualUpperBound") + } + val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION by error { + parameter("expectedUpperBound") + parameter("actualUpperBound") } val TYPE_ARGUMENTS_NOT_ALLOWED by error() val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error { 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 3e404736cdf..55a2bdcf822 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 @@ -282,7 +282,8 @@ object FirErrors { val RECURSION_IN_IMPLICIT_TYPES by error0() val INFERENCE_ERROR by error0() val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error0() - val UPPER_BOUND_VIOLATED by error1() + 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 NO_TYPE_ARGUMENTS_ON_RHS by error2>() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 71d959187fd..b1d37e19e46 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -581,7 +581,7 @@ internal fun checkCondition(condition: FirExpression, context: CheckerContext, r } } -fun extractTypeRefAndSourceFromTypeArgument(typeRef: FirTypeRef?, index: Int): Pair? { +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?) \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt index 57ba73c4080..602facfd0d4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirClassVarianceChecker.kt @@ -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 ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt index 362a8c5ab4e..3f1cf86c401 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirProjectionRelationChecker.kt @@ -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) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt index 6243b7ef12a..6b38ec805d4 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedChecker.kt @@ -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? = null + var typeArgumentRefsAndSources: List? = 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() + 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? = null, - typeArguments: List? = null + typeArguments: List? = null, + typeArgumentRefsAndSources: List? = 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() ?: 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) -} +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 3911cf3eb35..b12ecadfe31 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -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, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt index ba03eca5cbc..5a7cc7d9cc9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/substitution/Substitutors.kt @@ -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 } diff --git a/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.fir.kt b/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.fir.kt index 1d587359492..c8a6567a2f2 100644 --- a/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/boundViolationInTypeAliasConstructor.fir.kt @@ -4,8 +4,8 @@ typealias N = Num typealias N2 = N val x1 = Num<String>("") -val x2 = N("") -val x3 = N2("") +val x2 = N<String>("") +val x3 = N2<String>("") class TColl> @@ -13,5 +13,5 @@ typealias TC = TColl typealias TC2 = TC val y1 = TCollAny>() -val y2 = TC() -val y3 = TC2() +val y2 = TCAny>() +val y3 = TC2Any>() diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.fir.kt b/compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.fir.kt deleted file mode 100644 index a597dc04782..00000000000 --- a/compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER - -class TColl> - -typealias TC = TColl -typealias TC2 = TC - -fun test1(x: TC2>) {} -fun test2(x: TC2>) {} -fun test3(x: TC2>) {} -fun test4(x: TC2>) {} - -val test5 = TC2>() -val test6 = TC2>() -val test7 = TC2>() -val test8 = TC2>() diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.kt b/compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.kt index ad38c5b85db..c28152b7ac1 100644 --- a/compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.kt +++ b/compiler/testData/diagnostics/tests/typealias/boundsViolationInDeepTypeAliasExpansion.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER class TColl> diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.fir.kt b/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.fir.kt index 0f44913f3b9..e2b8b801c57 100644 --- a/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.fir.kt @@ -10,22 +10,22 @@ typealias MMMM = NL typealias TC = TColl fun test1(x: NA) {} -fun test2(x: NA) {} +fun test2(x: NA) {} fun test3(x: NL) {} -fun test4(x: NL) {} +fun test4(x: NL) {} val test5 = NA() -val test6 = NA() +val test6 = NA<Any>() val test7 = NL() val test8 = MMMM() -val test9dwd = NL() +val test9dwd = NL<Any>() fun test9(x: TC>) {} fun test10(x: TC>) {} fun test11(x: TC>) {} -fun test12(x: TC>) {} +fun test12(x: TC>) {} val test13 = TC>() val test14 = TC>() val test15 = TC>() -val test16 = TC>() +val test16 = TCList>() diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasRHS.fir.kt b/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasRHS.fir.kt index 7d71da84dce..09485f45348 100644 --- a/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasRHS.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasRHS.fir.kt @@ -3,18 +3,18 @@ class TC> typealias TCAlias = TC -typealias TCAliasT = TC +typealias TCAliasT = TCAny> typealias TCAliasC = TC -typealias TCAliasT1 = TCAlias +typealias TCAliasT1 = TCAlias typealias TCAliasC1 = TCAlias -typealias Test1 = TC +typealias Test1 = TCAny> typealias Test2 = TC> -typealias Test3 = TCAlias +typealias Test3 = TCAlias typealias Test4 = TCAlias> -typealias Test5 = TCAliasT -typealias Test6 = TCAliasC +typealias Test5 = TCAliasT +typealias Test6 = TCAliasC typealias Test7 = TCAliasC> -typealias Test8 = TCAliasT1 -typealias Test9 = TCAliasC1 +typealias Test8 = TCAliasT1 +typealias Test9 = TCAliasC1 typealias Test10 = TCAliasC1> diff --git a/compiler/testData/diagnostics/tests/typealias/kt19601.fir.kt b/compiler/testData/diagnostics/tests/typealias/kt19601.fir.kt index 324ac3752e4..7d01bb10612 100644 --- a/compiler/testData/diagnostics/tests/typealias/kt19601.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/kt19601.fir.kt @@ -8,4 +8,4 @@ interface Num typealias N = Num -class Test2> \ No newline at end of file +class Test2N> diff --git a/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.fir.kt b/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.fir.kt index 6082beca0e4..1294e041f74 100644 --- a/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/wrongNumberOfArgumentsInTypeAliasConstructor.fir.kt @@ -30,7 +30,7 @@ typealias N = Num val testN0 = N("") val testN1 = N(1) -val testN1a = N("") +val testN1a = N<String>("") val testN2 = N(1) class MyPair(val string: T1, val number: T2) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 3fa0e8b5e40..da919c98c06 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -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, ) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 3d131387e57..4f7a52ef261 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -872,7 +872,14 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract class UpperBoundViolated : KtFirDiagnostic() { override val diagnosticClass get() = UpperBoundViolated::class - abstract val upperBound: KtType + abstract val expectedUpperBound: KtType + abstract val actualUpperBound: KtType + } + + abstract class UpperBoundViolatedInTypealiasExpansion : KtFirDiagnostic() { + override val diagnosticClass get() = UpperBoundViolatedInTypealiasExpansion::class + abstract val expectedUpperBound: KtType + abstract val actualUpperBound: KtType } abstract class TypeArgumentsNotAllowed : KtFirDiagnostic() { diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 0e224e41b0f..b4fed17713e 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -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 { 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 { + override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic) +} + internal class TypeArgumentsNotAllowedImpl( firDiagnostic: FirPsiDiagnostic, override val token: ValidityToken,