Skip to content

fix: a refused typedef's operator, a generic instance's name, and a build's second file - #381

Closed
cmj0121 wants to merge 6 commits into
mainfrom
fix/two-minor
Closed

cmj0121 wants to merge 6 commits into
mainfrom
fix/two-minor

Conversation

@cmj0121

@cmj0121 cmj0121 commented Oct 20, 2026

Copy link
Copy Markdown
Owner

Fixes

  • < on a strong typedef over a tuple overflows the compiler's stack #378 < (and every operator but ==) on type Pair = (int, str) overflowed the compiler's stack. The checker
    refuses the typedef with E9042 and records its underlying type as unknown. c_scalar_repr answered Pair itself
    for that, and chk_binary re-entered itself with the answer. It now asks c_repr_of, so a refused typedef answers
    unknown and the declaration's E9042 is the report.
  • zerg lint names a generic's mangled instance in E3001 #379 no diagnostic names a generic instance's mangled symbol (least$int). E3001, E3114 and E3083 now spell
    their name through chk_call_name. A call to a template that collides with one in another file is quiet, so
    E3060 is the one report.
  • zerg lint names a generic's mangled instance in E3001 #379 zerg build --emit tokens|lib|bin read only the first file and dropped the rest, errors included. These
    stages now refuse a second file by name: a build is one entry file and the modules its imports reach
    (docs/runtime/package.md).

Deviation

Two files that each declare a private generic of one name are still refused (E3060), though the file owns its
private names. docs/runtime/package.md (en and zh-TW) now marks this [deviation], naming #380, which holds the
real fix: key templates by their declaring file.

Tests

  • refuse: a typedef over a tuple under <, and two modules' private templates are E3060 alone.
  • reject: E3001, E3114 and E3083 name the template; a second file on each one-entry stage is refused by name.
  • diag.sh: every reject and refuse case now asserts that no quoted name holds a $.
  • scripts/lib/case.sh: one copy of the multi-file case splitter, shared by both scripts.

Each case was red before its fix. All CI gates were run locally and are green; the two changed scripts also pass
under /bin/bash 3.2.

Closes #378
Closes #379

🤖 Generated with Claude Code

https://claude.ai/code/session_01N8jd1oK2orM6diHxhvWhC7

    `type Pair = (int, str)` then `p < p` printed `StackOverflowError: stack
    overflow` and no diagnostic (#378). chk_typedef refuses the declaration
    with E9042 and registers TUnknown as its underlying type; c_scalar_repr
    then answered `Pair` itself for it, the same answer it gives a type that
    is no typedef, and chk_binary re-enters itself with that answer, so it
    asked the same question until the stack ran out. Every operator but an
    equality took that path, and so did a typedef over that typedef.

    c_scalar_repr now answers what the row holds, which is UNKNOWN for a
    refused typedef, as c_repr_of already does. chk_binary stops at an
    unknown operand, so the uses stay quiet and the declaration's E9042 is
    the report.
…instance

    The row a call to a generic reads is its instance's, keyed `least$int`, and
    the rules asked of that row printed the key: E3001, E3114 and E3083 named
    `least$int` or `least$_28_int_2c__20_str_29_`, a C symbol nobody wrote.
    Their sentences now go through chk_call_name, the one place a key becomes
    a name, so they print `least`.

    And when the caller's own file declares a template of that name too, the
    call is one E3060 already refused at the declaration: templates share one
    flat namespace (#380), so the call answered with the other file's
    instance and E3001 then refused it as a read of the other file. That
    instance is quiet now, so E3060 is the one report (#379).
    `--emit tokens`, `lib` and `bin` read `files[0]` and dropped every other
    file named on the line without a word, so `zerg build a.zg b.zg` built
    `a.zg`, exited 0 and never read `b.zg`, its errors included (#379).

    A build is an entry file and the modules its imports reach
    (docs/runtime/package.md), so loading the rest as more entries is a
    meaning the docs do not give. These stages refuse instead, exit 2 and
    name the first file they would not read, as the driver's other usage
    errors do. `ast`, `check` and `c` merge every file and are unchanged.
    A refuse case beside the other E9042 ones: `p < p` on `type Pair = (int,
    str)` must open with E9042 naming the declaration. It is red on the
    compiler before the fix, which overflowed its stack instead.
    - names_a_temp counts a quoted name holding a `$` as one the compiler
      minted, so every reject and refuse case asserts no instance name.
    - refuse: two private templates in two modules are E3060 alone, the
      deviation #380; `expect` takes a multi-file case and `expect_alone`
      pins the count. The seed builds that program, so it is no reject case.
    - reject: E3001, E3114 and E3083 against a generic's call name the
      template; `--emit tokens|lib|bin` with a second, ill-formed file
      refuses and names it. Each case was red before its fix.

    - scripts/lib/case.sh holds the `--- path` splitter both scripts write
      a case with, so the byte pipe has one copy.
    The file is the unit of naming, and two private plain functions of one
    name in two files are two functions; two private generics are refused as
    E3060, because templates sit in one table by bare name. Recorded as a
    deviation beside the private-type paragraph, en and zh-TW.
@cmj0121

cmj0121 commented Oct 20, 2026

Copy link
Copy Markdown
Owner Author

Merged to main as e33d58a, but gh pr merge returned 502 Bad Gateway and the PR record was never updated. e33d58a's parents are f144770 (the old main) and 078c6c5 (this branch's head). Its tree, 47b0607d, is the same tree this PR's CI run 39429640968 tested and passed. Closing by hand.

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.

zerg lint names a generic's mangled instance in E3001 < on a strong typedef over a tuple overflows the compiler's stack

1 participant