[FE] Show causing types in the INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION diagnostic

This commit is contained in:
Victor Petukhov
2022-05-25 18:14:19 +02:00
committed by teamcity
parent 6a34b184ac
commit 867ad24c86
51 changed files with 217 additions and 163 deletions
@@ -688,12 +688,15 @@ 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")
parameter<String>("description")
parameter<String>("causingTypes")
}
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning<PsiElement> {
parameter<String>("typeVariableDescription")
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
parameter<String>("description")
parameter<String>("causingTypes")
}
}
@@ -412,8 +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 error3<PsiElement, String, Collection<ConeKotlinType>, String>()
val INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION by warning2<PsiElement, String, Collection<ConeKotlinType>>()
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>()
// Reflection
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -950,16 +950,19 @@ 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 ({2}): {1}",
"Type argument for a type parameter {0} can''t be inferred because it has incompatible upper bounds: {1} ({2}{3})",
TO_STRING,
RENDER_COLLECTION_OF_TYPES,
TO_STRING,
TO_STRING
)
map.put(
INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION,
"Type argument for a type parameter {0} has possible incompatible upper bounds: {1}",
"Type argument for a type parameter {0} has possible incompatible upper bounds: {1} ({2}{3})",
TO_STRING,
RENDER_COLLECTION_OF_TYPES
RENDER_COLLECTION_OF_TYPES,
TO_STRING,
TO_STRING
)
map.put(TYPE_MISMATCH, "Type mismatch: inferred type is {1} but {0} was expected", TO_STRING, TO_STRING, NOT_RENDERED)
@@ -257,8 +257,9 @@ private fun mapInapplicableCandidateError(
diagnostic.candidate
)
}
is InferredEmptyIntersectionDiagnostic ->
reportInferredIntoEmptyIntersectionError(source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.kind)
is InferredEmptyIntersectionDiagnostic -> reportInferredIntoEmptyIntersectionError(
source, rootCause.typeVariable, rootCause.incompatibleTypes, rootCause.causingTypes, rootCause.kind
)
else -> genericDiagnostic
}
}.distinct()
@@ -400,6 +401,7 @@ private fun ConstraintSystemError.toDiagnostic(
source,
typeVariable as ConeTypeVariable,
incompatibleTypes as Collection<ConeKotlinType>,
causingTypes as Collection<ConeKotlinType>,
kind
)
}
@@ -411,18 +413,18 @@ private fun reportInferredIntoEmptyIntersectionError(
source: KtSourceElement,
typeVariable: ConeTypeVariable,
incompatibleTypes: Collection<ConeKotlinType>,
causingTypes: Collection<ConeKotlinType>,
kind: EmptyIntersectionTypeKind
): KtDiagnostic? {
val typeVariableText =
(typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString()
?: typeVariable.toString()
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()
)
}
val causingTypesText = if (incompatibleTypes == causingTypes) "" else ": ${causingTypes.joinToString()}"
val factory = if (kind.isPossiblyEmpty())
FirErrors.INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION else
FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION
return factory.createOn(source, typeVariableText, incompatibleTypes, kind.description, causingTypesText)
}
private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType