Skip to content

fix: emit bxor, not bnot, for binary '~' with --gen-target 5.1 - #1168

Merged
hishamhm merged 1 commit into
teal-language:mainfrom
dylanpulver:fix/binary-bxor-gen-target-51
Sep 4, 2026
Merged

fix: emit bxor, not bnot, for binary '~' with --gen-target 5.1#1168
hishamhm merged 1 commit into
teal-language:mainfrom
dylanpulver:fix/binary-bxor-gen-target-51

Conversation

@dylanpulver

Copy link
Copy Markdown
Contributor

~ is both unary bitwise NOT and binary bitwise XOR, but the 5.1 compat pass in teal/gen/lua_compat.tl matches on the operator token alone, so the unary branch swallows the binary one.

local function f(a: integer, b: integer): integer
   return a ~ b
end

tl gen --gen-target 5.1 before / after:

   return bit32.bnot(a)     -- before
   return bit32.bxor(a, b)  -- after

The right operand is dropped and the operation changes, silently: the checker accepts it as integer and the output is still valid Lua. &, |, << and >> are all correct; ~ is the only one of the five with a same-token unary form. The metamethod path splits the same way, sending a ~ b on a record with __bxor to __bnot with one argument.

The fix is an arity check, so binary ~ falls through to the existing bit_operators branch, which already maps ~ to bxor and __bxor.

Also spec/util.lua: gen() built its line arrays with gmatch("([^\n]*)\n"), which drops the final line, so a util.gen mismatch confined to the last line of the output was never reported. That is why the metamethod half stayed invisible, and why the existing __bnot metamethod test cannot catch a regression either. With \n? the suite is unchanged at 1941 passing, but both halves of this bug now fail it.

Regenerated the .lua artifacts with make.

Drafted with AI assistance (Claude Opus 5).

The '~' token is both unary bitwise NOT and binary bitwise XOR, and the
5.1 compat pass matched on the operator token alone. Binary '~' was
rewritten to bit32.bnot(a), dropping the right operand and changing the
operation; a __bxor metamethod call was dispatched to __bnot. Check the
arity so binary '~' falls through to the existing bit_operators branch.

spec/util.lua built its line arrays with gmatch("([^\n]*)\n"), which
drops the final line, so a util.gen mismatch confined to the last line
of generated output was never reported. That hid the metamethod half of
this bug from the new test and from the existing __bnot metamethod test.

@hishamhm hishamhm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM! Thank you, good catch!

@hishamhm
hishamhm merged commit 80d3169 into teal-language:main Sep 4, 2026
8 of 9 checks passed
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