Access metatables of UserValue and Table
Closed this issue · 7 comments
Background: I wanted to implement a library function in rust called "is_callable". It should check whether a Lua value is (a) a function or (b) some Lua object with a metatable that contains a callable __call entry.
I was able to get the metatables of tables from rust/rlua, but not for other types of Lua values...
Hi,
The metatables of userdata instances are deliberately protected from Lua code (by setting a dummy __metatable
entry in the metatable). You could get around it (I think) using debug.getmetatable()
, but you'd have to enable the debug
library (use Lua::new_with_debug
instead of Lua::new
); however there's a lot of functionality in debug
which can break safety assumptions made by the Rust code.
As far as other types, this is just how Lua is (with the exception of strings, where the metatable points to the _G.string
, so "":lower()
is the same as string.lower("")
.
Thank you for your reply! I understand that and don't wish to break rust's safety assumptions.
I just noticed there is no reliable way in Lua to detect whether an object is callable, except by trying and catching exceptions. So, I wish to implement an is_callable function, in rust. But I cannot get the metatable for all Lua types from rust, hence this question whether something could be done about it or if I'm missing something. :-)
Oops, my apologies! I see that I misread (or didn't quite read properly) your question.
I agree that there isn't a way to do so at the moment (other than the clunky option of loading the debug library and calling debug.getmetatable
!), but I don't see a particularly good reason not to add a get_metatable
method to AnyUserData
. I think @kyren may agree based on the comment on #173 unless I'm missing a reason why it might be unsafe for userdata specifically from the Rust side.
Actually the metatables for userdata are full of landmines and rlua assumes they're in very particular states to maintain safety, it would be better probably to do something other than give the plain metatable back or it should at least be unsafe.
Aha, I did wonder. Would something like a has_metamethod(&self, method: MetaMethod) -> bool
would be fine?
Or would it be safe enough to have a more general get_metamethod(&self, method: MetaMethod) -> Option<Function>
? The worst thing I can think of that you might do with that is call it with inappropriate arguments, but that should just result in an error via FromLuaMulti - I haven't looked into whether metamethods are handled differently from ordinary methods. I may have just made another bad assumption, though!
Hmm, for "my" problem the first one would probably suffice.
rlua is going to be deprecated soon and this feature is already supported by mlua