Why is 'name' nil for debug.getinfo(1)

3.1k views Asked by At

I'm trying to put together a lua testing framework that lets you know the function that had the problem, but when I switched from loadstring to _G, (I switched so my test harness could see the results of the function call) my functions started using 'nil' for the function name

Why can _G not detect the name of the current function in the following code? Also, how can I get the return results from loadstring (ie the 'false' from the blah call) or set the function name when using _G (ie. Tell the lua interpreter what the function name should be)?

function run_test(one, two)
    if one ~= two then
        print(debug.getinfo(2).name..' Failed')
    end
end

function blah()
    run_test(false, true)
    return false
end

local fname = 'blah'
local status, result = pcall(_G[fname])  -- Outputs 'nil'; result is 'false'
local status, result = pcall(loadstring(fname..'()'))  -- Outputs 'blah', result is 'nil'

The main thing I need is a way to call a function using a string of the function name, be able to see the function name inside the call (for test failures to point to the function that failed, like fname = 'blah' in the code above) and be able to get the return value

local fname = 'blah'
status, result = pcall(??Call fname somehow??)
assert(status)
assert(not result)

--stdout should be "blah Failed"
1

There are 1 answers

6
lhf On

This is a limitation of the heuristics used by Lua to provide names for functions.

In Lua, all functions are anonymous. A given function can be the value of several variables: global, local, and table fields. The Lua debug system tries to find a reasonable name for a value based on where it came from by looking into the bytecode being executed.

Consider the simpler example

blah()
pcall(blah)

In the first call, the debug system sees that the function being called comes from the global blah and debug.getinfo(1).name gives the expected result, blah.

In the second call, the debug system sees that the function being called comes from the first argument to pcall but it does not look further to see where that argument came from, and debug.getinfo(1).name gives nil.

The same thing happens when you call _G[name](). All the debug system sees is a field of a table and the name of the field is too far off.

Try adding print(debug.traceback()) as the first line of blah to see another take on this explanation.