[FIR] Report errors for upper bounded type variables by an empty intersection type

^KT-51221 Fixed
This commit is contained in:
Victor Petukhov
2022-02-11 12:25:06 +03:00
committed by teamcity
parent 65213e9a42
commit c16ae81a48
21 changed files with 206 additions and 26 deletions
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.diagnostics.WhenMissingCase
import org.jetbrains.kotlin.diagnostics.deprecationError2
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.*
@@ -683,6 +684,11 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val PLATFORM_CLASS_MAPPED_TO_KOTLIN by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
parameter<FqName>("kotlinClass")
}
val INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION by error<PsiElement> {
parameter<String>("typeVariableDescription")
parameter<Collection<ConeKotlinType>>("incompatibleTypes")
}
}
val REFLECTION by object : DiagnosticGroup("Reflection") {
@@ -412,6 +412,7 @@ 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>>()
// Reflection
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
@@ -253,6 +253,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCORRECT_CHARACT
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
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERRED_TYPE_VARIABLE_INTO_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
@@ -946,6 +947,12 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_ANNOTATION, "Redundant spread (*) operator")
map.put(REDUNDANT_SPREAD_OPERATOR_IN_NAMED_FORM_IN_FUNCTION, "Redundant spread (*) operator")
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''s upper bounded by incompatible types: {1}",
TO_STRING,
RENDER_COLLECTION_OF_TYPES
)
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)
@@ -17,12 +17,14 @@ import org.jetbrains.kotlin.fir.declarations.utils.isInfix
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.calls.*
import org.jetbrains.kotlin.fir.resolve.calls.InferredEmptyIntersectionDiagnostic
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeParameterBasedTypeVariable
import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeVariableForLambdaReturnType
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstraintPosition
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeLambdaArgumentConstraintPosition
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
@@ -253,6 +255,8 @@ private fun mapInapplicableCandidateError(
diagnostic.candidate
)
}
is InferredEmptyIntersectionDiagnostic ->
reportInferredIntoEmptyIntersectionError(source, rootCause.typeVariable, rootCause.incompatibleTypes)
else -> genericDiagnostic
}
}.distinct()
@@ -388,10 +392,29 @@ private fun ConstraintSystemError.toDiagnostic(
position.initialConstraint.asStringWithoutPosition(),
)
}
is InferredEmptyIntersection -> {
@Suppress("UNCHECKED_CAST")
reportInferredIntoEmptyIntersectionError(
source,
typeVariable as ConeTypeVariable,
incompatibleTypes as Collection<ConeKotlinType>
)
}
else -> null
}
}
private fun reportInferredIntoEmptyIntersectionError(
source: KtSourceElement,
typeVariable: ConeTypeVariable,
incompatibleTypes: Collection<ConeKotlinType>,
): KtDiagnosticWithParameters2<String, Collection<ConeKotlinType>>? {
val typeVariableText =
(typeVariable.typeConstructor.originalTypeParameter as? ConeTypeParameterLookupTag)?.name?.asString()
?: typeVariable.toString()
return FirErrors.INFERRED_TYPE_VARIABLE_INTO_EMPTY_INTERSECTION.createOn(source, typeVariableText, incompatibleTypes)
}
private val NewConstraintError.lowerConeType: ConeKotlinType get() = lowerType as ConeKotlinType
private val NewConstraintError.upperConeType: ConeKotlinType get() = upperType as ConeKotlinType