Skip to content

lua-language-server not detecting types when destructuring Tuple types with ~table.unpack~ #2873

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
4lph4-Ph4un opened this issue Sep 27, 2024 · 1 comment

Comments

@4lph4-Ph4un
Copy link

How are you using the lua-language-server?

Other

Which OS are you using?

Windows

What is the issue affecting?

Diagnostics/Syntax Checking

Expected Behaviour

I might be wrong here, but I assume this should work?
Language server should detect the types from the defined tuple:

---@alias my_tuple { [1]: integer, [2]: boolean }

---@type my_tuple
local tuple = {1, true}

--- This works!
local a, b = tuple[1], tuple[2]

--- This gets "integer" for "c", but "unknown" for "d:
local c, d = table.unpack(tuple)

Actual Behaviour

---@alias my_tuple { [1]: integer, [2]: boolean }

---@type my_tuple
local tuple = {1, true}

---  "c" should be "integer" and "d" "boolean":
local c, d = table.unpack(tuple)

Reproduction steps

  1. Define tuple like I did
  2. Create such tuple
  3. unpack to two variables

Additional Notes

I'm not sure if this is a feature that is even considered, but since I do use unpack sometimes to destructure tuples into their distinct variables, I feel this would be a good feature to have.

Log File

No response

@tomlau10
Copy link
Contributor

tomlau10 commented Sep 28, 2024

With your code, I am getting c: integer|boolean and d: unknown

Annotation of table.unpack

I guess this is due to how table.unpack is annotated:

---@version >5.2, JIT
---#DES 'table.unpack'
---@generic T
---@param list T[]
---@param i? integer
---@param j? integer
---@return T ...
---@nodiscard
function table.unpack(list, i, j) end

  • It is using a T[] to match the list. Although T is a generic type, is can only match one type (or a union type) => homogeneous array
  • In this case luals might be inferring that tuple is an array of integer|boolean => so it matches T to integer|boolean
  • And finally it is trying to return T ... (variadic return) but unfortunately, the generic support of luals is quite limited as seems currently no way to return variadic generic type, so we are getting d: unknown ...

Hack annotation?

In this PR #2587, @lewis6991 tried with with a "hack" to annotate unpack

  • This seems to support up to 9 unpack values of different types, which I believe it is more than enough to solve most common cases 👍
  • I just tried to copy this annotation to table.unpack, however, seems not working well ☹️
---@generic T1, T2, T3, T4, T5, T6, T7, T8, T9
---@param list {[1]: T1, [2]: T2, [3]: T3, [4]: T4, [5]: T5, [6]: T6, [7]: T7, [8]: T8, [9]: T9 }
---@return T1, T2, T3, T4, T5, T6, T7, T8, T9
---@nodiscard
function table.unpack(list) end

---@alias my_tuple { [1]: integer, [2]: boolean }

---@type my_tuple
local tuple = {1, true}

local a, b, c = table.unpack(tuple)
-- a: boolean|integer, b: boolean|integer, c: integer (extra one??)

local a, b, c = unpack(tuple)
-- same result as above
  • although it can provide types for the return value, none of them are actually correct 😇
  • I am using v3.10.6, maybe this hack doesn't work anymore after some recent change in luals ☹️

I'm not sure if this is a feature that is even considered

I don't know if it has been considered, but definitely it is currently not supported.

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

No branches or pull requests

2 participants