aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-29 13:15:54 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-12-29 13:15:54 -0300
commit4bd10b6fe81c0a56eb9e01e24fba10e655966870 (patch)
treeff21703d9f06a0dd4ca4f3317dd0cb7b048c9b8d
parent59e565d9555c07e82808d8c1db8f4f4d159b5e5c (diff)
downloadlua-4bd10b6fe81c0a56eb9e01e24fba10e655966870.tar.gz
lua-4bd10b6fe81c0a56eb9e01e24fba10e655966870.tar.bz2
lua-4bd10b6fe81c0a56eb9e01e24fba10e655966870.zip
Better error messages for calling non-callable objects
When available, use the calling code to find a suitable name for what was being called; this is particularly useful for errors of non-callable metamethods. This commit also improved the debug information for order metamethods.
-rw-r--r--ldebug.c23
-rw-r--r--ldebug.h1
-rw-r--r--ldo.c2
-rw-r--r--testes/db.lua6
-rw-r--r--testes/errors.lua14
-rw-r--r--testes/locals.lua17
6 files changed, 52 insertions, 11 deletions
diff --git a/ldebug.c b/ldebug.c
index 8cb00e51..819550d7 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -629,12 +629,10 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
629 case OP_LEN: tm = TM_LEN; break; 629 case OP_LEN: tm = TM_LEN; break;
630 case OP_CONCAT: tm = TM_CONCAT; break; 630 case OP_CONCAT: tm = TM_CONCAT; break;
631 case OP_EQ: tm = TM_EQ; break; 631 case OP_EQ: tm = TM_EQ; break;
632 case OP_LT: case OP_LE: case OP_LTI: case OP_LEI: 632 /* no cases for OP_EQI and OP_EQK, as they don't call metamethods */
633 *name = "order"; /* '<=' can call '__lt', etc. */ 633 case OP_LT: case OP_LTI: case OP_GTI: tm = TM_LT; break;
634 return "metamethod"; 634 case OP_LE: case OP_LEI: case OP_GEI: tm = TM_LE; break;
635 case OP_CLOSE: case OP_RETURN: 635 case OP_CLOSE: case OP_RETURN: tm = TM_CLOSE; break;
636 *name = "close";
637 return "metamethod";
638 default: 636 default:
639 return NULL; /* cannot find a reasonable name */ 637 return NULL; /* cannot find a reasonable name */
640 } 638 }
@@ -697,6 +695,19 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
697} 695}
698 696
699 697
698l_noret luaG_callerror (lua_State *L, const TValue *o) {
699 CallInfo *ci = L->ci;
700 const char *name = NULL; /* to avoid warnings */
701 const char *what = (isLua(ci)) ? funcnamefromcode(L, ci, &name) : NULL;
702 if (what != NULL) {
703 const char *t = luaT_objtypename(L, o);
704 luaG_runerror(L, "%s '%s' is not callable (a %s value)", what, name, t);
705 }
706 else
707 luaG_typeerror(L, o, "call");
708}
709
710
700l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) { 711l_noret luaG_forerror (lua_State *L, const TValue *o, const char *what) {
701 luaG_runerror(L, "bad 'for' %s (number expected, got %s)", 712 luaG_runerror(L, "bad 'for' %s (number expected, got %s)",
702 what, luaT_objtypename(L, o)); 713 what, luaT_objtypename(L, o));
diff --git a/ldebug.h b/ldebug.h
index a0a58486..55b3ae09 100644
--- a/ldebug.h
+++ b/ldebug.h
@@ -31,6 +31,7 @@ LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
31 StkId *pos); 31 StkId *pos);
32LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, 32LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
33 const char *opname); 33 const char *opname);
34LUAI_FUNC l_noret luaG_callerror (lua_State *L, const TValue *o);
34LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o, 35LUAI_FUNC l_noret luaG_forerror (lua_State *L, const TValue *o,
35 const char *what); 36 const char *what);
36LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, 37LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,
diff --git a/ldo.c b/ldo.c
index d39edab0..5e3828f4 100644
--- a/ldo.c
+++ b/ldo.c
@@ -372,7 +372,7 @@ void luaD_tryfuncTM (lua_State *L, StkId func) {
372 const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); 372 const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL);
373 StkId p; 373 StkId p;
374 if (unlikely(ttisnil(tm))) 374 if (unlikely(ttisnil(tm)))
375 luaG_typeerror(L, s2v(func), "call"); /* nothing to call */ 375 luaG_callerror(L, s2v(func)); /* nothing to call */
376 for (p = L->top; p > func; p--) /* open space for metamethod */ 376 for (p = L->top; p > func; p--) /* open space for metamethod */
377 setobjs2s(L, p, p-1); 377 setobjs2s(L, p, p-1);
378 L->top++; /* stack space pre-allocated by the caller */ 378 L->top++; /* stack space pre-allocated by the caller */
diff --git a/testes/db.lua b/testes/db.lua
index fdb0da4a..ce559ad9 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -823,8 +823,10 @@ assert(a + 30000 == "add" and a - 3.0 == "sub" and a * 3.0 == "mul" and
823 -a == "unm" and #a == "len" and a & 3 == "band") 823 -a == "unm" and #a == "len" and a & 3 == "band")
824assert(a|3 == "bor" and 3~a == "bxor" and a<<3 == "shl" and a>>1 == "shr") 824assert(a|3 == "bor" and 3~a == "bxor" and a<<3 == "shl" and a>>1 == "shr")
825assert (a==b and a.op == "eq") 825assert (a==b and a.op == "eq")
826assert (a>=b and a.op == "order") 826assert (a>=b and a.op == "le")
827assert (a>b and a.op == "order") 827assert ("x">=a and a.op == "le")
828assert (a>b and a.op == "lt")
829assert (a>10 and a.op == "lt")
828assert(~a == "bnot") 830assert(~a == "bnot")
829 831
830do -- testing for-iterator name 832do -- testing for-iterator name
diff --git a/testes/errors.lua b/testes/errors.lua
index a3f07021..4249f570 100644
--- a/testes/errors.lua
+++ b/testes/errors.lua
@@ -24,8 +24,9 @@ local function doit (s)
24end 24end
25 25
26 26
27local function checkmessage (prog, msg) 27local function checkmessage (prog, msg, debug)
28 local m = doit(prog) 28 local m = doit(prog)
29 if debug then print(m) end
29 assert(string.find(m, msg, 1, true)) 30 assert(string.find(m, msg, 1, true))
30end 31end
31 32
@@ -120,6 +121,17 @@ assert(not string.find(doit"a={13}; local bbbb=1; a[bbbb](3)", "'bbbb'"))
120checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number") 121checkmessage("a={13}; local bbbb=1; a[bbbb](3)", "number")
121checkmessage("a=(1)..{}", "a table value") 122checkmessage("a=(1)..{}", "a table value")
122 123
124-- calls
125checkmessage("local a; a(13)", "local 'a'")
126checkmessage([[
127 local a = setmetatable({}, {__add = 34})
128 a = a + 1
129]], "metamethod 'add'")
130checkmessage([[
131 local a = setmetatable({}, {__lt = {}})
132 a = a > a
133]], "metamethod 'lt'")
134
123-- tail calls 135-- tail calls
124checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'") 136checkmessage("local a={}; return a.bbbb(3)", "field 'bbbb'")
125checkmessage("a={}; do local a=1 end; return a:bbbb(3)", "method 'bbbb'") 137checkmessage("a={}; do local a=1 end; return a:bbbb(3)", "method 'bbbb'")
diff --git a/testes/locals.lua b/testes/locals.lua
index 1b43609b..add023ca 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -459,7 +459,22 @@ do -- errors due to non-closable values
459 getmetatable(xyz).__close = nil -- remove metamethod 459 getmetatable(xyz).__close = nil -- remove metamethod
460 end 460 end
461 local stat, msg = pcall(foo) 461 local stat, msg = pcall(foo)
462 assert(not stat and string.find(msg, "attempt to call a nil value")) 462 assert(not stat and string.find(msg, "metamethod 'close'"))
463
464 local function foo ()
465 local a1 <close> = func2close(function (_, msg)
466 assert(string.find(msg, "number value"))
467 error(12)
468 end)
469 local a2 <close> = setmetatable({}, {__close = print})
470 local a3 <close> = func2close(function (_, msg)
471 assert(msg == nil)
472 error(123)
473 end)
474 getmetatable(a2).__close = 4 -- invalidate metamethod
475 end
476 local stat, msg = pcall(foo)
477 assert(not stat and msg == 12)
463end 478end
464 479
465 480