luau icon indicating copy to clipboard operation
luau copied to clipboard

Intersections of specific function types and the top function type do not normalize correctly

Open melindatrace opened this issue 1 year ago • 1 comments

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

melindatrace avatar Sep 12 '24 23:09 melindatrace

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).

aatxe avatar Sep 13 '24 04:09 aatxe

I believe this issue has been fixed.

Image

melindatrace avatar Aug 21 '25 23:08 melindatrace