mirror of
https://github.com/luau-lang/luau.git
synced 2024-11-15 14:25:44 +08:00
5e0779fd57
# What's Changed? - Telemetry support for usage of any type in old/new solver - Bug fixes and flag removals with the new solver ## New Solver - Fixed constraint ordering bug to infer types more accurately - Improved inferring a call to `setmetatable()` ## VM - Restored global metatable lookup for `typeof` on lightuserdata to fix unintentional API change (Fixes #1335) --- ### Internal Contributors Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Dibri Nsofor <dnsofor@roblox.com> Co-authored-by: Jeremy Yoo <jyoo@roblox.com> Co-authored-by: Vighnesh Vijay <vvijay@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com> --------- Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Vighnesh <vvijay@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: David Cope <dcope@roblox.com> Co-authored-by: Lily Brown <lbrown@roblox.com> Co-authored-by: Vyacheslav Egorov <vegorov@roblox.com>
201 lines
5.0 KiB
C++
201 lines
5.0 KiB
C++
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
|
|
#include "ltm.h"
|
|
|
|
#include "lstate.h"
|
|
#include "lstring.h"
|
|
#include "ludata.h"
|
|
#include "ltable.h"
|
|
#include "lgc.h"
|
|
|
|
#include <string.h>
|
|
|
|
LUAU_FASTFLAGVARIABLE(LuauPreserveLudataRenaming, false)
|
|
|
|
// clang-format off
|
|
const char* const luaT_typenames[] = {
|
|
// ORDER TYPE
|
|
"nil",
|
|
"boolean",
|
|
|
|
|
|
"userdata",
|
|
"number",
|
|
"vector",
|
|
|
|
"string",
|
|
|
|
|
|
"table",
|
|
"function",
|
|
"userdata",
|
|
"thread",
|
|
"buffer",
|
|
};
|
|
|
|
const char* const luaT_eventname[] = {
|
|
// ORDER TM
|
|
|
|
"__index",
|
|
"__newindex",
|
|
"__mode",
|
|
"__namecall",
|
|
"__call",
|
|
"__iter",
|
|
"__len",
|
|
|
|
"__eq",
|
|
|
|
|
|
"__add",
|
|
"__sub",
|
|
"__mul",
|
|
"__div",
|
|
"__idiv",
|
|
"__mod",
|
|
"__pow",
|
|
"__unm",
|
|
|
|
|
|
"__lt",
|
|
"__le",
|
|
"__concat",
|
|
"__type",
|
|
"__metatable",
|
|
};
|
|
// clang-format on
|
|
|
|
static_assert(sizeof(luaT_typenames) / sizeof(luaT_typenames[0]) == LUA_T_COUNT, "luaT_typenames size mismatch");
|
|
static_assert(sizeof(luaT_eventname) / sizeof(luaT_eventname[0]) == TM_N, "luaT_eventname size mismatch");
|
|
static_assert(TM_EQ < 8, "fasttm optimization stores a bitfield with metamethods in a byte");
|
|
|
|
void luaT_init(lua_State* L)
|
|
{
|
|
int i;
|
|
for (i = 0; i < LUA_T_COUNT; i++)
|
|
{
|
|
L->global->ttname[i] = luaS_new(L, luaT_typenames[i]);
|
|
luaS_fix(L->global->ttname[i]); // never collect these names
|
|
}
|
|
for (i = 0; i < TM_N; i++)
|
|
{
|
|
L->global->tmname[i] = luaS_new(L, luaT_eventname[i]);
|
|
luaS_fix(L->global->tmname[i]); // never collect these names
|
|
}
|
|
}
|
|
|
|
/*
|
|
** function to be used with macro "fasttm": optimized for absence of
|
|
** tag methods.
|
|
*/
|
|
const TValue* luaT_gettm(Table* events, TMS event, TString* ename)
|
|
{
|
|
const TValue* tm = luaH_getstr(events, ename);
|
|
LUAU_ASSERT(event <= TM_EQ);
|
|
if (ttisnil(tm))
|
|
{ // no tag method?
|
|
events->tmcache |= cast_byte(1u << event); // cache this fact
|
|
return NULL;
|
|
}
|
|
else
|
|
return tm;
|
|
}
|
|
|
|
const TValue* luaT_gettmbyobj(lua_State* L, const TValue* o, TMS event)
|
|
{
|
|
/*
|
|
NB: Tag-methods were replaced by meta-methods in Lua 5.0, but the
|
|
old names are still around (this function, for example).
|
|
*/
|
|
Table* mt;
|
|
switch (ttype(o))
|
|
{
|
|
case LUA_TTABLE:
|
|
mt = hvalue(o)->metatable;
|
|
break;
|
|
case LUA_TUSERDATA:
|
|
mt = uvalue(o)->metatable;
|
|
break;
|
|
default:
|
|
mt = L->global->mt[ttype(o)];
|
|
}
|
|
return (mt ? luaH_getstr(mt, L->global->tmname[event]) : luaO_nilobject);
|
|
}
|
|
|
|
const TString* luaT_objtypenamestr(lua_State* L, const TValue* o)
|
|
{
|
|
if (FFlag::LuauPreserveLudataRenaming)
|
|
{
|
|
// Userdata created by the environment can have a custom type name set in the individual metatable
|
|
// If there is no custom name, 'userdata' is returned
|
|
if (ttisuserdata(o) && uvalue(o)->tag != UTAG_PROXY && uvalue(o)->metatable)
|
|
{
|
|
const TValue* type = luaH_getstr(uvalue(o)->metatable, L->global->tmname[TM_TYPE]);
|
|
|
|
if (ttisstring(type))
|
|
return tsvalue(type);
|
|
|
|
return L->global->ttname[ttype(o)];
|
|
}
|
|
|
|
// Tagged lightuserdata can be named using lua_setlightuserdataname
|
|
if (ttislightuserdata(o))
|
|
{
|
|
int tag = lightuserdatatag(o);
|
|
|
|
if (unsigned(tag) < LUA_LUTAG_LIMIT)
|
|
{
|
|
if (const TString* name = L->global->lightuserdataname[tag])
|
|
return name;
|
|
}
|
|
}
|
|
|
|
// For all types except userdata and table, a global metatable can be set with a global name override
|
|
if (Table* mt = L->global->mt[ttype(o)])
|
|
{
|
|
const TValue* type = luaH_getstr(mt, L->global->tmname[TM_TYPE]);
|
|
|
|
if (ttisstring(type))
|
|
return tsvalue(type);
|
|
}
|
|
|
|
return L->global->ttname[ttype(o)];
|
|
}
|
|
else
|
|
{
|
|
if (ttisuserdata(o) && uvalue(o)->tag != UTAG_PROXY && uvalue(o)->metatable)
|
|
{
|
|
const TValue* type = luaH_getstr(uvalue(o)->metatable, L->global->tmname[TM_TYPE]);
|
|
|
|
if (ttisstring(type))
|
|
return tsvalue(type);
|
|
}
|
|
else if (ttislightuserdata(o))
|
|
{
|
|
int tag = lightuserdatatag(o);
|
|
|
|
if (unsigned(tag) < LUA_LUTAG_LIMIT)
|
|
{
|
|
const TString* name = L->global->lightuserdataname[tag];
|
|
|
|
if (name)
|
|
return name;
|
|
}
|
|
}
|
|
else if (Table* mt = L->global->mt[ttype(o)])
|
|
{
|
|
const TValue* type = luaH_getstr(mt, L->global->tmname[TM_TYPE]);
|
|
|
|
if (ttisstring(type))
|
|
return tsvalue(type);
|
|
}
|
|
|
|
return L->global->ttname[ttype(o)];
|
|
}
|
|
}
|
|
|
|
const char* luaT_objtypename(lua_State* L, const TValue* o)
|
|
{
|
|
return getstr(luaT_objtypenamestr(L, o));
|
|
}
|