Pattern matching: work-around for smart cast target type instability #KT-14705 Fixed

This commit is contained in:
mglukhikh
2017-01-23 14:18:49 +03:00
committed by Mikhail Glukhikh
parent bc0550d7b7
commit b53ebd115b
3 changed files with 29 additions and 9 deletions
@@ -245,15 +245,6 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
possibleTypesForSubject: Set<KotlinType>
) {
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(
+14
View File
@@ -0,0 +1,14 @@
package test2
<info descr="null">enum</info> class En { A, B, С }
fun main(args: Array<String>) {
val en2: Any? = En.A
if (en2 is En) {
when (<info descr="Smart cast to test2.En">en2</info>) {
En.A -> {}
En.B -> {}
En.С -> {}
}
}
}
@@ -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");