terralang / terra

Terra is a low-level system programming language that is embedded in and meta-programmed by the Lua programming language.
terralang.org
Other
2.72k stars 201 forks source link

incorrect stack trace on call from Lua #418

Open aiverson opened 4 years ago

aiverson commented 4 years ago

Running this code

local struct foo {}
local terra bar(a: foo) end
local function baz(a) return bar(a) end
local function quux() return baz(5) end
quux()

produces this stack trace

st_test.t:5: bad argument #1 to 'quux' (cannot convert 'number' to 'struct foo')
stack traceback:
        [C]: in function 'quux'
        st_test.t:5: in main chunk

The stack trace ends a frame up from the actual error, saying that a bad argument was passed to a function that doesn't take an argument, misrepresenting the origin of the function quux, and not including the position of the actual error.

XeroOl commented 4 years ago

This behavior is probably intended. It's caused due to tail call optimization. You can find the same behavior in plain Lua, and it is documented and described in the lua reference manual. https://www.lua.org/manual/5.1/manual.html#2.5.8

A call of the form return functioncall is called a tail call. Lua implements proper tail calls (or proper tail recursion): in a tail call, the called function reuses the stack entry of the calling function. Therefore, there is no limit on the number of nested tail calls that a program can execute. However, a tail call erases any debug information about the calling function.

For example,

local function bar() error("uh oh") end
local function baz(a) return bar(a) end
local function quux() return baz(5) end
quux()

produces

luajit: test.lua:1: uh oh
stack traceback:
    [C]: in function 'error'
    test.lua:1: in function 'quux'
    test.lua:4: in main chunk

under luajit. Running with plain lua reveals what's happening:

lua5.1: test.lua:1: uh oh
stack traceback:
    [C]: in function 'error'
    test.lua:1: in function <test.lua:1>
    (tail call): ?
    (tail call): ?
    test.lua:4: in main chunk

Tail calls hide information from the call stack, which causes the information to be hidden.