Skip to content

fix(emit): an identity inside a composite is refused for the part - #372

Merged
cmj0121 merged 4 commits into
mainfrom
fix/368-identity-in-composite
Oct 17, 2026
Merged

cmj0121 merged 4 commits into
mainfrom
fix/368-identity-in-composite

Conversation

@cmj0121

@cmj0121 cmj0121 commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Closes #368.

What

A channel or a function value inside a composite is now refused by every rendering spelling, under E4076. That
covers print, str(…), an f-string hole, .display() and .debug(), at any depth. The refusal names the part and
the whole:

E4076 a chan[int] is an identity rather than a value, and the language gives it no rendering — a list[chan[int]]
renders by its parts and this one is a place to send to or to jump to, whose address is not a rendering of anything
the program wrote

Before this, print [ch], (1, ch), {"a": ch}, a struct field and an enum payload printed the channel's address.
print [f] reached cc (operand of type 'zg_fnptr').

How

c_display_check already refused a bare identity. It now also walks the parts the structural renderer would reach,
using c_identity_part over c_render_parts. That keeps a single E4076 report site. The walk stops where
c_render_runs stops: a type that declares its own display answers for what it holds, so a channel behind one still
renders.

Tests

  • reject: five cases, covering a list, a tuple holding a list (fn, str(…)), a map value (f-string), a struct
    field (.display()) and an enum payload. All five were RED on the compiler without the fix (four accepted, one
    reaching cc).
  • corpus: codegen/identity_behind_override checks that list[W], a tuple and a map holding a type with its own
    display still render. The seed cannot print a list[W], so the case is an oracle skip. leaks --atExit is clean.
  • Gates run one at a time, all OK: reject, lint, refuse, error-codes-check, docs-mirror, docs-links,
    fixpoint, oracle, corpus, sanitize-corpus.

Not here

The stale "a list has no rendering" comments are #371.

🤖 Generated with Claude Code

https://claude.ai/code/session_01N8jd1oK2orM6diHxhvWhC7

    The structural renderer walks a composite's parts and renders each one
    through c_render_of, which has no refusal of its own. So `print [ch]`
    printed the channel's address, and `print [f]` reached cc. A struct field
    or an enum payload did the same.
    c_display_check now walks the parts the renderer would reach
    (c_identity_part over c_render_parts) and refuses under E4076, naming the
    part and the whole. It stops where c_render_runs stops: a type that
    declares its own rendering answers for what it holds. (#368)
    One case per container the walk descends through: a list, a tuple holding
    a list, a map value, a struct field and an enum payload. Each kind of
    identity and each rendering spelling is covered. The sentence names both
    the part and the whole. All five were accepted, or reached cc, before the
    fix.
    format.md (en and zh-TW) says a composite that holds a channel or a function
    value is E4076 at any depth, and that a type declaring its own `display`
    answers for what it holds.
@cmj0121
cmj0121 merged commit 439092f into main Oct 17, 2026
8 checks passed
@cmj0121
cmj0121 deleted the fix/368-identity-in-composite branch October 17, 2026 11:35
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.

a channel inside a list, a map or a tuple renders as its address

1 participant