diff --git a/spec/lang/operator/ge_spec.lua b/spec/lang/operator/ge_spec.lua new file mode 100644 index 00000000..490952a8 --- /dev/null +++ b/spec/lang/operator/ge_spec.lua @@ -0,0 +1,41 @@ +local util = require("spec.util") + +describe(">=", function() + it("ok", util.check([[ + local x = 1 + local y = 2 + local z = true + if x >= y then + z = false + end + ]])) + + it("fail", util.check_type_error([[ + local x = 1 + local y = "hello" + local z = true + if x >= y then + z = false + end + ]], { + { msg = "cannot use operator '>=' for types integer and string" } + })) + + it("fails with not gotcha", util.check_type_error([[ + local x = 10 + local y = 20 + if not x >= y then + print("wat") + end + ]], { + { msg = "cannot use operator '>=' for types boolean and integer" } + })) + + it(">= on aliases to comparable types return boolean", util.check([[ + local type Test = integer + + local function f(a: Test, b: Test) : boolean + return a >= b + end + ]])) +end) diff --git a/spec/lang/operator/gt_spec.lua b/spec/lang/operator/gt_spec.lua new file mode 100644 index 00000000..fea13e95 --- /dev/null +++ b/spec/lang/operator/gt_spec.lua @@ -0,0 +1,41 @@ +local util = require("spec.util") + +describe(">", function() + it("ok", util.check([[ + local x = 1 + local y = 2 + local z = true + if x > y then + z = false + end + ]])) + + it("fail", util.check_type_error([[ + local x = 1 + local y = "hello" + local z = true + if x > y then + z = false + end + ]], { + { msg = "cannot use operator '>' for types integer and string" } + })) + + it("fails with not gotcha", util.check_type_error([[ + local x = 10 + local y = 20 + if not x > y then + print("wat") + end + ]], { + { msg = "cannot use operator '>' for types boolean and integer" } + })) + + it("> on aliases to comparable types return boolean", util.check([[ + local type Test = integer + + local function f(a: Test, b: Test) : boolean + return a > b + end + ]])) +end) diff --git a/spec/lang/operator/le_spec.lua b/spec/lang/operator/le_spec.lua new file mode 100644 index 00000000..6a5f1042 --- /dev/null +++ b/spec/lang/operator/le_spec.lua @@ -0,0 +1,41 @@ +local util = require("spec.util") + +describe("<=", function() + it("ok", util.check([[ + local x = 1 + local y = 2 + local z = true + if x <= y then + z = false + end + ]])) + + it("fail", util.check_type_error([[ + local x = 1 + local y = "hello" + local z = true + if x <= y then + z = false + end + ]], { + { msg = "cannot use operator '<=' for types integer and string" } + })) + + it("fails with not gotcha", util.check_type_error([[ + local x = 10 + local y = 20 + if not x <= y then + print("wat") + end + ]], { + { msg = "cannot use operator '<=' for types boolean and integer" } + })) + + it("<= on aliases to comparable types return boolean", util.check([[ + local type Test = integer + + local function f(a: Test, b: Test) : boolean + return a <= b + end + ]])) +end) diff --git a/tl.lua b/tl.lua index 00ab781a..abb36214 100644 --- a/tl.lua +++ b/tl.lua @@ -12611,6 +12611,10 @@ self:expand_type(node, values, elements) }) end if mt_name then t, meta_on_operator = self:check_metamethod(node, mt_name, ra, rb, ua, ub, flipped) + if flipped and not meta_on_operator then + ra, rb = rb, ra + ua, ub = ub, ua + end end if not t then t = self.errs:invalid_at(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", ua, ub) diff --git a/tl.tl b/tl.tl index 4090b605..8b03c9d4 100644 --- a/tl.tl +++ b/tl.tl @@ -12611,6 +12611,10 @@ do end if mt_name then t, meta_on_operator = self:check_metamethod(node, mt_name, ra, rb, ua, ub, flipped) + if flipped and not meta_on_operator then + ra, rb = rb, ra + ua, ub = ub, ua + end end if not t then t = self.errs:invalid_at(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", ua, ub)