Skip to content

check: report a generic struct, and say which backend lowers it - #3454

Merged
gHashTag merged 1 commit into
masterfrom
parity/combinations
Sep 8, 2026
Merged

check: report a generic struct, and say which backend lowers it#3454
gHashTag merged 1 commit into
masterfrom
parity/combinations

Conversation

@gHashTag

@gHashTag gHashTag commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Closes #3453

pub const Map(K, V) = struct { … }
$ t27c check specs/tri/collections/map.t27
Typecheck OK (0 errors, 0 warnings)

while the generated C says unknown type name 'K'.

Nothing noticed because the tolerance is deliberate: the parser records the
type parameters and collect_type_params hands them to the unknown-type check
so K and V are not reported as undeclared. Correct in itself — and it
silences the only reader that might have said something about the rest.

The obvious message would have been false

"No backend lowers generics." Measured — one does:

backend emits result
gen-rust pub struct Box<T>, pub fn get<T>(b: Box<T>) compiles
gen-c struct Box { … } — parameter dropped — then get(Box(T) b) unknown type name 'T'
gen-zig pub const Box = struct, then get(b: Box(T)) use of undeclared identifier 'T'
gen-verilog per-field regs, UNSUPPORTED_ICARUS no generic, no error

Two backends drop the parameter from the declaration and keep it at every
use
. That inconsistency is what the warning states, and
gen_rust_really_does_lower_a_generic compiles gen-rust's output so the
credited half is a checked claim rather than a nicer sentence.

Population

From the AST: 28 specs, 33 generic types, all under specs/tri/.

A matcher over generated C prototypes said "8 files, 36 prototypes" — a
different question (C prototypes carrying a two-parameter application),
blind to every Option(T).

Measured over 651 specs: exit codes 573 / 78 before and after, not one
moved
.

Found by accident, and recorded as such

The parity table gained combinations, and a matcher written to count
tuple parameters caught Map(K, V) instead — a tuple and a generic
application are both Name(A, B).

The tuple defect it was aiming at is real and latent: C emits
probe((u8, i32) x) verbatim, though c_tuple_info already handles the
return position. Corpus population 0, as for []*i32 reaching C as
*i32* x. Both said to be zero rather than left implied.

Mutation

mutant dead tests
detector disabled 2
non-generics also reported 1
message overstates ("no backend lowers it") 1

The first attempt at mutant 1 did not compile (E0282) — verified as a build
failure
rather than assumed to be a pass from an empty result. Full suite:
2620 passed, 0 failed.

Also

diagnostic_capacity.py now prints each instrument's version beside its count.
The same command gave 20 here and 50 on CI because one cc is Apple clang and
the other gcc — a diagnostic count measures the code, the instrument and the
machine
, and only the first was ever written down.

Closes #3453

    pub const Map(K, V) = struct { ... }
    $ t27c check specs/tri/collections/map.t27
    Typecheck OK (0 errors, 0 warnings)

while the generated C says `unknown type name 'K'`.

Nothing noticed because the tolerance is deliberate: the parser records the
type parameters and `collect_type_params` hands them to the unknown-type check
so `K` and `V` are not reported as undeclared. Correct in itself, and it
silences the only reader that might have said something about the rest.

THE OBVIOUS MESSAGE WOULD HAVE BEEN FALSE. "No backend lowers generics" --
measured, one does:

    gen-rust     pub struct Box<T>, pub fn get<T>(b: Box<T>)     COMPILES
    gen-c        struct Box { ... } without the parameter, then
                 get(Box(T) b)      "unknown type name 'T'"
    gen-zig      pub const Box = struct, then get(b: Box(T))
                                     "use of undeclared identifier 'T'"
    gen-verilog  per-field regs, UNSUPPORTED_ICARUS

Two backends drop the parameter from the declaration and keep it at every use.
That inconsistency is what the warning states, and a test compiles gen-rust's
output so the credited half is a checked claim rather than a nicer sentence.

Population, from the AST: 28 specs, 33 generic types, all under specs/tri/. A
matcher over generated C prototypes said 8 files and 36 prototypes; that is a
DIFFERENT question -- C prototypes carrying a two-parameter application -- and
it cannot see a single `Option(T)`. Measured over 651 specs: exit codes 573 and
78 before and after, and NOT ONE moved.

Whether C and Zig should monomorphise, refuse, or drop the parameter at the use
site as well is a design question and is not part of this.

FOUND BY ACCIDENT, and worth recording as such. The parity table gained
combinations, and a matcher written to count TUPLE parameters caught
`Map(K, V)` instead, because a tuple and a generic application are both
`Name(A, B)`. The tuple defect it was aiming at is real -- C emits
`probe((u8, i32) x)` verbatim, though `c_tuple_info` already handles the return
position -- and has a corpus population of ZERO, as does `[]*i32` reaching C as
`*i32* x`. Both are latent and said to be.

Three mutants, three dead. The first was verified to be a COMPILE failure
(E0282) rather than assumed to be a pass from an empty result.

`diagnostic_capacity.py` now prints each instrument's version beside its count.
The same command gave 20 here and 50 on CI because one `cc` is Apple clang and
the other gcc: a diagnostic count measures the code, the instrument AND the
machine, and only the first was ever written down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) September 8, 2026 02:42
@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 02:42:23 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)=cd001774cfbb != 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 0a35e22 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.

check: a generic struct is silent, and only one of four backends lowers it

1 participant