Skip to content

gen-c: an enum member is a constant in both spellings - #3470

Merged
gHashTag merged 1 commit into
masterfrom
c/enum-path-members
Sep 8, 2026
Merged

gen-c: an enum member is a constant in both spellings#3470
gHashTag merged 1 commit into
masterfrom
c/enum-path-members

Conversation

@gHashTag

@gHashTag gHashTag commented Sep 8, 2026

Copy link
Copy Markdown
Owner

gen-c: an enum member is a constant in both spellings

Closes #3469

Trit.pos was fixed one pass earlier. TokenKind::KwFn is the SAME
enum-member reference spelled with a path, and it was not: 917 X::Y
occurrences reached the generated C across 65 files, and C has no ::
in an expression at all.

MEASURED, whole corpus, -ferror-limit=0:
errors 13331 -> 12420 (-911)
files better/worse 27 / 0
compiling clean 303 -> 307
compiler_diagnostics 43 -> 0, compiler_lexer 133 -> 3,
igla_race_formal 393 -> 257, file_operations 163 -> 85

ONE RULE, TWO SPELLINGS. Both arms now call one helper, so a change to
the naming convention cannot reach one and miss the other. A mutant
disabling either call site is killed by the other's tests.

THE MEMBERSHIP TEST IS ON THE VARIANTS, NOT THE ENUM'S NAME. 12 corpus
sites name a member their enum does not declare (Trit::TRUE against an
enum of pos/neg/zero). Lowering those would emit a constant gen_c_enum
never wrote -- a diagnostic that hides the spec's mistake instead of
naming it. They stay loud, and the specs are what needs fixing.

PREDICTED 526, DELIVERED 505, AND THE 21 ARE ACCOUNTED FOR EXACTLY:
they sit inside emitted C comments (/* invariant ... is not a C constant expression: (ErrorCode::Success == 0) */), a path that prints
source text verbatim rather than through the expression emitter, and
they produce no errors. A gap between prediction and outcome is a
question, not a rounding error.

MY OWN READER OVER-COUNTED BY 9. c_error_classes.py searched for the
word error:; clang echoes the offending source line under each
message, so three lines of one spec containing "error: " in a STRING
LITERAL were counted as diagnostics. It is anchored on
file:line:col: error: now, and the self-check gained the case that
found it. The first version of that fixture put the string on a clean
line -- clang never echoed it, the control could not fail, and it
passed for the wrong reason.

AND I MEASURED A MUTANT. After the mutation run I restored compiler.rs
and did not rebuild, so the tool reported 13120 with unexpected type name 'Trit' back at 641 -- the numbers of the mutant that disables the
dotted arm. Two of my own instruments disagreeing by 700 is what caught
it.

A GUARD WAS WRITTEN, FOUND UNREACHABLE, AND REMOVED: a variant name is
an identifier, so the map can never hold b::c and a
!member.contains("::") test could not change the outcome.

rsplit_once survives as a mutant and is documented rather than papered
over: for a two-segment path the two are identical, and for the 477
three-segment paths in the specs both refuse, because the map is keyed
on a single identifier. Handling lexer::TokenKind::RBrace is a
separate repair and is named in #3469, not assumed.

CENSUS RE-BLESSED, AND THE DRIFT IS NOT THIS COMMIT'S. workflow files read 50 -> 51, jobs 71 -> 72, run: steps 235 -> 246. Stashing every
change here and running tri census pin --gate on clean origin/master
reproduces the failure, so it was already stale: ELEVEN workflow commits
have landed since the pin was last blessed on 2026-09-05, every one of
them by squash, and a squash does not run the hook. The pin binds local
commits and nothing that reaches master.

Tests: 5 new, full suite 3515 passed 0 failed. 34 stale seals refreshed.

🤖 Generated with Claude Code

Closes #3469

`Trit.pos` was fixed one pass earlier. `TokenKind::KwFn` is the SAME
enum-member reference spelled with a path, and it was not: 917 `X::Y`
occurrences reached the generated C across 65 files, and C has no `::`
in an expression at all.

MEASURED, whole corpus, -ferror-limit=0:
  errors            13331 -> 12420   (-911)
  files better/worse   27 / 0
  compiling clean     303 -> 307
  compiler_diagnostics 43 -> 0, compiler_lexer 133 -> 3,
  igla_race_formal    393 -> 257, file_operations 163 -> 85

ONE RULE, TWO SPELLINGS. Both arms now call one helper, so a change to
the naming convention cannot reach one and miss the other. A mutant
disabling either call site is killed by the other's tests.

THE MEMBERSHIP TEST IS ON THE VARIANTS, NOT THE ENUM'S NAME. 12 corpus
sites name a member their enum does not declare (`Trit::TRUE` against an
enum of pos/neg/zero). Lowering those would emit a constant `gen_c_enum`
never wrote -- a diagnostic that hides the spec's mistake instead of
naming it. They stay loud, and the specs are what needs fixing.

PREDICTED 526, DELIVERED 505, AND THE 21 ARE ACCOUNTED FOR EXACTLY:
they sit inside emitted C comments (`/* invariant ... is not a C
constant expression: (ErrorCode::Success == 0) */`), a path that prints
source text verbatim rather than through the expression emitter, and
they produce no errors. A gap between prediction and outcome is a
question, not a rounding error.

MY OWN READER OVER-COUNTED BY 9. `c_error_classes.py` searched for the
word `error:`; clang echoes the offending source line under each
message, so three lines of one spec containing `"error: "` in a STRING
LITERAL were counted as diagnostics. It is anchored on
`file:line:col: error: ` now, and the self-check gained the case that
found it. The first version of that fixture put the string on a clean
line -- clang never echoed it, the control could not fail, and it
passed for the wrong reason.

AND I MEASURED A MUTANT. After the mutation run I restored compiler.rs
and did not rebuild, so the tool reported 13120 with `unexpected type
name 'Trit'` back at 641 -- the numbers of the mutant that disables the
dotted arm. Two of my own instruments disagreeing by 700 is what caught
it.

A GUARD WAS WRITTEN, FOUND UNREACHABLE, AND REMOVED: a variant name is
an identifier, so the map can never hold `b::c` and a
`!member.contains("::")` test could not change the outcome.

`rsplit_once` survives as a mutant and is documented rather than papered
over: for a two-segment path the two are identical, and for the 477
three-segment paths in the specs both refuse, because the map is keyed
on a single identifier. Handling `lexer::TokenKind::RBrace` is a
separate repair and is named in #3469, not assumed.

CENSUS RE-BLESSED, AND THE DRIFT IS NOT THIS COMMIT'S. `workflow files
read` 50 -> 51, `jobs` 71 -> 72, `run: steps` 235 -> 246. Stashing every
change here and running `tri census pin --gate` on clean origin/master
reproduces the failure, so it was already stale: ELEVEN workflow commits
have landed since the pin was last blessed on 2026-09-05, every one of
them by squash, and a squash does not run the hook. The pin binds local
commits and nothing that reaches master.

Tests: 5 new, full suite 3515 passed 0 failed. 34 stale seals refreshed.

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

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-09-08 08:39:12 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)=3bf5755a85c1 != 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 344844b into master Sep 8, 2026
28 of 31 checks passed
@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.

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.

gen-c: the path spelling of an enum member reaches C verbatim -- 917 X::Y occurrences in 65 files

1 participant