FIR checker: report TYPE_PARAMETER_AS_REIFIED
This commit is contained in:
committed by
Mikhail Glukhikh
parent
5ba5b63dee
commit
e29b40b07f
+5
-2
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiTypeElement
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
@@ -18,6 +17,7 @@ import org.jetbrains.kotlin.fir.PrivateForInline
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
|
||||
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
|
||||
@@ -247,6 +246,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val TYPE_PARAMETER_IN_CATCH_CLAUSE by error<FirSourceElement, PsiElement>()
|
||||
val GENERIC_THROWABLE_SUBCLASS by error<FirSourceElement, KtTypeParameterList>()
|
||||
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME)
|
||||
|
||||
val TYPE_PARAMETER_AS_REIFIED by error<FirSourceElement, PsiElement> {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
}
|
||||
|
||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||
|
||||
@@ -193,6 +193,7 @@ object FirErrors {
|
||||
val TYPE_PARAMETER_IN_CATCH_CLAUSE by error0<FirSourceElement, PsiElement>()
|
||||
val GENERIC_THROWABLE_SUBCLASS by error0<FirSourceElement, KtTypeParameterList>()
|
||||
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error0<FirSourceElement, KtClassOrObject>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val TYPE_PARAMETER_AS_REIFIED by error1<FirSourceElement, PsiElement, FirTypeParameterSymbol>()
|
||||
|
||||
// Reflection
|
||||
val CALLABLE_REFERENCE_LHS_NOT_A_CLASS by error0<FirSourceElement, KtExpression>()
|
||||
|
||||
+15
-2
@@ -53,6 +53,13 @@ object FirGetClassCallChecker : FirBasicExpressionChecker() {
|
||||
return
|
||||
}
|
||||
|
||||
argument.safeAsTypeParameterSymbol?.let {
|
||||
if (!it.fir.isReified) {
|
||||
// E.g., fun <T: Any> foo(): Any = T::class
|
||||
reporter.reportOn(source, FirErrors.TYPE_PARAMETER_AS_REIFIED, it, context)
|
||||
}
|
||||
}
|
||||
|
||||
if (argument !is FirResolvedQualifier) return
|
||||
// TODO: differentiate RESERVED_SYNTAX_IN_CALLABLE_REFERENCE_LHS
|
||||
if (argument.typeArguments.isNotEmpty() && !argument.typeRef.coneType.isAllowedInClassLiteral(context)) {
|
||||
@@ -71,8 +78,14 @@ object FirGetClassCallChecker : FirBasicExpressionChecker() {
|
||||
get() {
|
||||
return this is FirResolvedQualifier ||
|
||||
this is FirResolvedReifiedParameterReference ||
|
||||
((this is FirQualifiedAccessExpression) &&
|
||||
(this.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol is FirTypeParameterSymbol)
|
||||
safeAsTypeParameterSymbol != null
|
||||
}
|
||||
|
||||
private val FirExpression.safeAsTypeParameterSymbol: FirTypeParameterSymbol?
|
||||
get() {
|
||||
return ((this as? FirQualifiedAccessExpression)
|
||||
?.calleeReference as? FirResolvedNamedReference)
|
||||
?.resolvedSymbol as? FirTypeParameterSymbol
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isAllowedInClassLiteral(context: CheckerContext): Boolean =
|
||||
|
||||
+3
@@ -185,6 +185,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_ARGUMENTS_NO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_ENUM
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION
|
||||
@@ -394,6 +395,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
map.put(REIFIED_TYPE_IN_CATCH_CLAUSE, "Reified type is forbidden for catch parameter")
|
||||
map.put(TYPE_PARAMETER_IN_CATCH_CLAUSE, "Type parameter is forbidden for catch parameter")
|
||||
|
||||
map.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead", SYMBOL)
|
||||
|
||||
// Reflection
|
||||
map.put(CALLABLE_REFERENCE_LHS_NOT_A_CLASS, "Left-hand side of a callable reference cannot be a type parameter")
|
||||
|
||||
|
||||
+2
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.render
|
||||
|
||||
@@ -27,6 +28,7 @@ object FirDiagnosticRenderers {
|
||||
when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
||||
is FirCallableSymbol<*> -> symbol.callableId.toString()
|
||||
is FirTypeParameterSymbol -> symbol.name.asString()
|
||||
else -> "???"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ val l1 = <!NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>List<String>?::class<!>
|
||||
val l2 = <!NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>List?::class<!>
|
||||
|
||||
fun <T : Any> foo() {
|
||||
val t1 = <!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>::class
|
||||
val t1 = <!TYPE_PARAMETER_AS_REIFIED!><!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>::class<!>
|
||||
val t2 = <!NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!><!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>?::class<!>
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
|
||||
fun <T: Any> dereferenceClass(): Any =
|
||||
<!OTHER_ERROR!>T<!>::class
|
||||
<!TYPE_PARAMETER_AS_REIFIED!><!TYPE_PARAMETER_IS_NOT_AN_EXPRESSION!>T<!>::class<!>
|
||||
|
||||
+7
@@ -797,6 +797,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.TYPE_PARAMETER_AS_REIFIED) { firDiagnostic ->
|
||||
TypeParameterAsReifiedImpl(
|
||||
firSymbolBuilder.buildTypeParameterSymbol(firDiagnostic.a.fir as FirTypeParameter),
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CALLABLE_REFERENCE_LHS_NOT_A_CLASS) { firDiagnostic ->
|
||||
CallableReferenceLhsNotAClassImpl(
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
|
||||
+5
@@ -564,6 +564,11 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = InnerClassOfGenericThrowableSubclass::class
|
||||
}
|
||||
|
||||
abstract class TypeParameterAsReified : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = TypeParameterAsReified::class
|
||||
abstract val typeParameter: KtTypeParameterSymbol
|
||||
}
|
||||
|
||||
abstract class CallableReferenceLhsNotAClass : KtFirDiagnostic<KtExpression>() {
|
||||
override val diagnosticClass get() = CallableReferenceLhsNotAClass::class
|
||||
}
|
||||
|
||||
+8
@@ -913,6 +913,14 @@ internal class InnerClassOfGenericThrowableSubclassImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class TypeParameterAsReifiedImpl(
|
||||
override val typeParameter: KtTypeParameterSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.TypeParameterAsReified(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class CallableReferenceLhsNotAClassImpl(
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
|
||||
Reference in New Issue
Block a user