Fix gentrace assertions when tracing tuples containing type aliases#5196
Merged
SeanTAllen merged 1 commit intomainfrom Apr 9, 2026
Merged
Fix gentrace assertions when tracing tuples containing type aliases#5196SeanTAllen merged 1 commit intomainfrom
SeanTAllen merged 1 commit intomainfrom
Conversation
PR #5145 stopped expanding type aliases during name resolution, so a type alias now persists as TK_TYPEALIASREF through codegen. Every codegen dispatch site was updated to unfold TK_TYPEALIASREF on demand, but two sites in gentrace.c were missed. Both only surface when a tuple is traced dynamically (e.g. as an element of a union), which is why ponylang/crdt's nightly started failing its build after #5145 landed: its `_Dot is (ID, U64)` alias wrapping a tuple exercises the first of these paths. trace_dynamic_tuple's TRACE_TUPLE branch duplicated the alias ref with ast_dup and passed it to the recursive trace_dynamic_tuple, which then iterated the alias ref's TK_ID / typeargs / cap / eph children as if they were tuple elements and tripped trace_type's default assertion. Unfold the alias once before the recursion so the callee sees the concrete TK_TUPLETYPE. trace_dynamic's TK_TYPEALIASREF case called typealias_unfold (which always returns a detached subtree) and passed the detached tree into the recursive trace_dynamic. When the detached subtree contained a tuple that reached trace_dynamic_tuple with tuple != NULL, the ast_swap(type, dontcare) at the top of trace_dynamic_tuple asserted on the NULL parent. Splice the unfolded form into the alias's position in its parent so downstream ast_swap always sees an attached tree; the rare detached-alias case is only reachable when tuple == NULL, so the in_tuple branch is never taken and the missing parent does not matter. A single regression test under test/full-program-tests exercises both scenarios: one field with an alias that expands directly to a tuple (bug 1) and another field with an alias that expands to a union containing a second alias-to-tuple (bug 2). Chained type aliases (alias of alias of tuple) are a known gap in the TRACE_TUPLE fix — typealias_unfold only unfolds one level. Constructing a test that reaches this site with a chained alias is currently blocked by other #5145 regressions elsewhere in codegen (the static trace_tuple path in gentrace.c and gen_digestof_value in genreference.c), which fire first for every configuration tried. That broader audit of every typealias_unfold call site is tracked in #5195. This is a regression against unreleased code, so no changelog or release notes entry.
SeanTAllen
added a commit
that referenced
this pull request
Apr 9, 2026
PR #5145 stopped expanding type aliases during name resolution, leaving them as TK_TYPEALIASREF in the AST. Every site that needs the underlying concrete type calls typealias_unfold on demand. The helper unfolded exactly one level, so chained aliases (`type A is B; type B is (U64, U64)`) returned another TK_TYPEALIASREF and any caller that inspected the head of the result crashed or miscompiled. PRs #5193 and #5196 fixed two crash sites with per-site unfolds, but the same bug class kept surfacing elsewhere. Make typealias_unfold transitive: if reify and apply_cap produce another TK_TYPEALIASREF, recurse until the head is concrete. The helper now guarantees its result has a non-alias head, so callers can rely on that postcondition. Termination is bounded by the alias chain length, which is finite because pass/names.c rejects cyclic alias defs via AST_FLAG_RECURSE_1 before any TK_TYPEALIASREF is emitted. Also fixes a related #5145 regression in gentrace_needed's TRACE_TUPLE branch, which iterated tuple element children without unfolding the alias and crashed on both single-level and chained tuple aliases. And removes the "known gap" comment in trace_dynamic_tuple's TRACE_TUPLE branch (added by #5196) since chained aliases now resolve to a concrete TK_TUPLETYPE through the transitive unfold. 11 new full-program-tests cover the affected codegen and expression paths. Each asserts a specific exit code so it catches both assertion crashes and silent miscompilation. Closes #5195
SeanTAllen
added a commit
that referenced
this pull request
Apr 9, 2026
PR #5145 stopped expanding type aliases during name resolution, leaving them as TK_TYPEALIASREF in the AST. Every site that needs the underlying concrete type calls typealias_unfold on demand. The helper unfolded exactly one level, so chained aliases (`type A is B; type B is (U64, U64)`) returned another TK_TYPEALIASREF and any caller that inspected the head of the result crashed or miscompiled. PRs #5193 and #5196 fixed two crash sites with per-site unfolds, but the same bug class kept surfacing elsewhere. Make typealias_unfold transitive: if reify and apply_cap produce another TK_TYPEALIASREF, recurse until the head is concrete. The helper now guarantees its result has a non-alias head, so callers can rely on that postcondition. Termination is bounded by the alias chain length, which is finite because pass/names.c rejects cyclic alias defs via AST_FLAG_RECURSE_1 before any TK_TYPEALIASREF is emitted. A coupling comment in names.c documents this dependency for future maintainers. Also fixes a related #5145 regression in gentrace_needed's TRACE_TUPLE branch, which iterated tuple element children without unfolding the operand types and crashed on both single-level and chained tuple aliases (found during review via an asymmetric argument/parameter pattern). And removes the now-stale "known gap" comment in trace_dynamic_tuple's TRACE_TUPLE branch (added by #5196) since chained aliases now resolve to a concrete TK_TUPLETYPE through the transitive unfold. The new full-program-tests cover the affected codegen and expression paths at specific exit codes so they catch both assertion crashes and silent miscompilation. Closes #5195
SeanTAllen
added a commit
that referenced
this pull request
Apr 9, 2026
PR #5145 stopped expanding type aliases during name resolution, leaving them as TK_TYPEALIASREF in the AST. Every site that needs the underlying concrete type calls typealias_unfold on demand. The helper unfolded exactly one level, so chained aliases (`type A is B; type B is (U64, U64)`) returned another TK_TYPEALIASREF and any caller that inspected the head of the result crashed or miscompiled. PRs #5193 and #5196 fixed two crash sites with per-site unfolds, but the same bug class kept surfacing elsewhere. Make typealias_unfold transitive: if reify and apply_cap produce another TK_TYPEALIASREF, recurse until the head is concrete. The helper now guarantees its result has a non-alias head, so callers can rely on that postcondition. Termination is bounded by the alias chain length, which is finite because pass/names.c rejects cyclic alias defs via AST_FLAG_RECURSE_1 before any TK_TYPEALIASREF is emitted. A coupling comment in names.c documents this dependency for future maintainers. Also fixes a related #5145 regression in gentrace_needed's TRACE_TUPLE branch, which iterated tuple element children without unfolding the operand types and crashed on both single-level and chained tuple aliases (found during review via an asymmetric argument/parameter pattern). And removes the now-stale "known gap" comment in trace_dynamic_tuple's TRACE_TUPLE branch (added by #5196) since chained aliases now resolve to a concrete TK_TUPLETYPE through the transitive unfold. The new full-program-tests cover the affected codegen and expression paths at specific exit codes so they catch both assertion crashes and silent miscompilation. Closes #5195
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two assertions in gentrace.c fire when codegen traces a dynamically-traced tuple whose element is a type alias. Both are PR #5145 regressions — aliases now persist as
TK_TYPEALIASREFthrough codegen instead of being expanded during name resolution, and these two sites were missed when the dispatch logic was updated. This is what's breaking theponylang/crdtnightly build:_Dot is (ID, U64)trips the first one.The
TRACE_TUPLEbranch oftrace_dynamic_tuplenow unfolds the alias once before recursing, so the recursive call sees a concreteTK_TUPLETYPEinstead of iterating(TK_ID, typeargs, cap, eph)as tuple children.The
TK_TYPEALIASREFcase oftrace_dynamicsplicestypealias_unfold's detached result into the alias's parent before recursing. That keeps the tree attached so downstreamast_swapcalls intrace_dynamic_tuplealways see a non-NULL parent. The rare detached-alias path is only reachable withtuple == NULL, which short-circuits the failingast_swap, and the else branch asserts the invariant.A new full-program-test covers both bugs with independent discrimination — one field exercises each fix.
Chained aliases (alias of alias of tuple) still trip the first fix because
typealias_unfoldonly unfolds one level. I could not construct a test that reaches this site with a chained alias because other PR #5145 regressions (the statictrace_tuplepath in gentrace.c andgen_digestof_valuein genreference.c) fire first. The broadertypealias_unfoldcall-site audit is tracked in #5195.This is against unreleased code, so no changelog or release notes entry.