From 4e616bb1f773b430f1997ec675f8336ad8f1803b Mon Sep 17 00:00:00 2001 From: Tom Lau Date: Fri, 6 Sep 2024 10:56:07 +0800 Subject: fix: ignore function's auto infer type when there is only `@overload` --- script/vm/function.lua | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/script/vm/function.lua b/script/vm/function.lua index 7a15ac5a..21a432c1 100644 --- a/script/vm/function.lua +++ b/script/vm/function.lua @@ -359,6 +359,7 @@ end ---@return number local function calcFunctionMatchScore(uri, args, func) if vm.isVarargFunctionWithOverloads(func) + or vm.isFunctionWithOnlyOverloads(func) or not isAllParamMatched(uri, args, func.args) then return -1 @@ -490,6 +491,36 @@ function vm.isVarargFunctionWithOverloads(func) return false end +---@param func table +---@return boolean +function vm.isFunctionWithOnlyOverloads(func) + if func.type ~= 'function' then + return false + end + if func._onlyOverloadFunction ~= nil then + return func._onlyOverloadFunction + end + + if not func.bindDocs then + func._onlyOverloadFunction = false + return false + end + local hasOverload = false + for _, doc in ipairs(func.bindDocs) do + if doc.type == 'doc.overload' then + hasOverload = true + elseif doc.type == 'doc.param' + or doc.type == 'doc.return' + then + -- has specified @param or @return, thus not only @overload + func._onlyOverloadFunction = false + return false + end + end + func._onlyOverloadFunction = hasOverload + return true +end + ---@param func parser.object ---@return boolean function vm.isEmptyFunction(func) -- cgit v1.2.3 From 9794cc44b6524f0d3bc4e0bab59275745802366b Mon Sep 17 00:00:00 2001 From: Tom Lau Date: Fri, 6 Sep 2024 10:57:50 +0800 Subject: fix: function param's auto infer type should use union of all overload --- script/vm/compiler.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 041d287e..50f260c2 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -1099,6 +1099,7 @@ local function compileFunctionParam(func, source) -- local call ---@type fun(f: fun(x: number));call(function (x) end) --> x -> number local funcNode = vm.compileNode(func) + local found = false for n in funcNode:eachObject() do if n.type == 'doc.type.function' and n.args[aindex] then local argNode = vm.compileNode(n.args[aindex]) @@ -1107,9 +1108,16 @@ local function compileFunctionParam(func, source) vm.setNode(source, an) end end - return true + -- NOTE: keep existing behavior for local call which only set type based on the 1st match + if func.parent.type == 'callargs' then + return true + end + found = true end end + if found then + return true + end local derviationParam = config.get(guide.getUri(func), 'Lua.type.inferParamType') if derviationParam and func.parent.type == 'local' and func.parent.ref then -- cgit v1.2.3 From 54f1bac0815c0e51494f057282984d173469838f Mon Sep 17 00:00:00 2001 From: Tom Lau Date: Fri, 6 Sep 2024 11:18:20 +0800 Subject: test: add test cases for new overload type match behavior --- test/type_inference/param_match.lua | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/type_inference/param_match.lua b/test/type_inference/param_match.lua index 906b9305..21dcf4d3 100644 --- a/test/type_inference/param_match.lua +++ b/test/type_inference/param_match.lua @@ -172,6 +172,44 @@ local v = 'y' local = f(v) ]] +TEST 'string|number' [[ +---@overload fun(a: string) +---@overload fun(a: number) +local function f() end +]] + +TEST '1|2' [[ +---@overload fun(a: 1) +---@overload fun(a: 2) +local function f() end +]] + +TEST 'string' [[ +---@overload fun(a: 1): string +---@overload fun(a: 2): number +local function f(a) end + +local = f(1) +]] + +TEST 'number' [[ +---@overload fun(a: 1): string +---@overload fun(a: 2): number +local function f(a) end + +local = f(2) +]] + +TEST 'string|number' [[ +---@overload fun(a: 1): string +---@overload fun(a: 2): number +local function f(a) end + +---@type number +local v +local = f(v) +]] + TEST 'number' [[ ---@overload fun(a: 1, c: fun(x: number)) ---@overload fun(a: 2, c: fun(x: string)) -- cgit v1.2.3 From fe84a713afe4a37629cc95ca3d8a3e9c23be8eb8 Mon Sep 17 00:00:00 2001 From: Tom Lau Date: Fri, 6 Sep 2024 12:08:16 +0800 Subject: doc: update changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 38d9aeb7..4d5061af 100644 --- a/changelog.md +++ b/changelog.md @@ -8,6 +8,7 @@ * `FIX` Fix `VM.OnCompileFunctionParam` function in plugins * `FIX` Lua 5.1: fix incorrect warning when using setfenv with an int as first parameter * `FIX` Improve type narrow by checking exact match on literal type params +* `FIX` Incorrect function params' type infer when there is only `@overload` [#2509](https://github.com/LuaLS/lua-language-server/issues/2509) [#2708](https://github.com/LuaLS/lua-language-server/issues/2708) [#2709](https://github.com/LuaLS/lua-language-server/issues/2709) ## 3.10.5 `2024-8-19` -- cgit v1.2.3