[FIR] Local variable assignment must be propagated before loops
When performing lookahead for local variable assignments, make sure assignments taking place within loops are being propagated before loops. This makes sure smartcasts within non-inline declarations before the loop are disallowed. ^KT-63867 Fixed
This commit is contained in:
+3
@@ -333,6 +333,9 @@ internal class FirLocalVariableAssignmentAnalyzer {
|
||||
override fun visitLoop(loop: FirLoop, data: MiniCfgData) {
|
||||
val entry = data.flow
|
||||
val assignedInside = visitElementWithLexicalScope(loop, data)
|
||||
// Now that the inner variables have been discarded, the rest can be propagated to prevent smartcasts
|
||||
// in declarations that came before this loop.
|
||||
entry.recordAssignments(assignedInside)
|
||||
// All forks in the loop should have the same set of variables assigned later, equal to the set
|
||||
// at the start of the loop.
|
||||
data.flow.recordAssignments(assignedInside)
|
||||
|
||||
Vendored
+36
-3
@@ -468,7 +468,7 @@ fun test48() {
|
||||
var x: Any = materialize()
|
||||
runWithoutContract {
|
||||
while (x is String) {
|
||||
x.length
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
@@ -536,7 +536,7 @@ fun test55() {
|
||||
runWithoutContract {
|
||||
for (i in 1..3) {
|
||||
require(x is String)
|
||||
x.length
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
@@ -619,4 +619,37 @@ fun test63() {
|
||||
x?.length ?: -1
|
||||
x = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun test64() {
|
||||
var x: Any = materialize()
|
||||
require(x is String)
|
||||
runWithoutContract {
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||
}
|
||||
for (i in 1..3) {
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
|
||||
fun test65() {
|
||||
var x: Any = materialize()
|
||||
require(x is String)
|
||||
atLeastOnce {
|
||||
x.length
|
||||
}
|
||||
for (i in 1..3) {
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
|
||||
fun test66() {
|
||||
var x: Any = materialize()
|
||||
require(x is String)
|
||||
exactlyOnce {
|
||||
x.length
|
||||
}
|
||||
for (i in 1..3) {
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+33
@@ -620,3 +620,36 @@ fun test63() {
|
||||
x = null
|
||||
}
|
||||
}
|
||||
|
||||
fun test64() {
|
||||
var x: Any = materialize()
|
||||
require(x is String)
|
||||
runWithoutContract {
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||
}
|
||||
for (i in 1..3) {
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
|
||||
fun test65() {
|
||||
var x: Any = materialize()
|
||||
require(x is String)
|
||||
atLeastOnce {
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||
}
|
||||
for (i in 1..3) {
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
|
||||
fun test66() {
|
||||
var x: Any = materialize()
|
||||
require(x is String)
|
||||
exactlyOnce {
|
||||
<!SMARTCAST_IMPOSSIBLE!>x<!>.length
|
||||
}
|
||||
for (i in 1..3) {
|
||||
x = 10
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user