Skip to content

Type inferencing of filter style functions #1883

Open

Description

@lewis6991

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.

Activity

  1. sumneko commented on Feb 6, 2023

    @sumneko
    Collaborator

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

  2. lewis6991 commented on Feb 6, 2023

    @lewis6991
    ContributorAuthor
    • 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?

  3. sumneko commented on Feb 6, 2023

    @sumneko
    Collaborator

    I will try it, thank you.

  4. itsfrank commented on Dec 23, 2023

    @itsfrank

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfeat/genericRelated to generic emulation feature

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions