Skip to content

gen-zig: a unary operator keeps its operand whole; -(a + b) no longer runs as -a + b (Closes #6549) - #8986

Merged
gHashTag merged 1 commit into
masterfrom
fix/zig-unary-parens-6549
Oct 11, 2026
Merged

gHashTag merged 1 commit into
masterfrom
fix/zig-unary-parens-6549

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #6549

Owner-approved hotfix of the frozen compiler. The owner (Architect) said "fix everything" on 2026-10-11. That is the Architect approval FROZEN.md section 5 step 2 asks for, so bootstrap/src/compiler.rs and its seal move in this PR.

Root cause

The parser keeps no parenthesis node, and gen-zig wrote a unary operator straight in front of its operand (self.gen_expr). So -(a + b) ran as -a + b, !(a and b) as !a and b, and ~(a | b) as ~a | b, with typecheck green. The t27o agent reported the !(...) form (see #8971).

Fix

The operand goes through gen_expr_maybe_paren, which parenthesizes a binary operand. This is one changed line. The Verilog, C and Rust emitters already parenthesize; only gen-zig had the defect. -(-a) still emits --a, which Zig 0.16 reads as a double negation (checked).

Freeze ceremony

FROZEN_HASH old 465abf513dc2e6dd805f7765a87aea1d31b1821473b2f1336f331978bef38a2d
FROZEN_HASH new 9795307e5869acf76fe406fa19a170bac05da4b539f6529b707fc59dc78a8fca (from master's own t27c frozen-digest)
cargo test --release (bootstrap/, zig 0.16 on PATH), master 5d9c0c1 138 binaries, 2988 passed, 9 failed, 2 ignored
same, this branch 138 binaries, 2988 passed, 9 failed, 2 ignored; the same 9 failures (corpus_zig_bodies, verilog_branch_context)

Blast radius

Measured on the t27c lab over 2237 tracked specs (git ls-files '*.t27' minus specs/scratch), gen, gen-verilog, gen-rust and gen-c, with t27c built from master and from this branch:

  • Zig changed for 20 existing specs. No Verilog, C or Rust output changed. No spec moved between generating and not generating.
  • t27c test-report on those 20: no pass/fail move. 7 run and pass on both sides: gf16 201/201, d_f19_test 16/16, trios-sacred SC-01 3/3, t27b comptime_float 4/4, comptime_float_f128 7/7, repeat_addr_unreached 1/1, verilog_emit 5/5. 13 stay blocked by unrelated compile errors, binary_crossentropy_loss among them (use of undeclared identifier 'new', line 135).
  • The changed sites are -(x * y) (gf16, SC-01, comptime_float_f128), ~(1 << k) masks (bitmap, bitvector, ternary_memory), !(p or q) guards (pins/parser, security, dedupe_identical_tests, feed_untested, trinity_fpga_adapter, verilog_emit, comptime_float, variant, gf16_matmul_top), &(.{} ** n) (pubsub, lsp/protocol, d_f19_test, repeat_addr_unreached) and the loss gradient in binary_crossentropy_loss.
  • Seals: tri seals drift --fix re-sealed the 17 that carry seals (27 files with twins). After it, drift is 0, check_seal_coverage.py passes, and check_seal_currency.py reports 0 stale. compiler_CodegenConformance.json is new.

Regression case

specs/compiler/codegen_conformance.t27 is one conformance spec for reference-path miscompiles. Later cases are added to it, not to a spec per bug (#8963). It has three tests: unary minus over a sum, ! over a conjunction, and ~ over a disjunction. They fail 0/3 on master and pass 3/3 here.

Gates

  • Hand-written Rust: compiler.rs +1 -1 (net 0).
  • check_budget and check_all from master's gen/c/policy/own_language.c both exit 0.
  • tri hooks pre-commit and tri hooks commit-msg pass.
  • The dupe scan finds no new duplicate body, and check_duplicate_declarations.py passes.

🤖 Generated with Claude Code

… runs as -a + b (Closes #6549)

Owner-approved hotfix of the frozen compiler: the owner (Architect) said
"fix everything" on 2026-10-11, which is the Architect approval FROZEN.md
section 5 step 2 asks for.

The parser keeps no parenthesis node, and gen-zig wrote a unary operator
straight in front of its operand. So -(a + b) ran as -a + b, !(a and b)
as !a and b, and ~(a | b) as ~a | b, with typecheck green. The operand now
goes through gen_expr_maybe_paren, which parenthesizes a binary operand.
The Verilog, C and Rust emitters already parenthesize; only gen-zig had it.
-(-a) emits --a, which Zig reads as double negation (checked, zig 0.16).

Seal: bootstrap/stage0/FROZEN_HASH
  old 465abf513dc2e6dd805f7765a87aea1d31b1821473b2f1336f331978bef38a2d
  new 9795307e5869acf76fe406fa19a170bac05da4b539f6529b707fc59dc78a8fca
cargo test --release in bootstrap/ (zig 0.16 on PATH): 138 binaries,
2988 passed, 9 failed, 2 ignored, identical to master 5d9c0c1 with the
same 9 failures. No Rust test added; the regression case is a .t27 spec.

Blast radius (2237 tracked specs, gen / gen-verilog / gen-rust / gen-c,
t27c from master vs this branch): the Zig of 20 existing specs changed;
no Verilog, C or Rust changed; no spec moved between generating and not.
test-report on the 20: no pass/fail move. 7 pass on both sides, 13 stay
blocked by unrelated compile errors. tri seals drift --fix re-sealed the
17 that carry seals (27 files with twins); drift is 0 after.
Regression: specs/compiler/codegen_conformance.t27, 0/3 on master, 3/3 here.
Hand-written Rust: +1 -1 (net 0).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-11 08:54:06 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 48
PRs with All Checks Green 2
READY 0
FAILING 48
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 48 + 0 + 0 = 48, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=9795307e5869 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag enabled auto-merge (squash) October 11, 2026 08:54
@gHashTag
gHashTag merged commit 5dc9dce into master Oct 11, 2026
36 of 39 checks passed
gHashTag pushed a commit that referenced this pull request Oct 11, 2026
Master fixed the unary-operand parens independently (#6549, #8986), with
its own conformance spec. This branch keeps master's line in compiler.rs
and drops its own duplicate test from bare_semicolon_zig.rs.
FROZEN_HASH follows the merged compiler.rs.

Conflicting seals were taken from master and then re-sealed against the
merged compiler. Over all 1865 specs, gen differs from master's t27c for
37 specs: the exp/log/sin/cos/tanh lowering and the bench-clock notice.
None of them is specs/ternary/trits.t27 or radix_economy.t27. For those
37, test-report moves only forward, and check_seal_currency reports 0
stale seals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ScHVrGSr6zZUdwkdC8DR9k
gHashTag added a commit that referenced this pull request Oct 11, 2026
Sealed and generated on the merged tree (master cc19d1f + the lane):
gen-zig #8986 and the emitter fixes changed the gen hashes, so the seals
are re-cut with the current compiler.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Oct 11, 2026
…9073)

The last gen-drift seals on master. queen_QueenHolds raced #9028
(gen-rust); policy_PolicyIssueShape was sealed by t27c 0.5.0 in #9059,
before #8986, #8991 and #9028 changed its Zig, Verilog and Rust output.
Re-saved with master b0b6569's t27c on the Railway lab. Spec hashes are
unchanged. check_seal_currency and check_seal_coverage both pass after it.

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

codegen(zig): unary minus drops the parentheses of its operand: -(a + b) runs as -a + b

2 participants