Problem with smart cast?

I ran into an issue today with smart cast of two same-named variables in different scopes.
A minimal reproduction example is like this:

fun main() {
    run {
        var modifiedVariable: Double? = null
        for (i in 1..3) {
            if (modifiedVariable != null) {
                println(i + modifiedVariable)
            }
            modifiedVariable = i + 0.1
        }
    }

    run {
        var modifiedVariable: Double? = null
        for (i in 1..3) {
            if (modifiedVariable != null) {
                println(i + modifiedVariable)
            }
            modifiedVariable = i + 0.1
        }
    }
}

The second block has a compile error “Smart cast to ‘Double’ is impossible, because ‘modifiedVariable’ is a local variable that is captured by a changing closure”.
That changing closure seems to be the first run{} block, except that that one never can change the variable local to the second block.
Indeed commenting out the first block fixes the compile error in the second, or renaming the variable to modifiedVariable2 in one of the blocks also fixes the error.
Is this a bug in the compiler or am I missing something?

Odd. Maybe it’s a bug related to inlining.

Here’s a runnable example for others to play around with and edit without leaving the forum:

fun main() {
    run {
        var modifiedVariable: Double? = null
        for (i in 1..3) {
            if (modifiedVariable != null) {
                println(i + modifiedVariable)
            }
            modifiedVariable = i + 0.1
        }
    }

    run {
        var modifiedVariable: Double? = null
        for (i in 1..3) {
            if (modifiedVariable != null) {
                println(i + modifiedVariable)
            }
            modifiedVariable = i + 0.1
        }
    }
}

Thanks for the runnable example! I’ve reported it as an issue here: https://youtrack.jetbrains.com/issue/KT-36681

1 Like