New J2K: separate nullability inference from common one & nullability bug fixes

It will be needed for structure mutability inference

#KT-21467 fixed
#KT-32609 fixed
#KT-32572 fixed
#KT-24677 fixed
This commit is contained in:
Ilya Kirillov
2019-07-25 00:31:50 +03:00
parent d7960caf89
commit 2bd5a1f196
234 changed files with 3940 additions and 1983 deletions
@@ -0,0 +1,10 @@
class Test {
fun foo() {
val ss = Array</*T2@*/Array</*T1@*/String?>>(5/*LIT*/, { arrayOfNulls</*T0@*/String?>(5/*LIT*/)/*Array<T0@String!!U>!!L*/ }/*Function0<Int, T3@Array<T4@String>>!!L*/)
}
}
//T4 := UPPER due to 'RETURN'
//LOWER <: T3 due to 'RETURN'
//T1 := T4 due to 'PARAMETER'
//T3 <: T2 due to 'PARAMETER'
+6
View File
@@ -0,0 +1,6 @@
fun test() {
val x: /*T2@*/Array</*T1@*/Int?> = arrayOfNulls</*T0@*/Int?>(10/*LIT*/)/*Array<T0@Int!!U>!!L*/
}
//T1 := UPPER due to 'INITIALIZER'
//LOWER <: T2 due to 'INITIALIZER'
@@ -0,0 +1,7 @@
fun test() {
val x: /*T0@*/Int = 10/*LIT*/
x/*T0@Int*/ > 0/*LIT*/
}
//LOWER <: T0 due to 'INITIALIZER'
//T0 := LOWER due to 'USE_AS_RECEIVER'
@@ -0,0 +1,11 @@
import java.util.Arrays.asList
fun test() {
val x: /*T2@*/List</*T1@*/Int> = asList</*T0@*/Int>(1/*LIT*/)/*MutableList<T0@Int>!!L*/
val i: /*T3@*/Int = Integer/*LIT*/.valueOf(""/*LIT*/)/*Int!!L*/
}
//LOWER <: T0 due to 'PARAMETER'
//T1 := T0 due to 'INITIALIZER'
//LOWER <: T2 due to 'INITIALIZER'
//LOWER <: T3 due to 'INITIALIZER'
@@ -0,0 +1,27 @@
open class A<T> {
open fun foo(): /*T3@*/Map</*T0@*/T, /*T2@*/List</*T1@*/T>>? {
TODO()
}
open fun bar(): /*T4@*/T? {
return null/*NULL!!U*/
}
}
class B : A</*T10@*/Int>() {
override fun foo(): /*T8@*/Map</*T5@*/Int, /*T7@*/List</*T6@*/Int>>? {
return null/*NULL!!U*/
}
override fun bar(): /*T9@*/Int {
return 42/*LIT*/
}
}
//UPPER <: T4 due to 'RETURN'
//UPPER <: T8 due to 'RETURN'
//T5 := T10 due to 'SUPER_DECLARATION'
//T6 := T10 due to 'SUPER_DECLARATION'
//T2 := T7 due to 'SUPER_DECLARATION'
//T3 := T8 due to 'SUPER_DECLARATION'
//LOWER <: T9 due to 'RETURN'
//T9 := T10 due to 'SUPER_DECLARATION'
+19
View File
@@ -0,0 +1,19 @@
fun a(): /*T0@*/Int? {
return 42/*LIT*/
}
val b: /*T1@*/Int? = 2/*LIT*/
fun c(p: /*T2@*/Int?) {
if (p/*T2@Int*/ == null/*LIT*/);
}
fun check() {
if (a()/*T0@Int*/ == null/*LIT*/ || b/*T1@Int*/ == null/*LIT*//*LIT*/);
}
//LOWER <: T0 due to 'RETURN'
//LOWER <: T1 due to 'INITIALIZER'
//T2 := UPPER due to 'COMPARE_WITH_NULL'
//T0 := UPPER due to 'COMPARE_WITH_NULL'
//T1 := UPPER due to 'COMPARE_WITH_NULL'
@@ -0,0 +1,9 @@
fun b(m: /*T2@*/Map</*T0@*/Int, /*T1@*/String>): /*T3@*/String? {
return m/*T2@Map<T0@Int, T1@String>*/.get(42/*LIT*/)/*T1@String!!U*/
}
//T0 := T0 due to 'RECEIVER_PARAMETER'
//T1 <: T1 due to 'RECEIVER_PARAMETER'
//LOWER <: T0 due to 'PARAMETER'
//T2 := LOWER due to 'USE_AS_RECEIVER'
//UPPER <: T3 due to 'RETURN'
@@ -0,0 +1,20 @@
fun <T, E, F, S> foo(x: /*T0@*/T, y: /*T2@*/List</*T1@*/E>, z: /*T4@*/List</*T3@*/F>, a: /*T5@*/S) {}
fun bar() {
val lst: /*T8@*/List</*T7@*/Int?> = listOf</*T6@*/Int?>(null/*NULL!!U*/)/*List<T6@Int>!!L*/
val lst2: /*T11@*/List</*T10@*/Int> = listOf</*T9@*/Int>(1/*LIT*/)/*List<T9@Int>!!L*/
foo</*T12@*/Int?, /*T13@*/Int?, /*T14@*/Int, /*T15@*/String>(null/*NULL!!U*/, lst/*T8@List<T7@Int>*/, lst2/*T11@List<T10@Int>*/, "nya"/*LIT*/)
}
//UPPER <: T6 due to 'PARAMETER'
//T6 <: T7 due to 'INITIALIZER'
//LOWER <: T8 due to 'INITIALIZER'
//LOWER <: T9 due to 'PARAMETER'
//T9 <: T10 due to 'INITIALIZER'
//LOWER <: T11 due to 'INITIALIZER'
//UPPER <: T12 due to 'PARAMETER'
//T7 <: T13 due to 'PARAMETER'
//T8 <: T2 due to 'PARAMETER'
//T10 <: T14 due to 'PARAMETER'
//T11 <: T4 due to 'PARAMETER'
//LOWER <: T15 due to 'PARAMETER'
+40
View File
@@ -0,0 +1,40 @@
fun notNullParameters(f: /*T3@*/Function2</*T0@*/Int, /*T1@*/Int, /*T2@*/String>) {}
fun nullableParameter(f: /*T7@*/Function2</*T4@*/Int?, /*T5@*/Int, /*T6@*/String>) {}
fun nullableReturnType(f: /*T11@*/Function2</*T8@*/Int, /*T9@*/Int, /*T10@*/String?>) {}
fun test() {
notNullParameters({ i: /*T12@*/Int, j: /*T13@*/Int ->
if (i/*T12@Int*/ < 10/*LIT*//*LIT*/ && j/*T13@Int*/ > 0/*LIT*//*LIT*//*LIT*/) ""/*LIT*/ else ""/*LIT*/
}/*Function2<T12@Int, T13@Int, T18@String>!!L*/)
nullableParameter({ i: /*T14@*/Int?, j: /*T15@*/Int ->
if (i/*T14@Int*/ == null/*LIT*/) ""/*LIT*/ else ""/*LIT*/
}/*Function2<T14@Int, T15@Int, T19@String>!!L*/)
nullableReturnType({ i: /*T16@*/Int, j: /*T17@*/Int ->
if (i/*T16@Int*/ < 10/*LIT*//*LIT*/) return@nullableReturnType null/*NULL!!U*/
return@nullableReturnType "nya"/*LIT*/
}/*Function2<T16@Int, T17@Int, T20@String>!!L*/)
}
//T12 := LOWER due to 'USE_AS_RECEIVER'
//T13 := LOWER due to 'USE_AS_RECEIVER'
//LOWER <: T18 due to 'RETURN'
//T0 <: T12 due to 'PARAMETER'
//T1 <: T13 due to 'PARAMETER'
//T18 <: T2 due to 'PARAMETER'
//LOWER <: T3 due to 'PARAMETER'
//T14 := UPPER due to 'COMPARE_WITH_NULL'
//LOWER <: T19 due to 'RETURN'
//T4 <: T14 due to 'PARAMETER'
//T5 <: T15 due to 'PARAMETER'
//T19 <: T6 due to 'PARAMETER'
//LOWER <: T7 due to 'PARAMETER'
//T16 := LOWER due to 'USE_AS_RECEIVER'
//UPPER <: T20 due to 'RETURN'
//LOWER <: T20 due to 'RETURN'
//T8 <: T16 due to 'PARAMETER'
//T9 <: T17 due to 'PARAMETER'
//T20 <: T10 due to 'PARAMETER'
//LOWER <: T11 due to 'PARAMETER'
+5
View File
@@ -0,0 +1,5 @@
fun test(a: /*T0@*/Boolean) {
if (a/*T0@Boolean*/) {}
}
//T0 := LOWER due to 'USE_AS_RECEIVER'
+25
View File
@@ -0,0 +1,25 @@
// RUNTIME_WITH_FULL_JDK
import java.util.stream.Collector
import java.util.stream.Collectors
import java.util.stream.Stream
fun test(list: /*T1@*/List</*T0@*/String>) {
val x: /*T9@*/List</*T8@*/String> = list/*T1@List<T0@String>*/.stream()/*Stream<T0@String>!!L*/
.map</*T3@*/String>({ x: /*T2@*/String -> x/*T2@String*/ + ""/*LIT*//*LIT*/ }/*Function1<T2@String, T10@String>!!L*/)/*Stream<T3@String>*/
.collect</*T6@*/List</*T5@*/String>, /*T7@*/Any?>(Collectors/*LIT*/.toList</*T4@*/String>()/*Collector<T4@String, Any, MutableList<T4@String>>*/)/*T6@List<T5@String>*/
}
//T0 <: T0 due to 'RECEIVER_PARAMETER'
//T1 := LOWER due to 'USE_AS_RECEIVER'
//T2 := LOWER due to 'USE_AS_RECEIVER'
//LOWER <: T10 due to 'RETURN'
//T0 := T0 due to 'RECEIVER_PARAMETER'
//T0 <: T2 due to 'PARAMETER'
//T10 <: T3 due to 'PARAMETER'
//T3 := T3 due to 'RECEIVER_PARAMETER'
//T3 := T4 due to 'PARAMETER'
//T5 := T4 due to 'PARAMETER'
//T5 <: T8 due to 'INITIALIZER'
//T6 <: T9 due to 'INITIALIZER'
+23
View File
@@ -0,0 +1,23 @@
class Test {
fun foo1(r: /*T2@*/Function1</*T0@*/Int, /*T1@*/String?>) {}
fun foo() {
foo1({ x: /*T3@*/Int -> ""/*LIT*/ }/*Function1<T3@Int, T5@String>!!L*/)
foo1({ i: /*T4@*/Int ->
if (i/*T4@Int*/ > 1/*LIT*//*LIT*/) {
return@foo1 null/*NULL!!U*/
}
""/*LIT*/
}/*Function1<T4@Int, T6@String>!!L*/)
}
}
//LOWER <: T5 due to 'RETURN'
//T0 <: T3 due to 'PARAMETER'
//T5 <: T1 due to 'PARAMETER'
//LOWER <: T2 due to 'PARAMETER'
//T4 := LOWER due to 'USE_AS_RECEIVER'
//UPPER <: T6 due to 'RETURN'
//LOWER <: T6 due to 'RETURN'
//T0 <: T4 due to 'PARAMETER'
//T6 <: T1 due to 'PARAMETER'
//LOWER <: T2 due to 'PARAMETER'
@@ -0,0 +1,9 @@
fun test() {
val x: /*T2@*/List</*T1@*/Int?> = listOf</*T0@*/Int?>(1/*LIT*/, null/*NULL!!U*/, 3/*LIT*/)/*List<T0@Int>!!L*/
}
//LOWER <: T0 due to 'PARAMETER'
//UPPER <: T0 due to 'PARAMETER'
//LOWER <: T0 due to 'PARAMETER'
//T0 <: T1 due to 'INITIALIZER'
//LOWER <: T2 due to 'INITIALIZER'
+8
View File
@@ -0,0 +1,8 @@
fun test(a: /*T1@*/List</*T0@*/Int>) {
for (i: /*T2@*/Int in a/*T1@List<T0@Int>*/) {
}
}
//T2 <: T0 due to 'ASSIGNMENT'
//T1 := LOWER due to 'USE_AS_RECEIVER'
+31
View File
@@ -0,0 +1,31 @@
fun bar(map: /*T2@*/HashMap</*T0@*/String?, /*T1@*/Int>, list1: /*T4@*/List</*T3@*/Int>, list2: /*T6@*/List</*T5@*/String?>) {
for (entry: /*T9@*/MutableMap.MutableEntry</*T7@*/String?, /*T8@*/Int> in map/*T2@HashMap<T0@String, T1@Int>*/.entries/*MutableSet<MutableEntry<T0@String, T1@Int>>*/) {
val value: /*T10@*/Int = entry/*T9@MutableEntry<T7@String, T8@Int>*/.value/*T8@Int*/
if (entry/*T9@MutableEntry<T7@String, T8@Int>*/.key/*T7@String*/ == null/*LIT*/) {
println(value/*T10@Int*/ + 1/*LIT*//*LIT*/)
}
}
for (i: /*T11@*/Int in list1/*T4@List<T3@Int>*/) {
i/*T11@Int*/ + 1/*LIT*/
}
for (i: /*T12@*/String? in list2/*T6@List<T5@String>*/) {
i/*T12@String*/ == null
}
}
//T2 := LOWER due to 'USE_AS_RECEIVER'
//T9 := LOWER due to 'USE_AS_RECEIVER'
//T8 <: T10 due to 'INITIALIZER'
//T9 := LOWER due to 'USE_AS_RECEIVER'
//T7 := UPPER due to 'COMPARE_WITH_NULL'
//T10 := LOWER due to 'USE_AS_RECEIVER'
//T0 := T7 due to 'ASSIGNMENT'
//T1 := T8 due to 'ASSIGNMENT'
//T11 := LOWER due to 'USE_AS_RECEIVER'
//T11 <: T3 due to 'ASSIGNMENT'
//T4 := LOWER due to 'USE_AS_RECEIVER'
//T12 := UPPER due to 'COMPARE_WITH_NULL'
//T12 <: T5 due to 'ASSIGNMENT'
//T6 := LOWER due to 'USE_AS_RECEIVER'
@@ -0,0 +1,16 @@
// RUNTIME_WITH_FULL_JDK
fun main() {
val list: /*T5@*/List</*T4@*/String?> =
listOf</*T0@*/String?>(""/*LIT*/, null/*NULL!!U*/)/*List<T0@String>!!L*/
.map</*T2@*/String?, /*T3@*/String?>({ x: /*T1@*/String? -> x/*T1@String*/ }/*Function1<T1@String, T6@String>!!L*/)/*List<T3@String>!!L*/
}
//LOWER <: T0 due to 'PARAMETER'
//UPPER <: T0 due to 'PARAMETER'
//T1 <: T6 due to 'RETURN'
//T0 <: T2 due to 'RECEIVER_PARAMETER'
//T2 <: T1 due to 'PARAMETER'
//T6 <: T3 due to 'PARAMETER'
//T3 <: T4 due to 'INITIALIZER'
//LOWER <: T5 due to 'INITIALIZER'
+18
View File
@@ -0,0 +1,18 @@
fun test() {
var x: /*T0@*/Int? = 1/*LIT*/
x/*T0@Int*/ = null/*NULL!!U*/
var y: /*T1@*/Int? = 5/*LIT*/
y/*T1@Int*/ = nullableFun()/*T2@Int*/
}
fun nullableFun(): /*T2@*/Int? {
return null/*NULL!!U*/
}
//LOWER <: T0 due to 'INITIALIZER'
//UPPER <: T0 due to 'ASSIGNMENT'
//T0 := UPPER due to 'COMPARE_WITH_NULL'
//LOWER <: T1 due to 'INITIALIZER'
//T2 <: T1 due to 'ASSIGNMENT'
//UPPER <: T2 due to 'RETURN'
@@ -0,0 +1,5 @@
val x: /*T0@*/Int? = null/*NULL!!U*/
fun foo(p: /*T1@*/Int? = null/*NULL!!U*/) {}
//UPPER <: T0 due to 'INITIALIZER'
//UPPER <: T1 due to 'INITIALIZER'
+5
View File
@@ -0,0 +1,5 @@
fun test() {
val x: /*T0@*/Int? = null/*NULL!!U*/
}
//UPPER <: T0 due to 'INITIALIZER'
+5
View File
@@ -0,0 +1,5 @@
fun nya() : /*T0@*/Int? {
return null/*NULL!!U*/
}
//UPPER <: T0 due to 'RETURN'
@@ -0,0 +1,16 @@
fun a(lst: /*T1@*/List</*T0@*/String>) {
val newList: /*T8@*/List</*T7@*/Int> = lst/*T1@List<T0@String>*/
.asSequence</*T2@*/String>()/*Sequence<T2@String>!!L*/
.map</*T4@*/String, /*T5@*/Int>({ x: /*T3@*/String -> 1/*LIT*/ }/*Function1<T3@String, T9@Int>!!L*/)/*Sequence<T5@Int>!!L*/
.toList</*T6@*/Int>()/*List<T6@Int>!!L*/
}
//T0 <: T2 due to 'RECEIVER_PARAMETER'
//T1 := LOWER due to 'USE_AS_RECEIVER'
//LOWER <: T9 due to 'RETURN'
//T2 <: T4 due to 'RECEIVER_PARAMETER'
//T4 <: T3 due to 'PARAMETER'
//T9 <: T5 due to 'PARAMETER'
//T5 <: T6 due to 'RECEIVER_PARAMETER'
//T6 <: T7 due to 'INITIALIZER'
//LOWER <: T8 due to 'INITIALIZER'
+7
View File
@@ -0,0 +1,7 @@
fun foo(o: /*T0@*/Int??) {
if (o/*T0@Int*/ == null/*LIT*/) return
val a: /*T1@*/Int = o/*T0@Int!!L*/
}
//T0 := UPPER due to 'COMPARE_WITH_NULL'
//LOWER <: T1 due to 'INITIALIZER'
@@ -0,0 +1,9 @@
import java.lang.reflect.Constructor
fun <T> foo(constructor: /*T1@*/Constructor</*T0@*/T>, args: /*T3@*/Array</*T2@*/Any?>) {
constructor/*T1@Constructor<T0@T>*/.newInstance(*args/*T3@Array<T2@Any>*/)
}
//T3 := LOWER due to 'USE_AS_RECEIVER'
//T0 := T0 due to 'RECEIVER_PARAMETER'
//T1 := LOWER due to 'USE_AS_RECEIVER'
+18
View File
@@ -0,0 +1,18 @@
open class A () {
open fun foo(x: /*T0@*/Int?): /*T1@*/Int? {
if (x/*T0@Int*/ == null/*LIT*/);
return null/*NULL!!U*/
}
}
class B : A() {
override fun foo(x: /*T2@*/Int?): /*T3@*/Int? {
return 1/*LIT*/
}
}
//T0 := UPPER due to 'COMPARE_WITH_NULL'
//UPPER <: T1 due to 'RETURN'
//LOWER <: T3 due to 'RETURN'
//T1 := T3 due to 'SUPER_DECLARATION'
//T0 := T2 due to 'SUPER_DECLARATION'
+18
View File
@@ -0,0 +1,18 @@
fun foo() {
val cast1: /*T1@*/Int = 1/*LIT*/ as /*T0@*/Int/*T0@Int*/
val cast2: /*T3@*/Int? = null/*NULL!!U*/ as /*T2@*/Int?/*T2@Int*/
val cast3: /*T5@*/Float = (1/*LIT*/ as /*T4@*/Int/*T4@Int*/)/*T4@Int*/.toFloat()/*Float!!L*/
val nya: /*T6@*/Int? = null/*NULL!!U*/
val cast4: /*T8@*/Int? = nya/*T6@Int*/ as /*T7@*/Int?/*T7@Int*/
}
//LOWER <: T0 due to 'ASSIGNMENT'
//T0 <: T1 due to 'INITIALIZER'
//UPPER <: T2 due to 'ASSIGNMENT'
//T2 <: T3 due to 'INITIALIZER'
//LOWER <: T4 due to 'ASSIGNMENT'
//T4 := LOWER due to 'USE_AS_RECEIVER'
//LOWER <: T5 due to 'INITIALIZER'
//UPPER <: T6 due to 'INITIALIZER'
//T6 <: T7 due to 'ASSIGNMENT'
//T7 <: T8 due to 'INITIALIZER'
+20
View File
@@ -0,0 +1,20 @@
fun foo() {
val a: /*T5@*/List</*T4@*/List</*T3@*/Int>> = listOf</*T2@*/List</*T1@*/Int>>(
listOf</*T0@*/Int>(
1/*LIT*/
)/*List<T0@Int>!!L*/
)/*List<T2@List<T1@Int>>!!L*/
val b: /*T7@*/List</*T6@*/Int> = a/*T5@List<T4@List<T3@Int>>*/.get(0/*LIT*/)/*T4@List<T3@Int>*/
}
//LOWER <: T0 due to 'PARAMETER'
//T0 <: T1 due to 'PARAMETER'
//LOWER <: T2 due to 'PARAMETER'
//T1 <: T3 due to 'INITIALIZER'
//T2 <: T4 due to 'INITIALIZER'
//LOWER <: T5 due to 'INITIALIZER'
//T3 <: T3 due to 'RECEIVER_PARAMETER'
//T4 <: T4 due to 'RECEIVER_PARAMETER'
//T5 := LOWER due to 'USE_AS_RECEIVER'
//T3 <: T6 due to 'INITIALIZER'
//T4 <: T7 due to 'INITIALIZER'
@@ -0,0 +1,20 @@
open class A<T> {
open fun foo(): /*T3@*/Map</*T0@*/T, /*T2@*/List</*T1@*/T>> {
TODO()
}
open fun bar(): /*T4@*/T {
TODO()
}
}
class B : A</*T9@*/Int>() {
override fun foo(): /*T8@*/Map</*T5@*/Int, /*T7@*/List</*T6@*/Int>> {
TODO()
}
}
//T5 := T9 due to 'SUPER_DECLARATION'
//T6 := T9 due to 'SUPER_DECLARATION'
//T2 := T7 due to 'SUPER_DECLARATION'
//T3 := T8 due to 'SUPER_DECLARATION'
@@ -0,0 +1,16 @@
open class A<T> {
open fun foo(x: /*T1@*/List</*T0@*/T>, y: /*T2@*/Boolean, z: /*T3@*/T) {
TODO()
}
}
class B : A</*T8@*/Int>() {
override fun foo(x: /*T5@*/List</*T4@*/Int>, y: /*T6@*/Boolean, z: /*T7@*/Int) {
TODO()
}
}
//T4 := T8 due to 'SUPER_DECLARATION'
//T1 := T5 due to 'SUPER_DECLARATION'
//T2 := T6 due to 'SUPER_DECLARATION'
//T7 := T8 due to 'SUPER_DECLARATION'
+9
View File
@@ -0,0 +1,9 @@
fun test() {
val x: /*T2@*/List</*T1@*/Any> = listOf</*T0@*/Any>()/*List<T0@Any>!!L*/
x/*T2@List<T1@Any>*/.get(0/*LIT*/)
}
//T0 <: T1 due to 'INITIALIZER'
//LOWER <: T2 due to 'INITIALIZER'
//T1 <: T1 due to 'RECEIVER_PARAMETER'
//T2 := LOWER due to 'USE_AS_RECEIVER'
+5
View File
@@ -0,0 +1,5 @@
fun test(a: /*T0@*/Boolean) {
while (a/*T0@Boolean*/) {}
}
//T0 := LOWER due to 'USE_AS_RECEIVER'