on master help sign in
Check finite boolean union patterns
commit9dd35c86758c99e4d8b1da628c63e543bb37459a authoriko <mail@iko.soy> dateSat 31 Oct 2026, 00:01 (5 hours ago) parent9f1517e
24 files changed+1586−147
docs/compiler.md+1−1 docs/status.md+8−7 jibb-dev/lib/jibb.hoon+102−12 tests/golden/types-union-finite-generic/about.txt+4 tests/golden/types-union-finite-generic/modules.txt+1 tests/golden/types-union-finite-generic/source.jibb+48 tests/golden/types-union-finite-generic/tokens.txt+336 tests/golden/types-union-finite-generic/tree.txt+143 tests/golden/types-union-finite-generic/types.txt+11 tests/golden/types-union-finite-limit/about.txt+4 tests/golden/types-union-finite-limit/modules.txt+1 tests/golden/types-union-finite-limit/source.jibb+35 tests/golden/types-union-finite-limit/tokens.txt+233 tests/golden/types-union-finite-limit/tree.txt+89 tests/golden/types-union-finite-limit/types.txt+10 tests/golden/types-union-finite/about.txt+4 tests/golden/types-union-finite/modules.txt+1 tests/golden/types-union-finite/source.jibb+45 tests/golden/types-union-finite/tokens.txt+238 tests/golden/types-union-finite/tree.txt+110 tests/golden/types-union-finite/types.txt+17 tests/golden/types-union-patterns/about.txt+1−1 tests/golden/types-union-patterns/types.txt+1−1 tests/lib/jibb.hoon+143−125
docs/compiler.md+1−1
@@ -68,7 +68,7 @@ A list literal can be inferred when a cast or known gate sample supplies a list
6868
6969A known union of `~` and a null-headed cell can be matched by `~` and `[~ value]` arms in either order. The payload binder is checked for shadowing. Unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported; this fragment infers the prelude’s `fall` and `need` signatures.
7070
71−A known closed union with two or more arms can be matched when each arm provably covers or excludes each remaining case in full. The checker binds payloads for an arm matching one case, accepts a binder-free catch-all, and reports missing cases and arms already covered. It checks tags by noun value, including loobean and null spellings, and supports imported and generic union cases. A pattern that might cover only part of a case, a binder spanning multiple cases, differing arm result types and some complex two-arm subjects remain unsupported; contextual union-pattern branches also remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked.
71+A known closed union with two or more arms can be matched when each arm provably covers or excludes each remaining case. The checker first tries whole cases; when a pattern splits a case, it can expand known `?` positions into their two noun values, up to 64 alternatives across the union. Binders retain the original case type, and one arm may bind several refinements of that case. It reports missing alternatives and arms already covered, checks tags by noun value, and supports imported and generic union cases. Other partial patterns, expansions above the limit, binders spanning distinct cases, differing arm result types and some complex two-arm subjects remain unsupported; contextual union-pattern branches also remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked.
7272
7373A known closed union can also provide context to each arm of a complete loobean or unit-shaped branch in a cast or a call with a known union sample. Nested branches and transparent groups work; a mismatch reports the expected union and the offending arm. General patterns and context through bodies with local definitions remain unsupported, and unrelated unresolved tags stay pending.
7474
docs/status.md+8−7
@@ -1,6 +1,6 @@
11# Status
22
3−As of 2026-10-30. The plan is [spec/implementation-plan.md](spec/implementation-plan.md); each milestone ends with its checks passing on a fake ship.
3+As of 2026-10-31. The plan is [spec/implementation-plan.md](spec/implementation-plan.md); each milestone ends with its checks passing on a fake ship.
44
55| # | Milestone | Status |
66| --- | --- | --- |
@@ -19,7 +19,7 @@ On 2026-10-30, @iko decided that Jibb drops `$?`, so a `+$` takes a union's case
1919
2020## Milestone 2: in progress
2121
22−The repository spec records the subsequent type-system and prelude decisions; those changes also need synchronization to the Claude document. An initial inference fragment and a standalone Hoon type reader are being tested. The fragment explicitly reports that it does not check a module; partial bridges pass selected Hoon atoms, term singletons, nested faced or unfaced cells, supported disjoint unions and opaque standard collections from `/sur` molds and marks into inference. Collections retain their names and supported arguments for printing and unification; nested supported union arguments are retained too. The bridge trusts unchanged results from the source-aware reader; a materialized type graph alone cannot reveal cases Hoon already collapsed. The source-validated standard prelude `list` mold shares this representation with imported lists; other Jibb-written collection molds and most prelude collection operations remain unsupported; malformed names and arities fail closed. Selected self-recursive `/sur` molds cross as opaque module-and-name identities; aliases, foreign references, recursive marks, unfolding and construction remain unsupported. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, direct `$^` unions whose cases can be proved disjoint, and one verified explicit union argument in a list, set, map or unit. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases, as @iko confirmed for imported `$%`, `$?` and `$^`, while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. Opt-in structured reader APIs preserve successful graphs and distinguish definite unsupported-aura and core evidence from failures the reader cannot prove; unverified union disjointness and name-only vase recognition remain unsupported. They revalidate and re-walk failed types. An opt-in partial checker entry point consumes unchanged reader results and reports definite aura or core errors at imported mold use sites when their inputs are unique. Ordered replay covers nested cell samples, record and function casts, and non-generic same-module aliases; unsupported prefixes, cycles and shadowing stop it. Union molds, generic applications, transitive modules and unsupported reader outcomes remain generic. Replay repeats inference and may add work. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and a source-derived partial prelude interface, caches completed interfaces per run, and detects missing sources and cycles. It does not yet check API or kind semantics, and the prelude inventory is incomplete. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, acyclic local value definitions with captures, selected single self-recursive top-level and local gates, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags, `~` and constructors for closed disjoint unions, including direct nonrecursive generic unions and propagation through complete loobean and unit-shaped branches in casts and known union-sample calls, including nested branches. Multi-argument calls form a right-nested sample, retain known faces and shared type variables, and can use known sample positions to contextualize list and union arguments. A definite mismatch points to the failing argument when the fragment can establish it, otherwise to the combined sample; unsupported contextual forms still fail closed. For a supported recursive gate, the checker infers the sample first and uses its exact type, including field faces, for one monomorphic self reference. It generalizes after the body is checked; subsequent uses instantiate it independently. Incompatible recursive arguments can report the gate and argument sites. For a complete loobean branch with one direct self-call arm, a separately inferred closed base type can seed the recursive result before the whole body is checked. Open or pending base types do not seed it; other branch shapes remain subject to the fragment’s existing limits. A supported single local recursive gate also uses a monomorphic self reference and generalizes variables free of the enclosing environment after checking its body; captured variables remain shared. The checker collects written capitals per `++` before inference, excluding nested definitions: a capital used in an enclosing definition is shared with its locals even when written later, while a capital introduced only in a local definition is generalized there. Sibling locals can introduce independent capitals with the same spelling; generic mold parameters keep their own scope. Top-level groups of syntactic gates are inferred together with monomorphic placeholders and shared substitutions, then generalized only after the whole group checks; downstream uses and library interfaces instantiate those schemes independently. A dependency graph identifies groups with two iterative depth-first passes; its conservative local-reference edges can reject otherwise valid programs. Local mutual groups, polymorphic recursion, value cycles, unresolved literal constraints and unresolved branch joins remain unsupported. Reporting repeats inference for a single recursive gate outside a group; grouped reports use the stored schemes. Its performance cost remains unmeasured. String interpolation accepts known atom auras, unrestricted `@`, tapes and isolated decimal literals; a known cell asks for a printer, and an explicitly generic atom asks for an aura. Loobeans, term singletons, non-tape collections, open types and a type fixed only later remain unsupported. A known closed union with two or more arms supports patterns that provably cover or exclude each remaining case in full, including payload binders, imported and generic cases, and binder-free catch-alls. Missing cases and covered arms are reported; partial-case patterns, multi-case binders, differing arm result types, some complex two-arm subjects and contextual union-pattern branches remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked. Contextual null-headed cells fit their cases, but do not supply a `|=%$` constructor; unresolved nulls remain pending and are reported separately from tags. A known union of `~` and a null-headed cell supports a complete `~` / `[~ value]` branch in either order, including shadow checks; unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported. This fragment infers the prelude’s `fall` and `need` signatures. With the validated prelude list and a known cast or gate sample, empty, nonempty and nested list literals infer their element types, including contextual union tags; a mismatched element names both sites. In that context `~` and zero-valued terms fit an empty list, and two-item unfaced cells form cons lists, including nested cons and imported-list contexts; invalid heads or tails name both sites. A zero nested inside a single tuple argument where a list is expected remains unsupported rather than a definite mismatch. Faced or longer cells and a missing or altered prelude list fail closed. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. For a known standard list with a supported element type, a complete `~` / `[item rest]` branch infers the element and tail types in either arm order and checks binders for shadowing. Uncontextualized list construction, unknown subjects, unsupported element types and other or incomplete list patterns remain unsupported. A value with type variable `A` can fit a field whose type is that same `A`, including in generic union payloads and nested or repeated record fields. Other variable-dependent face merges remain unsupported. Forced equality of distinct written capitals now reports both source sites, following @iko’s decision; forcing one to a concrete type remains unsupported. Imported record spines with repeated faces fail closed where used, but only with a generic unsupported diagnostic. Hoon may erase unfaced nested-cell boundaries, so the check can conservatively reject valid names in distinct erased scopes. Supported closed unions print using an in-scope name or imported alias; an unnamed nongeneric union prints its cases, parenthesized when nested. The latter is print-only. Generic union types retain all arguments in their printed name; if that name is unavailable, the partial printer reports the limitation. Different import faces for the same origin remain compatible; compatibility across distinct union origins and some generic-argument comparisons remain unsupported. Nonrecursive generic aliases can reorder, repeat or omit parameters while retaining a union’s origin, including through local scopes and library interfaces. A generic union declared directly inside a body remains unsupported, as do differing-variable face constraints in a union payload. A transitive generic union whose name is unavailable is reported as unsupported instead of hiding its arguments. Unfixed decimal literals default to `@ud` in gate-free inferred types; mutually recursive local groups and recursive molds, general branch tag context, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; a wrapper regression also rejects forged subjects, samples and tails. Its golden fixtures include three real Tlon files. A Clay test passes a Ford-built nested union through the reader into partial inference. The partial prelude includes `murn`, `join`, `snip`, `rear` and the newly agreed shared-type `clap`, parsed but still awaiting checker and backend validation, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
22+The repository spec records the subsequent type-system and prelude decisions; those changes also need synchronization to the Claude document. An initial inference fragment and a standalone Hoon type reader are being tested. The fragment explicitly reports that it does not check a module; partial bridges pass selected Hoon atoms, term singletons, nested faced or unfaced cells, supported disjoint unions and opaque standard collections from `/sur` molds and marks into inference. Collections retain their names and supported arguments for printing and unification; nested supported union arguments are retained too. The bridge trusts unchanged results from the source-aware reader; a materialized type graph alone cannot reveal cases Hoon already collapsed. The source-validated standard prelude `list` mold shares this representation with imported lists; other Jibb-written collection molds and most prelude collection operations remain unsupported; malformed names and arities fail closed. Selected self-recursive `/sur` molds cross as opaque module-and-name identities; aliases, foreign references, recursive marks, unfolding and construction remain unsupported. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, direct `$^` unions whose cases can be proved disjoint, and one verified explicit union argument in a list, set, map or unit. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases, as @iko confirmed for imported `$%`, `$?` and `$^`, while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. Opt-in structured reader APIs preserve successful graphs and distinguish definite unsupported-aura and core evidence from failures the reader cannot prove; unverified union disjointness and name-only vase recognition remain unsupported. They revalidate and re-walk failed types. An opt-in partial checker entry point consumes unchanged reader results and reports definite aura or core errors at imported mold use sites when their inputs are unique. Ordered replay covers nested cell samples, record and function casts, and non-generic same-module aliases; unsupported prefixes, cycles and shadowing stop it. Union molds, generic applications, transitive modules and unsupported reader outcomes remain generic. Replay repeats inference and may add work. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and a source-derived partial prelude interface, caches completed interfaces per run, and detects missing sources and cycles. It does not yet check API or kind semantics, and the prelude inventory is incomplete. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, acyclic local value definitions with captures, selected single self-recursive top-level and local gates, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags, `~` and constructors for closed disjoint unions, including direct nonrecursive generic unions and propagation through complete loobean and unit-shaped branches in casts and known union-sample calls, including nested branches. Multi-argument calls form a right-nested sample, retain known faces and shared type variables, and can use known sample positions to contextualize list and union arguments. A definite mismatch points to the failing argument when the fragment can establish it, otherwise to the combined sample; unsupported contextual forms still fail closed. For a supported recursive gate, the checker infers the sample first and uses its exact type, including field faces, for one monomorphic self reference. It generalizes after the body is checked; subsequent uses instantiate it independently. Incompatible recursive arguments can report the gate and argument sites. For a complete loobean branch with one direct self-call arm, a separately inferred closed base type can seed the recursive result before the whole body is checked. Open or pending base types do not seed it; other branch shapes remain subject to the fragment’s existing limits. A supported single local recursive gate also uses a monomorphic self reference and generalizes variables free of the enclosing environment after checking its body; captured variables remain shared. The checker collects written capitals per `++` before inference, excluding nested definitions: a capital used in an enclosing definition is shared with its locals even when written later, while a capital introduced only in a local definition is generalized there. Sibling locals can introduce independent capitals with the same spelling; generic mold parameters keep their own scope. Top-level groups of syntactic gates are inferred together with monomorphic placeholders and shared substitutions, then generalized only after the whole group checks; downstream uses and library interfaces instantiate those schemes independently. A dependency graph identifies groups with two iterative depth-first passes; its conservative local-reference edges can reject otherwise valid programs. Local mutual groups, polymorphic recursion, value cycles, unresolved literal constraints and unresolved branch joins remain unsupported. Reporting repeats inference for a single recursive gate outside a group; grouped reports use the stored schemes. Its performance cost remains unmeasured. String interpolation accepts known atom auras, unrestricted `@`, tapes and isolated decimal literals; a known cell asks for a printer, and an explicitly generic atom asks for an aura. Loobeans, term singletons, non-tape collections, open types and a type fixed only later remain unsupported. A known closed union with two or more arms supports patterns that provably cover or exclude each remaining case, including payload binders, imported and generic cases, and binder-free catch-alls. Partial boolean patterns can split known `?` positions into their two noun values, up to 64 alternatives across the union; binders retain their original case type. Missing alternatives and covered arms are reported. Other partial patterns, expansions above the limit, binders spanning distinct cases, differing arm result types, some complex two-arm subjects and contextual union-pattern branches remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked. Contextual null-headed cells fit their cases, but do not supply a `|=%$` constructor; unresolved nulls remain pending and are reported separately from tags. A known union of `~` and a null-headed cell supports a complete `~` / `[~ value]` branch in either order, including shadow checks; unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported. This fragment infers the prelude’s `fall` and `need` signatures. With the validated prelude list and a known cast or gate sample, empty, nonempty and nested list literals infer their element types, including contextual union tags; a mismatched element names both sites. In that context `~` and zero-valued terms fit an empty list, and two-item unfaced cells form cons lists, including nested cons and imported-list contexts; invalid heads or tails name both sites. A zero nested inside a single tuple argument where a list is expected remains unsupported rather than a definite mismatch. Faced or longer cells and a missing or altered prelude list fail closed. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. For a known standard list with a supported element type, a complete `~` / `[item rest]` branch infers the element and tail types in either arm order and checks binders for shadowing. Uncontextualized list construction, unknown subjects, unsupported element types and other or incomplete list patterns remain unsupported. A value with type variable `A` can fit a field whose type is that same `A`, including in generic union payloads and nested or repeated record fields. Other variable-dependent face merges remain unsupported. Forced equality of distinct written capitals now reports both source sites, following @iko’s decision; forcing one to a concrete type remains unsupported. Imported record spines with repeated faces fail closed where used, but only with a generic unsupported diagnostic. Hoon may erase unfaced nested-cell boundaries, so the check can conservatively reject valid names in distinct erased scopes. Supported closed unions print using an in-scope name or imported alias; an unnamed nongeneric union prints its cases, parenthesized when nested. The latter is print-only. Generic union types retain all arguments in their printed name; if that name is unavailable, the partial printer reports the limitation. Different import faces for the same origin remain compatible; compatibility across distinct union origins and some generic-argument comparisons remain unsupported. Nonrecursive generic aliases can reorder, repeat or omit parameters while retaining a union’s origin, including through local scopes and library interfaces. A generic union declared directly inside a body remains unsupported, as do differing-variable face constraints in a union payload. A transitive generic union whose name is unavailable is reported as unsupported instead of hiding its arguments. Unfixed decimal literals default to `@ud` in gate-free inferred types; mutually recursive local groups and recursive molds, general branch tag context, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; a wrapper regression also rejects forged subjects, samples and tails. Its golden fixtures include three real Tlon files. A Clay test passes a Ford-built nested union through the reader into partial inference. The partial prelude includes `murn`, `join`, `snip`, `rear` and the newly agreed shared-type `clap`, parsed but still awaiting checker and backend validation, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
2323
2424The shared prelude interface reserves every name present in the supplied vendored source and makes only supported inferred entries available, including `list`, `unit`, `same`, `fall`, `need`, `lure`, `weld`, `snoc` and `turn`. The validated standard `list` mold is injected when the prelude’s own gates are inferred; `weld` and `turn` have ordinary explicit result casts. An absent or altered `list` is not injected, and an altered declaration cannot leak through direct or transitive mold aliases. List-dependent prelude mold aliases remain unsupported because their templates are prepared before injection. Unsupported entries such as most list helpers remain reserved but unavailable; backend validation of the helpers remains outstanding. All callers use the same prelude origin, so a library can export a type containing unqualified `(unit A)` to another module. Preparation rejects empty, malformed, conflicting or import-bearing source; the prepared value is trusted and must come unchanged from `+prepare-prelude`. The module-scope fixture compares the prepared and source-taking paths against the real prelude and a two-module golden under eval and on the ship. The source and checker remain incomplete, so this does not establish complete shadowing coverage or a checked module.
2525
@@ -39,8 +39,8 @@ What the plan asks for, and where it is:
3939
4040Besides the plan's list:
4141
42−- 526 golden cases: 310 that parse and 216 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
43−- The 526-case corpus passed under `urbit eval` in 63.5 s. The fake ship passed all 532 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 32.6 s for sync and 38.9 s for tests. The importer golden compares 149 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
42+- 529 golden cases: 313 that parse and 216 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
43+- The 529-case corpus passed under `urbit eval` in 64.5 s. The fake ship passed all 535 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 33.2 s for sync and 37.6 s for tests. The importer golden compares 149 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
4444- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
4545- Two independent audits before 7c739b7, one of which compared the library with a reference parser written in Python from the doc over about 19,000 generated programs. Before ab797a9, a second Python parser, written from the decisions, agreed with the library on 8,000 generated programs and 900 hand-written probes.
4646- Speed: starting `urbit eval` and building the library takes about 8 s. After that, a 2,000-line module of 400 definitions parses in about a second. Loops over definitions, arms, lines and items grow no stack; nesting costs a few stack frames a level, and 100,000 nested brackets still parse (library section 3).
@@ -94,14 +94,15 @@ Besides the plan's list:
9494| 054e651 | 2026-10-30 | Report nested reader diagnostics |
9595| 98c19cd | 2026-10-30 | Infer known-aura string interpolation |
9696| ddba633 | 2026-10-30 | Infer top-level mutually recursive gates |
97−| This change | 2026-10-30 | Infer whole-case union patterns and prelude `turn` |
97+| 9f1517e | 2026-10-30 | Infer whole-case union patterns and prelude `turn` |
98+| This change | 2026-10-31 | Match finite boolean refinements of union cases |
9899
99100## Checking it
100101
101102On a machine set up as [development.md](development.md) says:
102103
103104```
104−tools/golden # 526 cases under urbit eval
105+tools/golden # 529 cases under urbit eval
105106tools/importer-test # the Hoon importer fixture projection
106107tools/type-import-test # the importer/checker bridge fixture
107108tools/type-mark-test # the mark/checker bridge fixture
@@ -111,7 +112,7 @@ tools/testdata/selftest # the tools themselves
111112tools/doc-blocks docs/spec # the doc's examples are golden cases
112113tools/ship start
113114tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
114−tools/ship test # the same 526 cases as -test arms on the ship
115+tools/ship test # the same 529 cases as -test arms on the ship
115116tools/testdata/ship-selftest
116117tools/ship check-commit # |commit stores .jibb files
117118tools/clay-fixtures # example /sur files and marks build through Clay
jibb-dev/lib/jibb.hoon+102−12
@@ -6704,8 +6704,9 @@
67046704 [%| ["a cell in interpolation needs a printer" ~[[(span-of p.i.ps) "cell without a printer"]]]]
67056705 [%| ["interpolation type needs unsupported inference" ~]]
67066706::
6707−:: Whole-case coverage for a known union. A pattern that might cover
6708−:: only part of a case stays unsupported until the general pattern matrix.
6707+:: Whole-case coverage for a known union. When a pattern may cover only
6708+:: part of a case, finite loobean refinements are tried below; other
6709+:: partial coverage stays unsupported until the general pattern matrix.
67096710+$ imatch ?(%full %none %unknown)
67106711++ union-pattern-items
67116712 |= [ps=(list pattern) t=itype]
@@ -6766,7 +6767,87 @@
67666767 ?: ?=(%cell -.p) (union-pattern-bind-items items.p t env globals)
67676768 `env
67686769::
6769−++ infer-known-union-branch
6770+:: Split loobean fields into finite refinements for partial patterns.
6771+:: Keep original cases for binder types and preserve whole-case matching
6772+:: before trying refinements. Cap products at 64; unknown, empty or opaque
6773+:: shapes stay unsupported rather than implying complete pattern checking.
6774++$ ifinite [origin=@ud base=itype part=itype]
6775+++ finite-product
6776+ |= [hs=(list itype) ts=(list itype) out=(list itype)]
6777+ ^- (list itype)
6778+ ?~ hs out
6779+ =/ rows=(list itype) (turn ts |=(t=itype [%cell i.hs t]))
6780+ $(hs t.hs, out (weld rows out))
6781+::
6782+++ finite-type
6783+ |= t=itype
6784+ ^- (unit (list itype))
6785+ ?- -.t
6786+ %flag
6787+ `~[[%const [%loobean %f 0 '%.y']] [%const [%loobean %f 1 '%.n']]]
6788+ %face
6789+ =/ body=(unit (list itype)) $(t body.t)
6790+ ?~ body ~
6791+ `(turn u.body |=(x=itype [%face name.t x]))
6792+ %cell
6793+ =/ hed=(unit (list itype)) $(t hed.t)
6794+ ?~ hed ~
6795+ =/ tal=(unit (list itype)) $(t tal.t)
6796+ ?~ tal ~
6797+ ?: (gth (mul (lent u.hed) (lent u.tal)) 64) ~
6798+ `(finite-product u.hed u.tal ~)
6799+ * `~[t]
6800+ ==
6801+::
6802+++ finite-cases
6803+ |= [xs=(list itype) out=(list ifinite) origin=@ud]
6804+ ^- (unit (list ifinite))
6805+ ?~ xs `out
6806+ =/ parts=(unit (list itype)) (finite-type i.xs)
6807+ ?~ parts ~
6808+ ?: (gth (add (lent out) (lent u.parts)) 64) ~
6809+ =/ rows=(list ifinite) (turn u.parts |=(t=itype [origin i.xs t]))
6810+ $(xs t.xs, out (weld out rows), origin +(origin))
6811+::
6812+++ infer-known-union-whole
6813+ |= [e=expr env=ienv state=istate]
6814+ ^- (unit iresult)
6815+ ?> ?=(%branch -.e)
6816+ =/ subject=iresult (infer-fragment subject.e env state)
6817+ ?: ?=(%| -.subject) `subject
6818+ =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
6819+ ?. ?=(%union -.typ) `[%| ["branch is not supported by partial inference" ~]]
6820+ =/ cases=(list itype) cases.typ
6821+ =/ remaining=(list itype) cases
6822+ =/ arms=(list arm) arms.e
6823+ =/ st=istate state.p.subject
6824+ =/ answer=(unit itype) ~
6825+ |-
6826+ ?~ arms
6827+ ?^ remaining
6828+ `[%| ["missing union case {(show-itype i.remaining sub.st)}" ~]]
6829+ ?~ answer `[%| ["empty union branch is not supported by partial inference" ~]]
6830+ `[%& u.answer st]
6831+ =/ a=arm i.arms
6832+ ?: (lien remaining |=(c=itype =(%unknown (union-pattern pat.a c))))
6833+ ~
6834+ =/ matching=(list itype) (skim remaining |=(c=itype =(%full (union-pattern pat.a c))))
6835+ ?~ matching
6836+ ?: (lien cases |=(c=itype =(%full (union-pattern pat.a c))))
6837+ `[%| ["branch arm is covered by earlier arms" ~[[at.pat.a "covered arm"]]]]
6838+ `[%| ["union pattern is not supported by partial inference" ~]]
6839+ ?: &(?=(^ t.matching) (union-pattern-has-bind pat.a))
6840+ `[%| ["a union pattern binding several cases is not supported by partial inference" ~]]
6841+ =/ bound=(unit ienv) (union-pattern-bind pat.a i.matching env globals.st)
6842+ ?~ bound `[%| ["pattern binder shadows a name" ~]]
6843+ =/ body=iresult (infer-fragment val.a u.bound st)
6844+ ?: ?=(%| -.body) `body
6845+ =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
6846+ =/ mismatch=? ?~(answer | !=((itype-normalize u.answer sub.state.p.body) result))
6847+ ?: mismatch `[%| ["union branch result matching needs unsupported inference" ~]]
6848+ $(arms t.arms, remaining (skim remaining |=(c=itype !=(%full (union-pattern pat.a c)))), st state.p.body, answer `result)
6849+::
6850+++ infer-known-union-finite
67706851 |= [e=expr env=ienv state=istate]
67716852 ^- iresult
67726853 ?> ?=(%branch -.e)
@@ -6774,35 +6855,44 @@
67746855 ?: ?=(%| -.subject) subject
67756856 =/ typ=itype (itype-normalize typ.p.subject sub.state.p.subject)
67766857 ?. ?=(%union -.typ) [%| ["branch is not supported by partial inference" ~]]
6777− =/ cases=(list itype) cases.typ
6778− =/ remaining=(list itype) cases
6858+ =/ expanded=(unit (list ifinite)) (finite-cases cases.typ ~ 0)
6859+ ?~ expanded [%| ["union pattern expansion needs unsupported inference" ~]]
6860+ =/ cases=(list ifinite) u.expanded
6861+ =/ remaining=(list ifinite) cases
67796862 =/ arms=(list arm) arms.e
67806863 =/ st=istate state.p.subject
67816864 =/ answer=(unit itype) ~
67826865 |-
67836866 ?~ arms
67846867 ?^ remaining
6785− [%| ["missing union case {(show-itype i.remaining sub.st)}" ~]]
6868+ [%| ["missing union case {(show-itype part.i.remaining sub.st)}" ~]]
67866869 ?~ answer [%| ["empty union branch is not supported by partial inference" ~]]
67876870 [%& u.answer st]
67886871 =/ a=arm i.arms
6789− ?: (lien remaining |=(c=itype =(%unknown (union-pattern pat.a c))))
6872+ ?: (lien remaining |=(c=ifinite =(%unknown (union-pattern pat.a part.c))))
67906873 [%| ["partial union pattern is not supported by partial inference" ~]]
6791− =/ matching=(list itype) (skim remaining |=(c=itype =(%full (union-pattern pat.a c))))
6874+ =/ matching=(list ifinite) (skim remaining |=(c=ifinite =(%full (union-pattern pat.a part.c))))
67926875 ?~ matching
6793− ?: (lien cases |=(c=itype =(%full (union-pattern pat.a c))))
6876+ ?: (lien cases |=(c=ifinite =(%full (union-pattern pat.a part.c))))
67946877 [%| ["branch arm is covered by earlier arms" ~[[at.pat.a "covered arm"]]]]
67956878 [%| ["union pattern is not supported by partial inference" ~]]
6796− ?: &(?=(^ t.matching) (union-pattern-has-bind pat.a))
6879+ ?: &((union-pattern-has-bind pat.a) (lien t.matching |=(c=ifinite !=(origin.c origin.i.matching))))
67976880 [%| ["a union pattern binding several cases is not supported by partial inference" ~]]
6798− =/ bound=(unit ienv) (union-pattern-bind pat.a i.matching env globals.st)
6881+ =/ bound=(unit ienv) (union-pattern-bind pat.a base.i.matching env globals.st)
67996882 ?~ bound [%| ["pattern binder shadows a name" ~]]
68006883 =/ body=iresult (infer-fragment val.a u.bound st)
68016884 ?: ?=(%| -.body) body
68026885 =/ result=itype (itype-normalize typ.p.body sub.state.p.body)
68036886 =/ mismatch=? ?~(answer | !=((itype-normalize u.answer sub.state.p.body) result))
68046887 ?: mismatch [%| ["union branch result matching needs unsupported inference" ~]]
6805− $(arms t.arms, remaining (skim remaining |=(c=itype !=(%full (union-pattern pat.a c)))), st state.p.body, answer `result)
6888+ $(arms t.arms, remaining (skim remaining |=(c=ifinite !=(%full (union-pattern pat.a part.c)))), st state.p.body, answer `result)
6889+::
6890+++ infer-known-union-branch
6891+ |= [e=expr env=ienv state=istate]
6892+ ^- iresult
6893+ =/ whole=(unit iresult) (infer-known-union-whole e env state)
6894+ ?~ whole (infer-known-union-finite e env state)
6895+ u.whole
68066896::
68076897++ known-union-subject
68086898 |= [e=expr env=ienv state=istate]
tests/golden/types-union-finite-generic/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Patterns: "Every case needs an arm or a catch-all"; Molds: "Type variables are capitals, generalized per `++`."
2+tests: Boolean refinements preserve generic payload and binder types; a shared payload variable infers, while distinct arm result variables, forcing an explicit capital, unresolved tags and partial string matches remain unsupported. An unavailable name in an earlier arm is not masked by pattern checking.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-finite-generic/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-union-finite-generic/source.jibbnew file+48
@@ -0,0 +1,48 @@
1++$ msg |$ [A B]
2+ [%ok bit=? val=A]
3+ [%err bit=? val=B]
4+++ shared |= m=(msg A A)
5+ ?- m
6+ [%ok %.y value] value
7+ [%ok %.n value] value
8+ [%err %.y value] value
9+ [%err %.n value] value
10+++ different |= m=(msg A B)
11+ ?- m
12+ [%ok %.y value] value
13+ [%ok %.n value] value
14+ [%err %.y value] value
15+ [%err %.n value] value
16+++ forced |= m=(msg A B)
17+ ?- m
18+ [%ok %.y value] ^- @t value
19+ [%ok %.n value] ^- @t value
20+ [%err %.y *] "x"
21+ [%err %.n *] "x"
22+++ earlier |= m=(msg @t @t)
23+ ?- m
24+ [%ok %.y *] unknown
25+ [%ok %.n *] "x"
26+ [%err * *] "x"
27+
28++$ choice |$ [A]
29+ [%hit on=? payload=A]
30+ %other
31+++ getter |= input=(choice @t)
32+ ?- input
33+ [%hit %.y payload] payload
34+ [%hit %.n payload] payload
35+ %other "other"
36+++ flag |= input=(choice @t)
37+ ?- input
38+ [%hit on *] on
39+ %other %.n
40+++ atom-parts |= input=(choice @t)
41+ ?- input
42+ [%hit %.y "hello"] "yes"
43+ * "no"
44+++ pending |= input=(choice @t)
45+ ?- input
46+ [%hit %.y *] %unknown
47+ [%hit %.n *] %unknown
48+ %other %unknown
tests/golden/types-union-finite-generic/tokens.txtnew file+336
@@ -0,0 +1,336 @@
1+1:1 glyph +$
2+1:4 name msg
3+1:8 glyph |$
4+1:11 glyph [
5+1:12 tight tvar A
6+1:14 tvar B
7+1:15 tight glyph ]
8+2:3 INDENT
9+2:3 glyph [
10+2:4 tight lit %ok
11+2:8 name bit
12+2:11 tight glyph =
13+2:12 tight glyph ?
14+2:14 name val
15+2:17 tight glyph =
16+2:18 tight tvar A
17+2:19 tight glyph ]
18+3:3 NEWLINE
19+3:3 glyph [
20+3:4 tight lit %err
21+3:9 name bit
22+3:12 tight glyph =
23+3:13 tight glyph ?
24+3:15 name val
25+3:18 tight glyph =
26+3:19 tight tvar B
27+3:20 tight glyph ]
28+4:1 DEDENT
29+4:1 NEWLINE
30+4:1 glyph ++
31+4:4 name shared
32+4:11 glyph |=
33+4:14 name m
34+4:15 tight glyph =
35+4:16 tight glyph (
36+4:17 tight name msg
37+4:21 tvar A
38+4:23 tvar A
39+4:24 tight glyph )
40+5:3 INDENT
41+5:3 glyph ?-
42+5:6 name m
43+6:5 INDENT
44+6:5 glyph [
45+6:6 tight lit %ok
46+6:10 lit %.y
47+6:14 name value
48+6:19 tight glyph ]
49+6:21 name value
50+7:5 NEWLINE
51+7:5 glyph [
52+7:6 tight lit %ok
53+7:10 lit %.n
54+7:14 name value
55+7:19 tight glyph ]
56+7:21 name value
57+8:5 NEWLINE
58+8:5 glyph [
59+8:6 tight lit %err
60+8:11 lit %.y
61+8:15 name value
62+8:20 tight glyph ]
63+8:22 name value
64+9:5 NEWLINE
65+9:5 glyph [
66+9:6 tight lit %err
67+9:11 lit %.n
68+9:15 name value
69+9:20 tight glyph ]
70+9:22 name value
71+10:1 DEDENT
72+10:1 DEDENT
73+10:1 NEWLINE
74+10:1 glyph ++
75+10:4 name different
76+10:14 glyph |=
77+10:17 name m
78+10:18 tight glyph =
79+10:19 tight glyph (
80+10:20 tight name msg
81+10:24 tvar A
82+10:26 tvar B
83+10:27 tight glyph )
84+11:3 INDENT
85+11:3 glyph ?-
86+11:6 name m
87+12:5 INDENT
88+12:5 glyph [
89+12:6 tight lit %ok
90+12:10 lit %.y
91+12:14 name value
92+12:19 tight glyph ]
93+12:21 name value
94+13:5 NEWLINE
95+13:5 glyph [
96+13:6 tight lit %ok
97+13:10 lit %.n
98+13:14 name value
99+13:19 tight glyph ]
100+13:21 name value
101+14:5 NEWLINE
102+14:5 glyph [
103+14:6 tight lit %err
104+14:11 lit %.y
105+14:15 name value
106+14:20 tight glyph ]
107+14:22 name value
108+15:5 NEWLINE
109+15:5 glyph [
110+15:6 tight lit %err
111+15:11 lit %.n
112+15:15 name value
113+15:20 tight glyph ]
114+15:22 name value
115+16:1 DEDENT
116+16:1 DEDENT
117+16:1 NEWLINE
118+16:1 glyph ++
119+16:4 name forced
120+16:11 glyph |=
121+16:14 name m
122+16:15 tight glyph =
123+16:16 tight glyph (
124+16:17 tight name msg
125+16:21 tvar A
126+16:23 tvar B
127+16:24 tight glyph )
128+17:3 INDENT
129+17:3 glyph ?-
130+17:6 name m
131+18:5 INDENT
132+18:5 glyph [
133+18:6 tight lit %ok
134+18:10 lit %.y
135+18:14 name value
136+18:19 tight glyph ]
137+18:21 glyph ^-
138+18:24 aura @t
139+18:27 name value
140+19:5 NEWLINE
141+19:5 glyph [
142+19:6 tight lit %ok
143+19:10 lit %.n
144+19:14 name value
145+19:19 tight glyph ]
146+19:21 glyph ^-
147+19:24 aura @t
148+19:27 name value
149+20:5 NEWLINE
150+20:5 glyph [
151+20:6 tight lit %err
152+20:11 lit %.y
153+20:15 glyph *
154+20:16 tight glyph ]
155+20:18 str "x"
156+21:5 NEWLINE
157+21:5 glyph [
158+21:6 tight lit %err
159+21:11 lit %.n
160+21:15 glyph *
161+21:16 tight glyph ]
162+21:18 str "x"
163+22:1 DEDENT
164+22:1 DEDENT
165+22:1 NEWLINE
166+22:1 glyph ++
167+22:4 name earlier
168+22:12 glyph |=
169+22:15 name m
170+22:16 tight glyph =
171+22:17 tight glyph (
172+22:18 tight name msg
173+22:22 aura @t
174+22:25 aura @t
175+22:27 tight glyph )
176+23:3 INDENT
177+23:3 glyph ?-
178+23:6 name m
179+24:5 INDENT
180+24:5 glyph [
181+24:6 tight lit %ok
182+24:10 lit %.y
183+24:14 glyph *
184+24:15 tight glyph ]
185+24:17 name unknown
186+25:5 NEWLINE
187+25:5 glyph [
188+25:6 tight lit %ok
189+25:10 lit %.n
190+25:14 glyph *
191+25:15 tight glyph ]
192+25:17 str "x"
193+26:5 NEWLINE
194+26:5 glyph [
195+26:6 tight lit %err
196+26:11 glyph *
197+26:13 glyph *
198+26:14 tight glyph ]
199+26:16 str "x"
200+28:1 DEDENT
201+28:1 DEDENT
202+28:1 NEWLINE
203+28:1 glyph +$
204+28:4 name choice
205+28:11 glyph |$
206+28:14 glyph [
207+28:15 tight tvar A
208+28:16 tight glyph ]
209+29:3 INDENT
210+29:3 glyph [
211+29:4 tight lit %hit
212+29:9 name on
213+29:11 tight glyph =
214+29:12 tight glyph ?
215+29:14 name payload
216+29:21 tight glyph =
217+29:22 tight tvar A
218+29:23 tight glyph ]
219+30:3 NEWLINE
220+30:3 lit %other
221+31:1 DEDENT
222+31:1 NEWLINE
223+31:1 glyph ++
224+31:4 name getter
225+31:11 glyph |=
226+31:14 name input
227+31:19 tight glyph =
228+31:20 tight glyph (
229+31:21 tight name choice
230+31:28 aura @t
231+31:30 tight glyph )
232+32:3 INDENT
233+32:3 glyph ?-
234+32:6 name input
235+33:5 INDENT
236+33:5 glyph [
237+33:6 tight lit %hit
238+33:11 lit %.y
239+33:15 name payload
240+33:22 tight glyph ]
241+33:24 name payload
242+34:5 NEWLINE
243+34:5 glyph [
244+34:6 tight lit %hit
245+34:11 lit %.n
246+34:15 name payload
247+34:22 tight glyph ]
248+34:24 name payload
249+35:5 NEWLINE
250+35:5 lit %other
251+35:12 str "other"
252+36:1 DEDENT
253+36:1 DEDENT
254+36:1 NEWLINE
255+36:1 glyph ++
256+36:4 name flag
257+36:9 glyph |=
258+36:12 name input
259+36:17 tight glyph =
260+36:18 tight glyph (
261+36:19 tight name choice
262+36:26 aura @t
263+36:28 tight glyph )
264+37:3 INDENT
265+37:3 glyph ?-
266+37:6 name input
267+38:5 INDENT
268+38:5 glyph [
269+38:6 tight lit %hit
270+38:11 name on
271+38:14 glyph *
272+38:15 tight glyph ]
273+38:17 name on
274+39:5 NEWLINE
275+39:5 lit %other
276+39:12 lit %.n
277+40:1 DEDENT
278+40:1 DEDENT
279+40:1 NEWLINE
280+40:1 glyph ++
281+40:4 name atom-parts
282+40:15 glyph |=
283+40:18 name input
284+40:23 tight glyph =
285+40:24 tight glyph (
286+40:25 tight name choice
287+40:32 aura @t
288+40:34 tight glyph )
289+41:3 INDENT
290+41:3 glyph ?-
291+41:6 name input
292+42:5 INDENT
293+42:5 glyph [
294+42:6 tight lit %hit
295+42:11 lit %.y
296+42:15 str "hello"
297+42:22 tight glyph ]
298+42:24 str "yes"
299+43:5 NEWLINE
300+43:5 glyph *
301+43:7 str "no"
302+44:1 DEDENT
303+44:1 DEDENT
304+44:1 NEWLINE
305+44:1 glyph ++
306+44:4 name pending
307+44:12 glyph |=
308+44:15 name input
309+44:20 tight glyph =
310+44:21 tight glyph (
311+44:22 tight name choice
312+44:29 aura @t
313+44:31 tight glyph )
314+45:3 INDENT
315+45:3 glyph ?-
316+45:6 name input
317+46:5 INDENT
318+46:5 glyph [
319+46:6 tight lit %hit
320+46:11 lit %.y
321+46:15 glyph *
322+46:16 tight glyph ]
323+46:18 lit %unknown
324+47:5 NEWLINE
325+47:5 glyph [
326+47:6 tight lit %hit
327+47:11 lit %.n
328+47:15 glyph *
329+47:16 tight glyph ]
330+47:18 lit %unknown
331+48:5 NEWLINE
332+48:5 lit %other
333+48:12 lit %unknown
334+48:20 DEDENT
335+48:20 DEDENT
336+48:20 NEWLINE
tests/golden/types-union-finite-generic/tree.txtnew file+143
@@ -0,0 +1,143 @@
1+(module
2+ (mold 1:1 msg
3+ (generic 1:8 A B
4+ (union 2:3
5+ (cell 2:3
6+ (const 2:4 %ok)
7+ (face 2:8 bit (flag 2:12))
8+ (face 2:14 val (tvar 2:18 A)))
9+ (cell 3:3
10+ (const 3:4 %err)
11+ (face 3:9 bit (flag 3:13))
12+ (face 3:15 val (tvar 3:19 B))))))
13+ (value 4:1 shared
14+ (gate 4:11
15+ (face 4:14 m
16+ (apply 4:16 msg (tvar 4:21 A) (tvar 4:23 A)))
17+ (body 5:3
18+ (branch 5:3
19+ (wing 5:6 m)
20+ (arm 6:5
21+ (cell 6:5 (lit 6:6 %ok) (lit 6:10 %.y) (bind 6:14 value))
22+ (wing 6:21 value))
23+ (arm 7:5
24+ (cell 7:5 (lit 7:6 %ok) (lit 7:10 %.n) (bind 7:14 value))
25+ (wing 7:21 value))
26+ (arm 8:5
27+ (cell 8:5 (lit 8:6 %err) (lit 8:11 %.y) (bind 8:15 value))
28+ (wing 8:22 value))
29+ (arm 9:5
30+ (cell 9:5 (lit 9:6 %err) (lit 9:11 %.n) (bind 9:15 value))
31+ (wing 9:22 value))))))
32+ (value 10:1 different
33+ (gate 10:14
34+ (face 10:17 m
35+ (apply 10:19 msg (tvar 10:24 A) (tvar 10:26 B)))
36+ (body 11:3
37+ (branch 11:3
38+ (wing 11:6 m)
39+ (arm 12:5
40+ (cell 12:5 (lit 12:6 %ok) (lit 12:10 %.y) (bind 12:14 value))
41+ (wing 12:21 value))
42+ (arm 13:5
43+ (cell 13:5 (lit 13:6 %ok) (lit 13:10 %.n) (bind 13:14 value))
44+ (wing 13:21 value))
45+ (arm 14:5
46+ (cell 14:5 (lit 14:6 %err) (lit 14:11 %.y) (bind 14:15 value))
47+ (wing 14:22 value))
48+ (arm 15:5
49+ (cell 15:5 (lit 15:6 %err) (lit 15:11 %.n) (bind 15:15 value))
50+ (wing 15:22 value))))))
51+ (value 16:1 forced
52+ (gate 16:11
53+ (face 16:14 m
54+ (apply 16:16 msg (tvar 16:21 A) (tvar 16:23 B)))
55+ (body 17:3
56+ (branch 17:3
57+ (wing 17:6 m)
58+ (arm 18:5
59+ (cell 18:5 (lit 18:6 %ok) (lit 18:10 %.y) (bind 18:14 value))
60+ (cast 18:21 (aura 18:24 @t) (wing 18:27 value)))
61+ (arm 19:5
62+ (cell 19:5 (lit 19:6 %ok) (lit 19:10 %.n) (bind 19:14 value))
63+ (cast 19:21 (aura 19:24 @t) (wing 19:27 value)))
64+ (arm 20:5
65+ (cell 20:5 (lit 20:6 %err) (lit 20:11 %.y) (any 20:15))
66+ (str 20:18 "x"))
67+ (arm 21:5
68+ (cell 21:5 (lit 21:6 %err) (lit 21:11 %.n) (any 21:15))
69+ (str 21:18 "x"))))))
70+ (value 22:1 earlier
71+ (gate 22:12
72+ (face 22:15 m
73+ (apply 22:17 msg (aura 22:22 @t) (aura 22:25 @t)))
74+ (body 23:3
75+ (branch 23:3
76+ (wing 23:6 m)
77+ (arm 24:5
78+ (cell 24:5 (lit 24:6 %ok) (lit 24:10 %.y) (any 24:14))
79+ (wing 24:17 unknown))
80+ (arm 25:5
81+ (cell 25:5 (lit 25:6 %ok) (lit 25:10 %.n) (any 25:14))
82+ (str 25:17 "x"))
83+ (arm 26:5
84+ (cell 26:5 (lit 26:6 %err) (any 26:11) (any 26:13))
85+ (str 26:16 "x"))))))
86+ (mold 28:1 choice
87+ (generic 28:11 A
88+ (union 29:3
89+ (cell 29:3
90+ (const 29:4 %hit)
91+ (face 29:9 on (flag 29:12))
92+ (face 29:14 payload (tvar 29:22 A)))
93+ (const 30:3 %other))))
94+ (value 31:1 getter
95+ (gate 31:11
96+ (face 31:14 input
97+ (apply 31:20 choice (aura 31:28 @t)))
98+ (body 32:3
99+ (branch 32:3
100+ (wing 32:6 input)
101+ (arm 33:5
102+ (cell 33:5 (lit 33:6 %hit) (lit 33:11 %.y) (bind 33:15 payload))
103+ (wing 33:24 payload))
104+ (arm 34:5
105+ (cell 34:5 (lit 34:6 %hit) (lit 34:11 %.n) (bind 34:15 payload))
106+ (wing 34:24 payload))
107+ (arm 35:5 (lit 35:5 %other) (str 35:12 "other"))))))
108+ (value 36:1 flag
109+ (gate 36:9
110+ (face 36:12 input
111+ (apply 36:18 choice (aura 36:26 @t)))
112+ (body 37:3
113+ (branch 37:3
114+ (wing 37:6 input)
115+ (arm 38:5
116+ (cell 38:5 (lit 38:6 %hit) (bind 38:11 on) (any 38:14))
117+ (wing 38:17 on))
118+ (arm 39:5 (lit 39:5 %other) (lit 39:12 %.n))))))
119+ (value 40:1 atom-parts
120+ (gate 40:15
121+ (face 40:18 input
122+ (apply 40:24 choice (aura 40:32 @t)))
123+ (body 41:3
124+ (branch 41:3
125+ (wing 41:6 input)
126+ (arm 42:5
127+ (cell 42:5 (lit 42:6 %hit) (lit 42:11 %.y) (str 42:15 "hello"))
128+ (str 42:24 "yes"))
129+ (arm 43:5 (any 43:5) (str 43:7 "no"))))))
130+ (value 44:1 pending
131+ (gate 44:12
132+ (face 44:15 input
133+ (apply 44:21 choice (aura 44:29 @t)))
134+ (body 45:3
135+ (branch 45:3
136+ (wing 45:6 input)
137+ (arm 46:5
138+ (cell 46:5 (lit 46:6 %hit) (lit 46:11 %.y) (any 46:15))
139+ (lit 46:18 %unknown))
140+ (arm 47:5
141+ (cell 47:5 (lit 47:6 %hit) (lit 47:11 %.n) (any 47:15))
142+ (lit 47:18 %unknown))
143+ (arm 48:5 (lit 48:5 %other) (lit 48:12 %unknown)))))))
tests/golden/types-union-finite-generic/types.txtnew file+11
@@ -0,0 +1,11 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ shared: $-((msg A A) A)
4+++ different: union branch result matching needs unsupported inference
5+++ forced: explicit capital constraints are not supported by partial inference
6+++ earlier: name is not available to partial inference
7++$ choice: cases proven disjoint; mold not checked
8+++ getter: $-((choice @t) @t)
9+++ flag: $-((choice @t) ?)
10+++ atom-parts: partial union pattern is not supported by partial inference
11+++ pending: union branch result matching needs unsupported inference
tests/golden/types-union-finite-limit/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Patterns: "Every case needs an arm or a catch-all"; Molds: the empty mold `!!` has no values.
2+tests: Whole-case matching remains available without expanding many booleans. Partial matching succeeds below the implementation's 64-alternative limit and fails closed above it; empty union cases remain unsupported rather than falsely checked.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-finite-limit/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-union-finite-limit/source.jibbnew file+35
@@ -0,0 +1,35 @@
1++$ msg
2+ [%go a=? b=? c=? d=? e=? f=? g=?]
3+ %other
4+++ whole |= input=msg
5+ ?- input
6+ [%go * * * * * * *] "ok"
7+ %other "other"
8+++ partial |= input=msg
9+ ?- input
10+ [%go %.y * * * * * *] "ok"
11+ * "other"
12+
13++$ under
14+ [%item a=? b=? c=? d=? e=?]
15+ %other
16+++ allowed |= m=under
17+ ?- m
18+ [%item %.y * * * *] "a"
19+ [%item %.n * * * *] "b"
20+ %other "c"
21++$ over
22+ [%item a=? b=? c=? d=? e=? f=?]
23+ %other
24+++ capped |= m=over
25+ ?- m
26+ [%item %.y * * * * *] "a"
27+ [%item %.n * * * * *] "b"
28+ %other "c"
29+
30++$ empty-msg
31+ !!
32+ %a
33+++ one |= m=empty-msg
34+ ?- m
35+ %a "yes"
tests/golden/types-union-finite-limit/tokens.txtnew file+233
@@ -0,0 +1,233 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %go
6+2:8 name a
7+2:9 tight glyph =
8+2:10 tight glyph ?
9+2:12 name b
10+2:13 tight glyph =
11+2:14 tight glyph ?
12+2:16 name c
13+2:17 tight glyph =
14+2:18 tight glyph ?
15+2:20 name d
16+2:21 tight glyph =
17+2:22 tight glyph ?
18+2:24 name e
19+2:25 tight glyph =
20+2:26 tight glyph ?
21+2:28 name f
22+2:29 tight glyph =
23+2:30 tight glyph ?
24+2:32 name g
25+2:33 tight glyph =
26+2:34 tight glyph ?
27+2:35 tight glyph ]
28+3:3 NEWLINE
29+3:3 lit %other
30+4:1 DEDENT
31+4:1 NEWLINE
32+4:1 glyph ++
33+4:4 name whole
34+4:10 glyph |=
35+4:13 name input
36+4:18 tight glyph =
37+4:19 tight name msg
38+5:3 INDENT
39+5:3 glyph ?-
40+5:6 name input
41+6:5 INDENT
42+6:5 glyph [
43+6:6 tight lit %go
44+6:10 glyph *
45+6:12 glyph *
46+6:14 glyph *
47+6:16 glyph *
48+6:18 glyph *
49+6:20 glyph *
50+6:22 glyph *
51+6:23 tight glyph ]
52+6:25 str "ok"
53+7:5 NEWLINE
54+7:5 lit %other
55+7:12 str "other"
56+8:1 DEDENT
57+8:1 DEDENT
58+8:1 NEWLINE
59+8:1 glyph ++
60+8:4 name partial
61+8:12 glyph |=
62+8:15 name input
63+8:20 tight glyph =
64+8:21 tight name msg
65+9:3 INDENT
66+9:3 glyph ?-
67+9:6 name input
68+10:5 INDENT
69+10:5 glyph [
70+10:6 tight lit %go
71+10:10 lit %.y
72+10:14 glyph *
73+10:16 glyph *
74+10:18 glyph *
75+10:20 glyph *
76+10:22 glyph *
77+10:24 glyph *
78+10:25 tight glyph ]
79+10:27 str "ok"
80+11:5 NEWLINE
81+11:5 glyph *
82+11:7 str "other"
83+13:1 DEDENT
84+13:1 DEDENT
85+13:1 NEWLINE
86+13:1 glyph +$
87+13:4 name under
88+14:3 INDENT
89+14:3 glyph [
90+14:4 tight lit %item
91+14:10 name a
92+14:11 tight glyph =
93+14:12 tight glyph ?
94+14:14 name b
95+14:15 tight glyph =
96+14:16 tight glyph ?
97+14:18 name c
98+14:19 tight glyph =
99+14:20 tight glyph ?
100+14:22 name d
101+14:23 tight glyph =
102+14:24 tight glyph ?
103+14:26 name e
104+14:27 tight glyph =
105+14:28 tight glyph ?
106+14:29 tight glyph ]
107+15:3 NEWLINE
108+15:3 lit %other
109+16:1 DEDENT
110+16:1 NEWLINE
111+16:1 glyph ++
112+16:4 name allowed
113+16:12 glyph |=
114+16:15 name m
115+16:16 tight glyph =
116+16:17 tight name under
117+17:3 INDENT
118+17:3 glyph ?-
119+17:6 name m
120+18:5 INDENT
121+18:5 glyph [
122+18:6 tight lit %item
123+18:12 lit %.y
124+18:16 glyph *
125+18:18 glyph *
126+18:20 glyph *
127+18:22 glyph *
128+18:23 tight glyph ]
129+18:25 str "a"
130+19:5 NEWLINE
131+19:5 glyph [
132+19:6 tight lit %item
133+19:12 lit %.n
134+19:16 glyph *
135+19:18 glyph *
136+19:20 glyph *
137+19:22 glyph *
138+19:23 tight glyph ]
139+19:25 str "b"
140+20:5 NEWLINE
141+20:5 lit %other
142+20:12 str "c"
143+21:1 DEDENT
144+21:1 DEDENT
145+21:1 NEWLINE
146+21:1 glyph +$
147+21:4 name over
148+22:3 INDENT
149+22:3 glyph [
150+22:4 tight lit %item
151+22:10 name a
152+22:11 tight glyph =
153+22:12 tight glyph ?
154+22:14 name b
155+22:15 tight glyph =
156+22:16 tight glyph ?
157+22:18 name c
158+22:19 tight glyph =
159+22:20 tight glyph ?
160+22:22 name d
161+22:23 tight glyph =
162+22:24 tight glyph ?
163+22:26 name e
164+22:27 tight glyph =
165+22:28 tight glyph ?
166+22:30 name f
167+22:31 tight glyph =
168+22:32 tight glyph ?
169+22:33 tight glyph ]
170+23:3 NEWLINE
171+23:3 lit %other
172+24:1 DEDENT
173+24:1 NEWLINE
174+24:1 glyph ++
175+24:4 name capped
176+24:11 glyph |=
177+24:14 name m
178+24:15 tight glyph =
179+24:16 tight name over
180+25:3 INDENT
181+25:3 glyph ?-
182+25:6 name m
183+26:5 INDENT
184+26:5 glyph [
185+26:6 tight lit %item
186+26:12 lit %.y
187+26:16 glyph *
188+26:18 glyph *
189+26:20 glyph *
190+26:22 glyph *
191+26:24 glyph *
192+26:25 tight glyph ]
193+26:27 str "a"
194+27:5 NEWLINE
195+27:5 glyph [
196+27:6 tight lit %item
197+27:12 lit %.n
198+27:16 glyph *
199+27:18 glyph *
200+27:20 glyph *
201+27:22 glyph *
202+27:24 glyph *
203+27:25 tight glyph ]
204+27:27 str "b"
205+28:5 NEWLINE
206+28:5 lit %other
207+28:12 str "c"
208+30:1 DEDENT
209+30:1 DEDENT
210+30:1 NEWLINE
211+30:1 glyph +$
212+30:4 name empty-msg
213+31:3 INDENT
214+31:3 glyph !!
215+32:3 NEWLINE
216+32:3 lit %a
217+33:1 DEDENT
218+33:1 NEWLINE
219+33:1 glyph ++
220+33:4 name one
221+33:8 glyph |=
222+33:11 name m
223+33:12 tight glyph =
224+33:13 tight name empty-msg
225+34:3 INDENT
226+34:3 glyph ?-
227+34:6 name m
228+35:5 INDENT
229+35:5 lit %a
230+35:8 str "yes"
231+35:13 DEDENT
232+35:13 DEDENT
233+35:13 NEWLINE
tests/golden/types-union-finite-limit/tree.txtnew file+89
@@ -0,0 +1,89 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %go)
6+ (face 2:8 a (flag 2:10))
7+ (face 2:12 b (flag 2:14))
8+ (face 2:16 c (flag 2:18))
9+ (face 2:20 d (flag 2:22))
10+ (face 2:24 e (flag 2:26))
11+ (face 2:28 f (flag 2:30))
12+ (face 2:32 g (flag 2:34)))
13+ (const 3:3 %other)))
14+ (value 4:1 whole
15+ (gate 4:10
16+ (face 4:13 input (ref 4:19 msg))
17+ (body 5:3
18+ (branch 5:3
19+ (wing 5:6 input)
20+ (arm 6:5
21+ (cell 6:5 (lit 6:6 %go) (any 6:10) (any 6:12) (any 6:14) (any 6:16) (any 6:18) (any 6:20) (any 6:22))
22+ (str 6:25 "ok"))
23+ (arm 7:5 (lit 7:5 %other) (str 7:12 "other"))))))
24+ (value 8:1 partial
25+ (gate 8:12
26+ (face 8:15 input (ref 8:21 msg))
27+ (body 9:3
28+ (branch 9:3
29+ (wing 9:6 input)
30+ (arm 10:5
31+ (cell 10:5 (lit 10:6 %go) (lit 10:10 %.y) (any 10:14) (any 10:16) (any 10:18) (any 10:20) (any 10:22) (any 10:24))
32+ (str 10:27 "ok"))
33+ (arm 11:5 (any 11:5) (str 11:7 "other"))))))
34+ (mold 13:1 under
35+ (union 14:3
36+ (cell 14:3
37+ (const 14:4 %item)
38+ (face 14:10 a (flag 14:12))
39+ (face 14:14 b (flag 14:16))
40+ (face 14:18 c (flag 14:20))
41+ (face 14:22 d (flag 14:24))
42+ (face 14:26 e (flag 14:28)))
43+ (const 15:3 %other)))
44+ (value 16:1 allowed
45+ (gate 16:12
46+ (face 16:15 m (ref 16:17 under))
47+ (body 17:3
48+ (branch 17:3
49+ (wing 17:6 m)
50+ (arm 18:5
51+ (cell 18:5 (lit 18:6 %item) (lit 18:12 %.y) (any 18:16) (any 18:18) (any 18:20) (any 18:22))
52+ (str 18:25 "a"))
53+ (arm 19:5
54+ (cell 19:5 (lit 19:6 %item) (lit 19:12 %.n) (any 19:16) (any 19:18) (any 19:20) (any 19:22))
55+ (str 19:25 "b"))
56+ (arm 20:5 (lit 20:5 %other) (str 20:12 "c"))))))
57+ (mold 21:1 over
58+ (union 22:3
59+ (cell 22:3
60+ (const 22:4 %item)
61+ (face 22:10 a (flag 22:12))
62+ (face 22:14 b (flag 22:16))
63+ (face 22:18 c (flag 22:20))
64+ (face 22:22 d (flag 22:24))
65+ (face 22:26 e (flag 22:28))
66+ (face 22:30 f (flag 22:32)))
67+ (const 23:3 %other)))
68+ (value 24:1 capped
69+ (gate 24:11
70+ (face 24:14 m (ref 24:16 over))
71+ (body 25:3
72+ (branch 25:3
73+ (wing 25:6 m)
74+ (arm 26:5
75+ (cell 26:5 (lit 26:6 %item) (lit 26:12 %.y) (any 26:16) (any 26:18) (any 26:20) (any 26:22) (any 26:24))
76+ (str 26:27 "a"))
77+ (arm 27:5
78+ (cell 27:5 (lit 27:6 %item) (lit 27:12 %.n) (any 27:16) (any 27:18) (any 27:20) (any 27:22) (any 27:24))
79+ (str 27:27 "b"))
80+ (arm 28:5 (lit 28:5 %other) (str 28:12 "c"))))))
81+ (mold 30:1 empty-msg
82+ (union 31:3 (void 31:3) (const 32:3 %a)))
83+ (value 33:1 one
84+ (gate 33:8
85+ (face 33:11 m (ref 33:13 empty-msg))
86+ (body 34:3
87+ (branch 34:3
88+ (wing 34:6 m)
89+ (arm 35:5 (lit 35:5 %a) (str 35:8 "yes")))))))
tests/golden/types-union-finite-limit/types.txtnew file+10
@@ -0,0 +1,10 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ whole: $-(msg @t)
4+++ partial: union pattern expansion needs unsupported inference
5++$ under: cases proven disjoint; mold not checked
6+++ allowed: $-(under @t)
7++$ over: cases proven disjoint; mold not checked
8+++ capped: union pattern expansion needs unsupported inference
9++$ empty-msg: cases proven disjoint; mold not checked
10+++ one: sample mold is not supported by partial inference
tests/golden/types-union-finite/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Patterns: "Every case needs an arm or a catch-all"; "An arm that earlier arms cover ... is an error"; "A name in a pattern always binds anew".
2+tests: Two boolean fields are split into finite alternatives for complete tables and wildcard patterns. A missing alternative is named, a covered partial arm is rejected even when it uses a different spelling of zero, and a whole-case binder retains its original `?` type. Shadowing and a binder spanning different union cases fail closed.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-finite/modules.txtnew file+1
@@ -0,0 +1 @@
1+# no module fixtures
tests/golden/types-union-finite/source.jibbnew file+45
@@ -0,0 +1,45 @@
1++$ msg
2+ [%p left=? right=?]
3+ %other
4+++ boolean-table |= m=msg
5+ ?- m
6+ [%p %.y %.y] "a"
7+ [%p %.y %.n] "b"
8+ [%p %.n %.y] "c"
9+ [%p %.n %.n] "d"
10+ %other "e"
11+++ wildcard |= m=msg
12+ ?- m
13+ [%p %.y *] "a"
14+ [%p %.n *] "b"
15+ %other "e"
16+++ covered |= m=msg
17+ ?- m
18+ [%p %.y *] "a"
19+ [%p %.y %.n] "b"
20+ * "e"
21+
22++$ choice
23+ [%a on=?]
24+ %other
25+++ missing |= x=choice
26+ ?- x
27+ [%a %.y] "yes"
28+ %other "other"
29+++ typed |= x=choice
30+ ?- x
31+ [%a value] value
32+ %other %.n
33+++ duplicate |= x=choice
34+ ?- x
35+ [%a %.y] "yes"
36+ [%a %$] "duplicate"
37+ * "other"
38+++ shadow |= x=choice
39+ ?- x
40+ [%a missing] "yes"
41+ %other "other"
42+++ many-bind |= x=choice
43+ ?- x
44+ value "anything"
45+ %other "dead"
tests/golden/types-union-finite/tokens.txtnew file+238
@@ -0,0 +1,238 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %p
6+2:7 name left
7+2:11 tight glyph =
8+2:12 tight glyph ?
9+2:14 name right
10+2:19 tight glyph =
11+2:20 tight glyph ?
12+2:21 tight glyph ]
13+3:3 NEWLINE
14+3:3 lit %other
15+4:1 DEDENT
16+4:1 NEWLINE
17+4:1 glyph ++
18+4:4 name boolean-table
19+4:18 glyph |=
20+4:21 name m
21+4:22 tight glyph =
22+4:23 tight name msg
23+5:3 INDENT
24+5:3 glyph ?-
25+5:6 name m
26+6:5 INDENT
27+6:5 glyph [
28+6:6 tight lit %p
29+6:9 lit %.y
30+6:13 lit %.y
31+6:16 tight glyph ]
32+6:18 str "a"
33+7:5 NEWLINE
34+7:5 glyph [
35+7:6 tight lit %p
36+7:9 lit %.y
37+7:13 lit %.n
38+7:16 tight glyph ]
39+7:18 str "b"
40+8:5 NEWLINE
41+8:5 glyph [
42+8:6 tight lit %p
43+8:9 lit %.n
44+8:13 lit %.y
45+8:16 tight glyph ]
46+8:18 str "c"
47+9:5 NEWLINE
48+9:5 glyph [
49+9:6 tight lit %p
50+9:9 lit %.n
51+9:13 lit %.n
52+9:16 tight glyph ]
53+9:18 str "d"
54+10:5 NEWLINE
55+10:5 lit %other
56+10:12 str "e"
57+11:1 DEDENT
58+11:1 DEDENT
59+11:1 NEWLINE
60+11:1 glyph ++
61+11:4 name wildcard
62+11:13 glyph |=
63+11:16 name m
64+11:17 tight glyph =
65+11:18 tight name msg
66+12:3 INDENT
67+12:3 glyph ?-
68+12:6 name m
69+13:5 INDENT
70+13:5 glyph [
71+13:6 tight lit %p
72+13:9 lit %.y
73+13:13 glyph *
74+13:14 tight glyph ]
75+13:16 str "a"
76+14:5 NEWLINE
77+14:5 glyph [
78+14:6 tight lit %p
79+14:9 lit %.n
80+14:13 glyph *
81+14:14 tight glyph ]
82+14:16 str "b"
83+15:5 NEWLINE
84+15:5 lit %other
85+15:12 str "e"
86+16:1 DEDENT
87+16:1 DEDENT
88+16:1 NEWLINE
89+16:1 glyph ++
90+16:4 name covered
91+16:12 glyph |=
92+16:15 name m
93+16:16 tight glyph =
94+16:17 tight name msg
95+17:3 INDENT
96+17:3 glyph ?-
97+17:6 name m
98+18:5 INDENT
99+18:5 glyph [
100+18:6 tight lit %p
101+18:9 lit %.y
102+18:13 glyph *
103+18:14 tight glyph ]
104+18:16 str "a"
105+19:5 NEWLINE
106+19:5 glyph [
107+19:6 tight lit %p
108+19:9 lit %.y
109+19:13 lit %.n
110+19:16 tight glyph ]
111+19:18 str "b"
112+20:5 NEWLINE
113+20:5 glyph *
114+20:7 str "e"
115+22:1 DEDENT
116+22:1 DEDENT
117+22:1 NEWLINE
118+22:1 glyph +$
119+22:4 name choice
120+23:3 INDENT
121+23:3 glyph [
122+23:4 tight lit %a
123+23:7 name on
124+23:9 tight glyph =
125+23:10 tight glyph ?
126+23:11 tight glyph ]
127+24:3 NEWLINE
128+24:3 lit %other
129+25:1 DEDENT
130+25:1 NEWLINE
131+25:1 glyph ++
132+25:4 name missing
133+25:12 glyph |=
134+25:15 name x
135+25:16 tight glyph =
136+25:17 tight name choice
137+26:3 INDENT
138+26:3 glyph ?-
139+26:6 name x
140+27:5 INDENT
141+27:5 glyph [
142+27:6 tight lit %a
143+27:9 lit %.y
144+27:12 tight glyph ]
145+27:14 str "yes"
146+28:5 NEWLINE
147+28:5 lit %other
148+28:12 str "other"
149+29:1 DEDENT
150+29:1 DEDENT
151+29:1 NEWLINE
152+29:1 glyph ++
153+29:4 name typed
154+29:10 glyph |=
155+29:13 name x
156+29:14 tight glyph =
157+29:15 tight name choice
158+30:3 INDENT
159+30:3 glyph ?-
160+30:6 name x
161+31:5 INDENT
162+31:5 glyph [
163+31:6 tight lit %a
164+31:9 name value
165+31:14 tight glyph ]
166+31:16 name value
167+32:5 NEWLINE
168+32:5 lit %other
169+32:12 lit %.n
170+33:1 DEDENT
171+33:1 DEDENT
172+33:1 NEWLINE
173+33:1 glyph ++
174+33:4 name duplicate
175+33:14 glyph |=
176+33:17 name x
177+33:18 tight glyph =
178+33:19 tight name choice
179+34:3 INDENT
180+34:3 glyph ?-
181+34:6 name x
182+35:5 INDENT
183+35:5 glyph [
184+35:6 tight lit %a
185+35:9 lit %.y
186+35:12 tight glyph ]
187+35:14 str "yes"
188+36:5 NEWLINE
189+36:5 glyph [
190+36:6 tight lit %a
191+36:9 lit %$
192+36:11 tight glyph ]
193+36:13 str "duplicate"
194+37:5 NEWLINE
195+37:5 glyph *
196+37:7 str "other"
197+38:1 DEDENT
198+38:1 DEDENT
199+38:1 NEWLINE
200+38:1 glyph ++
201+38:4 name shadow
202+38:11 glyph |=
203+38:14 name x
204+38:15 tight glyph =
205+38:16 tight name choice
206+39:3 INDENT
207+39:3 glyph ?-
208+39:6 name x
209+40:5 INDENT
210+40:5 glyph [
211+40:6 tight lit %a
212+40:9 name missing
213+40:16 tight glyph ]
214+40:18 str "yes"
215+41:5 NEWLINE
216+41:5 lit %other
217+41:12 str "other"
218+42:1 DEDENT
219+42:1 DEDENT
220+42:1 NEWLINE
221+42:1 glyph ++
222+42:4 name many-bind
223+42:14 glyph |=
224+42:17 name x
225+42:18 tight glyph =
226+42:19 tight name choice
227+43:3 INDENT
228+43:3 glyph ?-
229+43:6 name x
230+44:5 INDENT
231+44:5 name value
232+44:11 str "anything"
233+45:5 NEWLINE
234+45:5 lit %other
235+45:12 str "dead"
236+45:18 DEDENT
237+45:18 DEDENT
238+45:18 NEWLINE
tests/golden/types-union-finite/tree.txtnew file+110
@@ -0,0 +1,110 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %p)
6+ (face 2:7 left (flag 2:12))
7+ (face 2:14 right (flag 2:20)))
8+ (const 3:3 %other)))
9+ (value 4:1 boolean-table
10+ (gate 4:18
11+ (face 4:21 m (ref 4:23 msg))
12+ (body 5:3
13+ (branch 5:3
14+ (wing 5:6 m)
15+ (arm 6:5
16+ (cell 6:5 (lit 6:6 %p) (lit 6:9 %.y) (lit 6:13 %.y))
17+ (str 6:18 "a"))
18+ (arm 7:5
19+ (cell 7:5 (lit 7:6 %p) (lit 7:9 %.y) (lit 7:13 %.n))
20+ (str 7:18 "b"))
21+ (arm 8:5
22+ (cell 8:5 (lit 8:6 %p) (lit 8:9 %.n) (lit 8:13 %.y))
23+ (str 8:18 "c"))
24+ (arm 9:5
25+ (cell 9:5 (lit 9:6 %p) (lit 9:9 %.n) (lit 9:13 %.n))
26+ (str 9:18 "d"))
27+ (arm 10:5 (lit 10:5 %other) (str 10:12 "e"))))))
28+ (value 11:1 wildcard
29+ (gate 11:13
30+ (face 11:16 m (ref 11:18 msg))
31+ (body 12:3
32+ (branch 12:3
33+ (wing 12:6 m)
34+ (arm 13:5
35+ (cell 13:5 (lit 13:6 %p) (lit 13:9 %.y) (any 13:13))
36+ (str 13:16 "a"))
37+ (arm 14:5
38+ (cell 14:5 (lit 14:6 %p) (lit 14:9 %.n) (any 14:13))
39+ (str 14:16 "b"))
40+ (arm 15:5 (lit 15:5 %other) (str 15:12 "e"))))))
41+ (value 16:1 covered
42+ (gate 16:12
43+ (face 16:15 m (ref 16:17 msg))
44+ (body 17:3
45+ (branch 17:3
46+ (wing 17:6 m)
47+ (arm 18:5
48+ (cell 18:5 (lit 18:6 %p) (lit 18:9 %.y) (any 18:13))
49+ (str 18:16 "a"))
50+ (arm 19:5
51+ (cell 19:5 (lit 19:6 %p) (lit 19:9 %.y) (lit 19:13 %.n))
52+ (str 19:18 "b"))
53+ (arm 20:5 (any 20:5) (str 20:7 "e"))))))
54+ (mold 22:1 choice
55+ (union 23:3
56+ (cell 23:3
57+ (const 23:4 %a)
58+ (face 23:7 on (flag 23:10)))
59+ (const 24:3 %other)))
60+ (value 25:1 missing
61+ (gate 25:12
62+ (face 25:15 x (ref 25:17 choice))
63+ (body 26:3
64+ (branch 26:3
65+ (wing 26:6 x)
66+ (arm 27:5
67+ (cell 27:5 (lit 27:6 %a) (lit 27:9 %.y))
68+ (str 27:14 "yes"))
69+ (arm 28:5 (lit 28:5 %other) (str 28:12 "other"))))))
70+ (value 29:1 typed
71+ (gate 29:10
72+ (face 29:13 x (ref 29:15 choice))
73+ (body 30:3
74+ (branch 30:3
75+ (wing 30:6 x)
76+ (arm 31:5
77+ (cell 31:5 (lit 31:6 %a) (bind 31:9 value))
78+ (wing 31:16 value))
79+ (arm 32:5 (lit 32:5 %other) (lit 32:12 %.n))))))
80+ (value 33:1 duplicate
81+ (gate 33:14
82+ (face 33:17 x (ref 33:19 choice))
83+ (body 34:3
84+ (branch 34:3
85+ (wing 34:6 x)
86+ (arm 35:5
87+ (cell 35:5 (lit 35:6 %a) (lit 35:9 %.y))
88+ (str 35:14 "yes"))
89+ (arm 36:5
90+ (cell 36:5 (lit 36:6 %a) (lit 36:9 %$))
91+ (str 36:13 "duplicate"))
92+ (arm 37:5 (any 37:5) (str 37:7 "other"))))))
93+ (value 38:1 shadow
94+ (gate 38:11
95+ (face 38:14 x (ref 38:16 choice))
96+ (body 39:3
97+ (branch 39:3
98+ (wing 39:6 x)
99+ (arm 40:5
100+ (cell 40:5 (lit 40:6 %a) (bind 40:9 missing))
101+ (str 40:18 "yes"))
102+ (arm 41:5 (lit 41:5 %other) (str 41:12 "other"))))))
103+ (value 42:1 many-bind
104+ (gate 42:14
105+ (face 42:17 x (ref 42:19 choice))
106+ (body 43:3
107+ (branch 43:3
108+ (wing 43:6 x)
109+ (arm 44:5 (bind 44:5 value) (str 44:11 "anything"))
110+ (arm 45:5 (lit 45:5 %other) (str 45:12 "dead")))))))
tests/golden/types-union-finite/types.txtnew file+17
@@ -0,0 +1,17 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ boolean-table: $-(msg @t)
4+++ wildcard: $-(msg @t)
5+++ covered: branch arm is covered by earlier arms
6+/tests/golden/types-union-finite/source.jibb:19:5: covered arm
7+ [%p %.y %.n] "b"
8+ ^
9++$ choice: cases proven disjoint; mold not checked
10+++ missing: missing union case [%a on=%.n]
11+++ typed: $-(choice ?)
12+++ duplicate: branch arm is covered by earlier arms
13+/tests/golden/types-union-finite/source.jibb:36:5: covered arm
14+ [%a %$] "duplicate"
15+ ^
16+++ shadow: pattern binder shadows a name
17+++ many-bind: a union pattern binding several cases is not supported by partial inference
tests/golden/types-union-patterns/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Grammar, Patterns: "Every case needs an arm or a catch-all"; "An arm that earlier arms cover ... is an error"; "A name in a pattern always binds anew".
2−tests: Whole cases of a closed tagged union match payload binders and catch-alls; missing cases and covered arms are named, and shadowing fails. A pattern that could cover only part of a case stays unsupported. Null and loobean patterns are compared by noun value. A union-result or list-result context and a complex union subject stay unsupported rather than reporting a loobean mismatch.
2+tests: Whole cases of a closed tagged union match payload binders and catch-alls; missing cases and covered arms are named, and shadowing fails. A boolean pattern can cover part of a case when all finite alternatives are accounted for; other partial patterns stay unsupported. Null and loobean patterns are compared by noun value. A union-result or list-result context and a complex union subject stay unsupported rather than reporting a loobean mismatch.
33expect: parses
44expect-types: a partial inference report
tests/golden/types-union-patterns/types.txt+1−1
@@ -13,7 +13,7 @@ partial inference; module not checked
1313 ^
1414++ shadow: pattern binder shadows a name
1515+$ flags: cases proven disjoint; mold not checked
16−++ partial: partial union pattern is not supported by partial inference
16+++ partial: $-(flags @t)
1717++ not-known: branch is not supported by partial inference
1818+$ digits: cases proven disjoint; mold not checked
1919++ as-booleans: $-(digits @t)
tests/lib/jibb.hoon+143−125
@@ -1773,109 +1773,121 @@
17731773/* tok-504 %txt /tests/golden/types-union-context-flow/tokens/txt
17741774/* tre-504 %txt /tests/golden/types-union-context-flow/tree/txt
17751775/* typ-504 %txt /tests/golden/types-union-context-flow/types/txt
1776−/* src-505 %jibb /tests/golden/types-union-import/source/jibb
1777−/* tok-505 %txt /tests/golden/types-union-import/tokens/txt
1778−/* tre-505 %txt /tests/golden/types-union-import/tree/txt
1779−/* mod-505-1 %jibb /tests/golden/types-union-import/modules/ui/lib/jibb
1780−/* typ-505 %txt /tests/golden/types-union-import/types/txt
1781−/* mtre-505 %txt /tests/golden/types-union-import/module-trees/txt
1782−/* src-506 %jibb /tests/golden/types-union-local-pending/source/jibb
1783−/* tok-506 %txt /tests/golden/types-union-local-pending/tokens/txt
1784−/* tre-506 %txt /tests/golden/types-union-local-pending/tree/txt
1785−/* typ-506 %txt /tests/golden/types-union-local-pending/types/txt
1786−/* src-507 %jibb /tests/golden/types-union-overlap/source/jibb
1787−/* tok-507 %txt /tests/golden/types-union-overlap/tokens/txt
1788−/* tre-507 %txt /tests/golden/types-union-overlap/tree/txt
1789−/* typ-507 %txt /tests/golden/types-union-overlap/types/txt
1790−/* src-508 %jibb /tests/golden/types-union-overlap-nested/source/jibb
1791−/* tok-508 %txt /tests/golden/types-union-overlap-nested/tokens/txt
1792−/* tre-508 %txt /tests/golden/types-union-overlap-nested/tree/txt
1793−/* typ-508 %txt /tests/golden/types-union-overlap-nested/types/txt
1794−/* src-509 %jibb /tests/golden/types-union-patterns/source/jibb
1795−/* tok-509 %txt /tests/golden/types-union-patterns/tokens/txt
1796−/* tre-509 %txt /tests/golden/types-union-patterns/tree/txt
1797−/* typ-509 %txt /tests/golden/types-union-patterns/types/txt
1798−/* src-510 %jibb /tests/golden/types-union-patterns-generic/source/jibb
1799−/* tok-510 %txt /tests/golden/types-union-patterns-generic/tokens/txt
1800−/* tre-510 %txt /tests/golden/types-union-patterns-generic/tree/txt
1801−/* typ-510 %txt /tests/golden/types-union-patterns-generic/types/txt
1802−/* src-511 %jibb /tests/golden/types-union-patterns-import/source/jibb
1803−/* tok-511 %txt /tests/golden/types-union-patterns-import/tokens/txt
1804−/* tre-511 %txt /tests/golden/types-union-patterns-import/tree/txt
1805−/* mod-511-1 %jibb /tests/golden/types-union-patterns-import/modules/ui/lib/jibb
1806−/* typ-511 %txt /tests/golden/types-union-patterns-import/types/txt
1807−/* mtre-511 %txt /tests/golden/types-union-patterns-import/module-trees/txt
1808−/* src-512 %jibb /tests/golden/types-union-phantom-generic/source/jibb
1809−/* tok-512 %txt /tests/golden/types-union-phantom-generic/tokens/txt
1810−/* tre-512 %txt /tests/golden/types-union-phantom-generic/tree/txt
1811−/* typ-512 %txt /tests/golden/types-union-phantom-generic/types/txt
1812−/* src-513 %jibb /tests/golden/types-union-print-cross-namespace/source/jibb
1813−/* tok-513 %txt /tests/golden/types-union-print-cross-namespace/tokens/txt
1814−/* tre-513 %txt /tests/golden/types-union-print-cross-namespace/tree/txt
1815−/* mod-513-1 %jibb /tests/golden/types-union-print-cross-namespace/modules/ui/lib/jibb
1816−/* typ-513 %txt /tests/golden/types-union-print-cross-namespace/types/txt
1817−/* mtre-513 %txt /tests/golden/types-union-print-cross-namespace/module-trees/txt
1818−/* src-514 %jibb /tests/golden/types-union-print-distinct/source/jibb
1819−/* tok-514 %txt /tests/golden/types-union-print-distinct/tokens/txt
1820−/* tre-514 %txt /tests/golden/types-union-print-distinct/tree/txt
1821−/* mod-514-1 %jibb /tests/golden/types-union-print-distinct/modules/ui/left/jibb
1822−/* mod-514-2 %jibb /tests/golden/types-union-print-distinct/modules/ui/right/jibb
1823−/* mod-514-3 %jibb /tests/golden/types-union-print-distinct/modules/ui/twin/jibb
1824−/* typ-514 %txt /tests/golden/types-union-print-distinct/types/txt
1825−/* mtre-514 %txt /tests/golden/types-union-print-distinct/module-trees/txt
1826−/* src-515 %jibb /tests/golden/types-union-print-escape/source/jibb
1827−/* tok-515 %txt /tests/golden/types-union-print-escape/tokens/txt
1828−/* tre-515 %txt /tests/golden/types-union-print-escape/tree/txt
1829−/* typ-515 %txt /tests/golden/types-union-print-escape/types/txt
1830−/* src-516 %jibb /tests/golden/types-union-print-local/source/jibb
1831−/* tok-516 %txt /tests/golden/types-union-print-local/tokens/txt
1832−/* tre-516 %txt /tests/golden/types-union-print-local/tree/txt
1833−/* typ-516 %txt /tests/golden/types-union-print-local/types/txt
1834−/* src-517 %jibb /tests/golden/types-union-print-nested/source/jibb
1835−/* tok-517 %txt /tests/golden/types-union-print-nested/tokens/txt
1836−/* tre-517 %txt /tests/golden/types-union-print-nested/tree/txt
1837−/* typ-517 %txt /tests/golden/types-union-print-nested/types/txt
1838−/* src-518 %jibb /tests/golden/types-union-print-same-origin/source/jibb
1839−/* tok-518 %txt /tests/golden/types-union-print-same-origin/tokens/txt
1840−/* tre-518 %txt /tests/golden/types-union-print-same-origin/tree/txt
1841−/* mod-518-1 %jibb /tests/golden/types-union-print-same-origin/modules/ui/shared/jibb
1842−/* typ-518 %txt /tests/golden/types-union-print-same-origin/types/txt
1843−/* mtre-518 %txt /tests/golden/types-union-print-same-origin/module-trees/txt
1844−/* src-519 %jibb /tests/golden/types-union-print-transitive/source/jibb
1845−/* tok-519 %txt /tests/golden/types-union-print-transitive/tokens/txt
1846−/* tre-519 %txt /tests/golden/types-union-print-transitive/tree/txt
1847−/* mod-519-1 %jibb /tests/golden/types-union-print-transitive/modules/ui/mid/jibb
1848−/* mod-519-2 %jibb /tests/golden/types-union-print-transitive/modules/ui/base/jibb
1849−/* typ-519 %txt /tests/golden/types-union-print-transitive/types/txt
1850−/* mtre-519 %txt /tests/golden/types-union-print-transitive/module-trees/txt
1851−/* src-520 %jibb /tests/golden/types-union-singleton/source/jibb
1852−/* tok-520 %txt /tests/golden/types-union-singleton/tokens/txt
1853−/* tre-520 %txt /tests/golden/types-union-singleton/tree/txt
1854−/* typ-520 %txt /tests/golden/types-union-singleton/types/txt
1855−/* src-521 %jibb /tests/golden/types-union-tag-atoms/source/jibb
1856−/* tok-521 %txt /tests/golden/types-union-tag-atoms/tokens/txt
1857−/* tre-521 %txt /tests/golden/types-union-tag-atoms/tree/txt
1858−/* typ-521 %txt /tests/golden/types-union-tag-atoms/types/txt
1859−/* src-522 %jibb /tests/golden/types-union-tags/source/jibb
1860−/* tok-522 %txt /tests/golden/types-union-tags/tokens/txt
1861−/* tre-522 %txt /tests/golden/types-union-tags/tree/txt
1862−/* typ-522 %txt /tests/golden/types-union-tags/types/txt
1863−/* src-523 %jibb /tests/golden/types-union-unresolved/source/jibb
1864−/* tok-523 %txt /tests/golden/types-union-unresolved/tokens/txt
1865−/* tre-523 %txt /tests/golden/types-union-unresolved/tree/txt
1866−/* typ-523 %txt /tests/golden/types-union-unresolved/types/txt
1867−/* src-524 %jibb /tests/golden/types-union-unresolved-flow/source/jibb
1868−/* tok-524 %txt /tests/golden/types-union-unresolved-flow/tokens/txt
1869−/* tre-524 %txt /tests/golden/types-union-unresolved-flow/tree/txt
1870−/* typ-524 %txt /tests/golden/types-union-unresolved-flow/types/txt
1871−/* src-525 %jibb /tests/golden/types-unit-context/source/jibb
1872−/* tok-525 %txt /tests/golden/types-unit-context/tokens/txt
1873−/* tre-525 %txt /tests/golden/types-unit-context/tree/txt
1874−/* typ-525 %txt /tests/golden/types-unit-context/types/txt
1875−/* src-526 %jibb /tests/golden/types-unit-patterns/source/jibb
1876−/* tok-526 %txt /tests/golden/types-unit-patterns/tokens/txt
1877−/* tre-526 %txt /tests/golden/types-unit-patterns/tree/txt
1878−/* typ-526 %txt /tests/golden/types-unit-patterns/types/txt
1776+/* src-505 %jibb /tests/golden/types-union-finite/source/jibb
1777+/* tok-505 %txt /tests/golden/types-union-finite/tokens/txt
1778+/* tre-505 %txt /tests/golden/types-union-finite/tree/txt
1779+/* typ-505 %txt /tests/golden/types-union-finite/types/txt
1780+/* src-506 %jibb /tests/golden/types-union-finite-generic/source/jibb
1781+/* tok-506 %txt /tests/golden/types-union-finite-generic/tokens/txt
1782+/* tre-506 %txt /tests/golden/types-union-finite-generic/tree/txt
1783+/* typ-506 %txt /tests/golden/types-union-finite-generic/types/txt
1784+/* src-507 %jibb /tests/golden/types-union-finite-limit/source/jibb
1785+/* tok-507 %txt /tests/golden/types-union-finite-limit/tokens/txt
1786+/* tre-507 %txt /tests/golden/types-union-finite-limit/tree/txt
1787+/* typ-507 %txt /tests/golden/types-union-finite-limit/types/txt
1788+/* src-508 %jibb /tests/golden/types-union-import/source/jibb
1789+/* tok-508 %txt /tests/golden/types-union-import/tokens/txt
1790+/* tre-508 %txt /tests/golden/types-union-import/tree/txt
1791+/* mod-508-1 %jibb /tests/golden/types-union-import/modules/ui/lib/jibb
1792+/* typ-508 %txt /tests/golden/types-union-import/types/txt
1793+/* mtre-508 %txt /tests/golden/types-union-import/module-trees/txt
1794+/* src-509 %jibb /tests/golden/types-union-local-pending/source/jibb
1795+/* tok-509 %txt /tests/golden/types-union-local-pending/tokens/txt
1796+/* tre-509 %txt /tests/golden/types-union-local-pending/tree/txt
1797+/* typ-509 %txt /tests/golden/types-union-local-pending/types/txt
1798+/* src-510 %jibb /tests/golden/types-union-overlap/source/jibb
1799+/* tok-510 %txt /tests/golden/types-union-overlap/tokens/txt
1800+/* tre-510 %txt /tests/golden/types-union-overlap/tree/txt
1801+/* typ-510 %txt /tests/golden/types-union-overlap/types/txt
1802+/* src-511 %jibb /tests/golden/types-union-overlap-nested/source/jibb
1803+/* tok-511 %txt /tests/golden/types-union-overlap-nested/tokens/txt
1804+/* tre-511 %txt /tests/golden/types-union-overlap-nested/tree/txt
1805+/* typ-511 %txt /tests/golden/types-union-overlap-nested/types/txt
1806+/* src-512 %jibb /tests/golden/types-union-patterns/source/jibb
1807+/* tok-512 %txt /tests/golden/types-union-patterns/tokens/txt
1808+/* tre-512 %txt /tests/golden/types-union-patterns/tree/txt
1809+/* typ-512 %txt /tests/golden/types-union-patterns/types/txt
1810+/* src-513 %jibb /tests/golden/types-union-patterns-generic/source/jibb
1811+/* tok-513 %txt /tests/golden/types-union-patterns-generic/tokens/txt
1812+/* tre-513 %txt /tests/golden/types-union-patterns-generic/tree/txt
1813+/* typ-513 %txt /tests/golden/types-union-patterns-generic/types/txt
1814+/* src-514 %jibb /tests/golden/types-union-patterns-import/source/jibb
1815+/* tok-514 %txt /tests/golden/types-union-patterns-import/tokens/txt
1816+/* tre-514 %txt /tests/golden/types-union-patterns-import/tree/txt
1817+/* mod-514-1 %jibb /tests/golden/types-union-patterns-import/modules/ui/lib/jibb
1818+/* typ-514 %txt /tests/golden/types-union-patterns-import/types/txt
1819+/* mtre-514 %txt /tests/golden/types-union-patterns-import/module-trees/txt
1820+/* src-515 %jibb /tests/golden/types-union-phantom-generic/source/jibb
1821+/* tok-515 %txt /tests/golden/types-union-phantom-generic/tokens/txt
1822+/* tre-515 %txt /tests/golden/types-union-phantom-generic/tree/txt
1823+/* typ-515 %txt /tests/golden/types-union-phantom-generic/types/txt
1824+/* src-516 %jibb /tests/golden/types-union-print-cross-namespace/source/jibb
1825+/* tok-516 %txt /tests/golden/types-union-print-cross-namespace/tokens/txt
1826+/* tre-516 %txt /tests/golden/types-union-print-cross-namespace/tree/txt
1827+/* mod-516-1 %jibb /tests/golden/types-union-print-cross-namespace/modules/ui/lib/jibb
1828+/* typ-516 %txt /tests/golden/types-union-print-cross-namespace/types/txt
1829+/* mtre-516 %txt /tests/golden/types-union-print-cross-namespace/module-trees/txt
1830+/* src-517 %jibb /tests/golden/types-union-print-distinct/source/jibb
1831+/* tok-517 %txt /tests/golden/types-union-print-distinct/tokens/txt
1832+/* tre-517 %txt /tests/golden/types-union-print-distinct/tree/txt
1833+/* mod-517-1 %jibb /tests/golden/types-union-print-distinct/modules/ui/left/jibb
1834+/* mod-517-2 %jibb /tests/golden/types-union-print-distinct/modules/ui/right/jibb
1835+/* mod-517-3 %jibb /tests/golden/types-union-print-distinct/modules/ui/twin/jibb
1836+/* typ-517 %txt /tests/golden/types-union-print-distinct/types/txt
1837+/* mtre-517 %txt /tests/golden/types-union-print-distinct/module-trees/txt
1838+/* src-518 %jibb /tests/golden/types-union-print-escape/source/jibb
1839+/* tok-518 %txt /tests/golden/types-union-print-escape/tokens/txt
1840+/* tre-518 %txt /tests/golden/types-union-print-escape/tree/txt
1841+/* typ-518 %txt /tests/golden/types-union-print-escape/types/txt
1842+/* src-519 %jibb /tests/golden/types-union-print-local/source/jibb
1843+/* tok-519 %txt /tests/golden/types-union-print-local/tokens/txt
1844+/* tre-519 %txt /tests/golden/types-union-print-local/tree/txt
1845+/* typ-519 %txt /tests/golden/types-union-print-local/types/txt
1846+/* src-520 %jibb /tests/golden/types-union-print-nested/source/jibb
1847+/* tok-520 %txt /tests/golden/types-union-print-nested/tokens/txt
1848+/* tre-520 %txt /tests/golden/types-union-print-nested/tree/txt
1849+/* typ-520 %txt /tests/golden/types-union-print-nested/types/txt
1850+/* src-521 %jibb /tests/golden/types-union-print-same-origin/source/jibb
1851+/* tok-521 %txt /tests/golden/types-union-print-same-origin/tokens/txt
1852+/* tre-521 %txt /tests/golden/types-union-print-same-origin/tree/txt
1853+/* mod-521-1 %jibb /tests/golden/types-union-print-same-origin/modules/ui/shared/jibb
1854+/* typ-521 %txt /tests/golden/types-union-print-same-origin/types/txt
1855+/* mtre-521 %txt /tests/golden/types-union-print-same-origin/module-trees/txt
1856+/* src-522 %jibb /tests/golden/types-union-print-transitive/source/jibb
1857+/* tok-522 %txt /tests/golden/types-union-print-transitive/tokens/txt
1858+/* tre-522 %txt /tests/golden/types-union-print-transitive/tree/txt
1859+/* mod-522-1 %jibb /tests/golden/types-union-print-transitive/modules/ui/mid/jibb
1860+/* mod-522-2 %jibb /tests/golden/types-union-print-transitive/modules/ui/base/jibb
1861+/* typ-522 %txt /tests/golden/types-union-print-transitive/types/txt
1862+/* mtre-522 %txt /tests/golden/types-union-print-transitive/module-trees/txt
1863+/* src-523 %jibb /tests/golden/types-union-singleton/source/jibb
1864+/* tok-523 %txt /tests/golden/types-union-singleton/tokens/txt
1865+/* tre-523 %txt /tests/golden/types-union-singleton/tree/txt
1866+/* typ-523 %txt /tests/golden/types-union-singleton/types/txt
1867+/* src-524 %jibb /tests/golden/types-union-tag-atoms/source/jibb
1868+/* tok-524 %txt /tests/golden/types-union-tag-atoms/tokens/txt
1869+/* tre-524 %txt /tests/golden/types-union-tag-atoms/tree/txt
1870+/* typ-524 %txt /tests/golden/types-union-tag-atoms/types/txt
1871+/* src-525 %jibb /tests/golden/types-union-tags/source/jibb
1872+/* tok-525 %txt /tests/golden/types-union-tags/tokens/txt
1873+/* tre-525 %txt /tests/golden/types-union-tags/tree/txt
1874+/* typ-525 %txt /tests/golden/types-union-tags/types/txt
1875+/* src-526 %jibb /tests/golden/types-union-unresolved/source/jibb
1876+/* tok-526 %txt /tests/golden/types-union-unresolved/tokens/txt
1877+/* tre-526 %txt /tests/golden/types-union-unresolved/tree/txt
1878+/* typ-526 %txt /tests/golden/types-union-unresolved/types/txt
1879+/* src-527 %jibb /tests/golden/types-union-unresolved-flow/source/jibb
1880+/* tok-527 %txt /tests/golden/types-union-unresolved-flow/tokens/txt
1881+/* tre-527 %txt /tests/golden/types-union-unresolved-flow/tree/txt
1882+/* typ-527 %txt /tests/golden/types-union-unresolved-flow/types/txt
1883+/* src-528 %jibb /tests/golden/types-unit-context/source/jibb
1884+/* tok-528 %txt /tests/golden/types-unit-context/tokens/txt
1885+/* tre-528 %txt /tests/golden/types-unit-context/tree/txt
1886+/* typ-528 %txt /tests/golden/types-unit-context/types/txt
1887+/* src-529 %jibb /tests/golden/types-unit-patterns/source/jibb
1888+/* tok-529 %txt /tests/golden/types-unit-patterns/tokens/txt
1889+/* tre-529 %txt /tests/golden/types-unit-patterns/tree/txt
1890+/* typ-529 %txt /tests/golden/types-unit-patterns/types/txt
18791891=/ prepared-prelude (prepare-prelude:jibb prelude-source)
18801892|%
18811893:: one arm per case
@@ -2888,50 +2900,56 @@
28882900 (weld (check ~.types-union-constructor-shape src-503 `tok-503 `tre-503) (check-types ~.types-union-constructor-shape ~[%tests %golden ~.types-union-constructor-shape %source %jibb] src-503 `typ-503))
28892901++ test-types-union-context-flow
28902902 (weld (check ~.types-union-context-flow src-504 `tok-504 `tre-504) (check-types ~.types-union-context-flow ~[%tests %golden ~.types-union-context-flow %source %jibb] src-504 `typ-504))
2903+++ test-types-union-finite
2904+ (weld (check ~.types-union-finite src-505 `tok-505 `tre-505) (check-module-types ~.types-union-finite ~[%tests %golden ~.types-union-finite %source %jibb] src-505 `typ-505 ~ ~ ~))
2905+++ test-types-union-finite-generic
2906+ (weld (check ~.types-union-finite-generic src-506 `tok-506 `tre-506) (check-module-types ~.types-union-finite-generic ~[%tests %golden ~.types-union-finite-generic %source %jibb] src-506 `typ-506 ~ ~ ~))
2907+++ test-types-union-finite-limit
2908+ (weld (check ~.types-union-finite-limit src-507 `tok-507 `tre-507) (check-module-types ~.types-union-finite-limit ~[%tests %golden ~.types-union-finite-limit %source %jibb] src-507 `typ-507 ~ ~ ~))
28912909++ test-types-union-import
2892− (weld (weld (check ~.types-union-import src-505 `tok-505 `tre-505) (check-module-types ~.types-union-import ~[%tests %golden ~.types-union-import %source %jibb] src-505 `typ-505 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-505-1]])) (check-module-trees ~.types-union-import `mtre-505 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-505-1]]))
2910+ (weld (weld (check ~.types-union-import src-508 `tok-508 `tre-508) (check-module-types ~.types-union-import ~[%tests %golden ~.types-union-import %source %jibb] src-508 `typ-508 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-508-1]])) (check-module-trees ~.types-union-import `mtre-508 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-508-1]]))
28932911++ test-types-union-local-pending
2894− (weld (check ~.types-union-local-pending src-506 `tok-506 `tre-506) (check-types ~.types-union-local-pending ~[%tests %golden ~.types-union-local-pending %source %jibb] src-506 `typ-506))
2912+ (weld (check ~.types-union-local-pending src-509 `tok-509 `tre-509) (check-types ~.types-union-local-pending ~[%tests %golden ~.types-union-local-pending %source %jibb] src-509 `typ-509))
28952913++ test-types-union-overlap
2896− (weld (check ~.types-union-overlap src-507 `tok-507 `tre-507) (check-types ~.types-union-overlap ~[%tests %golden ~.types-union-overlap %source %jibb] src-507 `typ-507))
2914+ (weld (check ~.types-union-overlap src-510 `tok-510 `tre-510) (check-types ~.types-union-overlap ~[%tests %golden ~.types-union-overlap %source %jibb] src-510 `typ-510))
28972915++ test-types-union-overlap-nested
2898− (weld (check ~.types-union-overlap-nested src-508 `tok-508 `tre-508) (check-types ~.types-union-overlap-nested ~[%tests %golden ~.types-union-overlap-nested %source %jibb] src-508 `typ-508))
2916+ (weld (check ~.types-union-overlap-nested src-511 `tok-511 `tre-511) (check-types ~.types-union-overlap-nested ~[%tests %golden ~.types-union-overlap-nested %source %jibb] src-511 `typ-511))
28992917++ test-types-union-patterns
2900− (weld (check ~.types-union-patterns src-509 `tok-509 `tre-509) (check-module-types ~.types-union-patterns ~[%tests %golden ~.types-union-patterns %source %jibb] src-509 `typ-509 ~ ~ ~))
2918+ (weld (check ~.types-union-patterns src-512 `tok-512 `tre-512) (check-module-types ~.types-union-patterns ~[%tests %golden ~.types-union-patterns %source %jibb] src-512 `typ-512 ~ ~ ~))
29012919++ test-types-union-patterns-generic
2902− (weld (check ~.types-union-patterns-generic src-510 `tok-510 `tre-510) (check-module-types ~.types-union-patterns-generic ~[%tests %golden ~.types-union-patterns-generic %source %jibb] src-510 `typ-510 ~ ~ ~))
2920+ (weld (check ~.types-union-patterns-generic src-513 `tok-513 `tre-513) (check-module-types ~.types-union-patterns-generic ~[%tests %golden ~.types-union-patterns-generic %source %jibb] src-513 `typ-513 ~ ~ ~))
29032921++ test-types-union-patterns-import
2904− (weld (weld (check ~.types-union-patterns-import src-511 `tok-511 `tre-511) (check-module-types ~.types-union-patterns-import ~[%tests %golden ~.types-union-patterns-import %source %jibb] src-511 `typ-511 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-511-1]])) (check-module-trees ~.types-union-patterns-import `mtre-511 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-511-1]]))
2922+ (weld (weld (check ~.types-union-patterns-import src-514 `tok-514 `tre-514) (check-module-types ~.types-union-patterns-import ~[%tests %golden ~.types-union-patterns-import %source %jibb] src-514 `typ-514 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-514-1]])) (check-module-trees ~.types-union-patterns-import `mtre-514 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-514-1]]))
29052923++ test-types-union-phantom-generic
2906− (weld (check ~.types-union-phantom-generic src-512 `tok-512 `tre-512) (check-types ~.types-union-phantom-generic ~[%tests %golden ~.types-union-phantom-generic %source %jibb] src-512 `typ-512))
2924+ (weld (check ~.types-union-phantom-generic src-515 `tok-515 `tre-515) (check-types ~.types-union-phantom-generic ~[%tests %golden ~.types-union-phantom-generic %source %jibb] src-515 `typ-515))
29072925++ test-types-union-print-cross-namespace
2908− (weld (weld (check ~.types-union-print-cross-namespace src-513 `tok-513 `tre-513) (check-module-types ~.types-union-print-cross-namespace ~[%tests %golden ~.types-union-print-cross-namespace %source %jibb] src-513 `typ-513 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-513-1]])) (check-module-trees ~.types-union-print-cross-namespace `mtre-513 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-513-1]]))
2926+ (weld (weld (check ~.types-union-print-cross-namespace src-516 `tok-516 `tre-516) (check-module-types ~.types-union-print-cross-namespace ~[%tests %golden ~.types-union-print-cross-namespace %source %jibb] src-516 `typ-516 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-516-1]])) (check-module-trees ~.types-union-print-cross-namespace `mtre-516 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-516-1]]))
29092927++ test-types-union-print-distinct
2910− (weld (weld (check ~.types-union-print-distinct src-514 `tok-514 `tre-514) (check-module-types ~.types-union-print-distinct ~[%tests %golden ~.types-union-print-distinct %source %jibb] src-514 `typ-514 ~ ~ ~[['/ui/left.jibb' ~[~.ui ~.left ~.jibb] mod-514-1] ['/ui/right.jibb' ~[~.ui ~.right ~.jibb] mod-514-2] ['/ui/twin.jibb' ~[~.ui ~.twin ~.jibb] mod-514-3]])) (check-module-trees ~.types-union-print-distinct `mtre-514 ~[['/ui/left.jibb' ~[~.ui ~.left ~.jibb] mod-514-1] ['/ui/right.jibb' ~[~.ui ~.right ~.jibb] mod-514-2] ['/ui/twin.jibb' ~[~.ui ~.twin ~.jibb] mod-514-3]]))
2928+ (weld (weld (check ~.types-union-print-distinct src-517 `tok-517 `tre-517) (check-module-types ~.types-union-print-distinct ~[%tests %golden ~.types-union-print-distinct %source %jibb] src-517 `typ-517 ~ ~ ~[['/ui/left.jibb' ~[~.ui ~.left ~.jibb] mod-517-1] ['/ui/right.jibb' ~[~.ui ~.right ~.jibb] mod-517-2] ['/ui/twin.jibb' ~[~.ui ~.twin ~.jibb] mod-517-3]])) (check-module-trees ~.types-union-print-distinct `mtre-517 ~[['/ui/left.jibb' ~[~.ui ~.left ~.jibb] mod-517-1] ['/ui/right.jibb' ~[~.ui ~.right ~.jibb] mod-517-2] ['/ui/twin.jibb' ~[~.ui ~.twin ~.jibb] mod-517-3]]))
29112929++ test-types-union-print-escape
2912− (weld (check ~.types-union-print-escape src-515 `tok-515 `tre-515) (check-types ~.types-union-print-escape ~[%tests %golden ~.types-union-print-escape %source %jibb] src-515 `typ-515))
2930+ (weld (check ~.types-union-print-escape src-518 `tok-518 `tre-518) (check-types ~.types-union-print-escape ~[%tests %golden ~.types-union-print-escape %source %jibb] src-518 `typ-518))
29132931++ test-types-union-print-local
2914− (weld (check ~.types-union-print-local src-516 `tok-516 `tre-516) (check-types ~.types-union-print-local ~[%tests %golden ~.types-union-print-local %source %jibb] src-516 `typ-516))
2932+ (weld (check ~.types-union-print-local src-519 `tok-519 `tre-519) (check-types ~.types-union-print-local ~[%tests %golden ~.types-union-print-local %source %jibb] src-519 `typ-519))
29152933++ test-types-union-print-nested
2916− (weld (check ~.types-union-print-nested src-517 `tok-517 `tre-517) (check-types ~.types-union-print-nested ~[%tests %golden ~.types-union-print-nested %source %jibb] src-517 `typ-517))
2934+ (weld (check ~.types-union-print-nested src-520 `tok-520 `tre-520) (check-types ~.types-union-print-nested ~[%tests %golden ~.types-union-print-nested %source %jibb] src-520 `typ-520))
29172935++ test-types-union-print-same-origin
2918− (weld (weld (check ~.types-union-print-same-origin src-518 `tok-518 `tre-518) (check-module-types ~.types-union-print-same-origin ~[%tests %golden ~.types-union-print-same-origin %source %jibb] src-518 `typ-518 ~ ~ ~[['/ui/shared.jibb' ~[~.ui ~.shared ~.jibb] mod-518-1]])) (check-module-trees ~.types-union-print-same-origin `mtre-518 ~[['/ui/shared.jibb' ~[~.ui ~.shared ~.jibb] mod-518-1]]))
2936+ (weld (weld (check ~.types-union-print-same-origin src-521 `tok-521 `tre-521) (check-module-types ~.types-union-print-same-origin ~[%tests %golden ~.types-union-print-same-origin %source %jibb] src-521 `typ-521 ~ ~ ~[['/ui/shared.jibb' ~[~.ui ~.shared ~.jibb] mod-521-1]])) (check-module-trees ~.types-union-print-same-origin `mtre-521 ~[['/ui/shared.jibb' ~[~.ui ~.shared ~.jibb] mod-521-1]]))
29192937++ test-types-union-print-transitive
2920− (weld (weld (check ~.types-union-print-transitive src-519 `tok-519 `tre-519) (check-module-types ~.types-union-print-transitive ~[%tests %golden ~.types-union-print-transitive %source %jibb] src-519 `typ-519 ~ ~ ~[['/ui/mid.jibb' ~[~.ui ~.mid ~.jibb] mod-519-1] ['/ui/base.jibb' ~[~.ui ~.base ~.jibb] mod-519-2]])) (check-module-trees ~.types-union-print-transitive `mtre-519 ~[['/ui/mid.jibb' ~[~.ui ~.mid ~.jibb] mod-519-1] ['/ui/base.jibb' ~[~.ui ~.base ~.jibb] mod-519-2]]))
2938+ (weld (weld (check ~.types-union-print-transitive src-522 `tok-522 `tre-522) (check-module-types ~.types-union-print-transitive ~[%tests %golden ~.types-union-print-transitive %source %jibb] src-522 `typ-522 ~ ~ ~[['/ui/mid.jibb' ~[~.ui ~.mid ~.jibb] mod-522-1] ['/ui/base.jibb' ~[~.ui ~.base ~.jibb] mod-522-2]])) (check-module-trees ~.types-union-print-transitive `mtre-522 ~[['/ui/mid.jibb' ~[~.ui ~.mid ~.jibb] mod-522-1] ['/ui/base.jibb' ~[~.ui ~.base ~.jibb] mod-522-2]]))
29212939++ test-types-union-singleton
2922− (weld (check ~.types-union-singleton src-520 `tok-520 `tre-520) (check-types ~.types-union-singleton ~[%tests %golden ~.types-union-singleton %source %jibb] src-520 `typ-520))
2940+ (weld (check ~.types-union-singleton src-523 `tok-523 `tre-523) (check-types ~.types-union-singleton ~[%tests %golden ~.types-union-singleton %source %jibb] src-523 `typ-523))
29232941++ test-types-union-tag-atoms
2924− (weld (check ~.types-union-tag-atoms src-521 `tok-521 `tre-521) (check-types ~.types-union-tag-atoms ~[%tests %golden ~.types-union-tag-atoms %source %jibb] src-521 `typ-521))
2942+ (weld (check ~.types-union-tag-atoms src-524 `tok-524 `tre-524) (check-types ~.types-union-tag-atoms ~[%tests %golden ~.types-union-tag-atoms %source %jibb] src-524 `typ-524))
29252943++ test-types-union-tags
2926− (weld (check ~.types-union-tags src-522 `tok-522 `tre-522) (check-types ~.types-union-tags ~[%tests %golden ~.types-union-tags %source %jibb] src-522 `typ-522))
2944+ (weld (check ~.types-union-tags src-525 `tok-525 `tre-525) (check-types ~.types-union-tags ~[%tests %golden ~.types-union-tags %source %jibb] src-525 `typ-525))
29272945++ test-types-union-unresolved
2928− (weld (check ~.types-union-unresolved src-523 `tok-523 `tre-523) (check-types ~.types-union-unresolved ~[%tests %golden ~.types-union-unresolved %source %jibb] src-523 `typ-523))
2946+ (weld (check ~.types-union-unresolved src-526 `tok-526 `tre-526) (check-types ~.types-union-unresolved ~[%tests %golden ~.types-union-unresolved %source %jibb] src-526 `typ-526))
29292947++ test-types-union-unresolved-flow
2930− (weld (check ~.types-union-unresolved-flow src-524 `tok-524 `tre-524) (check-types ~.types-union-unresolved-flow ~[%tests %golden ~.types-union-unresolved-flow %source %jibb] src-524 `typ-524))
2948+ (weld (check ~.types-union-unresolved-flow src-527 `tok-527 `tre-527) (check-types ~.types-union-unresolved-flow ~[%tests %golden ~.types-union-unresolved-flow %source %jibb] src-527 `typ-527))
29312949++ test-types-unit-context
2932− (weld (check ~.types-unit-context src-525 `tok-525 `tre-525) (check-types ~.types-unit-context ~[%tests %golden ~.types-unit-context %source %jibb] src-525 `typ-525))
2950+ (weld (check ~.types-unit-context src-528 `tok-528 `tre-528) (check-types ~.types-unit-context ~[%tests %golden ~.types-unit-context %source %jibb] src-528 `typ-528))
29332951++ test-types-unit-patterns
2934− (weld (check ~.types-unit-patterns src-526 `tok-526 `tre-526) (check-types ~.types-unit-patterns ~[%tests %golden ~.types-unit-patterns %source %jibb] src-526 `typ-526))
2952+ (weld (check ~.types-unit-patterns src-529 `tok-529 `tre-529) (check-types ~.types-unit-patterns ~[%tests %golden ~.types-unit-patterns %source %jibb] src-529 `typ-529))
29352953::
29362954:: +check: run golden:jibb on a case and compare both outputs
29372955::