From b53ebd115b6a7a718c5c6473f32c37b237afeb83 Mon Sep 17 00:00:00 2001 From: mglukhikh Date: Mon, 23 Jan 2017 14:18:49 +0300 Subject: [PATCH] Pattern matching: work-around for smart cast target type instability #KT-14705 Fixed --- .../PatternMatchingTypingVisitor.kt | 18 +++++++++--------- idea/testData/checker/infos/SmartCastToEnum.kt | 14 ++++++++++++++ .../checkers/PsiCheckerTestGenerated.java | 6 ++++++ 3 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 idea/testData/checker/infos/SmartCastToEnum.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt index 65d80b23cac..207102c1793 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.kt @@ -245,15 +245,6 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping possibleTypesForSubject: Set ) { val subjectExpression = expression.subjectExpression ?: return - val isNullableType = TypeUtils.isNullableType(subjectType) - val bindingContext = contextBeforeSubject.trace.bindingContext - if (isNullableType && !WhenChecker.containsNullCase(expression, bindingContext)) { - val notNullableType = TypeUtils.makeNotNullable(subjectType) - if (checkSmartCastToExpectedTypeInSubject(contextBeforeSubject, subjectExpression, subjectType, - notNullableType)) { - return - } - } for (possibleCastType in possibleTypesForSubject) { val possibleCastClass = possibleCastType.constructor.declarationDescriptor as? ClassDescriptor ?: continue if (possibleCastClass.kind == ClassKind.ENUM_CLASS || possibleCastClass.modality == Modality.SEALED) { @@ -263,6 +254,15 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping } } } + val isNullableType = TypeUtils.isNullableType(subjectType) + val bindingContext = contextBeforeSubject.trace.bindingContext + if (isNullableType && !WhenChecker.containsNullCase(expression, bindingContext)) { + val notNullableType = TypeUtils.makeNotNullable(subjectType) + if (checkSmartCastToExpectedTypeInSubject(contextBeforeSubject, subjectExpression, subjectType, + notNullableType)) { + return + } + } } private fun checkSmartCastToExpectedTypeInSubject( diff --git a/idea/testData/checker/infos/SmartCastToEnum.kt b/idea/testData/checker/infos/SmartCastToEnum.kt new file mode 100644 index 00000000000..3542cca816d --- /dev/null +++ b/idea/testData/checker/infos/SmartCastToEnum.kt @@ -0,0 +1,14 @@ +package test2 + +enum class En { A, B, С } + +fun main(args: Array) { + val en2: Any? = En.A + if (en2 is En) { + when (en2) { + En.A -> {} + En.B -> {} + En.С -> {} + } + } +} diff --git a/idea/tests/org/jetbrains/kotlin/checkers/PsiCheckerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/checkers/PsiCheckerTestGenerated.java index c18b0f9f510..921fddcd634 100644 --- a/idea/tests/org/jetbrains/kotlin/checkers/PsiCheckerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/checkers/PsiCheckerTestGenerated.java @@ -917,6 +917,12 @@ public class PsiCheckerTestGenerated extends AbstractPsiCheckerTest { doTestWithInfos(fileName); } + @TestMetadata("SmartCastToEnum.kt") + public void testSmartCastToEnum() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/infos/SmartCastToEnum.kt"); + doTestWithInfos(fileName); + } + @TestMetadata("SmartCasts.kt") public void testSmartCasts() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/infos/SmartCasts.kt");