Skip to content

Commit

Permalink
produce a warning when unions are not auto-inferred
Browse files Browse the repository at this point in the history
See #705.
  • Loading branch information
hishamhm committed Oct 19, 2023
1 parent 9b43ecc commit ea7bfb1
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 2 deletions.
10 changes: 8 additions & 2 deletions spec/operator/or_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe("or", function()
local m2: {string:Ty} = m1 or { foo = t }
]]))

it("record or record: need to be compatible", util.check_type_error([[
it("record or record: need to be compatible", util.check_warnings([[
local record R1
x: number
end
Expand All @@ -21,7 +21,10 @@ describe("or", function()
local r1: R1
local r2: R2
local r3 = r2 or r1
print(r3)
]], {
-- no warnings because `r2 or r1` is not a valid union
}, {
{ msg = "cannot use operator 'or' for types R2 and R1" }
}))

Expand Down Expand Up @@ -97,11 +100,14 @@ describe("or", function()
{ msg = "cannot use operator 'or' for types boolean and {}" },
}))

it("does not produce new unions if not asked to", util.check_type_error([[
it("does not produce new unions if not asked to", util.check_warnings([[
local x: number | string
local s = x is string and x .. "!" or x + 1
print(s)
]], {
{ y = 3, msg = [[if a union type was intended, consider declaring it explicitly]] }
}, {
{ y = 3, msg = [[cannot use operator 'or' for types string and number]] },
}))

Expand Down
7 changes: 7 additions & 0 deletions tl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5870,6 +5870,10 @@ tl.type_check = function(ast, opts)
end

local function is_valid_union(typ)
if typ.typename ~= "union" then
return false, nil
end



local n_table_types = 0
Expand Down Expand Up @@ -10049,6 +10053,9 @@ tl.type_check = function(ast, opts)
node.type, meta_on_operator = check_metamethod(node, node.op.op, a, b)
if not node.type then
node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", resolve_tuple(orig_a), resolve_tuple(orig_b))
if node.op.op == "or" and is_valid_union(unite({ orig_a, orig_b })) then
node_warning("hint", node, "if a union type was intended, consider declaring it explicitly")
end
end
end

Expand Down
7 changes: 7 additions & 0 deletions tl.tl
Original file line number Diff line number Diff line change
Expand Up @@ -5870,6 +5870,10 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
end

local function is_valid_union(typ: Type): boolean, string
if typ.typename ~= "union" then
return false, nil
end

-- check for limitations in our union support
-- due to codegen limitations (we only check with type() so far)
local n_table_types = 0
Expand Down Expand Up @@ -10049,6 +10053,9 @@ tl.type_check = function(ast: Node, opts: TypeCheckOptions): Result, string
node.type, meta_on_operator = check_metamethod(node, node.op.op, a, b)
if not node.type then
node_error(node, "cannot use operator '" .. node.op.op:gsub("%%", "%%%%") .. "' for types %s and %s", resolve_tuple(orig_a), resolve_tuple(orig_b))
if node.op.op == "or" and is_valid_union(unite({orig_a, orig_b})) then
node_warning("hint", node, "if a union type was intended, consider declaring it explicitly")
end
end
end

Expand Down

0 comments on commit ea7bfb1

Please sign in to comment.