提交 7b61bf91 编写于 作者: D Denis Zharkov

FIR: Add nullability smartcast after !is check

^KT-39072 Fixed
上级 24948a8b
interface A {
val b: B
}
interface B
interface C : B {
fun q(): Boolean
}
fun A.foo(): String = ""
fun main(a: A?) {
val lb = a?.b
if (lb !is C) return
a.foo().length
}
FILE: boundSafeCallAndIsCheck.kt
public abstract interface A : R|kotlin/Any| {
public abstract val b: R|B|
public get(): R|B|
}
public abstract interface B : R|kotlin/Any| {
}
public abstract interface C : R|B| {
public abstract fun q(): R|kotlin/Boolean|
}
public final fun R|A|.foo(): R|kotlin/String| {
^foo String()
}
public final fun main(a: R|A?|): R|kotlin/Unit| {
lval lb: R|B?| = R|<local>/a|?.{ $subj$.R|/A.b| }
when () {
(R|<local>/lb| !is R|C|) -> {
^main Unit
}
}
R|<local>/a|.R|/foo|().R|kotlin/String.length|
}
......@@ -2152,6 +2152,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.kt");
}
@TestMetadata("boundSafeCallAndIsCheck.kt")
public void testBoundSafeCallAndIsCheck() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/boundSafeCallAndIsCheck.kt");
}
@TestMetadata("safeCallAndEqualityToBool.kt")
public void testSafeCallAndEqualityToBool() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.kt");
......
......@@ -2152,6 +2152,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/assignSafeCall.kt");
}
@TestMetadata("boundSafeCallAndIsCheck.kt")
public void testBoundSafeCallAndIsCheck() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/boundSafeCallAndIsCheck.kt");
}
@TestMetadata("safeCallAndEqualityToBool.kt")
public void testSafeCallAndEqualityToBool() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/safeCalls/safeCallAndEqualityToBool.kt");
......
......@@ -237,7 +237,8 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
when (val operation = typeOperatorCall.operation) {
FirOperation.IS, FirOperation.NOT_IS -> {
val expressionVariable = variableStorage.createSyntheticVariable(typeOperatorCall)
val isNotNullCheck = operation == FirOperation.IS && type.nullability == ConeNullability.NOT_NULL
val isNotNullCheck = type.nullability == ConeNullability.NOT_NULL
val isRegularIs = operation == FirOperation.IS
if (operandVariable.isReal()) {
val hasTypeInfo = operandVariable typeEq type
val hasNotTypeInfo = operandVariable typeNotEq type
......@@ -252,13 +253,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
flow.addTypeStatement(operandVariable typeEq any)
}
if (isNotNullCheck) {
flow.addImplication((expressionVariable eq true) implies (operandVariable typeEq any))
flow.addImplication((expressionVariable eq true) implies (operandVariable notEq null))
flow.addImplication((expressionVariable eq isRegularIs) implies (operandVariable typeEq any))
flow.addImplication((expressionVariable eq isRegularIs) implies (operandVariable notEq null))
}
} else {
if (isNotNullCheck) {
flow.addImplication((expressionVariable eq true) implies (operandVariable notEq null))
flow.addImplication((expressionVariable eq isRegularIs) implies (operandVariable notEq null))
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册