[FIR] Add DNN checks
Merge-request: KT-MR-7000 Merged-by: Nikolay Lunyak <lunyak.kolya@mail.ru>
This commit is contained in:
+4
@@ -705,6 +705,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<String>("description")
|
||||
parameter<String>("causingTypes")
|
||||
}
|
||||
|
||||
val INCORRECT_LEFT_COMPONENT_OF_INTERSECTION by error<KtTypeReference>()
|
||||
val INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION by error<KtTypeReference>()
|
||||
val NULLABLE_ON_DEFINITELY_NOT_NULLABLE by error<KtTypeReference>()
|
||||
}
|
||||
|
||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||
|
||||
@@ -417,6 +417,9 @@ object FirErrors {
|
||||
val PLATFORM_CLASS_MAPPED_TO_KOTLIN by warning1<PsiElement, FqName>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error4<PsiElement, String, Collection<ConeKotlinType>, String, String>()
|
||||
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning4<PsiElement, String, Collection<ConeKotlinType>, String, String>()
|
||||
val INCORRECT_LEFT_COMPONENT_OF_INTERSECTION by error0<KtTypeReference>()
|
||||
val INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION by error0<KtTypeReference>()
|
||||
val NULLABLE_ON_DEFINITELY_NOT_NULLABLE by error0<KtTypeReference>()
|
||||
|
||||
// Reflection
|
||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ object CommonTypeCheckers : TypeCheckers() {
|
||||
FirTypeAnnotationChecker,
|
||||
FirSuspendModifierChecker,
|
||||
FirDeprecatedTypeChecker,
|
||||
FirOptInUsageTypeRefChecker
|
||||
FirOptInUsageTypeRefChecker,
|
||||
FirDefinitelyNotNullableChecker,
|
||||
)
|
||||
}
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.type
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
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.types.*
|
||||
|
||||
object FirDefinitelyNotNullableChecker : FirTypeRefChecker() {
|
||||
override fun check(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val intersection = (typeRef as? FirResolvedTypeRef)?.delegatedTypeRef as? FirIntersectionTypeRef ?: return
|
||||
|
||||
if (intersection.isMarkedNullable) {
|
||||
reporter.reportOn(intersection.source, FirErrors.NULLABLE_ON_DEFINITELY_NOT_NULLABLE, context)
|
||||
}
|
||||
|
||||
if (!intersection.isLeftValidForDefinitelyNotNullable) {
|
||||
reporter.reportOn(intersection.leftType.source, FirErrors.INCORRECT_LEFT_COMPONENT_OF_INTERSECTION, context)
|
||||
}
|
||||
|
||||
if (!intersection.isRightValidForDefinitelyNotNullable) {
|
||||
reporter.reportOn(intersection.rightType.source, FirErrors.INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
@@ -252,6 +252,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCONSISTENT_TYPE_PARAMETER_BOUNDS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCONSISTENT_TYPE_PARAMETER_VALUES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_CHARACTER_LITERAL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_LEFT_COMPONENT_OF_INTERSECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INC_DEC_SHOULD_NOT_RETURN_UNIT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_UNSUCCESSFUL_FORK
|
||||
@@ -359,6 +361,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_TYPE_ARGUMENTS_ON_RHS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_VALUE_FOR_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_INLINE_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_ON_DEFINITELY_NOT_NULLABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER
|
||||
@@ -982,6 +985,18 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
TO_STRING,
|
||||
TO_STRING
|
||||
)
|
||||
map.put(
|
||||
NULLABLE_ON_DEFINITELY_NOT_NULLABLE,
|
||||
"'!!' type cannot be marked as nullable"
|
||||
)
|
||||
map.put(
|
||||
INCORRECT_LEFT_COMPONENT_OF_INTERSECTION,
|
||||
"Intersection types are only supported for definitely non-nullable types: left part should be a type parameter with nullable bounds"
|
||||
)
|
||||
map.put(
|
||||
INCORRECT_RIGHT_COMPONENT_OF_INTERSECTION,
|
||||
"Intersection types are only supported for definitely non-nullable types: right part should be non-nullable Any"
|
||||
)
|
||||
|
||||
map.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", TO_STRING, TO_STRING, NOT_RENDERED)
|
||||
map.put(THROWABLE_TYPE_MISMATCH, "Throwable type mismatch: actual type is {0}", TO_STRING, NOT_RENDERED)
|
||||
|
||||
+1
@@ -128,6 +128,7 @@ private fun ConeDiagnostic.toKtDiagnostic(
|
||||
is ConeLocalVariableNoTypeOrInitializer -> runIf(variable.isLocalMember) {
|
||||
FirErrors.VARIABLE_WITH_NO_TYPE_NO_INITIALIZER.createOn(source)
|
||||
}
|
||||
is ConeForbiddenIntersection -> null // reported in FirDefinitelyNotNullableChecker
|
||||
|
||||
is ConeUnderscoreIsReserved -> FirErrors.UNDERSCORE_IS_RESERVED.createOn(this.source)
|
||||
is ConeUnderscoreUsageWithoutBackticks -> FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.createOn(this.source)
|
||||
|
||||
+2
-5
@@ -523,14 +523,11 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
is FirDynamicTypeRef -> ConeDynamicType.create(session) to null
|
||||
is FirIntersectionTypeRef -> {
|
||||
val leftType = typeRef.leftType.coneType
|
||||
val rightType = typeRef.rightType.coneType
|
||||
|
||||
if (rightType.isAny && leftType is ConeTypeParameterType) {
|
||||
if (leftType is ConeTypeParameterType) {
|
||||
ConeDefinitelyNotNullType(leftType) to null
|
||||
} else {
|
||||
ConeErrorType(ConeUnsupported("Intersection types are not supported yet", typeRef.source)) to null
|
||||
ConeErrorType(ConeForbiddenIntersection) to null
|
||||
}
|
||||
|
||||
}
|
||||
else -> error(typeRef.render())
|
||||
}
|
||||
|
||||
+4
@@ -237,3 +237,7 @@ class ConeAmbiguousAlteredAssign(val altererNames: List<String?>) : ConeDiagnost
|
||||
override val reason: String
|
||||
get() = "Assign altered by multiple extensions"
|
||||
}
|
||||
|
||||
object ConeForbiddenIntersection : ConeDiagnostic {
|
||||
override val reason: String get() = "Such an intersection type is not allowed"
|
||||
}
|
||||
|
||||
@@ -191,3 +191,7 @@ val ConeKotlinType.canBeNull: Boolean
|
||||
}
|
||||
}
|
||||
|
||||
val FirIntersectionTypeRef.isLeftValidForDefinitelyNotNullable
|
||||
get() = leftType.coneType.let { it is ConeTypeParameterType && it.canBeNull && !it.isMarkedNullable }
|
||||
|
||||
val FirIntersectionTypeRef.isRightValidForDefinitelyNotNullable get() = rightType.coneType.isAny
|
||||
|
||||
Reference in New Issue
Block a user