Skip to content

Commit

Permalink
interfaces: enforce them to be abstract
Browse files Browse the repository at this point in the history
Fixes #757.
  • Loading branch information
hishamhm committed Aug 12, 2024
1 parent 2ec30ea commit 07c9ed4
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
71 changes: 67 additions & 4 deletions spec/declaration/record_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -434,16 +434,79 @@ for i, name in ipairs({"records", "arrayrecords", "interfaces", "arrayinterfaces
})[i]
}))

it("can extend generic functions", util.check([[
local type foo = ]]..statement..[[ ]]..array(i, "{foo}")..[[
it("only records can have record methods", util.check_type_error([[
local ]]..statement..[[ Foo ]]..array(i, "{Foo}")..[[
end
function Foo:example(data: string)
print(data)
end
]], {
({
nil,
nil,
{ msg = "interfaces are abstract" },
{ msg = "interfaces are abstract" },
})[i]
}))

it("only records can have record functions", util.check_type_error([[
local ]]..statement..[[ Foo ]]..array(i, "{Foo}")..[[
end
function Foo.example(data: string)
print(data)
end
]], {
({
nil,
nil,
{ msg = "interfaces are abstract" },
{ msg = "interfaces are abstract" },
})[i]
}))

it("functions can be implemented in instances", util.check([[
local ]]..statement..[[ Foo ]]..array(i, "{Foo}")..[[
example: function(string)
end
local my_f: Foo = {}
function my_f.example(data: string)
print(data)
end
]]))

it("methods can be implemented in instances", util.check([[
local ]]..statement..[[ Foo ]]..array(i, "{Foo}")..[[
example: function(Foo, string)
end
local my_f: Foo = {}
function my_f:example(data: string)
print(data)
end
]]))

it("with implement generic functions", util.check_type_error([[
local type Foo = ]]..statement..[[ ]]..array(i, "{Foo}")..[[
type bar = function<T>(T)
example: bar<string>
end
function foo.example(data: string)
function Foo.example(data: string)
print(data)
end
]]))
]], {
({
nil,
nil,
{ msg = "interfaces are abstract" },
{ msg = "interfaces are abstract" },
})[i]
}))

it("can use where with generic types", util.check([[
local type Success = ]]..statement..[[<T> ]]..array(i, "is {integer}")..[[
Expand Down
10 changes: 9 additions & 1 deletion tl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11518,7 +11518,15 @@ self:expand_type(node, values, elements) })
local rets = children[4]
assert(rets.typename == "tuple")

local rtype = self:to_structural(resolve_typedecl(children[1]))
local t = children[1]
local rtype = self:to_structural(resolve_typedecl(t))

do
local ok, err = ensure_not_abstract(t)
if not ok then
self.errs:add(node, err)
end
end

if self.feat_lax and rtype.typename == "unknown" then
return
Expand Down
10 changes: 9 additions & 1 deletion tl.tl
Original file line number Diff line number Diff line change
Expand Up @@ -11518,7 +11518,15 @@ do
local rets = children[4]
assert(rets is TupleType)

local rtype = self:to_structural(resolve_typedecl(children[1]))
local t = children[1]
local rtype = self:to_structural(resolve_typedecl(t))

do
local ok, err = ensure_not_abstract(t)
if not ok then
self.errs:add(node, err)
end
end

if self.feat_lax and rtype is UnknownType then
return
Expand Down

0 comments on commit 07c9ed4

Please sign in to comment.