Skip to content

Sanitise Lua method names where they are assigned - #1230

Merged
Frotty merged 7 commits into
masterfrom
lua/sanitise-method-names
Aug 16, 2026
Merged

Sanitise Lua method names where they are assigned#1230
Frotty merged 7 commits into
masterfrom
lua/sanitise-method-names

Conversation

@Frotty

@Frotty Frotty commented Aug 15, 2026

Copy link
Copy Markdown
Member

A method name becomes a Lua table key, so it has to be an identifier. A method specialised with two type arguments was named after them, commas included, and emitted

Class.get_specialized_integer, integer = impl

which is valid Lua assigning to two targets — so the syntax check passed and the wrong thing happened quietly. A tuple argument produced characters luac rejects outright.

What changed

LuaDispatchPreparation.normalizeMethodNames is the pass that gives one name to a whole dispatch group, so it sanitises before uniquing: two names that differed only in characters Lua has no place for still get a slot each. The backend maps every slot key and every LuaMethod name through the same function, so call sites and class tables keep agreeing. Lua's identifier rule now has one home, LuaIdentifiers.

Why the assertion is part of this

The luac check never caught this, because the broken output parses. So the check is on the names themselves: every emitted function, method, variable, field and call-by-name must match [A-Za-z_][A-Za-z0-9_]*, verified for every testLua compile. That is what stops this class of bug returning rather than the fix itself.

Repro that failed before and passes after: FastHashMapTests.tupleKeyLua.

Full test suite green.

Frotty added 5 commits August 15, 2026 03:39
Exercises type class bounds through the container they were added for.
Six of the seven cases pass on both backends with no compiler change:
int keys, tuple keys on Jass, a user class key, two specialisations
coexisting, and two instances of one specialisation.

tupleKeyLua fails and is a real, pre-existing backend bug. Method names
become Lua table keys, but luaMethod.initFor passes the name through raw
while every sibling (luaVar, luaFunc, luaClassVar) sanitises via
uniqueName. Names are valid identifiers in ordinary code, so nothing hit
it until a class method was specialised for Lua with more than one type
argument: specializeMethod builds name + "_specialized_" +
generics.makeName(), and makeName joins arguments with ", ". Two simple
arguments give "get_specialized_integer, integer", which emits
"Class.get_specialized_integer, integer = impl" -- valid Lua that assigns
to two targets and quietly writes a junk global. A tuple argument gives
"⦅integer, integer⦆" and fails the syntax check outright.
Method names become Lua table keys, so they must be identifiers. A method
specialised with two type arguments was named after them, commas included,
and emitted `Class.get_specialized_integer, integer = impl` - valid Lua that
quietly assigns to two targets; a tuple argument produced characters luac
rejects outright.

normalizeMethodNames is the pass that gives one name to a whole dispatch
group, so it sanitises before uniquing: two names that differed only in
characters Lua has no place for still get a slot each. The backend maps every
slot key and every LuaMethod name through the same function, so call sites and
class tables keep agreeing. Lua's identifier rule now has one home.

The luac check never caught this, because the broken output parses. Assert
instead on the names themselves: every emitted function, method, variable,
field and call-by-name must be an identifier, checked for every testLua
compile.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc994da12d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +21 to +26
for (int i = 0; i < name.length(); i++) {
if (!isIdentifierPart(name.charAt(i))) {
return false;
}
}
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject Lua keywords when validating identifiers

When a generated dispatch alias is a Lua keyword—for example, a closure implementing a Wurst interface method named goto, repeat, or nil—this character-only check returns true. Consequently toIdentifier preserves the keyword and the new assertion also accepts it, allowing the printer to emit invalid method/table-key syntax. Include the existing LuaReservedNames.LUA_KEYWORDS set in this validation and map reserved words to a safe identifier.

Useful? React with 👍 / 👎.

Wurst and Lua reserve different words, so a method can be declared repeat or
goto and reach the backend under that name. Method names survive it, because
the pass that assigns them uniques against the reserved set. A closure does not:
it adds the name it implements as a dispatch alias directly, so the alias
arrives as a bare keyword and is emitted as a table key.

luac rejects that, so it was loud rather than wrong, but the check added
alongside it accepted the name - and catching this before the syntax check is
the whole point of having it. isValid now rejects keywords and toIdentifier maps
them out of the way.

Underscores rather than a counter, so a keyword maps to the same name wherever
it is derived: call sites and class tables have to agree without consulting each
other.
@Frotty

Frotty commented Aug 16, 2026

Copy link
Copy Markdown
Member Author

Addressed: keywords are now rejected by isValid and mapped out of the way by toIdentifier.

Confirmed the path first — it is reachable. Method names were already safe, because normalizeMethodNames uniques against the reserved set. A closure is not: addDirectAliases adds the name it implements as a dispatch alias directly, so an interface method declared repeat arrives as a bare keyword and is emitted as a table key. Repro fails on the previous commit with luac: <name> expected near 'repeat' and passes now, kept as TypeClassTests.closureImplementingALuaKeywordName.

The sharper half of your point was the second one: the assertion added in this PR accepted the name, and catching this before the syntax check is the whole reason it exists. It rejects keywords now.

Mapping is by trailing underscore rather than a counter, so a keyword maps to the same name wherever it is derived — call sites and class tables have to agree without consulting each other.

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7871731728

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .claude/ralph-loop.local.md Outdated
Comment on lines +2 to +5
active: true
iteration: 1
session_id: 0413fc86-e9a2-4954-bc47-1620ed81d95e
max_iterations: 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Remove the active machine-local loop configuration

Checking in this session-specific file with active: true, max_iterations: 0, a stale session ID, and a developer-local path/branch can cause Ralph/Claude loop tooling in another checkout to inherit an unbounded automation session unrelated to this compiler change. Remove the file and add it to the ignore rules so repository users do not activate another developer's local loop state.

AGENTS.md reference: AGENTS.md:L64-L64

Useful? React with 👍 / 👎.

Neither of these belongs in a branch that gets merged. The loop configuration
is machine-local state - an active session id, an iteration count, a path and a
branch name from one checkout - and another checkout picking it up would inherit
an automation session that has nothing to do with it. The brief beside it is
one run's instructions, not documentation of anything.

Both came in with the branch this work was based on rather than with the work.
Ignored as well, so they do not come back the next time either is written.
@Frotty

Frotty commented Aug 16, 2026

Copy link
Copy Markdown
Member Author

Removed, and you were right that it should never have been there. Both .claude/ralph-loop.local.md and LOOP.md are gone from all six branches, with /.claude/ and /LOOP.md added to .gitignore so neither comes back when the tooling rewrites them.

For the record on how they got in: neither file was touched by any commit in this work. They arrived with e4da96d7d, an existing commit on the branch this stack was cut from, and I did not check what that base was carrying before opening the PRs. Neither is in master, so removing them nets to nothing in the diffs — all six now contain only compiler and test files.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

Reviewed commit: a587e86c96

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Frotty
Frotty merged commit b9fda9d into master Aug 16, 2026
3 checks passed
@Frotty
Frotty deleted the lua/sanitise-method-names branch August 16, 2026 07:21
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.

1 participant