Skip to content

Breakpoints skipped when overwriting for-loop control variable with string.gsub #339

@CarlChengpy

Description

@CarlChengpy

Summary
When assigning the result of string.gsub(...) back to a for-loop control variable (line = ...), VSCode Lua Debug fails to hit breakpoints inside the loop body—even though the logic clearly runs. Rewriting the result to a different local/global variable (cleaned = ...) restores normal breakpoint behavior.


Environment


Minimal Reproducible Code:

function func(lines)
   for line in lines do
      -- Breakpoint here will NOT be hit:
      line = string.gsub(line, '#.*', '')
   end
end

Replace that line with:

      -- Breakpoint here WILL be hit:
      cleaned = string.gsub(line, '#.*', '')

And the breakpoint reliably hits.


Bytecode Comparison (luac -l -p)

Problematic case: line = string.gsub(...)

...
9       [4]     CALL    6 4 2
10      [4]     MOVE    5 6     ; line = result of gsub
...

Working case: cleaned = string.gsub(...)

...
9       [4]     CALL    6 4 2
10      [4]     SETTABUP 0 0 6 ; _ENV["cleaned"] = result
...

In the broken version, line is the loop control variable from TFORCALL. Assigning to it uses MOVE instead of SETLOCAL, and this appears to prevent the debug hook from attaching a breakpoint on that line.


Suspected Cause

The assignment line = ... is treated specially due to its relation to the for iterator. Lua internally may optimize or generate different metadata for it, and the debug extension seems to skip that line for hook registration.


Expected Behavior

Breakpoints should be respected regardless of whether the assignment target is a loop control variable or not, especially if the line clearly contains a side-effecting function call like string.gsub.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions