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

Ipairs with generic #2969

Open
ChouUn opened this issue Nov 27, 2024 · 3 comments
Open

Ipairs with generic #2969

ChouUn opened this issue Nov 27, 2024 · 3 comments

Comments

@ChouUn
Copy link

ChouUn commented Nov 27, 2024

How are you using the lua-language-server?

Visual Studio Code Extension (sumneko.lua)

Which OS are you using?

Windows

What is the issue affecting?

Annotations

Expected Behaviour

Should have got a correct type inference in a generic function.

Actual Behaviour

  1. could not specify a V-related type for result in the generic function
  2. ipairs will be inferred as unknown
  3. returns of the generic function will be inferred as a strange type

Reproduction steps

---@class Test
---@field name string

---@type Test[]
local tests = {
    { name = "test1" },
    { name = "test2" },
    { name = "test3" },
}

--[[
CORRECT:
    function group_by(rows: <V>[], key: string)
    -> table<string, <V>[]>
]]
---@generic V
---@param rows V[]
---@param key string
---@return table<string, V[]>
local function group_by(rows, key)
    --[[
        ---@type table<string, V[]>
        GOT: Undefined type or alias `V`.
    ]]
    local result = {}
    -- WRONG: local v: unknown
    for i, v in ipairs(rows) do
        local k = v[key]
        if not result[k] then
            result[k] = {}
        end
        table.insert(result[k], v)
    end
    return result
end

--[[
WRONG:
    local groups: table<string, <V>[]> | { [<K>]: Test }
EXPECTED:
    local groups: table<string, Test[]>
]]
local groups = group_by(tests, "name")

Additional Notes

No response

Log File

No response

@tomlau10
Copy link
Contributor

seems there are 2 separate issues 😕

  1. the unknown value type in ipairs when the input table is a generic array type
  2. the strange type returned by table<K, V> expression, when one of them is a generic type

More observations on the 2nd issue:

  • table is defined in builtin.lua meta file
    ---@class table<K, V>: { [K]: V }
  • it is already defined with generic types and extended with generics
  • somehow when resolving the generic type with the same sign name, it will mess up. In this case it is the V
    • in the function group_by(), V is matched to Test
    • and then V has the same sign name as that of table<K, V> in builtin meta
    • => causing confusions with { [K]: V } and resolved to an incorrect { [<K>]: Test } type

The current workaround I found for this 2nd issue is to instead just use literal table notation { [string]: V[] } 🤔

---@class Test
---@field name string

---@type Test[]
local tests = {}

---@generic V
---@param rows V[]
---@param key string
---@return {[string]: V[]}
local function group_by(rows, key) end

local groups = group_by(tests, "name")
--> groups: { [string]: Test[] }

@ChouUn
Copy link
Author

ChouUn commented Nov 27, 2024

As a temporary solution for second issue, it stopped things from getting worse. 🥰

local groups: { [string]: Test[] } {
    [string]: Test[],
}

Although the types are still weird, it works anyway! 😇
Would you suggest that I split it into 2~3 issues, or treat it as a complete use case for systematic thinking? 🤔

@tomlau10
Copy link
Contributor

I think it is better to split into 2 issues 🤔 since the ipairs one has nothing to do with the table<K, V> one.
But of course in the new issue, you can link it to this current issue for more context 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants