aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-02-28 10:10:27 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-02-28 10:10:27 -0300
commit127a8e80fe0d74efd26994b3877cdc77b712ea56 (patch)
tree12b8b3be0660884f4a1075af37e0f58cbd43a3d3
parentf9e35627ed26dff4114a1d01ff113d8b4cc91ab5 (diff)
downloadlua-127a8e80fe0d74efd26994b3877cdc77b712ea56.tar.gz
lua-127a8e80fe0d74efd26994b3877cdc77b712ea56.tar.bz2
lua-127a8e80fe0d74efd26994b3877cdc77b712ea56.zip
'__close' gets no error object if there is no error
Instead of receiving nil as a second argument, __close metamethods are called with just one argument when there are no errors.
-rw-r--r--ldo.c4
-rw-r--r--lfunc.c32
-rw-r--r--manual/manual.of7
-rw-r--r--testes/locals.lua44
4 files changed, 60 insertions, 27 deletions
diff --git a/ldo.c b/ldo.c
index 4705b26c..3ddc5a4c 100644
--- a/ldo.c
+++ b/ldo.c
@@ -111,10 +111,6 @@ void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop) {
111 setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); 111 setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
112 break; 112 break;
113 } 113 }
114 case LUA_OK: { /* special case only for closing upvalues */
115 setnilvalue(s2v(oldtop)); /* no error message */
116 break;
117 }
118 default: { 114 default: {
119 lua_assert(errorstatus(errcode)); /* real error */ 115 lua_assert(errorstatus(errcode)); /* real error */
120 setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */ 116 setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */
diff --git a/lfunc.c b/lfunc.c
index d6853ff8..c62a5d23 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -100,21 +100,23 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
100 100
101 101
102/* 102/*
103** Call closing method for object 'obj' with error message 'err'. The 103** Call closing method for object 'obj' with error object 'err'. The
104** boolean 'yy' controls whether the call is yieldable. 104** boolean 'yy' controls whether the call is yieldable.
105** (This function assumes EXTRA_STACK.) 105** (This function assumes EXTRA_STACK.)
106*/ 106*/
107static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { 107static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) {
108 StkId top = L->top.p; 108 StkId top = L->top.p;
109 StkId func = top;
109 const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); 110 const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
110 setobj2s(L, top, tm); /* will call metamethod... */ 111 setobj2s(L, top++, tm); /* will call metamethod... */
111 setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ 112 setobj2s(L, top++, obj); /* with 'self' as the 1st argument */
112 setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ 113 if (err != NULL) /* if there was an error... */
113 L->top.p = top + 3; /* add function and arguments */ 114 setobj2s(L, top++, err); /* then error object will be 2nd argument */
115 L->top.p = top; /* add function and arguments */
114 if (yy) 116 if (yy)
115 luaD_call(L, top, 0); 117 luaD_call(L, func, 0);
116 else 118 else
117 luaD_callnoyield(L, top, 0); 119 luaD_callnoyield(L, func, 0);
118} 120}
119 121
120 122
@@ -144,11 +146,17 @@ static void prepcallclosemth (lua_State *L, StkId level, TStatus status,
144 int yy) { 146 int yy) {
145 TValue *uv = s2v(level); /* value being closed */ 147 TValue *uv = s2v(level); /* value being closed */
146 TValue *errobj; 148 TValue *errobj;
147 if (status == CLOSEKTOP) 149 switch (status) {
148 errobj = &G(L)->nilvalue; /* error object is nil */ 150 case LUA_OK:
149 else { /* 'luaD_seterrorobj' will set top to level + 2 */ 151 L->top.p = level + 1; /* call will be at this level */
150 errobj = s2v(level + 1); /* error object goes after 'uv' */ 152 /* FALLTHROUGH */
151 luaD_seterrorobj(L, status, level + 1); /* set error object */ 153 case CLOSEKTOP: /* don't need to change top */
154 errobj = NULL; /* no error object */
155 break;
156 default: /* 'luaD_seterrorobj' will set top to level + 2 */
157 errobj = s2v(level + 1); /* error object goes after 'uv' */
158 luaD_seterrorobj(L, status, level + 1); /* set error object */
159 break;
152 } 160 }
153 callclosemethod(L, uv, errobj, yy); 161 callclosemethod(L, uv, errobj, yy);
154} 162}
diff --git a/manual/manual.of b/manual/manual.of
index a55c7b49..ff4e79fe 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -1612,10 +1612,11 @@ or exiting by an error.
1612Here, to @emph{close} a value means 1612Here, to @emph{close} a value means
1613to call its @idx{__close} metamethod. 1613to call its @idx{__close} metamethod.
1614When calling the metamethod, 1614When calling the metamethod,
1615the value itself is passed as the first argument 1615the value itself is passed as the first argument.
1616and the error object that caused the exit (if any) 1616If there was an error,
1617the error object that caused the exit
1617is passed as a second argument; 1618is passed as a second argument;
1618if there was no error, the second argument is @nil. 1619otherwise, there is no second argument.
1619 1620
1620The value assigned to a to-be-closed variable 1621The value assigned to a to-be-closed variable
1621must have a @idx{__close} metamethod 1622must have a @idx{__close} metamethod
diff --git a/testes/locals.lua b/testes/locals.lua
index 090d846b..910deb8a 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -280,6 +280,32 @@ do
280end 280end
281 281
282 282
283do -- testing presence of second argument
284 local function foo (howtoclose, obj, n)
285 local ca -- copy of 'a' visible inside its close metamethod
286 do
287 local a <close> = func2close(function (...)
288 local t = table.pack(...)
289 assert(select("#", ...) == n)
290 assert(t.n == n and t[1] == ca and (t.n < 2 or t[2] == obj))
291 ca = 15 -- final value to be returned if howtoclose=="scope"
292 end)
293 ca = a
294 if howtoclose == "ret" then return obj -- 'a' closed by return
295 elseif howtoclose == "err" then error(obj) -- 'a' closed by error
296 end
297 end -- 'a' closed by end of scope
298 return ca -- ca now should be 15
299 end
300 -- with no errors, closing methods receive no extra argument
301 assert(foo("scope", nil, 1) == 15) -- close by end of scope
302 assert(foo("ret", 32, 1) == 32) -- close by return
303 -- with errors, they do
304 local st, msg = pcall(foo, "err", 23, 2) -- close by error
305 assert(not st and msg == 23)
306end
307
308
283-- testing to-be-closed x compile-time constants 309-- testing to-be-closed x compile-time constants
284-- (there were some bugs here in Lua 5.4-rc3, due to a confusion 310-- (there were some bugs here in Lua 5.4-rc3, due to a confusion
285-- between compile levels and stack levels of variables) 311-- between compile levels and stack levels of variables)
@@ -865,8 +891,10 @@ do
865 if extra then 891 if extra then
866 extrares = co() -- runs until first (extra) yield 892 extrares = co() -- runs until first (extra) yield
867 end 893 end
868 local res = table.pack(co()) -- runs until yield inside '__close' 894 local res = table.pack(co()) -- runs until "regular" yield
869 assert(res.n == 2 and res[2] == nil) 895 -- regular yield will yield all values passed to the close function;
896 -- without errors, that is only the object being closed.
897 assert(res.n == 1 and type(res[1]) == "table")
870 local res2 = table.pack(co()) -- runs until end of function 898 local res2 = table.pack(co()) -- runs until end of function
871 assert(res2.n == t.n) 899 assert(res2.n == t.n)
872 for i = 1, #t do 900 for i = 1, #t do
@@ -879,10 +907,10 @@ do
879 end 907 end
880 908
881 local function foo () 909 local function foo ()
882 local x <close> = func2close(coroutine.yield) 910 local x <close> = func2close(coroutine.yield) -- "regular" yield
883 local extra <close> = func2close(function (self) 911 local extra <close> = func2close(function (self)
884 assert(self == extrares) 912 assert(self == extrares)
885 coroutine.yield(100) 913 coroutine.yield(100) -- first (extra) yield
886 end) 914 end)
887 extrares = extra 915 extrares = extra
888 return table.unpack{10, x, 30} 916 return table.unpack{10, x, 30}
@@ -891,21 +919,21 @@ do
891 assert(extrares == 100) 919 assert(extrares == 100)
892 920
893 local function foo () 921 local function foo ()
894 local x <close> = func2close(coroutine.yield) 922 local x <close> = func2close(coroutine.yield) -- "regular" yield
895 return 923 return
896 end 924 end
897 check(foo, false) 925 check(foo, false)
898 926
899 local function foo () 927 local function foo ()
900 local x <close> = func2close(coroutine.yield) 928 local x <close> = func2close(coroutine.yield) -- "regular" yield
901 local y, z = 20, 30 929 local y, z = 20, 30
902 return x 930 return x
903 end 931 end
904 check(foo, false, "x") 932 check(foo, false, "x")
905 933
906 local function foo () 934 local function foo ()
907 local x <close> = func2close(coroutine.yield) 935 local x <close> = func2close(coroutine.yield) -- "regular" yield
908 local extra <close> = func2close(coroutine.yield) 936 local extra <close> = func2close(coroutine.yield) -- extra yield
909 return table.unpack({}, 1, 100) -- 100 nils 937 return table.unpack({}, 1, 100) -- 100 nils
910 end 938 end
911 check(foo, true, table.unpack({}, 1, 100)) 939 check(foo, true, table.unpack({}, 1, 100))