From 1344a9b1bb6b2224a0f2edd8f5141313ebdbb5c7 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 3 Jan 2023 18:03:21 +0100 Subject: [PATCH] ConeTypeIntersector: preserve raw & dynamic types as is --- ...nosisCompilerFirTestdataTestGenerated.java | 12 ++++++++ .../intersectDynamicAndString.fir.txt | 13 +++++++++ .../intersectDynamicAndString.kt | 8 +++++ .../intersectRawAndMutable.fir.txt | 27 +++++++++++++++++ .../intersectRawAndMutable.kt | 29 +++++++++++++++++++ .../runners/FirDiagnosticTestGenerated.java | 12 ++++++++ ...DiagnosticsWithLightTreeTestGenerated.java | 12 ++++++++ .../kotlin/fir/types/ConeTypeIntersector.kt | 3 +- 8 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.kt create mode 100644 compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.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 398a056a324..d3055b055f0 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 @@ -4722,6 +4722,18 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/inapplicableRemoveAll.kt"); } + @Test + @TestMetadata("intersectDynamicAndString.kt") + public void testIntersectDynamicAndString() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.kt"); + } + + @Test + @TestMetadata("intersectRawAndMutable.kt") + public void testIntersectRawAndMutable() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.kt"); + } + @Test @TestMetadata("javaEnumSynthetic.kt") public void testJavaEnumSynthetic() throws Exception { diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.fir.txt new file mode 100644 index 00000000000..2d0dd5783e8 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.fir.txt @@ -0,0 +1,13 @@ +FILE: intersectDynamicAndString.kt + public final fun bar(): R|dynamic| { + ^bar R|kotlin/TODO|() + } + public final fun foo(): R|kotlin/Unit| { + lval x: R|dynamic| = R|/bar|() + when () { + (R|/x| is R|kotlin/String|) -> { + lval y: R|dynamic| = R|/x| + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.kt new file mode 100644 index 00000000000..be561ac571e --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.kt @@ -0,0 +1,8 @@ +fun bar(): dynamic = TODO() + +fun foo() { + val x = bar() + if (x is String) { + val y = x + } +} diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.fir.txt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.fir.txt new file mode 100644 index 00000000000..66b164b2e14 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.fir.txt @@ -0,0 +1,27 @@ +FILE: test.kt + public abstract interface StringSet : R|kotlin/collections/MutableSet| { + } + public final fun foo(arg: R|kotlin/Boolean|): R|kotlin/Unit| { + lval x: R|ft, @EnhancedNullability java/util/ArrayList<*>>| = Q|Producer|.R|/Producer.foo|() + when () { + (R|/x| is R|kotlin/collections/Set<*>|) -> { + lval y: R|ft, @EnhancedNullability java/util/ArrayList<*>>| = R|/x| + } + } + + when () { + (R|/x| is R|kotlin/collections/MutableSet<*>|) -> { + lval y: R|ft, @EnhancedNullability java/util/ArrayList<*>>| = R|/x| + } + } + + when () { + (R|/x| is R|StringSet|) -> { + R|/x|.R|SubstitutionOverride|(String()) + R|/x|.R|SubstitutionOverride|(Int(1)) + R|/x|.R|SubstitutionOverride|(Null(null)) + R|/x|.R|SubstitutionOverride|>|().R|SubstitutionOverride|().R|kotlin/String.length| + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.kt b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.kt new file mode 100644 index 00000000000..6c0f92b7a61 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.kt @@ -0,0 +1,29 @@ +// FILE: Producer.java + +import java.util.*; +import org.jetbrains.annotations.*; + +public class Producer { + @NotNull + public static ArrayList foo() { return null; } +} + +// FILE: test.kt + +interface StringSet : MutableSet + +fun foo(arg: Boolean) { + val x = Producer.foo() + if (x is Set<*>) { + val y = ..java.util.ArrayList<*> & kotlin.collections.Set<*> & java.util.ArrayList..java.util.ArrayList<*>")!>x + } + if (x is MutableSet<*>) { + val y = ..java.util.ArrayList<*> & kotlin.collections.MutableSet<*> & java.util.ArrayList..java.util.ArrayList<*>")!>x + } + if (x is StringSet) { + x.add("") + x.add(1) + x.add(null) + x.iterator().next().length + } +} 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 0795bfdb28c..f0d886c8ca9 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 @@ -4722,6 +4722,18 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/inapplicableRemoveAll.kt"); } + @Test + @TestMetadata("intersectDynamicAndString.kt") + public void testIntersectDynamicAndString() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.kt"); + } + + @Test + @TestMetadata("intersectRawAndMutable.kt") + public void testIntersectRawAndMutable() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.kt"); + } + @Test @TestMetadata("javaEnumSynthetic.kt") public void testJavaEnumSynthetic() 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 0d4c68dc2b7..269666163f1 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 @@ -4722,6 +4722,18 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/inapplicableRemoveAll.kt"); } + @Test + @TestMetadata("intersectDynamicAndString.kt") + public void testIntersectDynamicAndString() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectDynamicAndString.kt"); + } + + @Test + @TestMetadata("intersectRawAndMutable.kt") + public void testIntersectRawAndMutable() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intersectRawAndMutable.kt"); + } + @Test @TestMetadata("javaEnumSynthetic.kt") public void testJavaEnumSynthetic() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt index 96a125f8411..73d64707fac 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/types/ConeTypeIntersector.kt @@ -27,7 +27,8 @@ object ConeTypeIntersector { } } - if (inputTypes.any { it is ConeFlexibleType }) { + // Note: we aren't sure how to intersect raw & dynamic types properly (see KT-55762) + if (inputTypes.any { it is ConeFlexibleType } && inputTypes.none { it.isRaw() || it is ConeDynamicType }) { // (A..B) & C = (A & C)..(B & C) val lowerBound = intersectTypes(context, inputTypes.map { it.lowerBoundIfFlexible() }) val upperBound = intersectTypes(context, inputTypes.map { it.upperBoundIfFlexible() })