Description
The Type-Checking for setmetatable
bugs out when you try to use another table with a metatable attached ({@ metatable t, m}
), preventing the autocompleter from working properly, especially when using the __index
metamethod.
Repro
--!strict
local Foo = {}
Foo.__index = Foo
Foo.A = 1
function new1()
return setmetatable({}, Foo)
end
local Bar = {}
Bar.__index = Bar
Bar.B = 2
setmetatable(Bar, Foo)
function new2()
return setmetatable(new1(), Bar) -- 'setmetatable should take a table'
end
print(new2().B) -- Bugged
Additional Info
This is the specific bug that prevents writing Strictly-Typed OOP as it prevents the SubClass
type from reading methods from itself in the below examples.
SuperClass (Not Bugged)
--!strict
local SuperClass = {}
SuperClass.__index = SuperClass
type self = {
SuperValue: number
}
export type SuperClass = typeof(setmetatable({} :: self, SuperClass))
function SuperClass.new(): SuperClass
local self: SuperClass = setmetatable({} :: self, SuperClass)
self.SuperValue = 1
return self
end
function SuperClass:Foo(): ()
local self: SuperClass = self
print("Foo")
end
return SuperClass
SubClass
--!strict
local SuperClass = require(SuperClass)
local SubClass = {}
SubClass.__index = SubClass
setmetatable(SubClass, SuperClass)
type self = SuperClass.SuperClass & {
SubValue: number
}
export type SubClass = typeof(setmetatable({} :: self, SubClass))
function SubClass.new(): SubClass
local self = setmetatable(SuperClass.new() :: self, SubClass)
self.SuperValue = 1
self.SubValue = 1
self:Bar() -- Nope
return self
end
function SubClass:Bar(): ()
local self: SubClass = self
print("Bar")
end
return SubClass