Skip to content

Commit 50d4642

Browse files
committed
A set of tests for smart casts after loops, see KT-6283, KT-6284. Existing DoWhile and WhileTrue tests corrected in accordance.
1 parent 2065309 commit 50d4642

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+441
-2
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
// See KT-6283
5+
do {
6+
p!!.length()
7+
} while (!x())
8+
// Do-while loop is executed at least once, so
9+
// p should be not null here
10+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
11+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
// See KT-6283
5+
do {
6+
p!!.length()
7+
if (p == "abc") break
8+
} while (!x())
9+
// p should be smart casted despite of break
10+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
11+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
// See KT-6283
5+
do {
6+
p!!.length()
7+
if (p == "abc") continue
8+
} while (!x())
9+
// p should be smart casted despite of continue
10+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
11+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun x(): Boolean { return true }
2+
3+
fun y(): Boolean { return false }
4+
5+
public fun foo(p: String?): Int {
6+
do {
7+
if (y()) break
8+
// We do not always reach this statement
9+
p!!.length()
10+
} while (!x())
11+
// Here we have do while loop but p is still nullable due to break before
12+
return p<!UNSAFE_CALL!>.<!>length()
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
5+
internal fun y(): kotlin.Boolean
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun x(): Boolean { return true }
2+
3+
fun y(): Boolean { return false }
4+
5+
public fun foo(p: String?): Int {
6+
do {
7+
if (y()) continue
8+
// We do not always reach this statement
9+
p!!.length()
10+
} while (!x())
11+
// Here we have do while loop but p is still nullable due to continue before
12+
return p<!UNSAFE_CALL!>.<!>length()
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
5+
internal fun y(): kotlin.Boolean
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
// Exotic variant with unused literal
5+
do <!UNUSED_FUNCTION_LITERAL!>{ ->
6+
p!!.length()
7+
}<!> while (!x())
8+
// Literal is not called so p.length() is unsafe
9+
return p<!UNSAFE_CALL!>.<!>length()
10+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public fun foo(p: String?, y: String?): Int {
2+
do {
3+
// After the check, smart cast should work
4+
if (y == null) {
5+
"null".toString()
6+
break
7+
}
8+
<!DEBUG_INFO_SMARTCAST!>y<!>.length()
9+
p!!.length()
10+
} while (true)
11+
return y?.length() ?: -1
12+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Int
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
public fun foo(x: String?, y: String?): Int {
2+
do {
3+
// After the check, smart cast should work
4+
if (x != null) {
5+
if (x == "abc") break
6+
y!!.length()
7+
} else {
8+
y!!.length()
9+
}
10+
// y!! in both branches
11+
<!DEBUG_INFO_SMARTCAST!>y<!>.length()
12+
} while (true)
13+
// break is possible before so !! is necessary
14+
return y!!.length()
15+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package
2+
3+
public fun foo(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Int
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public fun foo(p: String?, y: String?): Int {
2+
do {
3+
// After the check, smart cast should work
4+
if (y == null) break
5+
<!DEBUG_INFO_SMARTCAST!>y<!>.length()
6+
p!!.length()
7+
} while (true)
8+
return y?.length() ?: -1
9+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Int
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?, r: String?): Int {
4+
do {
5+
do {
6+
p!!.length()
7+
} while (r == null)
8+
} while (!x())
9+
// Auto cast possible
10+
<!DEBUG_INFO_SMARTCAST!>r<!>.length()
11+
// Auto cast possible
12+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
13+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ r: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?, r: String?, q: String?): Int {
4+
while(true) {
5+
q!!.length()
6+
do {
7+
do {
8+
p!!.length()
9+
} while (!x())
10+
} while (r == null)
11+
if (!x()) break
12+
}
13+
// Smart cast is possible everywhere
14+
<!DEBUG_INFO_SMARTCAST!>r<!>.length()
15+
<!DEBUG_INFO_SMARTCAST!>q<!>.length()
16+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
17+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ r: kotlin.String?, /*2*/ q: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?, r: String?, q: String?): Int {
4+
while(true) {
5+
q!!.length()
6+
do {
7+
p!!.length()
8+
} while (r == null)
9+
if (!x()) break
10+
}
11+
// Smart cast is possible everywhere
12+
<!DEBUG_INFO_SMARTCAST!>r<!>.length()
13+
<!DEBUG_INFO_SMARTCAST!>q<!>.length()
14+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
15+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ r: kotlin.String?, /*2*/ q: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?, r: String?, q: String?): Int {
4+
while(true) {
5+
q!!.length()
6+
do {
7+
while(true) {
8+
p!!.length()
9+
if (x()) break
10+
}
11+
} while (r == null)
12+
if (!x()) break
13+
}
14+
// Smart cast is possible everywhere
15+
<!DEBUG_INFO_SMARTCAST!>r<!>.length()
16+
<!DEBUG_INFO_SMARTCAST!>q<!>.length()
17+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
18+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ r: kotlin.String?, /*2*/ q: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fun x(p: String): Boolean { return p == "abc" }
2+
3+
public fun foo(p: String?, r: String?, q: String?): Int {
4+
while(true) {
5+
q!!.length()
6+
@loop do {
7+
while(true) {
8+
p!!.length()
9+
if (x(<!DEBUG_INFO_SMARTCAST!>p<!>)) break@loop
10+
if (x(<!DEBUG_INFO_SMARTCAST!>q<!>)) break
11+
}
12+
} while (r == null)
13+
if (!x(<!DEBUG_INFO_SMARTCAST!>p<!>)) break
14+
}
15+
// Long break allows r == null
16+
r<!UNSAFE_CALL!>.<!>length()
17+
// Smart cast is possible
18+
<!DEBUG_INFO_SMARTCAST!>q<!>.length()
19+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
20+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ r: kotlin.String?, /*2*/ q: kotlin.String?): kotlin.Int
4+
internal fun x(/*0*/ p: kotlin.String): kotlin.Boolean
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public fun foo(p: String?, y: String?): Int {
2+
do {
3+
// After this !!, y. should be smartcasted in loop as well as outside
4+
y!!.length()
5+
if (p == null) break
6+
<!DEBUG_INFO_SMARTCAST!>y<!>.length()
7+
} while (true)
8+
return <!DEBUG_INFO_SMARTCAST!>y<!>.length()
9+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?, /*1*/ y: kotlin.String?): kotlin.Int
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
while(x()) {
5+
p!!.length()
6+
if (x()) break
7+
}
8+
// p is nullable because it's possible loop body is not executed at all
9+
return p<!UNSAFE_CALL!>.<!>length()
10+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
// Like whileTrue but 2 == 2 is in use
5+
while(2 == 2) {
6+
p!!.length()
7+
if (x()) break
8+
}
9+
// Smart cast should not work in this case, see KT-6284
10+
return p<!UNSAFE_CALL!>.<!>length()
11+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
// KT-6284
5+
while(true) {
6+
p!!.length()
7+
if (x()) break
8+
}
9+
// while (true) loop body is executed at least once
10+
// so p is not null here
11+
return <!DEBUG_INFO_SMARTCAST!>p<!>.length()
12+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fun x(): Boolean { return true }
2+
3+
public fun foo(p: String?): Int {
4+
while(true) {
5+
if (x()) break
6+
// We do not always reach this statement
7+
p!!.length()
8+
}
9+
// Here we have while (true) loop but p is nullable due to break before
10+
return p<!UNSAFE_CALL!>.<!>length()
11+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package
2+
3+
public fun foo(/*0*/ p: kotlin.String?): kotlin.Int
4+
internal fun x(): kotlin.Boolean

0 commit comments

Comments
 (0)