FIR: Add nullability smartcast after !is check
^KT-39072 Fixed
This commit is contained in:
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
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
|
||||
}
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
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|
|
||||
}
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
-4
@@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user