Skip to content

fix: keep async flag when instantiating generic function aliases - #3476

Open
ybai08 wants to merge 1 commit into
LuaLS:masterfrom
ybai08:fix/async-generic-alias
Open

ybai08 wants to merge 1 commit into
LuaLS:masterfrom
ybai08:fix/async-generic-alias

Conversation

@ybai08

@ybai08 ybai08 commented Oct 18, 2026

Copy link
Copy Markdown

Summary

  • cloneObject in script/vm/generic.lua builds a new doc.type.function when a generic is resolved, but it copied only args/returns. The async flag (and asyncPos) set by the LuaDoc parser for async fun was dropped. So ---@alias Name<T> async fun(): T lost its async-ness once used as Name<string>, whether through ---@type, a ---@field, or a local function annotated with it. await-in-sync stopped warning and hover stopped showing async. Non-generic aliases and async fun<T>(...) were not affected, because they are not cloned.
  • The clone now copies async and asyncPos from the source.
  • The changelog Unreleased section has a FIX entry that links Async flag lost when alias with type parameters (@alias Name<T> async fun) is used #3469.

Test plan

  • test/diagnostics/await-in-sync.lua: a generic async alias used via ---@type on a local, on a local function, and via a class ---@field now reports await-in-sync in a sync caller. Each of these fails without the change and passes with it. Another case checks there is no warning inside an ---@async caller.
  • test/hover/init.lua: hover of ---@type AsyncGenericFunc<string> now shows local f: async AsyncGenericFunc<string> (it was local f: AsyncGenericFunc<string>).
  • bin/lua-language-server test.lua --name=diagnostics and --name=hover pass.
  • Full bin/lua-language-server test.lua passes (test finish.), on darwin-arm64 only.

Fixes #3469

cloneObject rebuilt doc.type.function without copying `async`/`asyncPos`,
so `---@alias Name<T> async fun(): T` lost its async flag once used as
`Name<string>`, and await-in-sync/hover treated it as a sync function.

Fixes LuaLS#3469

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

中文:变更整体方向正确:cloneObject 在克隆泛型别名解析后的函数类型时保留了 async/asyncPos,测试覆盖了诊断与 hover 场景。未发现明确的功能性缺陷或安全问题。建议补充一个回归测试,覆盖 asyncPos 的保留(例如 hover 或诊断中依赖 async 关键字位置的行为),因为当前测试只验证了 async 标志,未验证 asyncPos 是否被正确保留;若 asyncPos 指向原类型节点而克隆对象位置不同,可能导致定位异常。另外建议确认 cloneObject 的其他调用路径不会因新增字段而产生意外行为(例如非函数类型的克隆),但基于当前 diff 未发现证据表明存在问题。

English: The change is directionally correct: cloneObject now preserves async/asyncPos when cloning a resolved generic alias function type, and tests cover diagnostics and hover. No clear functional defects or security issues were found. Suggest adding a regression test that covers preservation of asyncPos (e.g., behavior relying on the async keyword position in hover or diagnostics), since current tests only verify the async flag and not whether asyncPos is correctly retained; if asyncPos points to the original type node while the cloned object has different positions, it could cause incorrect location reporting. Also suggest confirming that other call paths of cloneObject are not affected by the new fields (e.g., cloning non-function types), though no evidence of a problem was found in the current diff.

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 this pull request may close these issues.

Async flag lost when alias with type parameters (@alias Name<T> async fun) is used

1 participant