[FIR] Report type-parameterized implicit invoke call over type-parameterized property access

^KT-59988
This commit is contained in:
Evgeniy.Zhelenskiy
2023-11-20 04:59:11 +01:00
committed by Space Team
parent 86c09a1c78
commit f5168527ae
14 changed files with 47 additions and 44 deletions
@@ -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,
)
@@ -1526,6 +1526,7 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
interface TypeArgumentsNotAllowed : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = TypeArgumentsNotAllowed::class
val place: String
}
interface TypeArgumentsForOuterClassWhenNestedReferenced : KtFirDiagnostic<PsiElement> {
@@ -1830,6 +1830,7 @@ internal class UpperBoundViolatedInTypealiasExpansionImpl(
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.UpperBoundViolatedInTypealiasExpansion
internal class TypeArgumentsNotAllowedImpl(
override val place: String,
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.TypeArgumentsNotAllowed
@@ -6,15 +6,15 @@ FILE: typeArgumentsNotAllowed.kt
super<R|kotlin/Any|>()
}
public abstract val x: <ERROR TYPE REF: Type arguments not allowed>
public get(): <ERROR TYPE REF: Type arguments not allowed>
public abstract val x: <ERROR TYPE REF: Type arguments not allowed for type parameters>
public get(): <ERROR TYPE REF: Type arguments not allowed for type parameters>
public abstract fun foo(): <ERROR TYPE REF: Type arguments not allowed>
public abstract fun foo(): <ERROR TYPE REF: Type arguments not allowed for type parameters>
}
public final fun <T> foo(): R|kotlin/Unit| {
R|rest/bar<Inapplicable(INAPPLICABLE): rest/bar>#|<<ERROR TYPE REF: Type arguments not allowed>>()
R|rest/bar|<R|kotlin/collections/List<kotlin/collections/List<ERROR CLASS: Type arguments not allowed>>|>()
R|rest/bar<Inapplicable(INAPPLICABLE): rest/bar>#|<<ERROR TYPE REF: Type arguments not allowed for type parameters>>()
R|rest/bar|<R|kotlin/collections/List<kotlin/collections/List<ERROR CLASS: Type arguments not allowed for type parameters>>|>()
}
public final fun <T> bar(): R|kotlin/Unit| {
}
@@ -43,9 +43,9 @@ FILE: typeArgumentsNotAllowed.kt
public final fun <G> gest(): R|kotlin/Unit| {
}
public final fun <T> fest(): R|kotlin/Unit| {
lval b: R|kotlin/collections/List<ERROR CLASS: Type arguments not allowed>|
R|rest/gest<Inapplicable(INAPPLICABLE): rest/gest>#|<<ERROR TYPE REF: Type arguments not allowed>>()
lval b: R|kotlin/collections/List<ERROR CLASS: Type arguments not allowed for type parameters>|
R|rest/gest<Inapplicable(INAPPLICABLE): rest/gest>#|<<ERROR TYPE REF: Type arguments not allowed for type parameters>>()
R|rest/gest|<R|T|>()
lval c: R|kotlin/collections/List<kotlin/collections/List<kotlin/collections/List<ERROR CLASS: Type arguments not allowed>>>|
R|rest/gest|<R|kotlin/collections/List<kotlin/collections/List<ERROR CLASS: Type arguments not allowed>>|>()
lval c: R|kotlin/collections/List<kotlin/collections/List<kotlin/collections/List<ERROR CLASS: Type arguments not allowed for type parameters>>>|
R|rest/gest|<R|kotlin/collections/List<kotlin/collections/List<ERROR CLASS: Type arguments not allowed for type parameters>>|>()
}
@@ -52,7 +52,7 @@ fun f4() {
receiver.hello1
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello1<!><Int>
receiver.hello1<Int, String>() // legal `String.invoke` call
receiver.<!TYPE_ARGUMENTS_NOT_ALLOWED!>hello1<!><Int, String>()
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello1<!><String>
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello1<!><Int, String>
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello1<!><Int, String, String>
@@ -60,14 +60,14 @@ fun f4() {
with (ContextImpl<String>()) {
hello2
<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello2<!><String>
hello2<String, Int>() // legal `String.invoke` call
<!TYPE_ARGUMENTS_NOT_ALLOWED!>hello2<!><String, Int>()
<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello2<!><Int>
<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello2<!><String, Int>
<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello2<!><String, Int, Int>
receiver.hello3
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello3<!><Int, String>
receiver.hello3<Int, String>() // legal `String.invoke` call
receiver.<!TYPE_ARGUMENTS_NOT_ALLOWED!>hello3<!><Int, String>()
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello3<!><String, Int>
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello3<!><Int>
receiver.<!EXPLICIT_TYPE_ARGUMENTS_IN_PROPERTY_ACCESS!>hello3<!><Int, String, String>
@@ -690,7 +690,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<ConeKotlinType>("expectedUpperBound")
parameter<ConeKotlinType>("actualUpperBound")
}
val TYPE_ARGUMENTS_NOT_ALLOWED by error<PsiElement>()
val TYPE_ARGUMENTS_NOT_ALLOWED by error<PsiElement> {
parameter<String>("place")
}
val TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED by error<PsiElement>()
val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error<PsiElement> {
parameter<Int>("expectedCount")
@@ -422,7 +422,7 @@ object FirErrors {
val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error0<PsiElement>()
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 TYPE_ARGUMENTS_NOT_ALLOWED by error1<PsiElement, String>()
val TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED 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<*>>()
@@ -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
}
}
}
@@ -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(
@@ -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 ->
@@ -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
}
@@ -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) {
@@ -1,13 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// ISSUE: KT-40396
val <C> C.foo get() = Foo<C>()
class Foo<K> {
operator fun <T> invoke(body: () -> Unit) {}
}
class Bar {
val bar = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!> {}
val baz = foo<Int> {}
}
+2 -1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
// ISSUE: KT-40396
@@ -10,4 +11,4 @@ class Foo<K> {
class Bar {
val bar = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!> {}
val baz = <!TYPE_ARGUMENTS_NOT_ALLOWED!>foo<!><Int> {}
}
}