[FIR] Implement REIFIED_TYPE_FORBIDDEN_SUBSTITUTION
This commit is contained in:
committed by
teamcityserver
parent
bade6cb611
commit
173813f7cf
+4
@@ -491,6 +491,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
val REIFIED_TYPE_FORBIDDEN_SUBSTITUTION by error<PsiElement> {
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
|
||||
val FINAL_UPPER_BOUND by warning<KtTypeReference> {
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
|
||||
@@ -321,6 +321,7 @@ object FirErrors {
|
||||
val TYPE_PARAMETER_AS_REIFIED by error1<PsiElement, FirTypeParameterSymbol>()
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY by error1<PsiElement, FirTypeParameterSymbol>()
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING by warning1<PsiElement, FirTypeParameterSymbol>()
|
||||
val REIFIED_TYPE_FORBIDDEN_SUBSTITUTION by error1<PsiElement, ConeKotlinType>()
|
||||
val FINAL_UPPER_BOUND by warning1<KtTypeReference, ConeKotlinType>()
|
||||
val UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE by error0<KtTypeReference>()
|
||||
val BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER by error0<KtElement>()
|
||||
|
||||
+1
-3
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirAnonymousFunctionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.syntax.FirAnonymousFunctionSyntaxChecker
|
||||
|
||||
object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
override val annotationCallCheckers: Set<FirAnnotationCallChecker>
|
||||
@@ -43,7 +41,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirSealedClassConstructorCallChecker,
|
||||
FirUninitializedEnumChecker,
|
||||
FirFunInterfaceConstructorReferenceChecker,
|
||||
FirTypeParameterAsReifiedChecker
|
||||
FirReifiedChecker
|
||||
)
|
||||
|
||||
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
||||
|
||||
+10
-3
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
object FirTypeParameterAsReifiedChecker : FirQualifiedAccessExpressionChecker() {
|
||||
object FirReifiedChecker : FirQualifiedAccessExpressionChecker() {
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val calleReference = expression.calleeReference
|
||||
val typeArguments = expression.typeArguments
|
||||
@@ -33,13 +33,13 @@ object FirTypeParameterAsReifiedChecker : FirQualifiedAccessExpressionChecker()
|
||||
val typeArgument = typeArgumentProjection.toConeTypeProjection().type
|
||||
val typeParameter = typeParameters[index]
|
||||
|
||||
if (source != null && (typeParameter.isTypeParameterOfKotlinArray())) {
|
||||
if (source != null && typeParameter.isReifiedTypeParameterOrFromKotlinArray()) {
|
||||
checkArgumentAndReport(typeArgument, source, false, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirTypeParameterSymbol.isTypeParameterOfKotlinArray(): Boolean {
|
||||
private fun FirTypeParameterSymbol.isReifiedTypeParameterOrFromKotlinArray(): Boolean {
|
||||
val containingDeclaration = containingDeclarationSymbol
|
||||
return isReified ||
|
||||
containingDeclaration is FirRegularClassSymbol && containingDeclaration.classId == StandardClassIds.Array
|
||||
@@ -69,10 +69,17 @@ object FirTypeParameterAsReifiedChecker : FirQualifiedAccessExpressionChecker()
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED
|
||||
}
|
||||
symbol = typeArgument.toSymbol(context.session) as FirTypeParameterSymbol
|
||||
} else if (typeArgument != null && typeArgument.cannotBeReified()) {
|
||||
reporter.reportOn(source, FirErrors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, typeArgument, context)
|
||||
return
|
||||
}
|
||||
|
||||
if (factory != null && !symbol.isReified) {
|
||||
reporter.reportOn(source, factory, symbol, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.cannotBeReified(): Boolean {
|
||||
return this.isNothing || this.isNullableNothing || this is ConeCapturedType
|
||||
}
|
||||
}
|
||||
+6
@@ -320,6 +320,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_RETURN_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SETTER_PARAMETER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_VISIBILITY_MODIFIER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REIFIED_TYPE_PARAMETER_NO_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_BOUND
|
||||
@@ -794,6 +795,11 @@ class FirDefaultErrorMessages {
|
||||
"Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
REIFIED_TYPE_FORBIDDEN_SUBSTITUTION,
|
||||
"Cannot use ''{0}'' as reified type parameter",
|
||||
RENDER_TYPE
|
||||
)
|
||||
map.put(
|
||||
FINAL_UPPER_BOUND,
|
||||
"''{0}'' is a final type, and thus a value of the type parameter is predetermined",
|
||||
|
||||
+3
-3
@@ -24,9 +24,9 @@ fun <T> test(x: T) {
|
||||
|
||||
baz<Int, String?>(<!NULL_FOR_NONNULL_TYPE!>null<!>, null, ::foo)
|
||||
baz<Int?, String>(null, <!NULL_FOR_NONNULL_TYPE!>null<!>, ::foo)
|
||||
baz(null, "", ::foo)
|
||||
baz(1, null, ::foo)
|
||||
baz(null, null, ::foo)
|
||||
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>baz<!>(null, "", ::foo)
|
||||
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>baz<!>(1, null, ::foo)
|
||||
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>baz<!>(null, null, ::foo)
|
||||
|
||||
val s3: Pair<Int, String?> = <!TYPE_MISMATCH, TYPE_MISMATCH!>bar(null, null, ::foo)<!>
|
||||
val s4: Pair<Int?, String> = <!INITIALIZER_TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>bar(null, null, ::foo)<!>
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ fun test1() {
|
||||
val f2: Foo<in Nothing> = foo1 { it checkType { _<Nothing>() } }
|
||||
|
||||
val f3: Foo<out Int> = foo2 { it checkType { _<Int>() } }
|
||||
val f4: Foo<in Nothing> = foo2 { it checkType { _<Nothing>() } }
|
||||
}
|
||||
val f4: Foo<in Nothing> = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>foo2<!> { it checkType { _<Nothing>() } }
|
||||
}
|
||||
|
||||
+3
-3
@@ -22,7 +22,7 @@ fun test2() {
|
||||
}
|
||||
|
||||
fun test3() {
|
||||
takeReifiedUnbound(null)
|
||||
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>takeReifiedUnbound<!>(null)
|
||||
}
|
||||
|
||||
fun test4(): Bound = takeReifiedUnbound(null)
|
||||
@@ -35,7 +35,7 @@ fun test5(): Bound? = select(
|
||||
fun test6() {
|
||||
select(
|
||||
null,
|
||||
materializeReified()
|
||||
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>materializeReified<!>()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -48,6 +48,6 @@ fun test7(): Bound? =
|
||||
fun test8() {
|
||||
select(
|
||||
null,
|
||||
materializeReifiedUnbound()
|
||||
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>materializeReifiedUnbound<!>()
|
||||
)
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -28,7 +28,7 @@ inline fun <reified T : In<T>> testIn(): T {
|
||||
// Unexpected behaviour
|
||||
inline fun <reified T : Out<T>> testOut(): T {
|
||||
return try {
|
||||
outBound()
|
||||
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>outBound<!>()
|
||||
} catch (ex: Exception) {
|
||||
throw Exception()
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ fun test4(
|
||||
) {}
|
||||
|
||||
fun test5() {
|
||||
arrayOf<Nothing>()
|
||||
Array<Nothing>(10) { throw Exception() }
|
||||
arrayOf<<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing<!>>()
|
||||
Array<<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing<!>>(10) { throw Exception() }
|
||||
}
|
||||
|
||||
fun <T> foo(): Array<T> = (object {} as Any) as Array<T>
|
||||
|
||||
+6
-6
@@ -5,12 +5,12 @@ inline fun<reified T> foo(block: () -> T): String = block().toString()
|
||||
inline fun <reified T: Any> javaClass(): Class<T> = T::class.java
|
||||
|
||||
fun box() {
|
||||
val a = arrayOf(null!!)
|
||||
val b = Array<Nothing?>(5) { null!! }
|
||||
val c = foo() { null!! }
|
||||
val a = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>arrayOf<!>(null!!)
|
||||
val b = Array<<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing?<!>>(5) { null!! }
|
||||
val c = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>foo<!>() { null!! }
|
||||
val d = foo<Any> { null!! }
|
||||
val e = foo { "1" as Nothing }
|
||||
val e1 = foo { "1" as Nothing? }
|
||||
val e = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>foo<!> { "1" as Nothing }
|
||||
val e1 = <!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>foo<!> { "1" as Nothing? }
|
||||
|
||||
val f = javaClass<Nothing>()
|
||||
val f = javaClass<<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>Nothing<!>>()
|
||||
}
|
||||
|
||||
+7
@@ -1454,6 +1454,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.REIFIED_TYPE_FORBIDDEN_SUBSTITUTION) { firDiagnostic ->
|
||||
ReifiedTypeForbiddenSubstitutionImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.FINAL_UPPER_BOUND) { firDiagnostic ->
|
||||
FinalUpperBoundImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
|
||||
+5
@@ -1034,6 +1034,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val typeParameter: KtTypeParameterSymbol
|
||||
}
|
||||
|
||||
abstract class ReifiedTypeForbiddenSubstitution : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = ReifiedTypeForbiddenSubstitution::class
|
||||
abstract val type: KtType
|
||||
}
|
||||
|
||||
abstract class FinalUpperBound : KtFirDiagnostic<KtTypeReference>() {
|
||||
override val diagnosticClass get() = FinalUpperBound::class
|
||||
abstract val type: KtType
|
||||
|
||||
+8
@@ -1659,6 +1659,14 @@ internal class TypeParameterAsReifiedArrayWarningImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ReifiedTypeForbiddenSubstitutionImpl(
|
||||
override val type: KtType,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ReifiedTypeForbiddenSubstitution(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class FinalUpperBoundImpl(
|
||||
override val type: KtType,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
|
||||
Reference in New Issue
Block a user