Skip to content

Way to @type annotate array of functions without { [integer]: fun() } #2367

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

Closed
d-enk opened this issue Oct 12, 2023 · 2 comments · Fixed by #2991
Closed

Way to @type annotate array of functions without { [integer]: fun() } #2367

d-enk opened this issue Oct 12, 2023 · 2 comments · Fixed by #2991

Comments

@d-enk
Copy link
Contributor

d-enk commented Oct 12, 2023

---@type { v: integer }[]
_ = {
	{ v = "" }, --- b: integer - Cannot assign `string` to `integer`.
}

---@type { [integer]: fun(v: integer) }
_ = {
	[2] = function(v)
		_ = v --- b: integer
	end,

	function(v)
		_ = v --- b: any ???
	end,
}


---@type fun(v: integer)[]
_ = {
	[2] = function(v)
		_ = v --- b: any
	end,

	function(v)
		_ = v --- v: any ???
	end,
}

I wish the last option would work, or at least without [2] in { [integer]: fun() }

@tomlau10
Copy link
Contributor

tomlau10 commented Aug 26, 2024

Hi, I randomly come across this issue and after some debugging, I think I have found the cause of this.
There is a difference between { function () end } and { [1] = function () end }

  • the 1st one is parsed as tableexp type
  • the 2nd one is parsed as tableindex type

And in the code here:

if guide.isAssign(parent)
and parent.value == source then
vm.setNode(source, vm.compileNode(parent))

also here:
local assignTypeMap = {
['setglobal'] = true,
['local'] = true,
['self'] = true,
['setlocal'] = true,
['setfield'] = true,
['setmethod'] = true,
['setindex'] = true,
['tablefield'] = true,
['tableindex'] = true,
['label'] = true,
['doc.class'] = true,
['doc.alias'] = true,
['doc.enum'] = true,
['doc.field'] = true,
['doc.class.name'] = true,
['doc.alias.name'] = true,
['doc.enum.name'] = true,
['doc.field.name'] = true,
['doc.type.field'] = true,
['doc.type.array'] = true,
}
function m.isAssign(source)
local tp = source.type
if assignTypeMap[tp] then

  • only tableindex is considered as an assign type
  • thus when writing the function without [1] = / [2] =, no type inferencing is done.

I added the tableexp in the assignTypeMap and the following starts to work 👀
(but strange enough, the [index] style not works on some cases ...)

---@type { [integer]: fun(v: integer) }
local _ = {
    [2] = function(v) end,  --> v: integer
    function(v) end,        --> v: integer
}

---@type fun(v: integer)[]
local _ = {
    [2] = function(v) end,  --> v: any ??? doesn't work
    function(v) end,        --> v: integer
}

---@type fun(v: integer)[]
local _ = {
    [1] = function(v) end,  --> v: any ??? doesn't work
    [2] = function(v) end,  --> v: any ??? doesn't work
}

still maybe you would like to try it out and open PR after testing 😄 @d-enk

@tomlau10
Copy link
Contributor

(revisited from #2250 (comment))

I tried to debug into why fun(v: integer)[] annotation doesn't work and seems I found it 👀

As explained before, { function () end } is parsed as tableexp, while { [1] = function () end } is parsed as tableindex.
Then I looked into how the type infer in tableindex object is compiled and added some debug print here and there.
Finally I found the difference in this piece of logic:

local key = guide.getKeyName(source)
if not hasMarkDoc then
if key then
vm.compileByParentNode(source.node, key, function (src)
if src.type == 'doc.field'
or src.type == 'doc.type.field'
or src.type == 'doc.type.name' then
hasMarkDoc = true
vm.setNode(source, vm.compileNode(src))

  • when using ---@type { [integer]: fun(v: integer) }, the pushed src is of type doc.type.field
  • while using ---@type fun(v: integer)[], the pushed src is of type doc.type.function

So I added or src.type == 'doc.type.function' in the above if case, and it worked 🎉


I may try to open a PR after more testing when I have time later 😄

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

Successfully merging a pull request may close this issue.

2 participants