Skip to content

gen-c: name the element type of a bare literal list - #3461

Merged
gHashTag merged 1 commit into
masterfrom
c/literal-list-type
Sep 8, 2026
Merged

gen-c: name the element type of a bare literal list#3461
gHashTag merged 1 commit into
masterfrom
c/literal-list-type

Conversation

@gHashTag

@gHashTag gHashTag commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Refs #3459

var x = [1, 2, 3];   →   __auto_type x = { 1, 2, 3 };
error: cannot use '__auto_type' with initializer list in C

1401 of these remained after the previous pass, all one shape. Rust writes
let mut x = [1, 2, 3] and Zig var x = .{ 1, 2, 3 }; only C has no inference
for a brace list, so the type has to be named.

The choice is not arbitrary — it matches what a scalar literal already
gets: var x = 1 emits uint32_t x = 1 here and var x: u32 = 1 in Zig. A
fractional element makes the list double, which is C's own promotion.

Measured — -ferror-limit=0

before after
errors 14738 14276
__auto_type with initializer list 1401 837
files better 31

igla/race/ternary_gemm 437 → 348 · igla/race/rtl 268 → 197 ·
igla/race/bram_weights 279 → 228.

The corpus refuted my first version

A string literal is an ExprLiteral whose value is the text without its
quotes
, so ["12", "34"] passed a digit test and the list was typed
uint32_t:

incompatible pointer to integer conversion initializing 'uint32_t'
with an expression of type 'char *'

four of them in one file. The per-file check is the only reason it was seen —
the aggregate improved either way.

Two files still rise and both are unmasking, checked one at a time.

A speculation reverted, with its reason recorded

A one-element literal [7] arrives as an ExprArrayLiteral with zero
children
— confirmed by instrumenting the branch — while the emitted C still
reads { 7 }, so the element is kept somewhere this code does not read.
lit.value was the obvious candidate, was tried, and is empty too. 334 of the
remaining 837 are { 0 }
and every one takes that path. Filed rather than
guessed at.

Mutation

mutant dead tests
inference not consulted 2
string guard removed 1
floats typed as u32 1
kind != ExprLiteral removed 0 — subsumed, kept, and why is in the comment

The last one differs from the has_init parameter deleted last pass: that one
no caller could reach; this one is reachable, and dropping it would make
correctness depend on the accident that non-literal nodes carry no numeric
text. Probed with an identifier, a call and a binary expression — all three
still refused.

Full suite: 2639 passed, 0 failed. 47 seals refreshed in the same commit.

Refs #3459

    var x = [1, 2, 3];   ->   __auto_type x = { 1, 2, 3 };
    error: cannot use '__auto_type' with initializer list in C

1401 of these remained after the previous pass, all one shape. Rust writes
`let mut x = [1, 2, 3]` and Zig `var x = .{ 1, 2, 3 }`; only C has no
inference for a brace list, so the type has to be named.

The choice is not arbitrary: it matches what a SCALAR literal already gets --
`var x = 1` emits `uint32_t x = 1` here and `var x: u32 = 1` in Zig -- and any
fractional element makes the list `double`, which is C's own promotion.

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

    errors                              14738 -> 14276
    __auto_type with initializer list    1401 ->   837
    files better                           31

THE CORPUS REFUTED THE FIRST VERSION. A string literal is an `ExprLiteral`
whose `value` is the text WITHOUT its quotes, so `["12", "34"]` passed the
digit test and the list was typed `uint32_t`:

    incompatible pointer to integer conversion initializing 'uint32_t'
    with an expression of type 'char *'

four of them in one file. `extra_kind == "string"` is the tag, and the `#define`
path upstream already knew it. The per-file check is the only reason this was
seen; the aggregate improved either way.

Two files still rise and both are unmasking, checked one at a time: an unnamed
tuple struct losing `f0`, and `member reference base type 'int'`. A third, a
`uint16_t` field initialised from a `uint32_t[4]`, was wrong before and had no
type to be wrong against.

A SPECULATION WAS REVERTED WITH ITS REASON RECORDED. A one-element literal
`[7]` arrives as an `ExprArrayLiteral` with ZERO children -- confirmed by
instrumenting the branch -- while the emitted C still reads `{ 7 }`, so the
element is kept somewhere this code does not read. `lit.value` was the obvious
candidate, was tried, and is empty too. 334 of the remaining 837 are `{ 0 }`.

A mutant survived on a guard that is SUBSUMED rather than unreachable: deleting
`kind != ExprLiteral` changes nothing, because an identifier, a call and a
binary expression all reach the value checks with nothing numeric to offer --
probed, all three. It stays, and the difference from the `has_init` parameter
deleted last pass is written into the comment: that one no caller could reach,
this one is reachable and dropping it would make correctness depend on an
accident. Three other mutants died.

47 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:11
@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:11:33 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)=1515e2cbfd01 != 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 91e8597 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