ConeTypeIntersector: preserve raw & dynamic types as is

This commit is contained in:
Mikhail Glukhikh
2023-01-03 18:03:21 +01:00
committed by Space Team
parent 55fdb43620
commit 1344a9b1bb
8 changed files with 115 additions and 1 deletions
@@ -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 {
@@ -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|<local>/x| is R|kotlin/String|) -> {
lval y: R|dynamic| = R|<local>/x|
}
}
}
@@ -0,0 +1,8 @@
fun bar(): <!UNSUPPORTED!>dynamic<!> = TODO()
fun foo() {
val x = bar()
if (x is String) {
val y = <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing..kotlin.Any?! & kotlin.Nothing..kotlin.Any?!")!>x<!>
}
}
@@ -0,0 +1,27 @@
FILE: test.kt
public abstract interface StringSet : R|kotlin/collections/MutableSet<kotlin/String>| {
}
public final fun foo(arg: R|kotlin/Boolean|): R|kotlin/Unit| {
lval x: R|ft<Raw type java/util/ArrayList<kotlin/Any!>, @EnhancedNullability java/util/ArrayList<*>>| = Q|Producer|.R|/Producer.foo|()
when () {
(R|<local>/x| is R|kotlin/collections/Set<*>|) -> {
lval y: R|ft<Raw type java/util/ArrayList<kotlin/Any!>, @EnhancedNullability java/util/ArrayList<*>>| = R|<local>/x|
}
}
when () {
(R|<local>/x| is R|kotlin/collections/MutableSet<*>|) -> {
lval y: R|ft<Raw type java/util/ArrayList<kotlin/Any!>, @EnhancedNullability java/util/ArrayList<*>>| = R|<local>/x|
}
}
when () {
(R|<local>/x| is R|StringSet|) -> {
R|<local>/x|.R|SubstitutionOverride</StringSet.add: R|kotlin/Boolean|>|(String())
R|<local>/x|.R|SubstitutionOverride<java/util/ArrayList.add: R|kotlin/Boolean|>|(Int(1))
R|<local>/x|.R|SubstitutionOverride<java/util/ArrayList.add: R|kotlin/Boolean|>|(Null(null))
R|<local>/x|.R|SubstitutionOverride</StringSet.iterator: R|kotlin/collections/MutableIterator<kotlin/String>|>|().R|SubstitutionOverride<kotlin/collections/MutableIterator.next: R|kotlin/String|>|().R|kotlin/String.length|
}
}
}
@@ -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<String>
fun foo(arg: Boolean) {
val x = Producer.foo()
if (x is Set<*>) {
val y = <!DEBUG_INFO_EXPRESSION_TYPE("java.util.ArrayList<kotlin.Any..kotlin.Any?!>..java.util.ArrayList<*> & kotlin.collections.Set<*> & java.util.ArrayList<kotlin.Any..kotlin.Any?!>..java.util.ArrayList<*>")!>x<!>
}
if (x is MutableSet<*>) {
val y = <!DEBUG_INFO_EXPRESSION_TYPE("java.util.ArrayList<kotlin.Any..kotlin.Any?!>..java.util.ArrayList<*> & kotlin.collections.MutableSet<*> & java.util.ArrayList<kotlin.Any..kotlin.Any?!>..java.util.ArrayList<*>")!>x<!>
}
if (x is StringSet) {
x.add("")
x.add(1)
x.add(null)
x.iterator().next().length
}
}
@@ -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 {
@@ -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 {
@@ -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() })