[NI] Improve CST algorithm to handle non-fixed variables

#KT-32456 Fixed
 #KT-32423 Fixed
 #KT-32818 Fixed
 #KT-33197 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2019-08-28 01:23:18 +03:00
parent ba6648d535
commit ca8da22569
41 changed files with 605 additions and 81 deletions
@@ -0,0 +1,90 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
fun <T> select(x: T, y: T): T = x
open class Inv<K>
class SubInv<V> : Inv<V>()
fun testSimple() {
val a0 = select(Inv<Int>(), SubInv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>a0<!>
val a1 = select(SubInv<Int>(), Inv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>a1<!>
}
fun testNullability() {
val n1 = select(Inv<Int?>(), SubInv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int?>")!>n1<!>
val n2 = select(SubInv<Int?>(), Inv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int?>")!>n2<!>
}
fun testNested() {
val n1 = select(Inv<Inv<Int>>(), SubInv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<Inv<kotlin.Int>>")!>n1<!>
val n2 = select(SubInv<SubInv<Int>>(), Inv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<SubInv<kotlin.Int>>")!>n2<!>
fun <K> createInvInv(): Inv<Inv<K>> = TODO()
val n3 = select(SubInv<SubInv<Int>>(), createInvInv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<out Inv<kotlin.Int>>")!>n3<!>
}
fun testCaptured(cSub: SubInv<out Number>, cInv: Inv<out Number>) {
val c1 = select(cInv, SubInv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<out kotlin.Number>")!>c1<!>
val c2 = select(cSub, Inv())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<out kotlin.Number>")!>c2<!>
}
fun testVariableWithBound() {
fun <K : Number> createWithNumberBound(): Inv<K> = TODO()
fun <K : <!FINAL_UPPER_BOUND!>Int<!>> createWithIntBound(): Inv<K> = TODO()
val c1 = select(SubInv<Int>(), createWithNumberBound())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Int>")!>c1<!>
// should be an error after variable fixation
val c2 = select(SubInv<String>(), createWithNumberBound())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.String>")!>c2<!>
// should be an error after variable fixation
val c3 = select(SubInv<Double>(), createWithIntBound())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Double>")!>c3<!>
}
fun testCapturedVariable() {
fun <K> createInvOut(): Inv<out K> = TODO()
fun <V> createSubInvOut(): SubInv<out V> = TODO()
fun <K> createInvIn(): Inv<in K> = TODO()
val c1 = select(SubInv<Number>(), createInvOut())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<kotlin.Number>")!>c1<!>
val c2 = select(createSubInvOut<Number>(), createInvOut())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<out kotlin.Number>")!>c2<!>
val c3 = select(SubInv<Number>(), createInvIn())
<!DEBUG_INFO_EXPRESSION_TYPE("Inv<out kotlin.Number>")!>c3<!>
}
@@ -0,0 +1,23 @@
package
public fun </*0*/ T> select(/*0*/ x: T, /*1*/ y: T): T
public fun testCaptured(/*0*/ cSub: SubInv<out kotlin.Number>, /*1*/ cInv: Inv<out kotlin.Number>): kotlin.Unit
public fun testCapturedVariable(): kotlin.Unit
public fun testNested(): kotlin.Unit
public fun testNullability(): kotlin.Unit
public fun testSimple(): kotlin.Unit
public fun testVariableWithBound(): kotlin.Unit
public open class Inv</*0*/ K> {
public constructor Inv</*0*/ K>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class SubInv</*0*/ V> : Inv<V> {
public constructor SubInv</*0*/ V>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,5 @@
// !WITH_NEW_INFERENCE
fun <T : Any> nullable(): T? = null
val value = nullable<Int>() ?: <!OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>nullable()<!>
@@ -0,0 +1,4 @@
package
public val value: kotlin.Int
public fun </*0*/ T : kotlin.Any> nullable(): T?
@@ -0,0 +1,19 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_EXPRESSION
fun test(condition: Boolean) {
val list1 =
if (condition) mutableListOf<Int>()
else emptyList()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.collections.List<kotlin.Int>")!>list1<!>
val list2 =
if (condition) mutableListOf()
else emptyList<Int>()
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.collections.List<kotlin.Int>")!>list2<!>
}
fun <T> mutableListOf(): MutableList<T> = TODO()
fun <T> emptyList(): List<T> = TODO()
@@ -0,0 +1,5 @@
package
public fun </*0*/ T> emptyList(): kotlin.collections.List<T>
public fun </*0*/ T> mutableListOf(): kotlin.collections.MutableList<T>
public fun test(/*0*/ condition: kotlin.Boolean): kotlin.Unit
@@ -0,0 +1,30 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
// FILE: Inv2.java
public class Inv2<K, V> {}
// FILE: JavaSet.java
public class JavaSet {
public static <E> java.util.Set<E> newIdentityHashSet() { return null; }
public static <K, V> V get(Inv2<K, V> slice, K key) { return null; }
}
// FILE: test.kt
fun <K> select(x: K, y: K): K = x
fun <K, T> addElementToSlice(
slice: Inv2<K, MutableCollection<T>>,
key: K,
element: T
) {
val a = select(JavaSet.get(slice, key), JavaSet.newIdentityHashSet())
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.collections.MutableCollection<T>..kotlin.collections.Collection<T>?)")!>a<!>
a.add(element)
}
@@ -0,0 +1,22 @@
package
public fun </*0*/ K, /*1*/ T> addElementToSlice(/*0*/ slice: Inv2<K, kotlin.collections.MutableCollection<T>>, /*1*/ key: K, /*2*/ element: T): kotlin.Unit
public fun </*0*/ K> select(/*0*/ x: K, /*1*/ y: K): K
public open class Inv2</*0*/ K : kotlin.Any!, /*1*/ V : kotlin.Any!> {
public constructor Inv2</*0*/ K : kotlin.Any!, /*1*/ V : kotlin.Any!>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class JavaSet {
public constructor JavaSet()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public open fun </*0*/ K : kotlin.Any!, /*1*/ V : kotlin.Any!> get(/*0*/ slice: Inv2<K!, V!>!, /*1*/ key: K!): V!
public open fun </*0*/ E : kotlin.Any!> newIdentityHashSet(): kotlin.collections.(Mutable)Set<E!>!
}
@@ -0,0 +1,12 @@
// !LANGUAGE: +NewInference
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
class Inv<T>
fun <K> select(x: K, y: K): K = x
fun <V> outToOut(x: Inv<out V>): Inv<out V> = TODO()
fun test(invOutAny: Inv<out Any>, invAny: Inv<Any>) {
val a: Inv<out Any> = select(invAny, outToOut(invOutAny))
}
@@ -0,0 +1,12 @@
package
public fun </*0*/ V> outToOut(/*0*/ x: Inv<out V>): Inv<out V>
public fun </*0*/ K> select(/*0*/ x: K, /*1*/ y: K): K
public fun test(/*0*/ invOutAny: Inv<out kotlin.Any>, /*1*/ invAny: Inv<kotlin.Any>): kotlin.Unit
public final class Inv</*0*/ T> {
public constructor Inv</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -11,13 +11,13 @@ fun <K> elvisExact(x: K?, y: K): @kotlin.internal.Exact K = y
fun <T : Number> materialize(): T? = null
fun test(nullableSample: ISample, any: Any) {
<!DEBUG_INFO_EXPRESSION_TYPE("ISample")!>elvisSimple(
<!DEBUG_INFO_EXPRESSION_TYPE("ISample?")!>elvisSimple(
nullableSample,
<!DEBUG_INFO_EXPRESSION_TYPE("{ISample & Number}?")!>materialize()<!>
)<!>
elvisSimple(
<!DEBUG_INFO_EXPRESSION_TYPE("ISample")!>elvisSimple(nullableSample, materialize())<!>,
<!DEBUG_INFO_EXPRESSION_TYPE("ISample?")!>elvisSimple(nullableSample, materialize())<!>,
any
)