diff --git a/spec/lang/stdlib/require_spec.lua b/spec/lang/stdlib/require_spec.lua index 90fc6060..83084a1f 100644 --- a/spec/lang/stdlib/require_spec.lua +++ b/spec/lang/stdlib/require_spec.lua @@ -1216,7 +1216,7 @@ describe("require", function() assert.same({}, result.syntax_errors) assert.same({ - { filename = "main.tl", x = 37, y = 1, msg = "type is not a record" }, + { filename = "main.tl", x = 30, y = 1, msg = "'require' did not return a type, got integer" }, { filename = "main.tl", x = 45, y = 1, msg = "cannot index key 'Foo' in type integer" }, }, result.type_errors) end) @@ -1324,4 +1324,29 @@ describe("require", function() }, result.type_errors) end) + it("a module returning an interface instance can be required concretely (#825)", function () + util.mock_io(finally, { + ["foo.tl"] = [[ + local interface IFoo + bar: function(self) + end + + local foo: IFoo = {} + + return foo + ]], + ["main.tl"] = [[ + local foo = require("foo") + + foo.bar = function(self) + print("bar") + end + ]], + }) + local result, err = tl.process("main.tl") + + assert.same({}, result.syntax_errors) + assert.same({}, result.type_errors) + end) + end) diff --git a/tl.lua b/tl.lua index 211e8731..c8728a40 100644 --- a/tl.lua +++ b/tl.lua @@ -11148,7 +11148,7 @@ self:expand_type(node, values, elements) }) if not (ty.typename == "typedecl") then - return a_type(n, "typedecl", { def = ty }) + return self.errs:invalid_at(n.e1, "'require' did not return a type, got %s", ty) end if ty.is_alias then return self:resolve_typealias(ty) @@ -11669,14 +11669,15 @@ self:expand_type(node, values, elements) }) local expected = self:find_var_type("@return") if not expected then - expected = self:infer_at(node, got) - local module_type = resolve_tuple(expected) + local module_type = resolve_tuple(got) if module_type.typename == "nominal" then self:resolve_nominal(module_type) - self.module_type = module_type.found + self.module_type = module_type.resolved else self.module_type = drop_constant_value(module_type) end + + expected = self:infer_at(node, got) self.st[2].vars["@return"] = { t = expected } end local expected_t = expected.tuple diff --git a/tl.tl b/tl.tl index 3af6c1ee..cb445db6 100644 --- a/tl.tl +++ b/tl.tl @@ -11148,7 +11148,7 @@ do ) ) if not ty is TypeDeclType then - return a_type(n, "typedecl", { def = ty } as TypeDeclType) + return self.errs:invalid_at(n.e1, "'require' did not return a type, got %s", ty) end if ty.is_alias then return self:resolve_typealias(ty) @@ -11669,14 +11669,15 @@ do local expected = self:find_var_type("@return") as TupleType if not expected then -- if at the toplevel - expected = self:infer_at(node, got) - local module_type = resolve_tuple(expected) + local module_type = resolve_tuple(got) if module_type is NominalType then self:resolve_nominal(module_type) - self.module_type = module_type.found + self.module_type = module_type.resolved else self.module_type = drop_constant_value(module_type) end + + expected = self:infer_at(node, got) self.st[2].vars["@return"] = { t = expected } end local expected_t = expected.tuple