One rule, four positions, three treatments - #2897
Merged
Merged
Conversation
`types_compatible` rejects narrowing F64 -> F32, with a comment naming the
issue that added it. Measured where the rejection actually applies:
assignment x = d; compared -> ERROR
argument p(d) compared -> warning, under "Typecheck OK"
declaration var x: f32 = d; NOT COMPARED
return -> f32 { return d; } NOT COMPARED
A soundness fix guarding one of four narrowing sites guards one of four.
This adds the declaration comparison, at the severity the argument position
already uses -- a warning, so no ratchet can move. Cost across the corpus: 18
warnings in 13 files. I expected noise and got a work list.
THE CHECK FOUND THE BUG THAT MADE IT NECESSARY. Two of the 18 read
`Str <- F64`:
var period_str : &str = "83.333";
`infer_expr` returns Str when the literal's VALUE starts with a quote. The
parser marks the node `extra_kind: "string"` and the lexeme does not always
carry the quote, so a quoted string fell through to the float branch, and any
string whose text parses as a number was typed as that number. `"hello"` was
fine only because it does not parse as a float and landed on Unknown, which is
compatible with everything and therefore silent.
Two silences composed: the declaration was never compared, and the value that
would have failed the comparison was mistyped. Neither was visible alone.
Fixed by reading the marker the parser already sets:
specs that typecheck 627 -> 628 (specs/pins/emitter_xdc.t27)
regressions 0
bootstrap ratchet "No new failures. Baseline holds."
remaining warnings 16 (8 U64 <- F64, 7 F32 <- F64)
The remaining 16 are countable debt rather than a silence. The return position
is still not compared; that is named here and not fixed.
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:07
…ation # Conflicts: # .claude/skills/ci-gates/SKILL.md
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
PR DashboardGenerated at: 2026-08-29 22:09:27 UTC
Summary
Seal Status
|
gHashTag
added a commit
that referenced
this pull request
Aug 29, 2026
#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 <noreply@anthropic.com>
gHashTag
added a commit
that referenced
this pull request
Aug 29, 2026
* Remove emitter_xdc from the corpus ledger; it passes now The corpus ratchet has been red on master for at least three consecutive runs and the reason is mine. #2897 fixed the string-literal inference bug and `specs/pins/emitter_xdc.t27` began to typecheck. I updated `tools/specs_generate_baseline.txt` and did not know about `docs/reports/suite_expectations.json`, which still listed the spec as expected-to-fail. An UNEXPECTED PASS is a ratchet failure by design: docs/CORPUS-RATCHET.md says "you fixed something. Remove the entry and lower max_entries". entries 151 -> 150 max_entries 151 -> 150 (down, the only direction the cap may move) RATCHET: CLEAN Control both ways: with the entry restored the ratchet reports `UNEXPECTED PASSES: 1` and exits 1; without it, exit 0. This is #2892's lesson one level up. That day I found a fix that had not travelled from one command to its neighbour; here it did not travel from one LEDGER to its sibling. When a repair makes a spec pass, grep every file that names the spec -- not only the ledger you happen to know. Refs #2864 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * skill: the second ledger Refs #2864 --------- Co-authored-by: Claude <noreply@anthropic.com>
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.
types_compatiblerejects narrowingF64 -> F32, with a comment naming theissue that added it. Where does that rejection actually apply?
x = d;p(d)Typecheck OKheadervar x: f32 = d;-> f32 { return d; }A soundness fix guarding one of four narrowing sites guards one of four.
What this adds
The declaration comparison, at the severity the argument position already uses
— a warning, so no ratchet can move. Cost across the whole corpus:
I expected noise and got a work list.
The check found the bug that made it necessary
Two of the 18 read
Str <- F64:infer_exprreturnsStrwhen the literal's value starts with a quote. Theparser marks the node
extra_kind: "string", and the lexeme does not alwayscarry the quote — so a quoted string fell through to the float branch, and any
string whose text parses as a number was typed as that number.
"hello"was fine only by luck: it does not parse as a float, so it landed onUnknown, which is compatible with everything and therefore silent.Two silences composed — the declaration was never compared, and the value
that would have failed the comparison was mistyped. Neither was visible alone.
Fixed by reading the marker the parser already sets.
Result
specs/pins/emitter_xdc.t27)U64 <- F64, 7F32 <- F64)The remaining 16 are countable debt rather than a silence.
18446744073709551552in
var cleared : u64 = z & 18446744073709551552is typed F64 because itexceeds
i64— that is theU64 <- F64family, named here and not fixed.The return position is still not compared. Also named here and not fixed:
making the declaration check an error rather than a warning would be the
consistent choice and would fail specs that pass today — the owner's call.
Controls
var s : &str = "83.333";var s : &str = "hello";var x: f32 = d;(d is f64)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