[FE] Introduce warnings on possible empty intersection types, and improve errors reporting in general
^KT-52361 Fixed
This commit is contained in:
committed by
teamcity
parent
e133ee3765
commit
6a34b184ac
+6
@@ -688,6 +688,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error<PsiElement> {
|
||||
parameter<String>("typeVariableDescription")
|
||||
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
|
||||
parameter<String>("kind")
|
||||
}
|
||||
|
||||
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning<PsiElement> {
|
||||
parameter<String>("typeVariableDescription")
|
||||
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -412,7 +412,8 @@ object FirErrors {
|
||||
val SMARTCAST_IMPOSSIBLE by error4<KtExpression, ConeKotlinType, FirExpression, String, Boolean>()
|
||||
val REDUNDANT_NULLABLE by warning0<KtTypeReference>(SourceElementPositioningStrategies.REDUNDANT_NULLABLE)
|
||||
val PLATFORM_CLASS_MAPPED_TO_KOTLIN by warning1<PsiElement, FqName>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error2<PsiElement, String, Collection<ConeKotlinType>>()
|
||||
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error3<PsiElement, String, Collection<ConeKotlinType>, String>()
|
||||
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning2<PsiElement, String, Collection<ConeKotlinType>>()
|
||||
|
||||
// Reflection
|
||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
+9
-1
@@ -254,6 +254,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INC_DEC_SHOULD_NO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_UNSUCCESSFUL_FORK
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFIX_MODIFIER_REQUIRED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZATION_BEFORE_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION
|
||||
@@ -949,7 +950,14 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
map.put(INFERENCE_UNSUCCESSFUL_FORK, "Unsuccessful inference fork at position: {0}", TO_STRING)
|
||||
map.put(
|
||||
INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION,
|
||||
"Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds: {1}",
|
||||
"Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds ({2}): {1}",
|
||||
TO_STRING,
|
||||
RENDER_COLLECTION_OF_TYPES,
|
||||
TO_STRING
|
||||
)
|
||||
map.put(
|
||||
INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION,
|
||||
"Type argument for a type parameter {0} has possible incompatible upper bounds: {1}",
|
||||
TO_STRING,
|
||||
RENDER_COLLECTION_OF_TYPES
|
||||
)
|
||||
|
||||
+14
-4
@@ -35,6 +35,8 @@ import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.types.EmptyIntersectionTypeKind
|
||||
import org.jetbrains.kotlin.types.isPossiblyEmpty
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
@@ -256,7 +258,7 @@ private fun mapInapplicableCandidateError(
|
||||
)
|
||||
}
|
||||
is InferredEmptyIntersectionDiagnostic ->
|
||||
reportInferredIntoEmptyIntersectionError(source, rootCause.typeVariable, rootCause.incompatibleTypes)
|
||||
reportInferredIntoEmptyIntersectionError(source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.kind)
|
||||
else -> genericDiagnostic
|
||||
}
|
||||
}.distinct()
|
||||
@@ -397,7 +399,8 @@ private fun ConstraintSystemError.toDiagnostic(
|
||||
reportInferredIntoEmptyIntersectionError(
|
||||
source,
|
||||
typeVariable as ConeTypeVariable,
|
||||
incompatibleTypes as Collection<ConeKotlinType>
|
||||
incompatibleTypes as Collection<ConeKotlinType>,
|
||||
kind
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
@@ -408,11 +411,18 @@ private fun reportInferredIntoEmptyIntersectionError(
|
||||
source: KtSourceElement,
|
||||
typeVariable: ConeTypeVariable,
|
||||
incompatibleTypes: Collection<ConeKotlinType>,
|
||||
): KtDiagnosticWithParameters2<String, Collection<ConeKotlinType>>? {
|
||||
kind: EmptyIntersectionTypeKind
|
||||
): KtDiagnostic? {
|
||||
val typeVariableText =
|
||||
(typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString()
|
||||
?: typeVariable.toString()
|
||||
return FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.createOn(source, typeVariableText, incompatibleTypes)
|
||||
return if (kind.isPossiblyEmpty()) {
|
||||
FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION.createOn(source, typeVariableText, incompatibleTypes)
|
||||
} else {
|
||||
FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.createOn(
|
||||
source, typeVariableText, incompatibleTypes, kind.description?.let { " ($it)" }.orEmpty()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType
|
||||
|
||||
Reference in New Issue
Block a user