Calls cannot be tail in the scope of a to-be-closed variable
A to-be-closed variable must be closed when a block ends, so even a 'return foo()' cannot directly returns the results of 'foo'; the function must close the scope before returning.
This commit is contained in:
@@ -53,6 +53,7 @@ typedef struct BlockCnt {
|
||||
lu_byte nactvar; /* # active locals outside the block */
|
||||
lu_byte upval; /* true if some variable in the block is an upvalue */
|
||||
lu_byte isloop; /* true if 'block' is a loop */
|
||||
lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */
|
||||
} BlockCnt;
|
||||
|
||||
|
||||
@@ -510,6 +511,7 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
|
||||
bl->firstlabel = fs->ls->dyd->label.n;
|
||||
bl->firstgoto = fs->ls->dyd->gt.n;
|
||||
bl->upval = 0;
|
||||
bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc);
|
||||
bl->previous = fs->bl;
|
||||
fs->bl = bl;
|
||||
lua_assert(fs->freereg == fs->nactvar);
|
||||
@@ -1631,6 +1633,7 @@ static void tocloselocalstat (LexState *ls) {
|
||||
checknext(ls, '=');
|
||||
exp1(ls, 0);
|
||||
markupval(fs, fs->nactvar);
|
||||
fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
|
||||
adjustlocalvars(ls, 1);
|
||||
luaK_codeABC(fs, OP_TBC, fs->nactvar - 1, 0, 0);
|
||||
}
|
||||
@@ -1701,7 +1704,7 @@ static void retstat (LexState *ls) {
|
||||
nret = explist(ls, &e); /* optional return values */
|
||||
if (hasmultret(e.k)) {
|
||||
luaK_setmultret(fs, &e);
|
||||
if (e.k == VCALL && nret == 1) { /* tail call? */
|
||||
if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */
|
||||
SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
|
||||
lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user