[FIR] Reuse shouldReportAsPerRules1() in FirCastOperatorsChecker

This change better aligns the checker with
the description in KT-57779.

^KT-57779
This commit is contained in:
Nikolay Lunyak
2024-03-06 17:48:28 +02:00
committed by Space Team
parent 4c0ec0fae4
commit a4c33ee785
3 changed files with 24 additions and 23 deletions
@@ -115,3 +115,24 @@ internal fun FirExpression.toArgumentInfo(context: CheckerContext) =
originalType = mostOriginalTypeIfSmartCast.fullyExpandedType(context.session).finalApproximationOrSelf(context),
context.session,
)
private fun TypeInfo.isSubtypeOf(other: TypeInfo, context: CheckerContext) =
notNullType.isSubtypeOf(other.notNullType, context.session)
internal fun areUnrelated(a: TypeInfo, b: TypeInfo, context: CheckerContext): Boolean {
return !a.isSubtypeOf(b, context) && !b.isSubtypeOf(a, context)
}
internal fun areRelated(a: TypeInfo, b: TypeInfo, context: CheckerContext): Boolean = !areUnrelated(a, b, context)
/**
* See [KT-57779](https://youtrack.jetbrains.com/issue/KT-57779) for more information.
*/
internal fun shouldReportAsPerRules1(l: TypeInfo, r: TypeInfo, context: CheckerContext): Boolean {
val oneIsFinal = l.isFinal || r.isFinal
return when {
oneIsFinal -> areUnrelated(l, r, context)
else -> false
}
}
@@ -53,7 +53,7 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker(MppCheckerKind.Commo
|| l.type.isNullableNothing && !r.type.isNullable
return when {
l.type.isNothing && r.type.isNothingOrNullableNothing -> Applicability.APPLICABLE
l.type.isNothing -> Applicability.APPLICABLE
r.type.isNothing -> Applicability.IMPOSSIBLE_CAST
isNullableNothingWithNotNull -> when (expression.operation) {
// (null as? WhatEver) == null
@@ -71,23 +71,16 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker(MppCheckerKind.Commo
useless: Applicability,
context: CheckerContext,
): Applicability {
val oneIsFinal = l.isFinal || r.isFinal
val oneIsNotNull = !l.type.isNullable || !r.type.isNullable
return when {
isRefinementUseless(context, l.directType.upperBoundIfFlexible(), r.directType, expression) -> useless
oneIsNotNull && oneIsFinal && areUnrelated(l, r, context) -> impossible
oneIsNotNull && shouldReportAsPerRules1(l, r, context) -> impossible
isCastErased(l.directType, r.directType, context) -> Applicability.CAST_ERASED
else -> Applicability.APPLICABLE
}
}
private fun areUnrelated(a: TypeInfo, b: TypeInfo, context: CheckerContext) =
!a.isSubtypeOf(b, context) && !b.isSubtypeOf(a, context)
private fun TypeInfo.isSubtypeOf(other: TypeInfo, context: CheckerContext) =
notNullType.isSubtypeOf(other.notNullType, context.session)
/**
* K1 reports different diagnostics for different
* cases, and this enum helps to replicate the K1's
@@ -105,19 +105,6 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker(MppCheck
}
}
private fun shouldReportAsPerRules1(l: TypeInfo, r: TypeInfo, context: CheckerContext): Boolean {
val oneIsFinal = l.isFinal || r.isFinal
return when {
l.type.isNothingOrNullableNothing || r.type.isNothingOrNullableNothing -> false
oneIsFinal -> !l.isSubtypeOf(r, context) && !r.isSubtypeOf(l, context)
else -> false
}
}
private fun TypeInfo.isSubtypeOf(other: TypeInfo, context: CheckerContext) =
notNullType.isSubtypeOf(other.notNullType, context.session)
/**
* K1 reports different diagnostics for different
* cases, and this enum helps to replicate the K1's
@@ -155,7 +142,7 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker(MppCheck
val shouldProperlyReportError = context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsForComparisonOperators)
// In this case K1 reports nothing
val shouldRelaxDiagnostic = (l.isPrimitive || r.isPrimitive) && (l.isSubtypeOf(r, context) || r.isSubtypeOf(l, context))
val shouldRelaxDiagnostic = (l.isPrimitive || r.isPrimitive) && areRelated(l, r, context)
&& !shouldProperlyReportError
return when {