Skip to content

Commit

Permalink
record functions inherit type variables from the record definition (#669
Browse files Browse the repository at this point in the history
)

Fixes #657.
  • Loading branch information
hishamhm committed Jul 10, 2023
1 parent 293c3d2 commit 54ef78e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
15 changes: 15 additions & 0 deletions spec/declaration/record_method_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,21 @@ describe("record method", function()
end
]]))

it("inherits type variables from the record definition (regression test for #657)", util.check([[
local record Test<T>
value: T
end
function Test.new(value: T): Test<T>
return setmetatable({ value = value }, { __index = Test })
end
function Test:print()
local t: T
t = self.value
end
]]))

describe("redeclaration: ", function()
it("an inconsistent arity in redeclaration produces an error (regression test for #496)", util.check_type_error([[
local record Y
Expand Down
29 changes: 28 additions & 1 deletion tl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,7 @@ local is_attribute = attributes






local function is_array_type(t)
Expand Down Expand Up @@ -3200,6 +3201,8 @@ end








Expand Down Expand Up @@ -3542,6 +3545,7 @@ local function recurse_node(root,
recurse_typeargs(ast, visit_type)
xs[1] = recurse(ast.fn_owner)
xs[2] = recurse(ast.name)
extra_callback("before_arguments", ast, xs, visit_node)
xs[3] = recurse(ast.args)
xs[4] = recurse_type(ast.rets, visit_type)
extra_callback("before_statements", ast, xs, visit_node)
Expand Down Expand Up @@ -8110,10 +8114,18 @@ tl.type_check = function(ast, opts)
end

if t.typename == "typetype" then
local typevals
if t.def.typeargs then
typevals = {}
for _, a in ipairs(t.def.typeargs) do
table.insert(typevals, a_type({ typename = "typevar", typevar = a.typearg }))
end
end
return a_type({
y = exp.y,
x = exp.x,
typename = "nominal",
typevals = typevals,
names = { exp.tk },
found = t,
})
Expand Down Expand Up @@ -9629,10 +9641,25 @@ tl.type_check = function(ast, opts)
widen_all_unions()
begin_scope(node)
end,
before_arguments = function(node, children)
node.rtype = resolve_tuple_and_nominal(resolve_typetype(children[1]))


if node.rtype.typeargs then
for _, typ in ipairs(node.rtype.typeargs) do
add_var(nil, typ.typearg, a_type({
y = typ.y,
x = typ.x,
typename = "typearg",
typearg = typ.typearg,
}))
end
end
end,
before_statements = function(node, children)
add_internal_function_variables(node)

local rtype = resolve_tuple_and_nominal(resolve_typetype(children[1]))
local rtype = node.rtype
if rtype.typename == "emptytable" then
rtype.typename = "record"
rtype.fields = {}
Expand Down
29 changes: 28 additions & 1 deletion tl.tl
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,7 @@ local record Node
body: Node
implicit_global_function: boolean
is_predeclared_local_function: boolean
rtype: Type

name: Node

Expand Down Expand Up @@ -3182,12 +3183,14 @@ end
local record VisitorCallbacks<N, T>
before: function(N, {T})
before_expressions: function({N}, {T})
before_arguments: function({N}, {T})
before_statements: function({N}, {T})
before_e2: function({N}, {T})
after: function(N, {T}, T): T
end

local enum VisitorExtraCallback
"before_arguments"
"before_statements"
"before_expressions"
"before_e2"
Expand Down Expand Up @@ -3542,6 +3545,7 @@ local function recurse_node<T>(root: Node,
recurse_typeargs(ast, visit_type)
xs[1] = recurse(ast.fn_owner)
xs[2] = recurse(ast.name)
extra_callback("before_arguments", ast, xs, visit_node)
xs[3] = recurse(ast.args)
xs[4] = recurse_type(ast.rets, visit_type)
extra_callback("before_statements", ast, xs, visit_node)
Expand Down Expand Up @@ -8110,10 +8114,18 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
end

if t.typename == "typetype" then
local typevals: Type
if t.def.typeargs then
typevals = {}
for _, a in ipairs(t.def.typeargs) do
table.insert(typevals, a_type { typename = "typevar", typevar = a.typearg })
end
end
return a_type {
y = exp.y,
x = exp.x,
typename = "nominal",
typevals = typevals,
names = { exp.tk },
found = t,
}
Expand Down Expand Up @@ -9629,10 +9641,25 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
widen_all_unions()
begin_scope(node)
end,
before_arguments = function(node: Node, children: {Type})
node.rtype = resolve_tuple_and_nominal(resolve_typetype(children[1]))

-- add type arguments from the record implicitly
if node.rtype.typeargs then
for _, typ in ipairs(node.rtype.typeargs) do
add_var(nil, typ.typearg, a_type {
y = typ.y,
x = typ.x,
typename = "typearg",
typearg = typ.typearg,
})
end
end
end,
before_statements = function(node: Node, children: {Type})
add_internal_function_variables(node)

local rtype = resolve_tuple_and_nominal(resolve_typetype(children[1]))
local rtype = node.rtype
if rtype.typename == "emptytable" then
rtype.typename = "record"
rtype.fields = {}
Expand Down

0 comments on commit 54ef78e

Please sign in to comment.