Skip to content

Fix annotations for LuaJIT jit library - #1252

Open
ligurio wants to merge 7 commits into
EmmyLuaLs:mainfrom
ligurio:ligurio/gh-xxxx-correct-jit-lib
Open

ligurio wants to merge 7 commits into
EmmyLuaLs:mainfrom
ligurio:ligurio/gh-xxxx-correct-jit-lib

Conversation

@ligurio

@ligurio ligurio commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

@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.

Code Review: LuaJIT Standard Library Type Definitions

Summary

The changes improve type accuracy for LuaJIT's jit, jit.profile, and jit.util modules. Overall the direction is good, but there are several correctness issues worth addressing.


Issues & Recommendations

1. jit.luajit.attach return type missing

--- @param func   function
--- @param event? string
function jit.attach(func, event) end
  • Issue: jit.attach returns the previous callback (or nil). The return type is undocumented, so callers lose type info.
  • Suggestion: Add --- @return function? (or the appropriate callback signature).

2. jit.luajit.security mode type is too narrow

--- @param mode? 'prng' | 'strhash' | 'strid' | 'mcode'
  • Issue: LuaJIT's jit.security accepts "prng", "strhash", "strid", "mcode", and "none" (to query all). Also, when mode is omitted the return is a table of statuses, not an integer.
  • Suggestion: Either add 'none' to the union, or document the overload:
    --- @overload fun(): table
    --- @param mode? 'prng' | 'strhash' | 'strid' | 'mcode'
    --- @return integer status

3. jit.luajit.flush overload inconsistency

--- @overload fun(tr: integer)
--- @param func?      function|boolean
--- @param recursive? boolean
function jit.flush(func, recursive) end
  • Issue: The @overload signature fun(tr: integer) conflicts with the primary signature fun(func?: function|boolean, recursive?: boolean). A bare integer argument will match neither cleanly (integer is not function|boolean).
  • Suggestion: Make the primary param type include integer:
    --- @param func? function|boolean|integer
    or drop the overload and use a union type.

4. jit.luajit.opt.start param type too restrictive

--- @param ... string|number
  • Issue: LuaJIT's jit.opt.start accepts strings like "hotloop=10" and also numbers (e.g. jit.opt.start(3)). string|number is fine, but note that boolean is also accepted in some versions. Minor — acceptable as-is, but worth confirming against the target LuaJIT version.

5. jit/profile.luadumpstack return type mismatch

--- @overload fun(th: thread, fmt: string, depth: integer): string
--- @param fmt   string
--- @param depth integer
--- @return string dump
function profile.dumpstack(fmt, depth) end
  • Issue: The overload declares a thread first param, but the primary signature omits it. The @return string dump applies to the primary signature, which is fine, but the overload's return is redundant/inconsistent. Also, profile.dumpstack can return nil on error.
  • Suggestion: Align both signatures and use string?:
    --- @overload fun(th: thread, fmt: string, depth: integer): string?
    --- @param fmt   string
    --- @param depth integer
    --- @return string? dump

6. jit/util.luafuncinfo.lua.proto type changed incorrectly

--- @class jit.funcinfo.lua
--- @field proto Proto
...
-    ---@type Proto[]
-    proto = {},
  • Issue: In LuaJIT, funcinfo.lua.proto is a list of child prototypes (Proto[]), not a single Proto. The change from Proto[] to Proto is a regression.
  • Suggestion: Revert to --- @field proto Proto[] and keep the ---@type Proto[] annotation on the field.

7. jit/util.luaTrace class removed but still referenced

  • Issue: The --- @class Trace declaration was removed, and tr params were changed to integer. This is correct (traces are identified by integer IDs), but ensure no other file references Trace as a type. A grep for Trace across the stdlib is recommended.
  • Suggestion: Confirm no dangling references remain.

8. jit/util.luatracesnap overload return arity

--- @overload fun(tr: integer, sn: integer, getpos: boolean): jit.snap? snap, integer? pos
--- @param tr integer
--- @param sn integer
--- @return jit.snap? snap
function util.tracesnap(tr, sn) end
  • Issue: The overload returns two values, but the primary signature only declares one. When getpos is true, the function returns (snap, pos). The primary signature should also allow the second return, or the overload should be the canonical form.
  • Suggestion: Add --- @return integer? pos to the primary signature as well, or restructure to a single signature with optional getpos.

9. jit/util.luafuncinfo param union function|Proto

  • Issue: This is correct for LuaJIT (accepts either a function or a proto object), but Proto is declared as an empty class. Consider adding a note or minimal fields so tooling can distinguish it from any.

Minor / Style

  • jit.lua: The removed --- @overload fun(...): ... lines had malformed syntax (param func inside the overload). Good cleanup.
  • jit.lua: version_num changed from number to integer — correct, since it's a bit-packed integer.
  • jit.lua: arch union expanded with mips32r6/mips64r6 variants — good, matches LuaJIT 2.1.
  • jit/profile.lua: vmstvmstate rename in the callback signature is a good clarity fix, but verify it matches the actual LuaJIT API docs (the parameter is positional, so the name is cosmetic).

Priority Fixes

  1. jit.util.lua: proto should be Proto[] (regression).
  2. jit.lua: jit.flush overload conflicts with primary signature.
  3. jit.lua: jit.security missing 'none' mode / table return overload.
  4. jit.lua: jit.attach missing return type.
  5. jit/profile.lua: dumpstack should return string?.

Fix the malformed @overload comments of jit.on/off/flush, make their
function argument optional, type the jit.opt.start flags as string|number,
type jit.version_num as integer, extend the jit.arch union and add the
LuaJIT jit.security and jit.attach functions.

Part of tarantool/tarantool#13024
Make the profile.start mode argument optional, name the callback
vmstate argument after the LuaJIT implementation and document the
string returned by profile.dumpstack.

Part of tarantool/tarantool#13024
Trace functions take a trace number, not the unused Trace type, so
type their tr arguments as integer. Accept function|Proto for the
reflection functions, type the funcinfo proto field as a single
Proto and add the getpos argument and position result of tracesnap.

Part of tarantool/tarantool#13024
@ligurio
ligurio force-pushed the ligurio/gh-xxxx-correct-jit-lib branch from fd8419f to d92a5b0 Compare September 17, 2026 18:18
@ligurio

ligurio commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

Pinned commit: c6ffc141a8762b41703f9287d63d93622a13dd8f (branch v2.1). Every link below embeds this hash.


1. jit.attach return type — review is wrong

lib_jit.c#L123-L149. The function ends with return 0; — it pushes nothing on the stack. The detach branch's setnilV(L->top++) is a temporary value for lua_next iteration and is undone by L->top--.

Verdict: do not add @return function?. No change.


2. jit.security modes / return — review is wrong

  • lib_jit.c#L116-L121: lj_lib_checkopt(L, 1, -1, LJ_SECURITY_MODESTRING)setintV(...)return 1. Always a single integer.
  • lj_arch.h#L775-L776: LJ_SECURITY_MODESTRING = "\004prng\007strhash\005strid\005mcode"exactly 4 modes, no none.
  • lj_arch.h#L768-L774: LJ_SECURITY_MODE packs 2 bits per mode; (MODE >> (2*idx)) & 3 yields one integer.
  • lj_lib.c#L308-L323 + #L196-L210: since def = -1 < 0, lj_lib_checkstr is used — the argument is required (omitting it errors); there is no table-return path.

Verdict: do not add a table overload or 'none'. At most mode?mode. No change.


3. jit.flush overload — review is correct

lib_jit.c#L78-L88: if the first arg is tvisnumber, it is a trace number; otherwise setjitmode. setjitmode accepts func|proto (L50), true, or nothing; the second arg is bool.

Status (working tree): overload removed, primary → function|boolean|integer.


4. jit.opt.start type — review is wrong about boolean

lib_jit.c#L514-L529: lj_lib_checkstr(L, i). lj_lib.c#L196-L210 coerces number → string (L202-L205); boolean/other raises lj_err_argt (L208).

Verdict: string|number is correct; boolean is not accepted. No change.


5. profile.dumpstack return — review is wrong about nil

lib_jit.c#L606-L622: signature [thread,] fmt, depth, always ends with lua_pushlstring(L, p, len); return 1;. luaJIT_profile_dumpstack always return sb->b;.

The overload fun(th: thread, fmt: string, depth: integer): string is consistent with the primary fun(fmt, depth): string.

Verdict: string? is unnecessary. No change.


6. funcinfo.proto is a single Proto, not an array — review is wrong

lib_jit.c#L170-L209; Lua branch at #L196: setprotoV(L, ..., pt) where pt is a single GCproto * from lj_lib_checkLproto. The children field is a boolean flag (L189-L190), not a list.

Verdict: the current @field proto Proto is correct; reverting to Proto[] would itself be the regression. No change.


7. Trace references — review is correct, nothing to fix

Traces are integer TraceNo (jit_checktracelj_lib_checkint(L, 1)), matching the Traceinteger change. rg '\bTrace\b' over resources/std reports 0 matches.

Verdict: confirmed clean.


8. tracesnap return arity — review is correct

lib_jit.c#L343-L369: getpos comes from the 3rd argument (L348); with getpos it returns 2 values (L361-L365), otherwise 1.

Status (working tree): overload collapsed into a single signature with getpos? and two @returns (snap, pos).


9. Proto empty class — minor, acceptable

lj_lib_checkLproto (lj_lib.c) accepts function|Proto; Proto is an opaque GCproto * with no exposed API fields.

Verdict: leave empty.


Minor notes

  • jit.on/off/flush also accept a proto (lib_jit.c#L49-L51); the current union lacks Proto. Optionally add Proto (declared in jit/util.lua).
  • jit.arch (lj_arch.h#L190-L431): union is complete; mips32r6/mips32r6el are defined (L408, L423) but MIPS32R6 is rejected at build time (#error "No support for MIPS32R6"), so effectively unreachable — not critical.
  • profile.start callback: lib_jit.c#L548-L562, comment /* callback(thread, samples, vmstate) */ (L562); vmstate is a 1-char string. The rename is cosmetic; the API is positional.

Summary

# Topic Verdict Action
1 jit.attach return review wrong no change
2 jit.security modes review wrong no change
3 jit.flush overload review correct applied: union, overload removed
4 jit.opt.start type review wrong no change
5 dumpstack return review wrong no change
6 funcinfo.proto review wrong no change
7 Trace refs review correct confirmed clean
8 tracesnap arity review correct applied: single signature
9 Proto class minor leave empty

No commits made; edits remain in the working tree.

Patch with fixups

--- a/crates/emmylua_code_analysis/resources/std/jit.lua
+++ b/crates/emmylua_code_analysis/resources/std/jit.lua
@@ -18,8 +18,7 @@ function jit.on(func, recursive) end
 --- @param recursive? boolean
 function jit.off(func, recursive) end
 
---- @overload fun(tr: integer)
---- @param func?      function|boolean
+--- @param func?      function|boolean|integer
 --- @param recursive? boolean
 function jit.flush(func, recursive) end
 
diff --git a/crates/emmylua_code_analysis/resources/std/jit/util.lua b/crates/emmylua_code_analysis/resources/std/jit/util.lua
index 258407e8..e7b19a68 100644
--- a/crates/emmylua_code_analysis/resources/std/jit/util.lua
+++ b/crates/emmylua_code_analysis/resources/std/jit/util.lua
@@ -83,10 +83,11 @@ function util.tracek(tr, idx) end
 
 --- @class jit.snap: integer[]
 
---- @overload fun(tr: integer, sn: integer, getpos: boolean): jit.snap? snap, integer? pos
---- @param tr integer
---- @param sn integer
+--- @param tr     integer
+--- @param sn     integer
+--- @param getpos? boolean
 --- @return jit.snap? snap

@ligurio

ligurio commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

https://github.com/EmmyLuaLs/emmylua-analyzer-rust/actions/runs/35258029478/job/105326440119?pr=1252


   Compiling icu_properties_data v2.2.0
error: unused import: `node::*`
  --> crates/emmylua_parser/src/syntax/mod.rs:14:9
   |
14 | pub use node::*;
   |         ^^^^^^^
   |
   = note: `-D unused-imports` implied by `-D warnings`
   = help: to override `-D warnings` add `#[allow(unused_imports)]`

    Checking icu_collections v2.2.0

@ligurio

ligurio commented Sep 21, 2026

Copy link
Copy Markdown
Contributor Author

@CppCXY could you take a look?

@CppCXY

CppCXY commented Sep 21, 2026

Copy link
Copy Markdown
Member

The type name "Proto" is too generic; it should be changed to JIT.Proto. Also, the code needs to be formatted with luafmt. Other than that, there aren't many issues.

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.

2 participants