Skip to content

Commit 47cffdc

Browse files
committed
Bug: tbc variables in "for" loops don't avoid tail calls
1 parent 36de01d commit 47cffdc

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

lparser.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,17 @@ static void markupval (FuncState *fs, int level) {
416416
}
417417

418418

419+
/*
420+
** Mark that current block has a to-be-closed variable.
421+
*/
422+
static void marktobeclosed (FuncState *fs) {
423+
BlockCnt *bl = fs->bl;
424+
bl->upval = 1;
425+
bl->insidetbc = 1;
426+
fs->needclose = 1;
427+
}
428+
429+
419430
/*
420431
** Find a variable with the given name 'n'. If it is an upvalue, add
421432
** this upvalue into all intermediate functions. If it is a global, set
@@ -1599,7 +1610,7 @@ static void forlist (LexState *ls, TString *indexname) {
15991610
line = ls->linenumber;
16001611
adjust_assign(ls, 4, explist(ls, &e), &e);
16011612
adjustlocalvars(ls, 4); /* control variables */
1602-
markupval(fs, fs->nactvar); /* last control var. must be closed */
1613+
marktobeclosed(fs); /* last control var. must be closed */
16031614
luaK_checkstack(fs, 3); /* extra space to call generator */
16041615
forbody(ls, base, line, nvars - 4, 1);
16051616
}
@@ -1703,11 +1714,9 @@ static int getlocalattribute (LexState *ls) {
17031714
}
17041715

17051716

1706-
static void checktoclose (LexState *ls, int level) {
1717+
static void checktoclose (FuncState *fs, int level) {
17071718
if (level != -1) { /* is there a to-be-closed variable? */
1708-
FuncState *fs = ls->fs;
1709-
markupval(fs, level + 1);
1710-
fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
1719+
marktobeclosed(fs);
17111720
luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0);
17121721
}
17131722
}
@@ -1751,7 +1760,7 @@ static void localstat (LexState *ls) {
17511760
adjust_assign(ls, nvars, nexps, &e);
17521761
adjustlocalvars(ls, nvars);
17531762
}
1754-
checktoclose(ls, toclose);
1763+
checktoclose(fs, toclose);
17551764
}
17561765

17571766

testes/locals.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,29 @@ do
335335
end
336336

337337

338+
do
339+
-- bug in 5.4.3: previous condition (calls cannot be tail in the
340+
-- scope of to-be-closed variables) must be valid for tbc variables
341+
-- created by 'for' loops.
342+
343+
local closed = false
344+
345+
local function foo ()
346+
return function () return true end, 0, 0,
347+
func2close(function () closed = true end)
348+
end
349+
350+
local function tail() return closed end
351+
352+
local function foo1 ()
353+
for k in foo() do return tail() end
354+
end
355+
356+
assert(foo1() == false)
357+
assert(closed == true)
358+
end
359+
360+
338361
do print("testing errors in __close")
339362

340363
-- original error is in __close

0 commit comments

Comments
 (0)