Skip to content

Commit

Permalink
fix: do not close nested types too early
Browse files Browse the repository at this point in the history
Closes #775.
  • Loading branch information
hishamhm committed Aug 13, 2024
1 parent 07c9ed4 commit e178c42
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 20 deletions.
20 changes: 20 additions & 0 deletions spec/declaration/record_function_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,25 @@ describe("record function", function()
]], {}, {
{ y = 7, msg = "different number of return values: got 1, expected 0" },
}))

it("does not close nested types too early (regression test for #775)", util.check([[
-- declare a nested record
local record mul
record Fil
mime: function(Fil)
end
end
-- declare an alias
local type Fil = mul.Fil
-- this works
function mul.Fil:new_method1(self: Fil)
end
-- should work as well for alias
function Fil:new_method2(self: Fil)
end
]]))
end)
end)
37 changes: 27 additions & 10 deletions tl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12277,22 +12277,38 @@ self:expand_type(node, values, elements) })
end,
}

function TypeChecker:begin_temporary_record_types(typ)
self:add_var(nil, "@self", type_at(typ, a_type(typ, "typedecl", { def = typ })))

for fname, ftype in fields_of(typ) do
if ftype.typename == "typealias" then
self:resolve_nominal(ftype.alias_to)
self:add_var(nil, fname, ftype)
elseif ftype.typename == "typedecl" then
self:add_var(nil, fname, ftype)
end
end
end

function TypeChecker:end_temporary_record_types(typ)


local scope = self.st[#self.st]
scope.vars["@self"] = nil
for fname, ftype in fields_of(typ) do
if ftype.typename == "typealias" or ftype.typename == "typedecl" then
scope.vars[fname] = nil
end
end
end

local visit_type
visit_type = {
cbs = {
["record"] = {
before = function(self, typ)
self:begin_scope()
self:add_var(nil, "@self", type_at(typ, a_type(typ, "typedecl", { def = typ })))

for fname, ftype in fields_of(typ) do
if ftype.typename == "typealias" then
self:resolve_nominal(ftype.alias_to)
self:add_var(nil, fname, ftype)
elseif ftype.typename == "typedecl" then
self:add_var(nil, fname, ftype)
end
end
self:begin_temporary_record_types(typ)
end,
after = function(self, typ, children)
local i = 1
Expand Down Expand Up @@ -12386,6 +12402,7 @@ self:expand_type(node, values, elements) })
end
end

self:end_temporary_record_types(typ)
self:end_scope()

return typ
Expand Down
37 changes: 27 additions & 10 deletions tl.tl
Original file line number Diff line number Diff line change
Expand Up @@ -12277,22 +12277,38 @@ do
end,
}

function TypeChecker:begin_temporary_record_types(typ: RecordType)
self:add_var(nil, "@self", type_at(typ, a_typedecl(typ, typ)))

for fname, ftype in fields_of(typ) do
if ftype is TypeAliasType then
self:resolve_nominal(ftype.alias_to)
self:add_var(nil, fname, ftype)
elseif ftype is TypeDeclType then
self:add_var(nil, fname, ftype)
end
end
end

function TypeChecker:end_temporary_record_types(typ: RecordType)
-- drop @self and nested records from scope
-- to avoid closing them prematurely in end_scope()
local scope = self.st[#self.st]
scope.vars["@self"] = nil
for fname, ftype in fields_of(typ) do
if ftype is TypeAliasType or ftype is TypeDeclType then
scope.vars[fname] = nil
end
end
end

local visit_type: Visitor<TypeChecker, TypeName,Type,Type>
visit_type = {
cbs = {
["record"] = {
before = function(self: TypeChecker, typ: RecordType)
self:begin_scope()
self:add_var(nil, "@self", type_at(typ, a_typedecl(typ, typ)))

for fname, ftype in fields_of(typ) do
if ftype is TypeAliasType then
self:resolve_nominal(ftype.alias_to)
self:add_var(nil, fname, ftype)
elseif ftype is TypeDeclType then
self:add_var(nil, fname, ftype)
end
end
self:begin_temporary_record_types(typ)
end,
after = function(self: TypeChecker, typ: RecordType, children: {Type}): Type
local i = 1
Expand Down Expand Up @@ -12386,6 +12402,7 @@ do
end
end

self:end_temporary_record_types(typ)
self:end_scope()

return typ
Expand Down

0 comments on commit e178c42

Please sign in to comment.