gen-c: a field of a *T is reached with an arrow - #3478
Merged
Conversation
Closes #3477 Rust and Zig auto-dereference, so `p.field` on a `*T` is correct in both. C is the ONLY backend that spells the two accesses differently, and the dot travelled into it unchanged. MEASURED, whole corpus, -ferror-limit=0: errors 12321 -> 12071 (-250) files better/worse 17 / 0 compiling clean 307 -> 308 base_ternary_memory 31 -> 0, compiler_stdlib 52 -> 17, server_session 28 -> 6, nn_hslm 65 -> 41 THE POPULATION WAS SPLIT BEFORE ANY CODE WAS WRITTEN. 469 diagnostics over 389 lines in 52 files; of those lines 214 are real FIELDS, where `->` is the repair, and 175 are METHOD calls (`len` 165, `push`, `length`) that belong to #3464 -- an arrow there moves the error without answering it, so a slice parameter is deliberately left with its dot. Of the 214, 152 have a base that is a parameter declared `*T`, which is the population this rule reaches, measured in the terms the rule evaluates. THE CORPUS CAUGHT A REGRESSION THE TESTS DID NOT. The per-item name set was cleared in `gen_c_fn` only, so a test block's own `MemoryCell cell;` inherited the `cell` of a preceding `*MemoryCell` parameter and became `cell->scope`: +38 errors in one file, the single worse file in the run. `gen_c_bench` cleared NEITHER per-item set -- a pre-existing asymmetry of the same shape. Both sets are cleared in all three item emitters now, and two tests pin it. THE `array_typed_names` HALF OF THAT HAS A POPULATION OF ZERO, and the zero is measured rather than assumed: the whole corpus was generated with and without that one line and all 582 headers diffed byte for byte, with no difference. It is kept because it is the same boundary, not because anything reaches it. A MUTANT THAT DROPS THE BASE-IS-AN-IDENTIFIER CHECK SURVIVED every test. A field-access node carries the FIELD's name, so `b.inner` reads as if `inner` were the base -- and `inner` can be a pointer parameter. `fn collide(inner: *Cell, b: Box)` kills it. AND THIS REPO'S SEAL TOOL REPORTS A TRUNCATED LIST. It prints 20 stale seals then `... and N more`, so a reseal list scraped from that output is short by construction. This pass had 51 stale seals over 26 specs and the report named 17: nine specs would have stayed stale after a run that reported success. `--stale-specs` prints the whole list, one path per line. Latent, filed not fixed: `#include <assert.h>` is emitted only when the module has a TEST block, so a `bench` whose body asserts does not compile alone. All 29 specs whose bench calls `assert` also have a test block, so the population is zero today. Tests: 7 new, full suite 3529 passed 0 failed. 51 stale seals refreshed (26 specs). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gHashTag
enabled auto-merge (squash)
September 8, 2026 10:11
Contributor
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
Contributor
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.
gen-c: a field of a *T is reached with an arrow
Closes #3477
Rust and Zig auto-dereference, so
p.fieldon a*Tis correct inboth. C is the ONLY backend that spells the two accesses differently,
and the dot travelled into it unchanged.
MEASURED, whole corpus, -ferror-limit=0:
errors 12321 -> 12071 (-250)
files better/worse 17 / 0
compiling clean 307 -> 308
base_ternary_memory 31 -> 0, compiler_stdlib 52 -> 17,
server_session 28 -> 6, nn_hslm 65 -> 41
THE POPULATION WAS SPLIT BEFORE ANY CODE WAS WRITTEN. 469 diagnostics
over 389 lines in 52 files; of those lines 214 are real FIELDS, where
->is the repair, and 175 are METHOD calls (len165,push,length) that belong to #3464 -- an arrow there moves the error withoutanswering it, so a slice parameter is deliberately left with its dot.
Of the 214, 152 have a base that is a parameter declared
*T, which isthe population this rule reaches, measured in the terms the rule
evaluates.
THE CORPUS CAUGHT A REGRESSION THE TESTS DID NOT. The per-item name set
was cleared in
gen_c_fnonly, so a test block's ownMemoryCell cell;inherited the
cellof a preceding*MemoryCellparameter and becamecell->scope: +38 errors in one file, the single worse file in the run.gen_c_benchcleared NEITHER per-item set -- a pre-existing asymmetryof the same shape. Both sets are cleared in all three item emitters now,
and two tests pin it.
THE
array_typed_namesHALF OF THAT HAS A POPULATION OF ZERO, and thezero is measured rather than assumed: the whole corpus was generated
with and without that one line and all 582 headers diffed byte for byte,
with no difference. It is kept because it is the same boundary, not
because anything reaches it.
A MUTANT THAT DROPS THE BASE-IS-AN-IDENTIFIER CHECK SURVIVED every test.
A field-access node carries the FIELD's name, so
b.innerreads as ifinnerwere the base -- andinnercan be a pointer parameter.fn collide(inner: *Cell, b: Box)kills it.AND THIS REPO'S SEAL TOOL REPORTS A TRUNCATED LIST. It prints 20 stale
seals then
... and N more, so a reseal list scraped from that outputis short by construction. This pass had 51 stale seals over 26 specs and
the report named 17: nine specs would have stayed stale after a run that
reported success.
--stale-specsprints the whole list, one path perline.
Latent, filed not fixed:
#include <assert.h>is emitted only when themodule has a TEST block, so a
benchwhose body asserts does notcompile alone. All 29 specs whose bench calls
assertalso have a testblock, so the population is zero today.
Tests: 7 new, full suite 3529 passed 0 failed. 51 stale seals refreshed
(26 specs).
🤖 Generated with Claude Code