Skip to content

gen-c: type a one-element literal list, from the field that holds it - #3462

Merged
gHashTag merged 1 commit into
masterfrom
c/one-element-literal
Sep 8, 2026
Merged

gen-c: type a one-element literal list, from the field that holds it#3462
gHashTag merged 1 commit into
masterfrom
c/one-element-literal

Conversation

@gHashTag

@gHashTag gHashTag commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Refs #3459

334 of the remaining 837 __auto_type x = { … } errors were one-element
lists. The previous pass filed them rather than guessing: [7] arrives as an
ExprArrayLiteral with zero children while the emitted C still reads
{ 7 }, and children and value had both been searched and both were empty.

The field is extra_size — and the comment naming it sits on the emitter
arm forty lines from the code that reads it:

the parser stores the literal's ELEMENT TEXT in extra_size ("1,2,3" for a
list, "0;4" for a repeat) with no children

Two ends had to move together: the condition upstream still demanded non-empty
children, and the declarator took its length from children.len(). Both now
read extra_size, with the repeat form v;n taking n as the length rather
than counting commas.

Measured — -ferror-limit=0

before after
errors 14276 14165
__auto_type with initializer list 837 670
files better 18

Two files rise and both are unmasking. Across two passes the class has gone
1729 → 670.

A mutant was better than my guard, for one input

Deleting the dotted-token check types [1.2.3] as double x[1] = { 1.2.3 }
a malformed literal inside a well-formed declaration — so the guard is
load-bearing. But its first version required digits on both sides of the
dot
, which refuses 1., and 1. is valid C.

The mutant exposed both halves at once: the check was needed and wrong.
It now accepts at most one dot with digits on at least one side.

input before now
[1.5] double double
[1.] refused double
[1.2.3] refused refused
[a.b] refused refused

.5 is refused and stays refused: the lexer drops the leading dot and emits
{ 5 }, so the value is corrupt before this code sees it. Typing a corrupted
initialiser turns a loud error into a quiet wrong answer.

The theoretical risk, named

["12"] — a one-element list whose sole element is a quoted all-digit string —
is indistinguishable in extra_size from [12], because the quotes are gone
by then; the old binary emitted { 12 } too. Corpus population of that form:
0, measured, against 22 single-element string lists whose contents are not
digits and which the inference refuses.

Full suite: 2642 passed, 0 failed. 32 seals refreshed in the same commit.

Refs #3459

334 of the remaining 837 `__auto_type x = { ... }` errors were one-element
lists. The previous pass filed them rather than guessing: `[7]` arrives as an
`ExprArrayLiteral` with ZERO children while the emitted C still reads `{ 7 }`,
and `children` and `value` had both been searched and both were empty.

The field is `extra_size`, and the comment naming it sits on the emitter arm
FORTY LINES from the code that reads it:

    the parser stores the literal's ELEMENT TEXT in extra_size
    ("1,2,3" for a list, "0;4" for a repeat) with no children

Two ends had to move together: the condition upstream still demanded non-empty
`children`, and the declarator took its length from `children.len()`. Both now
read `extra_size`, with the repeat form `v;n` taking `n` as the length rather
than counting commas.

MEASURED, whole corpus, -ferror-limit=0:

    errors                              14276 -> 14165
    __auto_type with initializer list     837 ->   670
    files better                           18

Two files rise and both are unmasking. Across two passes the class has gone
1729 -> 670.

A MUTANT WAS BETTER THAN MY GUARD FOR ONE INPUT. Deleting the dotted-token
check types `[1.2.3]` as `double x[1] = { 1.2.3 }` -- a malformed literal
inside a well-formed declaration -- so the guard is load-bearing. But its first
version required digits on BOTH sides of the dot, which refuses `1.`, and `1.`
is valid C. The mutant exposed both halves at once: needed AND wrong. It now
accepts at most one dot with digits on at least one side.

`.5` is refused and stays refused: the lexer drops the leading dot and emits
`{ 5 }`, so the value is corrupt before this code sees it, and typing a
corrupted initialiser turns a loud error into a quiet wrong answer.

The theoretical risk is named rather than hidden. A one-element list whose sole
element is a QUOTED all-digit string, `["12"]`, is indistinguishable in
`extra_size` from `[12]`, because the quotes are gone by then -- the old binary
emitted `{ 12 }` too. Corpus population of that form: ZERO, measured, against
22 single-element string lists whose contents are not digits and which the
inference refuses.

Three mutants, three dead. 32 seals refreshed in the same commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) September 8, 2026 04:38
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

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

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-09-08 04:38:35 UTC

Summary

Status Count
Total Open PRs 16
PRs with Failing Checks 13
PRs with All Checks Green 3
READY 2
FAILING 13
PENDING 0
NO CHECKS YET 0

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

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=6e4a6550acfa != 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 b3966f1 into master Sep 8, 2026
29 of 33 checks passed
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.

1 participant