kikito/inspect.lua

custom __metatable metafield that is not nil or table breaks inspecting

IntendedConsequence opened this issue · 3 comments

So, what subject says. I was using Penlight's tablex.readonly to make tables read only (obviously) and catch mutation attempts. Apparently tablex.readonly not only sets __newindex metafields but also sets __metatable to false. Setting __metatable metafield to anything other than nil will cause getmetatable to return what's in __metatable field. Which leads us to the problem in function processRecursive:

local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)

-- if getmetatable(processed) returns false, then mt also is set to false,
-- and setmetatable call fails
local mt  = processRecursive(process, getmetatable(processed)--[[, etc]])
setmetatable(processedCopy, mt) -- boom

my solution was a simple workaround:

local mt  = processRecursive(process, getmetatable(processed)--[[, etc]])
-- solution
if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field
setmetatable(processedCopy, mt) -- no boom

it works, but perhaps it would be better to write a proper support for such cases. Maybe?

Hi, thanks for reporting this!

perhaps it would be better to write a proper support for such cases. Maybe?

I don't see a way to implement this cleanly. Would you consider sending me a PR with your change (and ideally, with a test which makes sure the problem is fixed)?

I don't see a way to implement this cleanly. Would you consider sending me a PR with your change (and ideally, with a test which makes sure the problem is fixed)?

I'll try to find time for it. Hm, how about using debug.getmetatable?

I'll try to find time for it

Thanks a lot!

how about using debug.getmetatable?

The debug package is not available in all systems. By depending on it we would make inspect.lua break on those. I'd rather avoid that if possible.