[FIR] Support makeDefinitelyNotNull for intersection types

This commit is contained in:
Dmitriy Novozhilov
2020-02-12 17:21:30 +03:00
parent b71e4ebb3f
commit 643a4b9c3b
8 changed files with 25 additions and 109 deletions
@@ -211,7 +211,9 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
}
private fun ConeKotlinType.makeDefinitelyNotNullOrNotNull(): ConeKotlinType {
// TODO: add intersection types, see fun SimpleType.makeSimpleTypeDefinitelyNotNullOrNotNull() in SpecialTypes.kt
if (this is ConeIntersectionType) {
return ConeIntersectionType(intersectedTypes.map { it.makeDefinitelyNotNullOrNotNull() })
}
return ConeDefinitelyNotNullType.create(this) ?: this.withNullability(false) as ConeKotlinType
}
@@ -0,0 +1,7 @@
fun <X> test_1(a: X) {
if (a is String?) {
takeString(a!!)
}
}
fun takeString(s: String) {}
@@ -1,8 +1,8 @@
FILE: smartcastOnBangBang.kt
FILE: definitelyNotNullIntersectionType.kt
public final fun <X> test_1(a: R|X|): R|kotlin/Unit| {
when () {
(R|<local>/a| is R|kotlin/String?|) -> {
<Inapplicable(INAPPLICABLE): [/takeString]>#(R|<local>/a|!!)
R|/takeString|(R|<local>/a|!!)
}
}
@@ -1,59 +0,0 @@
digraph smartcastOnBangBang_kt {
graph [splines=ortho nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function test_1" style="filled" fillcolor=red];
subgraph cluster_1 {
color=blue
1 [label="Enter when"];
subgraph cluster_2 {
color=blue
2 [label="Enter when branch condition "];
3 [label="Access variable R|<local>/a|"];
4 [label="Type operator: a is String?"];
5 [label="Exit when branch condition"];
}
6 [label="Synthetic else branch"];
7 [label="Enter when branch result"];
subgraph cluster_3 {
color=blue
8 [label="Enter block"];
9 [label="Access variable R|<local>/a|"];
10 [label="Check not null: R|<local>/a|!!"];
11 [label="Function call: <Inapplicable(INAPPLICABLE): [/takeString]>#(R|<local>/a|!!)"];
12 [label="Exit block"];
}
13 [label="Exit when branch result"];
14 [label="Exit when"];
}
15 [label="Exit function test_1" style="filled" fillcolor=red];
}
0 -> {1};
1 -> {2};
2 -> {3};
3 -> {4};
4 -> {5};
5 -> {7 6};
6 -> {14};
7 -> {8};
8 -> {9};
9 -> {10};
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {14};
14 -> {15};
subgraph cluster_4 {
color=red
16 [label="Enter function takeString" style="filled" fillcolor=red];
17 [label="Exit function takeString" style="filled" fillcolor=red];
}
16 -> {17};
}
@@ -1,8 +0,0 @@
// !DUMP_CFG
fun <X> test_1(a: X) {
if (a is String?) {
<!INAPPLICABLE_CANDIDATE!>takeString<!>(a!!)
}
}
fun takeString(s: String) {}
@@ -1082,6 +1082,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/inference/capturedTypeForJavaTypeParameter.kt");
}
@TestMetadata("definitelyNotNullIntersectionType.kt")
public void testDefinitelyNotNullIntersectionType() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/inference/definitelyNotNullIntersectionType.kt");
}
@TestMetadata("nestedLambdas.kt")
public void testNestedLambdas() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt");
@@ -1576,24 +1581,6 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/problems")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Problems extends AbstractFirDiagnosticsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInProblems() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("smartcastOnBangBang.kt")
public void testSmartcastOnBangBang() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/receivers")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1082,6 +1082,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/inference/capturedTypeForJavaTypeParameter.kt");
}
@TestMetadata("definitelyNotNullIntersectionType.kt")
public void testDefinitelyNotNullIntersectionType() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/inference/definitelyNotNullIntersectionType.kt");
}
@TestMetadata("nestedLambdas.kt")
public void testNestedLambdas() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/inference/nestedLambdas.kt");
@@ -1576,24 +1581,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/problems")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Problems extends AbstractFirDiagnosticsWithLightTreeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInProblems() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/resolve/testData/resolve/smartcasts/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@TestMetadata("smartcastOnBangBang.kt")
public void testSmartcastOnBangBang() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/smartcasts/problems/smartcastOnBangBang.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/smartcasts/receivers")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
+3 -3
View File
@@ -33,7 +33,7 @@ FILE fqName:<root> fileName:/bangbang.kt
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String?
GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null
then: CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String? origin=EXCLEXCL
then: CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String origin=EXCLEXCL
<T0>: kotlin.String
arg0: TYPE_OP type=kotlin.String? origin=IMPLICIT_CAST typeOperand=kotlin.String?
GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null
@@ -41,8 +41,8 @@ FILE fqName:<root> fileName:/bangbang.kt
BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String?
GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null
then: ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/useString]>#' type=IrErrorType
CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String? origin=EXCLEXCL
then: CALL 'public final fun useString (s: kotlin.String): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
s: CALL 'public final fun CHECK_NOT_NULL <T0> (arg0: T0 of kotlin.internal.ir.CHECK_NOT_NULL?): T0 of kotlin.internal.ir.CHECK_NOT_NULL declared in kotlin.internal.ir' type=kotlin.String origin=EXCLEXCL
<T0>: kotlin.String
arg0: TYPE_OP type=kotlin.String? origin=IMPLICIT_CAST typeOperand=kotlin.String?
GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null