From d1fb8338ef1428d494bc08fedc86d6765aefa52b Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 21 Jan 2022 17:42:14 +0300 Subject: [PATCH] [FIR] Infer type of elvis from lhs if rhs is Nothing ^KT-50875 Fixed --- ...nosisCompilerFirTestdataTestGenerated.java | 6 +++++ ...TouchedTilContractsPhaseTestGenerated.java | 5 ++++ .../resolve/smartcasts/kt50875.fir.txt | 17 ++++++++++++++ .../testData/resolve/smartcasts/kt50875.kt | 23 +++++++++++++++++++ .../runners/FirDiagnosticTestGenerated.java | 6 +++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 +++++ ...ControlFlowStatementsResolveTransformer.kt | 10 ++++++-- .../diagnostics/tests/when/kt9972.fir.kt | 4 ++-- 8 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java index e66acee084e..1c63cfbac43 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java @@ -3645,6 +3645,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50788.kt"); } + @Test + @TestMetadata("kt50875.kt") + public void testKt50875() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt"); + } + @Test @TestMetadata("literalInWhenSubject.kt") public void testLiteralInWhenSubject() throws Exception { diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 9895006a3cc..9390f5f053f 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -3222,6 +3222,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50788.kt"); } + @TestMetadata("kt50875.kt") + public void testKt50875() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt"); + } + @TestMetadata("literalInWhenSubject.kt") public void testLiteralInWhenSubject() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/literalInWhenSubject.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.fir.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.fir.txt new file mode 100644 index 00000000000..6646d9f40f4 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.fir.txt @@ -0,0 +1,17 @@ +FILE: kt50875.kt + public abstract interface A : R|kotlin/Any| { + public abstract fun foo(): R|kotlin/Unit| + + } + @R|kotlin/Suppress|(names = vararg(String(INVISIBLE_MEMBER), String(INVISIBLE_REFERENCE))) public final fun checkNotNull(x: R|K?|, y: R|K|): R|@Exact K| { + ^checkNotNull R|/x| ?: R|/y| + } + public final fun test_1(any: R|kotlin/Any|, a: R|A|, nullableA: R|A?|): R|kotlin/Unit| { + lvar x: R|kotlin/Any| = R|/any| + R|/x| = R|/checkNotNull|(R|/nullableA|, R|/a|) + R|/x|.#() + R|/x| = R|/nullableA| ?: R|/a| + R|/x|.#() + R|/x| = R|/nullableA| ?: ^test_1 Unit + R|/x|.R|/A.foo|() + } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt new file mode 100644 index 00000000000..a4bd1ec6613 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt @@ -0,0 +1,23 @@ +// ISSUE: KT-50875 + +interface A { + fun foo() +} + +@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") +fun checkNotNull(x: K?, y: K): @kotlin.internal.Exact K { + return x ?: y +} + +fun test_1(any: Any, a: A, nullableA: A?) { + var x = any // x has type Any + + x = checkNotNull(nullableA, a) // inferred to Any + x.foo() // no smartcast + + x = nullableA ?: a // inferred to Any + x.foo() // no smartcast + + x = nullableA ?: return // inferred to Any, but has A type + x.foo() // smartcast +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index a25ce01ca53..91e02166ccb 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -3645,6 +3645,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50788.kt"); } + @Test + @TestMetadata("kt50875.kt") + public void testKt50875() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt"); + } + @Test @TestMetadata("literalInWhenSubject.kt") public void testLiteralInWhenSubject() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 58524dd0f2e..52150be6bda 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -3645,6 +3645,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50788.kt"); } + @Test + @TestMetadata("kt50875.kt") + public void testKt50875() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/kt50875.kt"); + } + @Test @TestMetadata("literalInWhenSubject.kt") public void testLiteralInWhenSubject() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt index 2a1256d7cfb..87402d1c6ba 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -243,6 +243,14 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran } } + if (result.rhs.typeRef.coneTypeSafe()?.isNothing == true) { + val lhsType = result.lhs.typeRef.coneTypeSafe() + if (lhsType != null) { + val newReturnType = lhsType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext) + result.replaceTypeRef(result.typeRef.resolvedTypeFromPrototype(newReturnType)) + } + } + session.typeContext.run { if (result.typeRef.coneTypeSafe()?.isNullableType() == true && result.rhs.typeRef.coneTypeSafe()?.isNullableType() == false @@ -255,8 +263,6 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran } } - - dataFlowAnalyzer.exitElvis(elvisExpression) return result } diff --git a/compiler/testData/diagnostics/tests/when/kt9972.fir.kt b/compiler/testData/diagnostics/tests/when/kt9972.fir.kt index c603b5ede70..12843090fd3 100644 --- a/compiler/testData/diagnostics/tests/when/kt9972.fir.kt +++ b/compiler/testData/diagnostics/tests/when/kt9972.fir.kt @@ -20,9 +20,9 @@ fun test1(): Int { } fun test2(): Int { - val x: String = when { + val x: String = when { true -> Any() else -> null - } ?: return 0 + } ?: return 0 return x.hashCode() }