luau icon indicating copy to clipboard operation
luau copied to clipboard

Metamethods with generics having their generics infered as the self type if the self type isn't a generic itself

Open gaymeowing opened this issue 1 year ago • 0 comments

With the code below when using the __call metamethod instead of export.retry, all of the generics get infered to the self type of unknown, when it would be expected for the generics to still be generics.


local function retry<T..., A...>(max_attempts: number, callback: (T...) -> (A...), ...: T...): (boolean, A...)
	local results = table.pack(pcall(callback, ...))

	if not results[1] then
		local attempts = 1

		repeat
			results = table.pack(pcall(callback, ...))
			attempts += 1
		until results[1] or attempts == max_attempts
	end
	return table.unpack(results) :: any
end

local function retry_call<T..., A...>(self: unknown, max_attempts: number, callback: (T...) -> (A...), ...: T...): (boolean, A...)
    return retry(max_attempts, callback, ...)
end

local mt = {
    __call = retry_call
}
mt.__index = mt
local tbl = {
    retry = retry
}

-- first argument of setmetatable even if its given a table throws a type error saying its not a table
local export: typeof(setmetatable(tbl, mt)) = setmetatable(tbl :: any, mt)

-- No error, works as expected, with the generics being infered properly
local success, result = export.retry(10, function(bar: number)
	return bar * 2
end, 10)

--[[
    TypeError: Type '(number) -> number' could not be converted into
    '(...unknown) -> (...unknown)'
    caused by:
    Type 'unknown' could not be converted into 'number'
--]]
local success, result = export(10, function(foo: number)
    return foo + 1
end, 10)

The issue with the metamethod type gets fixed when the self type itself is a generic, with the solver properly infering the functions generics

local function retry_call<S, T..., A...>(self: S, max_attempts: number, callback: (T...) -> (A...), ...: T...): (boolean, A...)
    return retry(max_attempts, callback, ...)
end

gaymeowing avatar May 23 '24 19:05 gaymeowing