Intersections of specific function types and the top function type do not normalize correctly
I have a Main function that will be called twice, and the second time it gets called it will print 64. However the type solver throws unclear type error.
type Func = () -> number
local FuncThatReturnsNumber: Func? = nil
local function GetFuncThatReturnsNumber(): Func
return function()
return 64
end
end
local function Main()
if FuncThatReturnsNumber then
local position = FuncThatReturnsNumber() -- TypeError: Cannot call a value of type ((() -> number)?) & (buffer | class | function | number | string | table | thread | true) Luau(1020)
-- local position: 'a
print(position)
else
FuncThatReturnsNumber = GetFuncThatReturnsNumber()
end
end
Main() -- Prints nothing
Main() -- Prints 64
This does not happen when the if statement is not wrapped inside a function.
type Func = () -> number
local FuncThatReturnsNumber: Func? = nil
local function GetFuncThatReturnsNumber(): Func
return function()
return 64
end
end
if FuncThatReturnsNumber then
local position = FuncThatReturnsNumber() -- number
print(position)
else
FuncThatReturnsNumber = GetFuncThatReturnsNumber()
end
The problem here is that intersections of the function type (or unions including it) with individual specific function types do not correctly simplify. So, (() -> number) | nil intersected with ~(false | nil) (which is what the refinement for a truthy test does) doesn't correctly simplify to () -> number. We might be able to fix this sooner, but this will definitely be addressed by the upcoming work on integrated e-graphs (#1285, but there's follow-up integration work that is under way).
I believe this issue has been fixed.