Refactoring of JetTypeInfo / BindingContext. Loop data flow analysis corrected.
Now BindingContext includes expression type info instead of jump out possible, data flow info and expression type. getType() was added into BindingContext, getType() and recordType() were added into BindingTrace. JetTypeInfo now includes also jump possible flag and jump point data flow info. Old TypeInfoWithJumpInfo deleted. TypeInfoFactory introduced to create JetTypeInfo instances. A pack of extra tests for break / continue in loops added.
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
public fun foo(x: String?, y: String?): Int {
|
||||
while (true) {
|
||||
val z = x ?: if (y == null) break else <!DEBUG_INFO_SMARTCAST!>y<!>
|
||||
// z is not null in both branches
|
||||
z.length()
|
||||
// y is not null in both branches
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>.length()
|
||||
}
|
||||
// y is null because of the break
|
||||
return y<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,15 @@
|
||||
public fun foo(x: String?): Int {
|
||||
var y: Any
|
||||
@loop while (true) {
|
||||
y = when (x) {
|
||||
null -> break@loop
|
||||
"abc" -> return 0
|
||||
"xyz" -> return 1
|
||||
else -> <!DEBUG_INFO_SMARTCAST!>x<!>.length()
|
||||
}
|
||||
// y is always Int after when
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>: Int
|
||||
}
|
||||
// x is null because of the break
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,12 @@
|
||||
fun bar(): Boolean { return true }
|
||||
|
||||
public fun foo(x: String?): Int {
|
||||
var y: Any
|
||||
do {
|
||||
y = ""
|
||||
y = if (x == null) break else <!DEBUG_INFO_SMARTCAST!>x<!>
|
||||
} while (bar())
|
||||
y.hashCode()
|
||||
// x is null because of the break
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
internal fun bar(): kotlin.Boolean
|
||||
public fun foo(/*0*/ x: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,10 @@
|
||||
public fun foo(x: String?): Int {
|
||||
var y: Any
|
||||
while (true) {
|
||||
y = if (x == null) break else <!DEBUG_INFO_SMARTCAST!>x<!>
|
||||
}
|
||||
// In future we can infer this initialization
|
||||
<!UNINITIALIZED_VARIABLE!>y<!>.hashCode()
|
||||
// x is null because of the break
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,10 @@
|
||||
public fun foo(x: String?): Int {
|
||||
while (true) {
|
||||
// After the check, smart cast should work
|
||||
val y = if (x == null) break else <!DEBUG_INFO_SMARTCAST!>x<!>
|
||||
// y is not null in both branches
|
||||
y.length()
|
||||
}
|
||||
// x is null because of the break
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,11 @@
|
||||
public fun foo(x: String?, y: String?): Int {
|
||||
while (true) {
|
||||
val z = (if (y == null) break else x) ?: <!DEBUG_INFO_SMARTCAST!>y<!>
|
||||
// z is not null in both branches
|
||||
z.length()
|
||||
// y is not null in both branches
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>.length()
|
||||
}
|
||||
// y is null because of the break
|
||||
return y<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,20 @@
|
||||
fun bar(): Boolean { return true }
|
||||
|
||||
public fun foo(x: String?): Int {
|
||||
var y: Int?
|
||||
y = 0
|
||||
@loop do {
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!> += when (x) {
|
||||
null -> break@loop
|
||||
"abc" -> return 0
|
||||
"xyz" -> return 1
|
||||
else -> <!DEBUG_INFO_SMARTCAST!>x<!>.length()
|
||||
}
|
||||
// y is always Int after when
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>: Int
|
||||
} while (bar())
|
||||
// y is always Int even here
|
||||
<!DEBUG_INFO_SMARTCAST!>y<!>: Int
|
||||
// x is null because of the break
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
internal fun bar(): kotlin.Boolean
|
||||
public fun foo(/*0*/ x: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,12 @@
|
||||
public fun foo(x: String?): Int {
|
||||
@loop while (true) {
|
||||
when (x) {
|
||||
null -> break@loop
|
||||
"abc" -> return 0
|
||||
"xyz" -> return 1
|
||||
else -> <!DEBUG_INFO_SMARTCAST!>x<!>.length()
|
||||
}
|
||||
}
|
||||
// x is null because of the break
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.String?): kotlin.Int
|
||||
@@ -0,0 +1,13 @@
|
||||
public fun foo(x: String?): Int {
|
||||
@loop while (true) {
|
||||
when (x) {
|
||||
null -> return -1
|
||||
"abc" -> return 0
|
||||
"xyz" -> return 1
|
||||
else -> break@loop
|
||||
}
|
||||
}
|
||||
// x is not null because of the break
|
||||
// but we are not able to detect it
|
||||
return x<!UNSAFE_CALL!>.<!>length()
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
public fun foo(/*0*/ x: kotlin.String?): kotlin.Int
|
||||
Reference in New Issue
Block a user