diff --git a/spec/declaration/record_spec.lua b/spec/declaration/record_spec.lua index be46f1c62..b9ea201ad 100644 --- a/spec/declaration/record_spec.lua +++ b/spec/declaration/record_spec.lua @@ -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) example: bar 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..[[ ]]..array(i, "is {integer}")..[[ diff --git a/tl.lua b/tl.lua index 0a68fde6b..4f135af23 100644 --- a/tl.lua +++ b/tl.lua @@ -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 diff --git a/tl.tl b/tl.tl index a6da2ed56..7d6250047 100644 --- a/tl.tl +++ b/tl.tl @@ -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