Skip to content

Type inferencing of filter style functions #1883

New issue

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

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

Already on GitHub? # to your account

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

# for free to join this conversation on GitHub. Already have an account? # 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