diff --git a/spec/declaration/global_spec.lua b/spec/declaration/global_spec.lua index d085e4970..1df30e985 100644 --- a/spec/declaration/global_spec.lua +++ b/spec/declaration/global_spec.lua @@ -137,7 +137,7 @@ describe("global", function() util.mock_io(finally, { ["foo.tl"] = "global x: number = 1" }) - util.check([[ + util.run_check([[ local foo = require("foo") global x: number x = 2 @@ -148,7 +148,7 @@ describe("global", function() util.mock_io(finally, { ["foo.tl"] = "global x : number = 1" }) - util.check([[ + util.run_check([[ local foo = require("foo") global x : number ]]) @@ -158,7 +158,7 @@ describe("global", function() util.mock_io(finally, { ["foo.tl"] = "global x : number = 1" }) - util.check_type_error([[ + util.run_check_type_error([[ local foo = require("foo") global x : number = 9 ]], { @@ -170,7 +170,7 @@ describe("global", function() util.mock_io(finally, { ["foo.tl"] = "global x: number" }) - util.check_type_error([[ + util.run_check_type_error([[ local foo = require("foo") global x : number ]], { @@ -182,7 +182,7 @@ describe("global", function() util.mock_io(finally, { ["foo.tl"] = "global x : number" }) - util.check_type_error([[ + util.run_check_type_error([[ local foo = require("foo") global x: number ]], { @@ -194,7 +194,7 @@ describe("global", function() util.mock_io(finally, { ["foo.tl"] = "global x, y: number, string = 1, 'hello'" }) - util.check_type_error([[ + util.run_check_type_error([[ local foo = require("foo") global x: string x = 2 @@ -213,7 +213,7 @@ describe("global", function() global type Building - global type Person + global record Person residence: Building end @@ -224,14 +224,14 @@ describe("global", function() global type Person - global type Building + global record Building owner: Person end return building ]], }) - util.check([[ + util.run_check([[ local person = require("person") local building = require("building") local b: Building = {} diff --git a/spec/declaration/record_spec.lua b/spec/declaration/record_spec.lua index 373f1cc43..a188a482c 100644 --- a/spec/declaration/record_spec.lua +++ b/spec/declaration/record_spec.lua @@ -246,7 +246,7 @@ for i, name in ipairs({"records", "arrayrecords", "interfaces", "arrayinterfaces it("can be nested", function() util.mock_io(finally, { ["req.d.tl"] = [[ - local type requests = ]]..statement..[[ ]]..array(i, "{requests}")..[[ + local type requests = record type RequestOpts = ]]..statement..[[ -- {string} @@ -265,21 +265,24 @@ for i, name in ipairs({"records", "arrayrecords", "interfaces", "arrayinterfaces return requests ]], }) - util.check_type_error([[ + util.run_check_type_error([[ local req = require("req") local r = req.get("http://example.com") print(r.status_code) print(r.status_coda) ]], { - { msg = "invalid key 'status_coda' in "..statement.." 'r' of type Response" } + { msg = (statement == "interface") + and "invalid key 'status_coda' in 'r' of interface type Response" + or "invalid key 'status_coda' in record 'r' of type Response" + } }) end) it("can be nested with shorthand syntax", function() util.mock_io(finally, { ["req.d.tl"] = [[ - local type requests = ]]..statement..[[ ]]..array(i, "{requests}")..[[ + local type requests = record ]]..statement..[[ RequestOpts {string} @@ -298,14 +301,17 @@ for i, name in ipairs({"records", "arrayrecords", "interfaces", "arrayinterfaces return requests ]], }) - util.check_type_error([[ + util.run_check_type_error([[ local req = require("req") local r = req.get("http://example.com") print(r.status_code) print(r.status_coda) ]], { - { msg = "invalid key 'status_coda' in "..statement.." 'r' of type Response" } + { msg = (statement == "interface") + and "invalid key 'status_coda' in 'r' of interface type Response" + or "invalid key 'status_coda' in record 'r' of type Response" + } }) end) @@ -519,7 +525,7 @@ for i, name in ipairs({"records", "arrayrecords", "interfaces", "arrayinterfaces it("can export types as nested " .. name, function() util.mock_io(finally, { ["req.d.tl"] = [[ - local type requests = ]]..statement..[[ ]]..array(i, "{requests}")..[[ + local record requests type RequestOpts = ]]..statement..[[ {string} @@ -538,7 +544,7 @@ for i, name in ipairs({"records", "arrayrecords", "interfaces", "arrayinterfaces return requests ]], }) - util.check([[ + return util.check([[ local req = require("req") local function f(): req.Response @@ -546,7 +552,7 @@ for i, name in ipairs({"records", "arrayrecords", "interfaces", "arrayinterfaces end print(f().status_code) - ]]) + ]])() end) it("resolves aliasing of nested " .. name .. " (see #400)", util.check([[ diff --git a/spec/error_reporting/typecheck_error_spec.lua b/spec/error_reporting/typecheck_error_spec.lua index 7cb614cb0..b6846beae 100644 --- a/spec/error_reporting/typecheck_error_spec.lua +++ b/spec/error_reporting/typecheck_error_spec.lua @@ -11,11 +11,11 @@ describe("typecheck errors", function() util.mock_io(finally, { ["bar.tl"] = "local x: string = 1", }) - util.check_type_error([[ + util.run_check_type_error([[ local bar = require "bar" ]], { { filename = "./bar.tl" } - })() + }) end) it("unknowns include filename", util.lax_check([[ @@ -28,11 +28,11 @@ describe("typecheck errors", function() util.mock_io(finally, { ["bar.lua"] = "local x: string = b" }) - util.lax_check([[ + util.run_lax_check([[ local bar = require "bar" ]], { { msg = "b", filename = "./bar.lua" } - })() + }) end) it("type mismatches across modules report their module names", function () @@ -54,7 +54,7 @@ describe("typecheck errors", function() return bbb ]] }) - util.check_type_error([[ + util.run_check_type_error([[ local aaa = require("aaa") local bbb = require("bbb") @@ -67,7 +67,7 @@ describe("typecheck errors", function() myfunc(b) ]], { { msg = "bbb.Thing is not a aaa.Thing" } - })() + }) end) it("localized type mismatches across module report their filenames", function () @@ -96,7 +96,7 @@ describe("typecheck errors", function() return bbb ]] }) - util.check_type_error([[ + util.run_check_type_error([[ local aaa = require("aaa") local bbb = require("bbb") @@ -107,7 +107,7 @@ describe("typecheck errors", function() aaa.myfunc(b) ]], { { msg = "argument 1: Thing (defined in ./bbb.tl:4) is not a Thing (defined in ./aaa.tl:1)" } - })() + }) end) it("type mismatches across local type names report their provenance", function () @@ -141,7 +141,7 @@ describe("typecheck errors", function() return bbb ]] }) - util.check_type_error([[ + util.run_check_type_error([[ local aaa = require("aaa") local bbb = require("bbb") @@ -150,7 +150,7 @@ describe("typecheck errors", function() aaa.myfunc(b) ]], { { msg = "argument 1: Thing (defined in ./bbb.tl:1) is not a Thing (defined in ./aaa.tl:1)" } - })() + }) end) end) diff --git a/spec/lexer/literals_spec.lua b/spec/lexer/literals_spec.lua index dd30da7de..23f112b28 100644 --- a/spec/lexer/literals_spec.lua +++ b/spec/lexer/literals_spec.lua @@ -55,6 +55,6 @@ describe("lexer", function() end local input = table.concat(code, "\n") - util.check(input) + util.run_check(input) end) end) diff --git a/spec/util.lua b/spec/util.lua index 51eedac20..25cbdae50 100644 --- a/spec/util.lua +++ b/spec/util.lua @@ -616,4 +616,16 @@ function util.gen(code, expected, gen_target) return gen(false, code, expected, gen_target) end +function util.run_check_type_error(...) + return util.check_type_error(...)() +end + +function util.run_check(...) + return util.check(...)() +end + +function util.run_lax_check(...) + return util.lax_check(...)() +end + return util diff --git a/tl.lua b/tl.lua index 471bf88cc..f48911d36 100644 --- a/tl.lua +++ b/tl.lua @@ -9215,7 +9215,11 @@ a.types[i], b.types[i]), } end if rec.kind == "variable" then - return nil, "invalid key '" .. key .. "' in record '" .. rec.tk .. "' of type %s" + if tbl.typename == "interface" then + return nil, "invalid key '" .. key .. "' in '" .. rec.tk .. "' of interface type %s" + else + return nil, "invalid key '" .. key .. "' in record '" .. rec.tk .. "' of type %s" + end else return nil, "invalid key '" .. key .. "' in type %s" end diff --git a/tl.tl b/tl.tl index 0c61ce5b7..7d1c5d180 100644 --- a/tl.tl +++ b/tl.tl @@ -9215,7 +9215,11 @@ do end if rec.kind == "variable" then - return nil, "invalid key '" .. key .. "' in record '" .. rec.tk .. "' of type %s" + if tbl is InterfaceType then + return nil, "invalid key '" .. key .. "' in '" .. rec.tk .. "' of interface type %s" + else + return nil, "invalid key '" .. key .. "' in record '" .. rec.tk .. "' of type %s" + end else return nil, "invalid key '" .. key .. "' in type %s" end