Repository navigation
LuaLS processes the wrong LuaDoc for Penlight tablex.filter #3317
Copy link
Copy link
Open
Description
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?
Libraries
Expected Behaviour
local tablex = require("pl.tablex")
tablex.filter(
{},
function() end -- no linting error
)Actual Behaviour
local tablex = require("pl.tablex")
tablex.filter(
{},
function() end -- Cannot assign `function` to parameter `"()"|"<"|"<="|"=="|">"...(+5)`. (...)
)Reproduction steps
- Setup LuaLS and copy example code into a .lua file
- Install Penlight using the Addon Manager
Additional Notes
Here's an extract of the LuaDoc. LuaLS seems to always pick the second definition instead of the first one which has the annotations for using a generic function.
---@generic T, A
---@param t T[]
---@param pred fun(val: T, arg: A): any
---@param arg A
---@return T[]
---@nodiscard
function tablex.filter(t, pred, arg) end
---filter an array's values using a predicate function
---@generic T
---@param t T[] -- a list-like table
---@param pred pl.BoolBinOpString -- a boolean function
---@param arg any -- optional argument to be passed as second argument of the predicate
---@return T[]
---@nodiscard
function tablex.filter(t, pred, arg) endLog File
I set --loglevel=trace and added the code to an empty file while having tail running on the log but there are no relevant details.
$ tail -f ./file_home_function_git_dragdown-modules.log
[13:59:35.741][debug][#0:script/vm/node.lua:490]: clearNodeCache
[13:59:35.741][trace][#0:script/files.lua:286]: Set text: untitled:Untitled-1 takes 0.00012299999999987 sec.
[13:59:35.741][trace][#0:script/files.lua:695]: Compile State: untitled:Untitled-1
[13:59:35.843][debug][#0:script/provider/provider.lua:1120]: textDocument/semanticTokens/range
[13:59:35.857][debug][#0:script/provider/diagnostic.lua:330]: publishDiagnostics untitled:Untitled-1 2
[13:59:40.272][debug][#0:script/vm/node.lua:490]: clearNodeCache
[13:59:40.273][trace][#0:script/files.lua:286]: Set text: untitled:Untitled-1 takes 0.00021399999999971 sec.
[13:59:40.373][trace][#0:script/files.lua:695]: Compile State: untitled:Untitled-1
[13:59:40.374][debug][#0:script/provider/provider.lua:1120]: textDocument/semanticTokens/range
[13:59:40.381][info] [#0:script/provider/diagnostic.lua:171]: clearDiagnostics untitled:Untitled-1
[13:59:47.118][debug][#0:script/vm/node.lua:490]: clearNodeCache
[13:59:47.118][trace][#0:script/files.lua:286]: Set text: untitled:Untitled-1 takes 0.00020199999999981 sec.
[13:59:47.219][trace][#0:script/files.lua:695]: Compile State: untitled:Untitled-1
[13:59:47.220][debug][#0:script/provider/provider.lua:1120]: textDocument/semanticTokens/range
[13:59:47.232][debug][#0:script/provider/diagnostic.lua:330]: publishDiagnostics untitled:Untitled-1 2
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
tomlau10 commentedon Dec 18, 2025
explanation of this behavior (?)
AFAIK, the server will try to type narrow the function signature when applicable.
One of the criteria is number of min/max params
lua-language-server/script/vm/function.lua
Lines 25 to 65 in 3a65772
print(min, max, def)just before thereturnline3, 3, 32, 3, 3minparam of the functions 😕=> the server thinks that the 1st function signature requires 3 params, all are required and none are optional
=> since your code snippet only gives 2 params
=> the server "filtered" it out, and narrowed to the 2nd one...
possible workaround
Looking at the code inside
vm.countParamsOfFunction, it basically uses:isNullable()to determine theminvalue.lua-language-server/script/vm/node.lua
Lines 162 to 178 in 3a65772
nil|any|...as optional, but not for generic param(I am not sure if this is intended behavior)
?marked param as optionalargas optional with?🤔---@param arg? A # note the `?` after `arg`or if you prefer using
|nil---@param arg A|nil # note the `|nil` after `A`=> then server can type narrow the function correctly
In short, the workaround is mark
argas optional.Meanwhile whether generic param not counted as optional is a "feature" or bug, has to be clarified by maintainers. 😕
FunctionDJ commentedon Dec 18, 2025
@tomlau10 Thanks a ton for this breakdown! Very insightful and comprehensible.
From the user-side, just passing any value as a third parameter (that can go unused in the predicate function) does indeed make LuaLS pick the correct type definition and doesn't yield a type warning.