lua-users home
lua-l archive

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


2014-11-07 11:59 GMT+00:00 Chris Cummings <chrisc@mediamolecule.com>:
> We’ve extended LUA to support some new value types to store vectors and
> quaternions in to make it a little better for maths. Along the way, as these
> new value types contain fields (vec.x, vec.y, etc), we modified the gettable
> function to read these properties from the lua value. This basically means
> luaV_gettable now contains an case in its type check statement that says
> ‘else if ttisvec(t)’, check the field requested and return it (so mynumber =
> myvec.x or mynumber = myvec[0] work). A lot of this was based off the
> approach of the existing experimental luavec library.
>
>
>
> However, on modifying luaV_settable in the same way, we noticed the value
> passed into the function is const:
>
>
>
> void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
>
>
>
> It then gets cast to a none-const table in the table case.
>
>
>
> Does anybody have any experience modifying these bits, and any idea as to
> whether it’s safe to cast away that const so that our lua code can write to
> the value (allowing myvec.x = 10 for example), or is there a good reason
> that value is read-only.

The reason the TValue is const, is that all mutable values are handled
by references, so this const and probably a lot of code could assume
(before your addition) the TValue itself is immutable. This means when
assigning it to variables, inserting it into tables, etc., any piece
of code might use the original TValue, or make a copy, depending on
what's more appropriate locally. And it didn't matter, it was all fine
and safe either way. But not with your type

Now when you update your vector, all places where it's been used, in
variables, in tables, might either have a pointer (copied a TValue*)
to it, or might have done a value copy (copied a TValue). For example:

local v = vec(1)

local t = {v}

v.x = 2

t[2] = v

assert(t[1] == t[2])

Can you predict if the assert will pass or fail? Does t[1] point (in
C) to the same TValue as v? Does t[2]? Here the two table entries got
created differently, so maybe t[1] is v, but t[2] isn't. But the
assert may still pass like that because the two verctors have the same
value, whereas if you swap the assignment to .x and the one to t[2],
it might fail.

I don't know the Lua source code so this is pure speculation, but by
changing very fundamental semantics of values (having a mutable type
not wrapped in references), you're opening a can of worms. I
personnally wouldn't even trust the author themselves if they assured
you it's safe, unless they provided a very thorough proof or an
exhaustive set of tests showing it.