Repository navigation
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?
Type Checking
Expected Behaviour
Given the following code:
---@class A
local A = {}
---@generic S
---@param self S
---@param str string
---@return S
function A:method1(str) end
---@generic S
---@param self S
---@param num1 number
---@param num2? number
---@param num3? number
---@return S
function A:method1(num1, num2, num3) end
---@class B: A
local B = {}
local x = B:method1("str")
local y = B:method1(1)
local z = B:method1(1, 2, 3)The following should be true:
local x = B:method1("str") --> local x: B
local y = B:method1(1) --> local y: B
local z = B:method1(1, 2, 3) --> local z: BAll three local variables should be the B type as that is what generic S would be during this method call.
Actual Behaviour
The following is given instead by LuaLS:
local x = B:method1("str") --> local x: unknown
local y = B:method1(1) --> local y: unknown
local z = B:method1(1, 2, 3) --> local z: BFrom my testing, it seems that given any amount of overloads and a method call the following seems to happen. Whether this is actually what happens in LuaLS is a different story as I could not figure out why this happens.
- Change the method call's parameters to be all
anys
B:method1("str")-->B:method1(any) - Check if that new call matches more than one overload.
B:method1(any)matchesA:method1(str: string)
B:method1(any)matchesA:method1(num1: number, num2?: number, num3?: number) - If multiple overloads were matched, return
unknowninstead.
Reproduction steps
- Paste the following code into a lua file and open it:
(Alternatively, use the test cases file found in the "Additional Notes" section)---@class A local A = {} ---@generic S ---@param self S ---@param str string ---@return S function A:method1(str) end ---@generic S ---@param self S ---@param num1 number ---@param num2? number ---@param num3? number ---@return S function A:method1(num1, num2, num3) end ---@class B: A local B = {} local x = B:method1("str") local y = B:method1(1) local z = B:method1(1, 2, 3)
- Hover over locals
x,y, andz. - Notice that locals
xandyhave the wrong type while localzis fine.
Additional Notes
This method of returning self is being done because the self keyword does not actually resolve to the class being used for the method call and always seems to be class that created the method instead.
This error started appearing in 3.10.1 and has not been fixed yet as of 3.13.6.

(The testing was done before 3.13.6 was released and I have personally tested 3.13.6 and confirm that it is still the same as 3.13.5)
The following file was used to get the information for the above chart.
testcases.txt
Reverting the changes made by #2898 and #2765 appears to fix this issue (while also re-introducing the bugs those PRs fixed.)
I have searched for other issues related to this, but only found mostly unrelated issues. However, i did find one comment on issue #723 that mentions this exact bug and the PR following it (#2898) seemed to only fix half of the issue. (As shown by version 3.12.0 correcting more than half of the test cases in the test case file.)
Activity
tomlau10 commentedon Feb 23, 2025
Hi, I am the author of #2898 and #2765 (though I am not author of LuaLS).
This is a very detailed bug report 👍
I will try to take a look when I have time.
But I cannot promise when / or even if possible I can come up a fix with it 🙁 .
It's been a while since I wrote those fix PRs.
I can give more details on it in case you want to do further debugging yourself.
PR #2765
This tries to fix #2758, where the infer on functions with overloads are inconsistent.
3.10.0run time error in #2776
3.10.1The regression fix
Seems we need to find out why the run time error fix in 8ecec08 (3.10.1) is problematic 🤔
tomlau10 commentedon Feb 23, 2025
known facts
3.10.0is correct3.10.03.10.13.10.1is the run time error fix in 8ecec08diff: 3.10.0...3.10.1
the overly complicated fix in 8ecec08
8ecec08 is the runtime error fix to #2776.
To be honest, now I don't know why @sumneko comes up with such a complicated fix 🙈
(I don't have enough knowledge in LuaLS's codebase at that time)
I reinvestigated #2776, the root cause seems to be that:
argnode incall.argsis already compiled by the time of removing unmatched function signatureargnode must exist afterwardsvm.removeNode()will lead to possible index nil value error in that callstack / callframethe fix
lua-language-server/script/vm/compiler.lua
Lines 643 to 660 in 64c7084
This seems passed all existing tests, as well as the reproduction snippet in your example 😄
I will try to open a PR soon.
GrandpaScout commentedon Feb 23, 2025
Gonna be honest, I might have confused 2765 with another PR, that's my bad. I did actually look into what was causing this but LuaLS is a complex beast and I couldn't find anything that would lead to the solution, so I'm glad you found something. Thanks for looking into this so quickly.