Variable shadowing is leaked from inline block to outer scope?

Could someone explain why compiler complain the code below:

https://pl.kotl.in/yYd7UP2GS

class TreeNode() {
  var child: TreeNode? = null
}

fun test(root: TreeNode?) {
  run {
    var node: TreeNode? = root
    while (node != null) {
      node = node.child
    }
  }
  
  fun innerMethod() {
    var node: TreeNode? = root
    while (node != null) {
      // Why compile error here?
      node = node.child // Smart cast to 'TreeNode' is impossible, because 'node' is a local variable that is captured by a changing closure
    }
  }
}

fun main() {
    test(TreeNode())
}

I fix the error like below, but still don’t understand the problem.

  fun innerMethod() {
    var node1: TreeNode? = root
    while (node1 != null) {
      node1 = node1.child
    }
  }

Seems like a bug your node in innerMethod is shadowing node from test.
Where in fact node is capured by the lambda you pass to run.

Feel free to open a bug.

Your fix is very reasonable, in general shadowing variables is not a great idea anyway.

1 Like

As far as I understand, shadowing is when child scope hides the parent scope.
But in this case, they are in 2 unrelated scopes. Why the later scope can be a shadow of previous scope in this case?
Do I misunderstand something?

oh you’re right :slight_smile:

It’s still a bug.

Maybe due to the fact that run gets inlined - don’t know I’m just guessing

3 Likes

Good point! I think it’s reasonable now. Thanks for your help!

Then, how could I create a new block with a separated child scope to replace the run block?

Created a bug inline block and variable shadowing problem : KT-52427 (jetbrains.com)