Skip to content

The fourth position, and the literal that made all four noisy - #2906

Merged
gHashTag merged 1 commit into
masterfrom
u64-literal-and-return
Aug 29, 2026
Merged

The fourth position, and the literal that made all four noisy#2906
gHashTag merged 1 commit into
masterfrom
u64-literal-and-return

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

#2897 found that #920's
F64 -> F32 rule held at an assignment (error) and a call argument
(warning), and nowhere else; it added the declaration. This adds the
return — the fourth and last position.

It immediately reported 277 warnings in 31 files, 255 of them identical:
returns F64 where F32 is declared. That is not a work list.

Root cause

A float literal committed to F64. A non-negative integer literal, six
lines above in the same match arm, was already context-polymorphic — with a
comment explaining that pinning it had caused 27 false errors. Nobody applied
the same reasoning to floats, so var x: f32 = 1.0; was a narrowing and
return 1.0 from an f32 function was a warning.

Made symmetric.

The control is the rule's own case, not the noise

probe before after
x = d (d: f64, x: f32) error still an error
x = 2.0 (literal) error accepted
return d (computed) silent warning
return 1.0 (literal) accepted

A binary expression is not a literal, so a computed narrowing still errors.
What stopped erroring is the case where the compiler knows the value exactly
and the narrowing is not one.

Result

before after
specs that typecheck 608 615
regressions 0
narrowing warnings 293 21 — all integer, a real work list
bootstrap test ratchet "No new failures. Baseline holds."

The +7 are exactly the family the census has pointed at since it was built:

specs/numeric/gf8.t27   gf12  gf20  gf24  gf32
bootstrap/tests/goldring/r_mulassign.t27   r_op.t27

Also: an integer literal above i64::MAX

It failed the i64 parse, reached the float branch and became F64, so

var cleared : u64 = z & 18446744073709551552;

read as a float initialising an integer — eight sites across five ternary
specs
, all bit masks (2⁶⁴−64 and 2⁶⁴−16). It now parses as u64/u128 and
stays context-polymorphic, matching the branch above it.

Gates, run locally

specs generate 0 · specs parse 0 · conflict markers 0 · seals fresh 0 ·
types ratchet 0 · skill check 0 · unparsed probe 0 · cargo test -p tri 0 ·
bootstrap test ratchet 0. FROZEN_HASH updated in the same commit, per M5.

Refs #2864

#2897 found that #920's F64 -> F32 rule held at an assignment (error) and a
call argument (warning), and nowhere else. It added the declaration. This adds
the RETURN -- the fourth and last position -- by threading the enclosing
function's declared return type through `check_stmt`.

It reported 277 warnings in 31 files, 255 of them identical: `returns F64 where
F32 is declared`. That is not a work list.

ROOT CAUSE. A float literal committed to F64 while a non-negative INTEGER
literal, six lines above in the same match arm, was already context-polymorphic
-- with a comment explaining that pinning it had caused 27 false errors. Nobody
had applied the same reasoning to floats, so `var x: f32 = 1.0;` was a
narrowing and `return 1.0` from an f32 function was a warning.

Made symmetric. The rule survives where it was aimed, and the control is the
rule's own case rather than the noise:

  x = d      (d: f64, x: f32)   still an ERROR
  x = 2.0    (literal)          accepted
  return d   (computed)         warning
  return 1.0 (literal)          accepted

A binary expression is not a literal, so a computed narrowing still errors.

  specs that typecheck   608 -> 615   zero regressions
  narrowing warnings     293 -> 21    all 21 integer, a real work list
  bootstrap ratchet      "No new failures. Baseline holds."

The +7 are exactly the family the census pointed at from the start: gf8, gf12,
gf20, gf24, gf32, and the two goldring compound-assignment specs.

ALSO: an integer literal above i64::MAX failed the i64 parse, reached the float
branch and became F64, so `var cleared : u64 = z & 18446744073709551552` read
as a float initialising an integer -- eight sites across five ternary specs,
all bit masks. It now parses as u64/u128 and stays context-polymorphic, matching
the branch above it.

FROZEN_HASH updated in the same commit, per M5.

Refs #2864

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) August 29, 2026 22:25
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-29 22:25:27 UTC

Summary

Status Count
Total Open PRs 10
PRs with Failing Checks 9
PRs with All Checks Green 1
READY 0
FAILING 9
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=eec367a5997f != 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 merged commit 952d96d into master Aug 29, 2026
26 of 28 checks passed
gHashTag added a commit that referenced this pull request Aug 29, 2026
Eleven narrowing warnings remained after #2906, and every one printed `:?`:
`parse_return_statement` created its node and never set `line`. One line to
capture `self.current.line` before consuming the keyword turned eleven rumours
into eleven addresses.

With addresses, eight of the eleven were the same shape:

    return x - (y >> shift);        cordic_fixed.t27, cordic_top.t27

`promote_types` typed every binary expression by rank, shifts included, so
`y >> shift` with `y: i16, shift: u32` produced U32 -- the shift AMOUNT decided
the type of the shifted VALUE. A shift's result has the type of the value being
shifted; C, Rust and Zig all agree. Every one of those eight read as a defect
in the spec while the defect was in the checker.

  narrowing warnings   11 -> 3
  specs that typecheck 615 -> 615, zero regressions
  bootstrap ratchet    "No new failures. Baseline holds."

The three that remain are genuine narrowing in the specs: `ts_ps / period_ps`
returned as u32, and `sign * prod` returned as i32 in gemm and systolic_array.

SELF-INFLICTED, and worth writing down. The probe harness ran

    grep -oE "returns \w+ where \w+|Typecheck OK" | head -1

and the compiler's FIRST line is `Typecheck OK (0 errors, 2 warnings)`. The
alternation matched the banner, `head -1` took it, and every probe reported
clean while warning underneath. It cost four measurements that contradicted
each other -- byte-identical files "disagreeing" -- and a dead hypothesis about
parameter shadowing chased into the symbol table. The correct hypothesis was
the first one I had; the harness hid its confirmation. When two identical
inputs give different answers, the difference is in the observer.

FROZEN_HASH updated in the same commit, per M5.

Refs #2864

Co-authored-by: Claude <noreply@anthropic.com>
gHashTag added a commit that referenced this pull request Aug 29, 2026
…ith it

The second of master's two red gates, and like the first it is not a regression.

    --- Ratchet (W628) ---
      ledger:              151 / 151 cap
      observed (primary):  150
      UNEXPECTED FAILURES: 0
      UNEXPECTED PASSES  : 1
        - specs/pins/emitter_xdc.t27 [typecheck] (fixed -- remove from the ledger)

#2906 fixed it: an integer literal above i64::MAX fell to the float branch, so a
bit mask read as a float initialising an integer. The spec typechecks; the ledger
entry outlived the failure it recorded, and the ratchet named the repair itself.

`max_entries` drops with the entry rather than staying at 151, so the slack
cannot hide the next one. The reason is written into the file beside the number.

Refs #2908
gHashTag added a commit that referenced this pull request Aug 29, 2026
…ived its failure (#2909)

* fix(seals): re-seal 926 gen-drifted specs -- master has been red for 29 runs

`seal-coverage` last passed on master at 588074c, 18:23. The first red is
d7ee76d -- #2866, mine -- which changed four emitters, so generated output moved
while the specs did not.

The `coverage` check was already failing on PR #2866 when I merged it.

Twenty-nine runs later the drift is cumulative:

    926 seals [gen-drift]
      926  gen_hash_rust
       62  gen_hash_verilog
       33  gen_hash_zig
       31  gen_hash_c

The gate calls re-sealing a STATEMENT that the new output is wanted and says to
read the acceptance columns first. Read:

    corpus ratchet, master:  UNEXPECTED PASSES 1
                             DISCARD WORSENED  0
                             GATE FAILURES     0

Red on an improvement -- one more spec passes than the ledger expects, nothing
worsened. Acceptance is better than what is recorded, so this records outputs
whose acceptance rose. That ledger entry (151 -> 150) belongs to the parallel
session's #2906 and is not touched here.

After: 1318 seals, 1224 hold, 94 known-broken already in seal_baseline.txt.
`check_seal_coverage.py` exits 0, and its --self-check still exits 0, so the
green is the gate working rather than the gate skipped.

Closes #2908

* fix(ratchet): drop the emitter_xdc entry -- 151 -> 150, cap lowered with it

The second of master's two red gates, and like the first it is not a regression.

    --- Ratchet (W628) ---
      ledger:              151 / 151 cap
      observed (primary):  150
      UNEXPECTED FAILURES: 0
      UNEXPECTED PASSES  : 1
        - specs/pins/emitter_xdc.t27 [typecheck] (fixed -- remove from the ledger)

#2906 fixed it: an integer literal above i64::MAX fell to the float branch, so a
bit mask read as a float initialising an integer. The spec typechecks; the ledger
entry outlived the failure it recorded, and the ratchet named the repair itself.

`max_entries` drops with the entry rather than staying at 151, so the slack
cannot hide the next one. The reason is written into the file beside the number.

Refs #2908
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