The fourth position, and the literal that made all four noisy - #2906
Merged
Conversation
#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
enabled auto-merge (squash)
August 29, 2026 22:25
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
This was referenced Aug 29, 2026
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#2897 found that #920's
F64 -> F32rule 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, sixlines 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 andreturn 1.0from anf32function was a warning.Made symmetric.
The control is the rule's own case, not the noise
x = d(d: f64,x: f32)x = 2.0(literal)return d(computed)return 1.0(literal)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
The +7 are exactly the family the census has pointed at since it was built:
Also: an integer literal above i64::MAX
It failed the
i64parse, reached the float branch and becameF64, soread 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/u128andstays 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 tri0 ·bootstrap test ratchet 0.
FROZEN_HASHupdated in the same commit, per M5.Refs #2864