Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type inferencing of filter style functions #1883

Open
lewis6991 opened this issue Feb 6, 2023 · 4 comments
Open

Type inferencing of filter style functions #1883

lewis6991 opened this issue Feb 6, 2023 · 4 comments
Labels
enhancement New feature or request feat/generic Related to generic emulation feature

Comments

@lewis6991
Copy link
Contributor

Given:

---@generic T
---@param f fun(a: T)
---@param t table<any, T>
---@return T[] (table)
local function tbl_filter(f, t)
  return t
end

---@type string[]
local s = {'a', 'b', 'c'}

local r1 = tbl_filter(function(a) end, s)

r1 is inferred as unknown[] because a is unknown despite s being known. However, could we infer a from s and force the typechecker to insist a is a string?

If I remove the type from a:

---@generic T
---@param f fun(a)
---@param t table<any, T>
---@return T[] (table)
local function tbl_filter2(f, t)
  return t
end

local r2 = tbl_filter2(function(_) end, s)

r2 is now inferred as string[] because only s is used to infer the type.

@sumneko sumneko added enhancement New feature or request feat/generic Related to generic emulation feature labels Feb 6, 2023
@sumneko
Copy link
Collaborator

sumneko commented Feb 6, 2023

I don't know how to design a strict rule.

@lewis6991
Copy link
Contributor Author

lewis6991 commented Feb 6, 2023

  • Look at all the sources of T
  • Make sure all the known sources match
  • For any unknown sources which come anonymous function arguments (or return values) insist it is the same type from the known sources.

Would that work?

@sumneko
Copy link
Collaborator

sumneko commented Feb 6, 2023

I will try it, thank you.

@carsakiller carsakiller mentioned this issue Feb 6, 2023
15 tasks
@itsfrank
Copy link

Interestingly, this does work as expected when using list T[] instead of table<any,T> (using version 3.7.3)

code:

---Filter a list
---@generic T
---@param list T[]
---@param p fun(v:T):boolean
---@return T[]
function iter.filter(list, p)
	local filtered = {}
	for _, v in ipairs(list) do
		if p(v) then
			table.insert(filtered, v)
		end
	end
	return filtered
end

-- number[]
local input = { 1, 2, 3, 4, 5 }

local filtered = iter.filter(input, function(v)
    return v % 2 == 0
end)

Screenshots of inferred types

filtered array:
Screen Shot 2023-12-23 at 2 12 55 PM

filter function param:
Screen Shot 2023-12-23 at 2 13 28 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feat/generic Related to generic emulation feature
Projects
None yet
Development

No branches or pull requests

3 participants