From 4cdddb1b08ad9bb3ec476a4b14c08dd4070424c4 Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Thu, 29 Feb 2024 16:01:42 +0200 Subject: [PATCH] [FIR] Unify checks for `is` and `as` --- .../expression/FirCastOperatorsChecker.kt | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt index 2a204a07336..c24d0f6457f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirCastOperatorsChecker.kt @@ -45,26 +45,14 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker(MppCheckerKind.Commo } } - private fun checkIsApplicability(l: TypeInfo, r: TypeInfo, expression: FirTypeOperatorCall, 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) -> Applicability.USELESS_IS_CHECK - isCastErased(l.directType, r.directType, context) -> Applicability.CAST_ERASED - oneIsNotNull && oneIsFinal && areUnrelated(l, r, context) -> Applicability.IMPOSSIBLE_IS_CHECK - else -> Applicability.APPLICABLE - } - } + private fun checkIsApplicability(l: TypeInfo, r: TypeInfo, expression: FirTypeOperatorCall, context: CheckerContext): Applicability = + checkAnyApplicability(l, r, expression, Applicability.IMPOSSIBLE_IS_CHECK, Applicability.USELESS_IS_CHECK, context) private fun checkAsApplicability(l: TypeInfo, r: TypeInfo, expression: FirTypeOperatorCall, context: CheckerContext): Applicability { - val oneIsFinal = l.isFinal || r.isFinal - val oneIsNotNull = !l.type.isNullable || !r.type.isNullable val isNullableNothingWithNotNull = !l.type.isNullable && r.type.isNullableNothing || l.type.isNullableNothing && !r.type.isNullable return when { - isRefinementUseless(context, l.directType.upperBoundIfFlexible(), r.directType, expression) -> Applicability.USELESS_CAST l.type.isNothing && r.type.isNothingOrNullableNothing -> Applicability.APPLICABLE r.type.isNothing -> Applicability.IMPOSSIBLE_CAST isNullableNothingWithNotNull -> when (expression.operation) { @@ -72,7 +60,23 @@ object FirCastOperatorsChecker : FirTypeOperatorCallChecker(MppCheckerKind.Commo FirOperation.SAFE_AS -> Applicability.USELESS_CAST else -> Applicability.IMPOSSIBLE_CAST } - oneIsNotNull && oneIsFinal && areUnrelated(l, r, context) -> Applicability.IMPOSSIBLE_CAST + else -> checkAnyApplicability(l, r, expression, Applicability.IMPOSSIBLE_CAST, Applicability.USELESS_CAST, context) + } + } + + private fun checkAnyApplicability( + l: TypeInfo, r: TypeInfo, + expression: FirTypeOperatorCall, + impossible: Applicability, + 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 isCastErased(l.directType, r.directType, context) -> Applicability.CAST_ERASED else -> Applicability.APPLICABLE }