From 7fa9e424b08f8d037a9c289c692caa87f26d6b3e Mon Sep 17 00:00:00 2001 From: Christopher Pruijsen Date: Tue, 29 Sep 2026 04:10:06 +0100 Subject: [PATCH] fix: LuaJIT ?? strips optional ? from the left-hand type integer? stores nil as a node flag, so ?? never saw a nil object and copied the optional type unchanged. Treat isOptional() as hasNil so the existing removeOptional() branch runs. --- changelog.md | 1 + script/vm/operator.lua | 2 +- test/type_inference/common.lua | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index f712d4813..b9916c8e9 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,7 @@ ## Unreleased +* `FIX` LuaJIT nil-coalescing `??` now strips the optional `?` from the left-hand type (e.g. `integer? ?? 2` infers `integer`) [#3459](https://github.com/LuaLS/lua-language-server/issues/3459) * `FIX` A `.gitignore` line containing only whitespace no longer ignores the entire workspace [#3458](https://github.com/LuaLS/lua-language-server/issues/3458) * `FIX` `need-check-nil` diagnostic is no longer reported on safe navigation access (e.g. `x?.field`, `f?.()`, `t?.[key]`), since the optional access itself already handles the nil check. Note that a non-safe access chained after a safe one (e.g. `x.upper()?.field`) still reports, because the safe access only protects its own result. diff --git a/script/vm/operator.lua b/script/vm/operator.lua index bb71b02b2..ed53cdfc3 100644 --- a/script/vm/operator.lua +++ b/script/vm/operator.lua @@ -272,7 +272,7 @@ vm.binarySwitch = util.switch() local node2 = vm.compileNode(source[2]) -- 统计具体类型:variable/local 是引用元信息,无具体类型时视为未知(可能为 nil) local count = 0 - local hasNil = false + local hasNil = node1:isOptional() for c in node1:eachObject() do if c.type == 'nil' or (c.type == 'global' and c.cate == 'type' and c.name == 'nil') then diff --git a/test/type_inference/common.lua b/test/type_inference/common.lua index 775634028..9a9d74355 100644 --- a/test/type_inference/common.lua +++ b/test/type_inference/common.lua @@ -3312,6 +3312,14 @@ end local = n or 0 ]] +config.set(nil, 'Lua.runtime.nonstandardSymbol', { '??' }) +TEST 'integer' [[ +---@type integer? +local foo = 1 +local = foo ?? 2 +]] +config.set(nil, 'Lua.runtime.nonstandardSymbol', {}) + TEST 'number' [=[ local = F()--[[@as number]] ]=]