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 87d7d694452..9d3a54953ac 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 @@ -2141,6 +2141,7 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert } add(FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED) { firDiagnostic -> TypeArgumentsNotAllowedImpl( + firDiagnostic.a, firDiagnostic as KtPsiDiagnostic, token, ) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index de820658657..fe1609d1118 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1526,6 +1526,7 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { interface TypeArgumentsNotAllowed : KtFirDiagnostic { override val diagnosticClass get() = TypeArgumentsNotAllowed::class + val place: String } interface TypeArgumentsForOuterClassWhenNestedReferenced : KtFirDiagnostic { diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 3a54ab44e2d..c431ac2638b 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1830,6 +1830,7 @@ internal class UpperBoundViolatedInTypealiasExpansionImpl( ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.UpperBoundViolatedInTypealiasExpansion internal class TypeArgumentsNotAllowedImpl( + override val place: String, firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.TypeArgumentsNotAllowed diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/typeArgumentsNotAllowed.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/typeArgumentsNotAllowed.fir.txt index f26b998783f..6320d0b4adc 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/typeArgumentsNotAllowed.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/typeArgumentsNotAllowed.fir.txt @@ -6,15 +6,15 @@ FILE: typeArgumentsNotAllowed.kt super() } - public abstract val x: - public get(): + public abstract val x: + public get(): - public abstract fun foo(): + public abstract fun foo(): } public final fun foo(): R|kotlin/Unit| { - R|rest/bar#|<>() - R|rest/bar|>|>() + R|rest/bar#|<>() + R|rest/bar|>|>() } public final fun bar(): R|kotlin/Unit| { } @@ -43,9 +43,9 @@ FILE: typeArgumentsNotAllowed.kt public final fun gest(): R|kotlin/Unit| { } public final fun fest(): R|kotlin/Unit| { - lval b: R|kotlin/collections/List| - R|rest/gest#|<>() + lval b: R|kotlin/collections/List| + R|rest/gest#|<>() R|rest/gest|() - lval c: R|kotlin/collections/List>>| - R|rest/gest|>|>() + lval c: R|kotlin/collections/List>>| + R|rest/gest|>|>() } diff --git a/compiler/fir/analysis-tests/testData/resolve/expresssions/propertyAccessWithExplicitTypeArguments.kt b/compiler/fir/analysis-tests/testData/resolve/expresssions/propertyAccessWithExplicitTypeArguments.kt index 13379db3428..2bcfcc3a844 100644 --- a/compiler/fir/analysis-tests/testData/resolve/expresssions/propertyAccessWithExplicitTypeArguments.kt +++ b/compiler/fir/analysis-tests/testData/resolve/expresssions/propertyAccessWithExplicitTypeArguments.kt @@ -52,7 +52,7 @@ fun f4() { receiver.hello1 receiver.hello1 - receiver.hello1() // legal `String.invoke` call + receiver.hello1() receiver.hello1 receiver.hello1 receiver.hello1 @@ -60,14 +60,14 @@ fun f4() { with (ContextImpl()) { hello2 hello2 - hello2() // legal `String.invoke` call + hello2() hello2 hello2 hello2 receiver.hello3 receiver.hello3 - receiver.hello3() // legal `String.invoke` call + receiver.hello3() receiver.hello3 receiver.hello3 receiver.hello3 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 266b9f56b4e..7ac3afa183a 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 @@ -690,7 +690,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("expectedUpperBound") parameter("actualUpperBound") } - val TYPE_ARGUMENTS_NOT_ALLOWED by error() + val TYPE_ARGUMENTS_NOT_ALLOWED by error { + parameter("place") + } val TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED by error() val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error { parameter("expectedCount") 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 059c057763e..eea1bea415a 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 @@ -422,7 +422,7 @@ object FirErrors { val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error0() val UPPER_BOUND_VIOLATED by error2() val UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION by error2() - val TYPE_ARGUMENTS_NOT_ALLOWED by error0() + val TYPE_ARGUMENTS_NOT_ALLOWED by error1() val TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED 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/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt index 134efe776b3..e9f6565d101 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirTypeArgumentsNotAllowedExpressionChecker.kt @@ -5,24 +5,34 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression -import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors +import org.jetbrains.kotlin.fir.expressions.FirImplicitInvokeCall +import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier +import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessExpressionChecker() { override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) { // analyze type parameters near // package names val explicitReceiver = expression.explicitReceiver + if (explicitReceiver is FirResolvedQualifier && explicitReceiver.symbol == null && explicitReceiver.typeArguments.isNotEmpty()) { + reporter.reportOn(explicitReceiver.source, FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED, "for packages", context) + return + } - if (explicitReceiver is FirResolvedQualifier && explicitReceiver.symbol == null) { - if (explicitReceiver.typeArguments.isNotEmpty()) { - reporter.reportOn(explicitReceiver.source, FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED, context) - return - } + if ( + expression is FirImplicitInvokeCall && explicitReceiver is FirPropertyAccessExpression && + expression.typeArguments.any { it.source != null } && + expression.toResolvedCallableSymbol()?.typeParameterSymbols?.isNotEmpty() == true && + explicitReceiver.toResolvedCallableSymbol()?.typeParameterSymbols?.isNotEmpty() == true + ) { + reporter.reportOn(expression.calleeReference.source, FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED, "on implicit invoke call", context) + return } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index cc09c195470..2d16113c160 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -33,8 +33,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.MODU import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME_OF_CONTAINING_DECLARATION_OR_FILE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME_OF_DECLARATION_OR_FILE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.OPTIONAL_SENTENCE -import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT_QUOTED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT_NAME_QUOTED +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT_QUOTED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_COLLECTION_OF_TYPES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_ENUM_ENTRY_QUOTED import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE @@ -1299,7 +1299,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { RENDER_TYPE ) - map.put(TYPE_ARGUMENTS_NOT_ALLOWED, "Type parameters cannot be parameterized with type arguments.") // * + map.put(TYPE_ARGUMENTS_NOT_ALLOWED, "Type arguments are not allowed {0}.", STRING) map.put(TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED, "Type arguments for outer class are redundant when nested class is referenced") val wrongNumberOfTypeArguments = "{0,choice,0#No type arguments|1#One type argument|1<{0,number,integer} type arguments} expected" map.put( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 0298166094a..cfd4ec1854b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -119,12 +119,12 @@ private fun ConeDiagnostic.toKtDiagnostic( is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.createOn(source, this.candidateSymbols) is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.createOn(source) - is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source ?: source) + is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source ?: source, "for type parameters") is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.createOn(source, this.name.asString()) is ConeWrongNumberOfTypeArgumentsError -> FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.createOn(this.source, this.desiredCount, this.symbol) - is ConeTypeArgumentsNotAllowedError -> - FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source) + is ConeTypeArgumentsNotAllowedOnPackageError -> + FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source, "for packages") is ConeTypeArgumentsForOuterClassWhenNestedReferencedError -> FirErrors.TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED.createOn(this.source) is ConeNestedClassAccessedViaInstanceReference -> 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 48407b72d2d..af10bd548cd 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 @@ -251,7 +251,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { for (part in typeRef.qualifier) { if (part.typeArgumentList.typeArguments.isNotEmpty()) { return ConeErrorType( - ConeUnexpectedTypeArgumentsError("Type arguments not allowed", part.typeArgumentList.source), + ConeUnexpectedTypeArgumentsError("Type arguments not allowed for type parameters", part.typeArgumentList.source), typeArguments = resultingArguments ) } @@ -289,7 +289,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { if (currentDeclaration == null) { // It's a package name if (qualifierPartArgsCount > 0) { - return ConeTypeArgumentsNotAllowedError(typeArgumentList.source!!) + return ConeTypeArgumentsNotAllowedOnPackageError(typeArgumentList.source!!) } break } 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 ca80739192c..2cb6b7b3b83 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 @@ -264,8 +264,8 @@ class ConeWrongNumberOfTypeArgumentsError( override val reason: String get() = "Wrong number of type arguments" } -class ConeTypeArgumentsNotAllowedError(source: KtSourceElement) : ConeDiagnosticWithSource(source) { - override val reason: String get() = "Type parameters cannot be parameterized with type arguments" +class ConeTypeArgumentsNotAllowedOnPackageError(source: KtSourceElement) : ConeDiagnosticWithSource(source) { + override val reason: String get() = "Type arguments are not allowed for packages" } class ConeTypeArgumentsForOuterClassWhenNestedReferencedError(source: KtSourceElement) : ConeDiagnosticWithSource(source) { diff --git a/compiler/testData/diagnostics/tests/inference/kt40396.fir.kt b/compiler/testData/diagnostics/tests/inference/kt40396.fir.kt deleted file mode 100644 index ae1f52903de..00000000000 --- a/compiler/testData/diagnostics/tests/inference/kt40396.fir.kt +++ /dev/null @@ -1,13 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER -// ISSUE: KT-40396 - -val C.foo get() = Foo() - -class Foo { - operator fun invoke(body: () -> Unit) {} -} - -class Bar { - val bar = foo {} - val baz = foo {} -} diff --git a/compiler/testData/diagnostics/tests/inference/kt40396.kt b/compiler/testData/diagnostics/tests/inference/kt40396.kt index 5b9fe4df45a..424cea76f9f 100644 --- a/compiler/testData/diagnostics/tests/inference/kt40396.kt +++ b/compiler/testData/diagnostics/tests/inference/kt40396.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER // ISSUE: KT-40396 @@ -10,4 +11,4 @@ class Foo { class Bar { val bar = foo {} val baz = foo {} -} \ No newline at end of file +}