diff --git a/spec/lang/operator/colon_spec.lua b/spec/lang/operator/colon_spec.lua new file mode 100644 index 000000000..104a493df --- /dev/null +++ b/spec/lang/operator/colon_spec.lua @@ -0,0 +1,22 @@ +local util = require("spec.util") + +describe(":", function() + describe("on self", function() + it("can resolve methods (regression test for #812)", util.check([[ + local interface A + get_type: function(A): string + end + + local interface B is A where self:get_type() == "b" + end + + local b: A = { + get_type = function(): string return "b" end + } + + if b is B then + print("woaw") + end + ]])) + end) +end) diff --git a/tl.lua b/tl.lua index 50b2c039d..9a281209e 100644 --- a/tl.lua +++ b/tl.lua @@ -8481,12 +8481,8 @@ do if not t then return a_type(w, "invalid", {}) end - - if t.typename == "typedecl" then - t = t.def - end - - return t + assert(t.typename == "typedecl") + return t.def end @@ -9431,7 +9427,11 @@ a.types[i], b.types[i]), } check_call = function(self, w, wargs, f, args, expected_rets, cm, argdelta) local arg1 = args.tuple[1] if cm == "method" and arg1 then - self:add_var(nil, "@self", a_type(w, "typedecl", { def = arg1 })) + local selftype = arg1 + if selftype.typename == "self" then + selftype = self:type_of_self(selftype) + end + self:add_var(nil, "@self", a_type(w, "typedecl", { def = selftype })) end local fargs = f.args.tuple @@ -9661,6 +9661,10 @@ a.types[i], b.types[i]), } tbl = self:to_structural(tbl) + if tbl.typename == "self" then + tbl = self:type_of_self(tbl) + end + if tbl.typename == "string" or tbl.typename == "enum" then tbl = self:find_var_type("string") end diff --git a/tl.tl b/tl.tl index 653e8a3b6..f303360df 100644 --- a/tl.tl +++ b/tl.tl @@ -8481,12 +8481,8 @@ do if not t then return an_invalid(w) end - - if t is TypeDeclType then - t = t.def - end - - return t + assert(t is TypeDeclType) + return t.def end -- ∃ x ∈ xs. t <: x @@ -9431,7 +9427,11 @@ do check_call = function(self: TypeChecker, w: Where, wargs: {Where}, f: FunctionType, args: TupleType, expected_rets: TupleType, cm: CallMode, argdelta: integer): boolean, {Error} local arg1 = args.tuple[1] if cm == "method" and arg1 then - self:add_var(nil, "@self", a_typedecl(w, arg1)) + local selftype = arg1 + if selftype is SelfType then + selftype = self:type_of_self(selftype) + end + self:add_var(nil, "@self", a_typedecl(w, selftype)) end local fargs = f.args.tuple @@ -9661,6 +9661,10 @@ do tbl = self:to_structural(tbl) + if tbl is SelfType then + tbl = self:type_of_self(tbl) + end + if tbl is StringType or tbl is EnumType then tbl = self:find_var_type("string") -- simulate string metatable end