Skip to content

fix(std): correct loadstring annotations for LuaJIT - #1298

Merged
CppCXY merged 2 commits into
EmmyLuaLs:mainfrom
ligurio:ligurio/gh-1274-fix-loadstring-ann
Oct 16, 2026
Merged

CppCXY merged 2 commits into
EmmyLuaLs:mainfrom
ligurio:ligurio/gh-1274-fix-loadstring-ann

Conversation

@ligurio

@ligurio ligurio commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

In LuaJIT loadstring() is an alias for load() and accepts an optional mode and env, so extend the loadstring() signature accordingly. Also add @NODISCARD to loadfile() for consistency with load()/loadstring().

Add a redundant-parameter regression test for the LuaJIT case.

Fixes #1274

In LuaJIT loadstring() is an alias for load() and accepts an optional
mode and env, so extend the loadstring signature accordingly. Also add
@NODISCARD to loadfile for consistency with load/loadstring.

Add a redundant-parameter regression test for the LuaJIT case.

Fixes EmmyLuaLs#1274
Add redundant-parameter coverage for load() and loadfile() so all
three LuaJIT load functions are exercised, mirroring the
loadstring regression test.

Follows up EmmyLuaLs#1274

@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

1. global.lua — loadstring signature change

Issue: mode parameter type may be incorrect for Lua 5.1

The loadstring function is annotated with @version 5.1, JIT. In standard Lua 5.1, loadstring only accepts (text, chunkname) — it does not accept mode or env. Only LuaJIT extends loadstring to accept mode/env (as an alias for load).

By adding mode/env unconditionally, the stdlib now advertises these parameters for plain Lua 5.1 as well, which will suppress legitimate RedundantParameter diagnostics for 5.1 users. Consider splitting the annotation or gating the extra params to JIT only (e.g., a separate @version JIT overload), rather than widening the shared signature.

Issue: mode type is std.loadmode, but load above uses the same — verify consistency

The new @param mode? std.loadmode matches load's annotation, which is good. However, note that LuaJIT's loadstring actually accepts the same mode strings as load ("b", "t", "bt"), so this is fine — just flagging that the type must be defined and exported.

Issue: @nodiscard added to loadfile — behavior change

Adding @nodiscard to loadfile is a semantic change unrelated to the stated issue (#1274). It will now flag every ignored loadfile(...) call. This may be intentional, but it's worth confirming:

  • It is inconsistent with load/loadstring, which already had @nodiscard — so this actually fixes an inconsistency. Good.
  • But it is a breaking change for users who intentionally ignore the result. Ensure this is called out in release notes.

2. Test file — redundant_parameter_test.rs

Issue: Repeated boilerplate across three tests

All three tests duplicate the same setup:

let mut ws = VirtualWorkspace::new();
let mut config = Emmyrc::default();
config.runtime.version = EmmyrcLuaVersion::LuaJIT;
ws.update_emmyrc(config);
ws.analysis.init_std_lib(None);

Consider extracting a helper (e.g., fn luajit_ws() -> VirtualWorkspace) to reduce duplication and make future version-specific tests easier to add.

Issue: use statements inside each test function

use crate::{Emmyrc, EmmyrcLuaVersion}; is repeated in all three test functions. Move these to the module level (or the enclosing mod test) to avoid repetition.

Issue: Guard tests use assert!(!ws.has_no_diagnostic(...)) — weak assertion

The negative guard only asserts that some diagnostic exists, not that it is specifically RedundantParameter. If an unrelated diagnostic (e.g., a type error from passing {} where table is expected, or a different check) fires, the test still passes vacuously. Prefer asserting the specific diagnostic code, e.g.:

assert!(ws.has_diagnostic(
    DiagnosticCode::RedundantParameter,
    r#"loadstring("return 42", nil, nil, {}, {})"#
));

(assuming such an API exists; otherwise check the diagnostic list explicitly).

Issue: Test naming / scope

The tests are named test_issue_1274_luajit_*, which is fine, but the load test (test_issue_1274_luajit_load) tests behavior that was presumably already working (since load already had mode/env). Confirm this test is actually exercising the new code path; if load was unchanged, this test may be redundant with existing coverage.

Minor: local _ = loadstring(...)

Using local _ = to suppress @nodiscard is a reasonable pattern, but note that _ is a real variable here. If the linter has an "unused local" check, this could itself trigger a diagnostic and interfere with the has_no_diagnostic assertion. Verify that _ is treated as a discard name by the analyzer.

3. General

  • Missing changelog / doc update: The stdlib change affects user-visible diagnostics. Ensure the release notes mention both the loadstring signature widening and the new @nodiscard on loadfile.
  • Version gating: The core concern is that loadstring's new params are only valid for JIT, but the annotation applies to 5.1, JIT. This is the most likely source of false negatives for 5.1 users.

Summary

Severity Issue
High loadstring mode/env params apply to Lua 5.1, but only JIT supports them → suppresses valid diagnostics
Medium Guard tests assert only "some diagnostic", not specifically RedundantParameter
Low Duplicated setup/use across three tests
Low @nodiscard on loadfile is a behavior change; needs release-note mention
Info local _ = discard pattern may interact with unused-local checks

@CppCXY
CppCXY merged commit 99c01a4 into EmmyLuaLs:main Oct 16, 2026
16 checks passed
@ligurio
ligurio deleted the ligurio/gh-1274-fix-loadstring-ann branch October 16, 2026 14:15
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.

Incorrect LuaJIT annotations for loadstring(), load() and loadfile()

2 participants