Small change in scope of variables in repeat-until

A close instruction is still inside the scope of the variables it is
closing. The extra close in a repeat-until (to close variables before
repeating the loop) was being coded outside that scope.
This commit is contained in:
Roberto I
2026-07-23 13:58:30 -03:00
parent d5bbe95584
commit 7579fc9d7e
2 changed files with 20 additions and 1 deletions

View File

@@ -1614,7 +1614,6 @@ static void repeatstat (LexState *ls, int line) {
statlist(ls);
check_match(ls, TK_UNTIL, TK_REPEAT, line);
condexit = cond(ls); /* read condition (inside scope block) */
leaveblock(fs); /* finish scope */
if (bl2.upval) { /* upvalues? */
int exit = luaK_jump(fs); /* normal exit must jump over fix */
luaK_patchtohere(fs, condexit); /* repetition must close upvalues */
@@ -1623,6 +1622,7 @@ static void repeatstat (LexState *ls, int line) {
luaK_patchtohere(fs, exit); /* normal exit comes to here */
}
luaK_patchlist(fs, condexit, repeat_init); /* close the loop */
leaveblock(fs); /* finish scope */
leaveblock(fs); /* finish loop */
}

View File

@@ -1179,6 +1179,25 @@ if rawget(_G, "T") then
end
do
-- detail in scopes of variables in the loop of 'repeat-until'
local res = {}
local function foo (a)
repeat
local x
local i <close> = setmetatable({}, {__close = function ()
res[#res + 1] = debug.getlocal(2, 2) -- get 'x'
res[#res + 1] = debug.getlocal(2, 3) -- get 'i'
a = true
end})
until a
end
foo(false)
-- loop variables still in scope when closing 'i', both when 'repeat'
-- repeats and when 'repeat' stops.
assert(res[1] == "x" and res[2] == "i" and res[3] == "x" and res[4] == "i")
end
-- to-be-closed variables in generic for loops
do