[FE] Introduce warnings on possible empty intersection types, and improve errors reporting in general

^KT-52361 Fixed
This commit is contained in:
Victor Petukhov
2022-05-23 10:10:59 +02:00
committed by teamcity
parent e133ee3765
commit 6a34b184ac
53 changed files with 501 additions and 335 deletions
@@ -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")
}
}
@@ -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)
@@ -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
)
@@ -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