lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Cuero Bugot wrote:
> While playing around I found a weird behavior with metatables. I
> did not find notes about it in the manual so I guess this is a bug.
> 
> meta={}
> setmetatable(meta, meta)
> meta.__newindex=function(t, key, value) print("set", t, key, value) end
> proxy = setmetatable({}, meta)
> 
> Then if you type:
> 	proxy.test = 42
> it does not call the metamethod __newindex().
> 
> I tested it against official Lua 5.1.4 release and against 5.1.4 +
> all official patches, it has the same behavior.

Yes, this is a bug in Lua 5.1 and 5.2 in luaV_settable. The order
of the metamethod caching and table operations is wrong if a table
is its own metatable:

- luaH_set() invalidates the metamethod cache of the table.
- luaH_set() sets a key for __newindex, but with a nil value.
- fasttm() goes to luaT_gettm since there's a metatable, but the
  cache is invalidated.
- luaT_gettm() looks up the __newindex key, but finds a nil value.
- luaT_gettm() sets the cache bit indicating 'no __newindex'.
- luaV_settable() sets the value for the __newindex key.

End result: there's a __newindex metamethod, but the metamethod
cache indicates there's none. Subsequent stores won't call the
metamethod.

[Note that LuaJIT 2.0 doesn't have that bug. And it doesn't create
unused keys in proxy tables, too.]

--Mike