Intuitive Debugger: Inside a function, I can’t query a local variable declared outside the function

Reproduction Steps

  1. Put this in a script:
local myVar = 123
function b()
	print()
end
b()
  1. Set a breakpoint on line 3 (print)
  2. Run
  3. Add myVar to the Watch window and it will be shown as void:
    image
    image
  4. Stop
  5. Change line 3 to print(myVar)
  6. Run
  7. Now myVar will be shown on My Watches:
    image
    image
  8. Stop
  9. Change line 1 to from local myVar = 123 to myVar = 123
  10. Change back line 3 from print(myVar) to print()
  11. Run
  12. This way it will also be shown on My Watches:
    image
    image

Expected Behavior
Since myVar belongs to the function scope, it should be shown in “My Watches”

Actual Behavior
myVar is only shown in “My Watches” in two cases:

  1. If I have any reference to this variable inside the function. Ex: print(myVar).
  2. If the variable is not declared as local. This is incongruous, as print(myVar) will print the contents of the variable, regardless of whether it is declared as local or not.

Issue Area: Studio
Issue Type: Display
Impact: Moderate
Frequency: Constantly

Hi rogeriodec_games,
This behavior is a byproduct of the way Lua works. If there is a variable that is referenced in a function but is outside the function scope (but still found in the script), then Lua will implicitly capture the variable as an upvalue and “bring it into scope” of the function. At this point, the variable will show up in the Watch window, because the Lua state will contain this variable and the debugger can find it when searching for all known variables.

Thank you for your feedback, although, what little I understood from your explanation, do you mean that this is how it is and will not change? That’s it?
Because, as I showed above, the first example is the wrong one, that is, the variable local MyVar should YES be visible by the Watch window when there’s a breakpoint inside the function, even it’s not explicitly referenced inside this function, since the scope of this variable is visible inside the function.

Considering what I put above, don’t you think this is a bug?

This is intended behavior on the Lua side, yes.
I understand that this behavior seems like it doesn’t line up. Let me step back a little and explain more.
So as you are likely aware, there are 3 types of lua variables in terms of scope:
Local : The variable will only be visible inside of the current lua frame. This can mean in a script (but not inside a function, as in how myVar is defined in your examples), or inside a function.
Global : The variable will be visible anywhere inside of the script. This is the default (like when you don’t explictly mention that a variable is local)
Upvalue: This is more clearly defined as an “external local” variable. This is a variable that was automatically brought into scope by the mechanism I mentioned in my earlier reply. If there is a local variable outside of the scope of a function but it is referenced, Lua will bring this variable into the function as an upvalue.

Now, to how this works under the hood in your examples:
myVar is a local variable. It will only be visible as a local variable when it is “in scope”, as in we are in the same function or frame the variable is in. This can be illustrated if you hit a breakpoint in line 5 of your example. myVar will be visible in this case, and if you switch to the Variables tab in the Watch window, in the scope column for myVar, it will say “Local”.
Now, in your example, if line 3 says print() and you hit a breakpoint on line 3, myVar does not appear in either tab of the Watch window. This is because it is a local variable, the function we are in is a different scope than where the variable was defined, and the local variable is not used in this function.
Lastly, if line 3 says print(myVar) , Lua recognizes that myVar is a local variable that is defined elsewhere in the script (as in, it isn’t in the function). So, it brings the variable into scope as an upvalue. This is illustrated by if you go to the Variables tab in the Watch window, under the Scope column, it will say “Upvalue” instead of “Local”. In each example, the debugger is fetching all that it knows about all variables defined in the current scope, and Lua is doing what it was designed to do, so this behavior is not considered a bug.

1 Like

Okay, although I don’t agree with the practical/intuitive aspect of the problem, I do and thank you for your extensive technical explanation. So be it.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.