on master help sign in
Print named and escaping union types
5c73614iko
docs/compiler.md+3−1
@@ -56,7 +56,9 @@ The core is split into chapters, `+| %name`, in this order:
56| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
56| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
57| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
57| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
58
58
59−The inference fragment supports fixed auras, unrestricted `@`, one-way widening into it and toward aura-family ancestors, generic variables and gates, faced and unfaced cells, cell sample binders, known record field reads, a two-binder cell pattern, a complete two-arm loobean branch, closed local mold aliases and acyclic forward value references. It instantiates generalized top-level definitions when they are used. Acyclic local value definitions can refer forward and generalize variables that are free of their enclosing environment; captured variables and explicit capitals remain shared. Acyclic simple local mold aliases can also refer forward, and are scoped to the body, not its gate's sample. Nonrecursive generic aliases of supported molds can be applied at exact arity, including locally and through library interfaces; their parameters are lexical. Closed, provably disjoint nonrecursive unions and tagged single-case molds support contextual term values and `|=%tag` constructors; unresolved tags remain pending. Recursive local groups, recursive molds and generic unions remain unsupported. It can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, complete imports, general patterns, general deferred constraints, recursive molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`. Some known tuple and record positions acquire matching faces, while variable-dependent face merges, tag context across branches, union type printing and ambiguous call-result propagation remain unsupported; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types. The current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
59+The inference fragment supports fixed auras, unrestricted `@`, one-way widening into it and toward aura-family ancestors, generic variables and gates, faced and unfaced cells, cell sample binders, known record field reads, a two-binder cell pattern, a complete two-arm loobean branch, closed local mold aliases and acyclic forward value references. It instantiates generalized top-level definitions when they are used. Acyclic local value definitions can refer forward and generalize variables that are free of their enclosing environment; captured variables and explicit capitals remain shared. Acyclic simple local mold aliases can also refer forward, and are scoped to the body, not its gate's sample. Nonrecursive generic aliases of supported molds can be applied at exact arity, including locally and through library interfaces; their parameters are lexical. Closed, provably disjoint nonrecursive unions and tagged single-case molds support contextual term values and `|=%tag` constructors; unresolved tags remain pending. Recursive local groups, recursive molds and generic unions remain unsupported. It can infer and generalize atom constraints arising from explicit capitals or bare sample binders, preserve those constraints through aliases, instantiate them independently, and print multiple constraints. Unresolved decimal variables default to `@ud` for inferred types without gates; defaulting inside gate types and other constraint cases remain incomplete. It does not yet check a module, complete imports, general patterns, general deferred constraints, recursive molds, dependency cycles or most errors with both conflicting excerpts. Definite cast and call mismatches, incompatible branches and overlapping union cases report both sites and excerpts. Concrete branch results can join at an explicitly present parent aura or `@`. Some known tuple and record positions acquire matching faces, while variable-dependent face merges, tag context across branches and ambiguous call-result propagation remain unsupported; function compatibility involving nested `@` and variable-dependent joins remain unsupported except for equal types. The current dependency pass can take quadratic time on long forward chains; the milestone's speed target remains unverified. A separate conservative pass reports unions whose cases are provably disjoint or overlapping and leaves other cases unresolved; it does not claim the mold is checked. Unsupported forms are reported as such, and the partial output says the module has not been checked.
60+
61+For supported closed unions, the type printer keeps the union’s origin separate from its displayed name. It prints an in-scope name such as `msg` or `msg.lib`, including in records and gates; an accessible imported alias may name a transitive union. A body-local union that escapes its scope, or an origin without an accessible name, prints its cases separated by spaces, parenthesized when nested. That case-list form is print-only. Two faces for the same imported origin remain compatible; compatibility between distinct union origins, including in gate types, remains unsupported. Generic unions remain unsupported, even when a parameter is unused. The Hoon bridge does not yet translate union forks into inference, so this printing support does not complete unnamed Hoon union imports.
60
62
61The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a mark door sample, removing its outer sample face and validating its build subject. The reader checks explicit Hoon `$%`, `$?` and `$^` unions against the Grammar’s disjointness rule (doc question 22). It re-evaluates statically recognizable source branches before Hoon can collapse them, checks materialized fork cases, and rejects shapes it cannot prove disjoint. Static records may also have verified standard-collection and `path` siblings. Explicit unions in collection arguments remain unsupported; other nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms and nested faced or unfaced cells with valid Jibb face names from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts those same shapes from declared mark imports in a separate list. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. For a recursive reference, the reader matches the exact Hoon hold against named arms in validated cores, including transitive Ford imports; it rejects missing, unlabelled or ambiguous origins. Its fixtures include three real Tlon files; `tools/importer-test` compares the internal projection under eval, and the ship test compares the same golden output. `tools/type-import-test` and `tools/type-mark-test` compare bridge reports under eval and on the ship. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
63The separate `jibb-dev/lib/jibb-import.hoon` is an unfinished reader for selected Hoon type graphs. It handles named recursion, nested map, set, queue, list, unit, jar and jug arguments, direct ordered maps, and direct `$^` unions whose source branches can be proved disjoint. It also reads ordered map fields in records when the map arguments are syntactically fixed atom molds and other fields are fixed atom molds or standard collections of static atom molds. Collection names must not be shadowed. The reader can also import a mark door sample, removing its outer sample face and validating its build subject. The reader checks explicit Hoon `$%`, `$?` and `$^` unions against the Grammar’s disjointness rule (doc question 22). It re-evaluates statically recognizable source branches before Hoon can collapse them, checks materialized fork cases, and rejects shapes it cannot prove disjoint. Static records may also have verified standard-collection and `path` siblings. Explicit unions in collection arguments remain unsupported; other nested ordered maps, general source-level disjointness and complete integration with the checker remain unfinished. `+golden-types-imports` can consume fixed-aura atoms and nested faced or unfaced cells with valid Jibb face names from caller-supplied reader results for declared `/-` imports; `+golden-types-with-marks` accepts those same shapes from declared mark imports in a separate list. Other forms remain unsupported. Its disjointness proof is conservative and can reject a valid union it cannot prove disjoint. Collection recognition requires the originating `/sur` core. The reader validates direct zuse subjects and Ford subjects consisting of faced imported cores and a validated tail, checking imported cores transitively; it rejects shadowed names, inconsistent core subjects and other subject shapes. For a recursive reference, the reader matches the exact Hoon hold against named arms in validated cores, including transitive Ford imports; it rejects missing, unlabelled or ambiguous origins. Its fixtures include three real Tlon files; `tools/importer-test` compares the internal projection under eval, and the ship test compares the same golden output. `tools/type-import-test` and `tools/type-mark-test` compare bridge reports under eval and on the ship. `tools/clay-fixtures` also passes Clay-built `/sur` molds and mark samples through the Clay-built importer and partial checker.
62
64
docs/status.md+7−6
@@ -19,7 +19,7 @@ On 2026-10-30, @iko decided that Jibb drops `$?`, so a `+$` takes a union's case
19
19
20## Milestone 2: in progress
20## Milestone 2: in progress
21
21
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 and nested faced or unfaced cells from `/sur` molds and marks into inference. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, and direct `$^` unions whose cases can be proved disjoint. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases (doc question 22), while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and the current prelude names, 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, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags and constructors for closed disjoint unions. Variable-dependent face merges remain unsupported. Unfixed decimal literals default to `@ud` in gate-free inferred types; recursive local groups, recursive and union generic molds, branch tag context, union type printing, 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; its golden fixtures include three real Tlon files. The prelude currently has only a few functions, 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 and nested faced or unfaced cells from `/sur` molds and marks into inference. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, and direct `$^` unions whose cases can be proved disjoint. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases (doc question 22), while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and the current prelude names, 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, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags and constructors for closed disjoint unions. Variable-dependent face merges remain unsupported. Supported closed unions print using an in-scope name or imported alias; a union whose name is not accessible prints its cases, parenthesized when nested. The latter is print-only. Different import faces for the same origin remain compatible; compatibility across distinct union origins is still unsupported, as are generic unions even when their parameters are unused. The Hoon bridge cannot yet bring union forks into inference. Unfixed decimal literals default to `@ud` in gate-free inferred types; recursive local groups and molds, 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; its golden fixtures include three real Tlon files. The prelude currently has only a few functions, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
23
23
24## Milestone 1: parser and mark
24## Milestone 1: parser and mark
25
25
@@ -37,8 +37,8 @@ What the plan asks for, and where it is:
37
37
38Besides the plan's list:
38Besides the plan's list:
39
39
40−- 468 golden cases: 252 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.
40+- 479 golden cases: 263 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.
41−- The 468-case corpus passed under `urbit eval` in 31.7 s. The fake ship passed all 473 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 27.0 s for sync and 18.8 s for tests. The importer golden compares 130 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.
41+- The 479-case corpus passed under `urbit eval` in 34.1 s. The fake ship passed all 484 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 25.5 s for sync and 29.8 s for tests. The importer golden compares 130 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- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
42- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
43- 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.
43- 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.
44- 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).
44- 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).
@@ -68,14 +68,15 @@ Besides the plan's list:
68| 8bf1b12 | 2026-10-30 | Infer selected record faces and check nested `$^` in static Hoon records |
68| 8bf1b12 | 2026-10-30 | Infer selected record faces and check nested `$^` in static Hoon records |
69| d8ac47d | 2026-10-30 | Cache library interfaces, preserve imported Hoon record faces, and check nested tagged unions |
69| d8ac47d | 2026-10-30 | Cache library interfaces, preserve imported Hoon record faces, and check nested tagged unions |
70| edd9277 | 2026-10-30 | Infer nonrecursive generic mold aliases with lexical parameters |
70| edd9277 | 2026-10-30 | Infer nonrecursive generic mold aliases with lexical parameters |
71−| This change | 2026-10-30 | Resolve selected contextual tags and check explicit imported unions |
71+| 4406f6f | 2026-10-30 | Resolve selected contextual tags and check explicit imported unions |
72+| This change | 2026-10-30 | Print supported named and escaping union types |
72
73
73## Checking it
74## Checking it
74
75
75On a machine set up as [development.md](development.md) says:
76On a machine set up as [development.md](development.md) says:
76
77
77```
78```
78−tools/golden # 468 cases under urbit eval
79+tools/golden # 479 cases under urbit eval
79tools/importer-test # the Hoon importer fixture projection
80tools/importer-test # the Hoon importer fixture projection
80tools/type-import-test # the importer/checker bridge fixture
81tools/type-import-test # the importer/checker bridge fixture
81tools/type-mark-test # the mark/checker bridge fixture
82tools/type-mark-test # the mark/checker bridge fixture
@@ -85,7 +86,7 @@ tools/testdata/selftest # the tools themselves
85tools/doc-blocks docs/spec # the doc's examples are golden cases
86tools/doc-blocks docs/spec # the doc's examples are golden cases
86tools/ship start
87tools/ship start
87tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
88tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
88−tools/ship test # the same 468 cases as -test arms on the ship
89+tools/ship test # the same 479 cases as -test arms on the ship
89tools/testdata/ship-selftest
90tools/testdata/ship-selftest
90tools/ship check-commit # |commit stores .jibb files
91tools/ship check-commit # |commit stores .jibb files
91tools/clay-fixtures # example /sur files and marks build through Clay
92tools/clay-fixtures # example /sur files and marks build through Clay
jibb-dev/lib/jibb.hoon+95−27
@@ -4595,8 +4595,9 @@
4595:: their defaulting and inferred generalization are implemented.
4595:: their defaulting and inferred generalization are implemented.
4596:: Bare @ is a separate unrestricted atom type. A directional fit check
4596:: Bare @ is a separate unrestricted atom type. A directional fit check
4597:: permits concrete atoms to widen to it, never the reverse. A fit that
4597:: permits concrete atoms to widen to it, never the reverse. A fit that
4598−:: needs a not-yet-implemented constraint remains unsupported. Only
4598+:: needs a not-yet-implemented constraint remains unsupported. Named closed
4599−:: unfaced cells are represented here.
4599+:: unions retain their module of origin separately from their
4600+:: displayed name. Union printing is informational; it is not Jibb syntax.
4600::
4601::
4601+$ itype
4602+$ itype
4602 $~ [%var 0]
4603 $~ [%var 0]
@@ -4608,7 +4609,7 @@
4608 [%flag ~]
4609 [%flag ~]
4609 [%tag id=@ud literal=lit constructor=?]
4610 [%tag id=@ud literal=lit constructor=?]
4610 [%const literal=lit]
4611 [%const literal=lit]
4611− [%union cases=(list itype)]
4612+ [%union cases=(list itype) origin=(unit [at=path name=term]) label=(unit @t)]
4612 [%face name=term body=itype]
4613 [%face name=term body=itype]
4613 [%fn sample=itype product=itype]
4614 [%fn sample=itype product=itype]
4614 [%cell hed=itype tal=itype]
4615 [%cell hed=itype tal=itype]
@@ -4676,6 +4677,9 @@
4676 =. a (itype-walk a sub)
4677 =. a (itype-walk a sub)
4677 =. b (itype-walk b sub)
4678 =. b (itype-walk b sub)
4678 ?: =(a b) `sub
4679 ?: =(a b) `sub
4680+ ?: &(?=(%union -.a) ?=(%union -.b))
4681+ ?: &(=(origin.a origin.b) =(cases.a cases.b)) `sub
4682+ ~
4679 ?: ?=(%var -.a)
4683 ?: ?=(%var -.a)
4680 ?: (itype-occurs id.a b sub) ~
4684 ?: (itype-occurs id.a b sub) ~
4681 `[[id.a b] sub]
4685 `[[id.a b] sub]
@@ -4946,7 +4950,9 @@
4946 =. actual (itype-walk actual sub)
4950 =. actual (itype-walk actual sub)
4947 =. expected (itype-walk expected sub)
4951 =. expected (itype-walk expected sub)
4948 ?: =(actual expected) [%ok sub next]
4952 ?: =(actual expected) [%ok sub next]
4949− ?: &(?=(%union -.actual) ?=(%union -.expected)) [%unknown ~]
4953+ ?: &(?=(%union -.actual) ?=(%union -.expected))
4954+ ?: &(=(origin.actual origin.expected) =(cases.actual cases.expected)) [%ok sub next]
4955+ [%unknown ~]
4950 ?: ?=(%union -.actual) [%unknown ~]
4956 ?: ?=(%union -.actual) [%unknown ~]
4951 ?: &(?=(%union -.expected) |(?=(%avar -.actual) ?=(%nvar -.actual))) [%unknown ~]
4957 ?: &(?=(%union -.expected) |(?=(%avar -.actual) ?=(%nvar -.actual))) [%unknown ~]
4952 ?: &(?=(%union -.expected) !?=(%var -.actual))
4958 ?: &(?=(%union -.expected) !?=(%var -.actual))
@@ -5032,6 +5038,7 @@
5032 [%unknown ~]
5038 [%unknown ~]
5033 =/ unified=(unit isub) (itype-unify actual expected sub)
5039 =/ unified=(unit isub) (itype-unify actual expected sub)
5034 ?~ unified
5040 ?~ unified
5041+ ?: |((itype-has-union (itype-normalize actual sub)) (itype-has-union (itype-normalize expected sub))) [%unknown ~]
5035 ?: (itype-family-related actual expected sub) [%unknown ~]
5042 ?: (itype-family-related actual expected sub) [%unknown ~]
5036 [%bad ~]
5043 [%bad ~]
5037 [%ok u.unified next]
5044 [%ok u.unified next]
@@ -5069,7 +5076,7 @@
5069+$ ischeme [typ=itype vars=(list @ud)]
5076+$ ischeme [typ=itype vars=(list @ud)]
5070+$ ienv (list [name=term scheme=ischeme])
5077+$ ienv (list [name=term scheme=ischeme])
5071+$ imold-types (list [name=term template=ischeme])
5078+$ imold-types (list [name=term template=ischeme])
5072−+$ ifile [values=ienv molds=imold-types]
5079++$ ifile [values=ienv molds=imold-types at=path]
5073+$ ijimports (list [face=term interface=ifile])
5080+$ ijimports (list [face=term interface=ifile])
5074+$ icaps (list [name=@t id=@ud])
5081+$ icaps (list [name=@t id=@ud])
5075+$ iparams (list [name=@t typ=itype])
5082+$ iparams (list [name=@t typ=itype])
@@ -5078,7 +5085,7 @@
5078:: This core has no Ford dependencies; unrecognized payloads fail closed.
5085:: This core has no Ford dependencies; unrecognized payloads fail closed.
5079+$ iexternals (list [module=term name=term result=*])
5086+$ iexternals (list [module=term name=term result=*])
5080+$ imark-externals (list [mark=term result=*])
5087+$ imark-externals (list [mark=term result=*])
5081−+$ istate [next=@ud sub=isub caps=icaps binders=(list @ud) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) params=iparams active=(list term) tags=(list @ud) in-mold=?]
5088++$ istate [next=@ud sub=isub caps=icaps binders=(list @ud) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) params=iparams active=(list term) tags=(list @ud) in-mold=? at=path top-molds=(list term)]
5082+$ idiag [msg=tape sites=(list [at=span note=tape])]
5089+$ idiag [msg=tape sites=(list [at=span note=tape])]
5083+$ iresult (each [typ=itype state=istate] idiag)
5090+$ iresult (each [typ=itype state=istate] idiag)
5084+$ isample-result (each [typ=itype env=ienv state=istate] tape)
5091+$ isample-result (each [typ=itype env=ienv state=istate] tape)
@@ -5099,7 +5106,7 @@
5099 ^- itype
5106 ^- itype
5100 =. t (itype-walk t sub)
5107 =. t (itype-walk t sub)
5101 ?: ?=(%union -.t)
5108 ?: ?=(%union -.t)
5102− [%union (turn cases.t |=(c=itype (itype-normalize c sub)))]
5109+ [%union (turn cases.t |=(c=itype (itype-normalize c sub))) origin.t label.t]
5103 ?: ?=(%face -.t)
5110 ?: ?=(%face -.t)
5104 [%face name.t $(t body.t)]
5111 [%face name.t $(t body.t)]
5105 ?: ?=(%fn -.t)
5112 ?: ?=(%fn -.t)
@@ -5190,7 +5197,7 @@
5190 %flag t
5197 %flag t
5191 %tag t
5198 %tag t
5192 %const t
5199 %const t
5193− %union [%union (turn cases.t |=(c=itype (itype-rename c ren)))]
5200+ %union [%union (turn cases.t |=(c=itype (itype-rename c ren))) origin.t label.t]
5194 %face [%face name.t $(t body.t)]
5201 %face [%face name.t $(t body.t)]
5195 %fn [%fn $(t sample.t) $(t product.t)]
5202 %fn [%fn $(t sample.t) $(t product.t)]
5196 %cell [%cell $(t hed.t) $(t tal.t)]
5203 %cell [%cell $(t hed.t) $(t tal.t)]
@@ -5369,6 +5376,47 @@
5369 ?: =(name name.i.ms) `template.i.ms
5376 ?: =(name name.i.ms) `template.i.ms
5370 $(ms t.ms)
5377 $(ms t.ms)
5371::
5378::
5379+:: An exported alias may name a union from another module. Only a
5380+:: nongeneric alias of the same origin is usable through this import face.
5381+::
5382+++ imported-union-alias
5383+ |= [origin=[at=path name=term] molds=imold-types]
5384+ ^- (unit term)
5385+ ?~ molds ~
5386+ =/ template=ischeme template.i.molds
5387+ ?: &(?=(~ vars.template) ?=(%union -.typ.template))
5388+ ?:(=(`origin origin.typ.template) `name.i.molds $(molds t.molds))
5389+ $(molds t.molds)
5390+::
5391+:: Only names exported by this directly imported module are visible through
5392+:: its face. Other origins retain identity but print as unnamed unions.
5393+::
5394+++ itype-in-import
5395+ |= [t=itype iface=ifile face=term]
5396+ ^- itype
5397+ ?- -.t
5398+ %union
5399+ =/ label=(unit @t)
5400+ ?~ origin.t ~
5401+ =/ alias=(unit term) ~
5402+ =? alias &(=(at.u.origin.t at.iface) ?=(^ (find-jibb-mold name.u.origin.t iface))) `name.u.origin.t
5403+ =? alias ?=(~ alias) (imported-union-alias u.origin.t molds.iface)
5404+ ?~ alias ~
5405+ `(crip "{(trip u.alias)}.{(trip face)}")
5406+ [%union (turn cases.t |=(c=itype (itype-in-import c iface face))) origin.t label]
5407+ %face [%face name.t $(t body.t)]
5408+ %fn [%fn $(t sample.t) $(t product.t)]
5409+ %cell [%cell $(t hed.t) $(t tal.t)]
5410+ * t
5411+ ==
5412+::
5413+++ label-direct-union
5414+ |= [typ=itype body=shape name=term state=istate]
5415+ ^- itype
5416+ ?. &(?=(%union -.body) ?=(%union -.typ)) typ
5417+ ?. (lien top-molds.state |=(n=term =(n name))) typ
5418+ [%union cases.typ `[at.state name] `name]
5419+::
5372:: Generic mold parameters are lexical and distinct from the enclosing
5420:: Generic mold parameters are lexical and distinct from the enclosing
5373:: value's capital variables. Arguments are substituted only once, so
5421:: value's capital variables. Arguments are substituted only once, so
5374:: an argument's variable ID cannot be captured by a template ID.
5422:: an argument's variable ID cannot be captured by a template ID.
@@ -5433,6 +5481,8 @@
5433 =/ out=(unit [typ=itype state=istate])
5481 =/ out=(unit [typ=itype state=istate])
5434 (infer-simple-shape body.sh state(next next.fresh, params params.fresh, in-mold &))
5482 (infer-simple-shape body.sh state(next next.fresh, params params.fresh, in-mold &))
5435 ?~ out ~
5483 ?~ out ~
5484+ :: Generic union identity must include its arguments; defer that case.
5485+ ?: ?=(%union -.typ.u.out) ~
5436 =/ used=(list @ud) (itype-vars typ.u.out)
5486 =/ used=(list @ud) (itype-vars typ.u.out)
5437 ?. (levy used |=(n=@ud (lien vars.fresh |=(p=@ud =(p n))))) ~
5487 ?. (levy used |=(n=@ud (lien vars.fresh |=(p=@ud =(p n))))) ~
5438 `[[typ.u.out vars.fresh] state.u.out(params params.state, in-mold in-mold.state)]
5488 `[[typ.u.out vars.fresh] state.u.out(params params.state, in-mold in-mold.state)]
@@ -5459,7 +5509,7 @@
5459 =/ cs=(unit [types=(list itype) state=istate]) (infer-shape-args cases.sh state)
5509 =/ cs=(unit [types=(list itype) state=istate]) (infer-shape-args cases.sh state)
5460 ?~ cs ~
5510 ?~ cs ~
5461 ?: (lien types.u.cs |=(t=itype ?=(^ (itype-vars t)))) ~
5511 ?: (lien types.u.cs |=(t=itype ?=(^ (itype-vars t)))) ~
5462− `[[%union types.u.cs] state.u.cs]
5512+ `[[%union types.u.cs ~ ~] state.u.cs]
5463 %cell (infer-simple-fields fields.sh state)
5513 %cell (infer-simple-fields fields.sh state)
5464 %fn
5514 %fn
5465 =/ arg=(unit [typ=itype state=istate]) $(sh sample.sh)
5515 =/ arg=(unit [typ=itype state=istate]) $(sh sample.sh)
@@ -5477,7 +5527,7 @@
5477 =/ found=(unit ischeme) (find-jibb-mold n u.iface)
5527 =/ found=(unit ischeme) (find-jibb-mold n u.iface)
5478 ?~ found ~
5528 ?~ found ~
5479 ?^ vars.u.found ~
5529 ?^ vars.u.found ~
5480− `[typ.u.found state]
5530+ `[(itype-in-import typ.u.found u.iface i.t.names.sh) state]
5481 =/ found=(unit itype)
5531 =/ found=(unit itype)
5482 (find-imported-mold i.t.names.sh n externals.state surs.state)
5532 (find-imported-mold i.t.names.sh n externals.state surs.state)
5483 ?~ found ~
5533 ?~ found ~
@@ -5493,7 +5543,7 @@
5493 =/ out=(unit [typ=itype state=istate])
5543 =/ out=(unit [typ=itype state=istate])
5494 $(sh u.found, state state(active [n active.state], in-mold &, params ~))
5544 $(sh u.found, state state(active [n active.state], in-mold &, params ~))
5495 ?~ out ~
5545 ?~ out ~
5496− `[typ.u.out state.u.out(active active.state, in-mold in-mold.state, params params.state)]
5546+ `[(label-direct-union typ.u.out u.found n state) state.u.out(active active.state, in-mold in-mold.state, params params.state)]
5497 %apply
5547 %apply
5498 ?~ ref.sh ~
5548 ?~ ref.sh ~
5499 =/ args=(unit [types=(list itype) state=istate]) (infer-shape-args args.sh state)
5549 =/ args=(unit [types=(list itype) state=istate]) (infer-shape-args args.sh state)
@@ -5508,7 +5558,7 @@
5508 ?~ vars.u.template ~
5558 ?~ vars.u.template ~
5509 =/ applied=(unit itype) (template-apply u.template types.u.args)
5559 =/ applied=(unit itype) (template-apply u.template types.u.args)
5510 ?~ applied ~
5560 ?~ applied ~
5511− `[u.applied state.u.args]
5561+ `[(itype-in-import u.applied u.iface i.t.ref.sh) state.u.args]
5512 ?: (lien active.state.u.args |=(x=term =(x n))) ~
5562 ?: (lien active.state.u.args |=(x=term =(x n))) ~
5513 =/ found=(unit shape) (find-simple-mold n molds.state.u.args)
5563 =/ found=(unit shape) (find-simple-mold n molds.state.u.args)
5514 ?~ found ~
5564 ?~ found ~
@@ -5519,6 +5569,7 @@
5519 =/ out=(unit [typ=itype state=istate])
5569 =/ out=(unit [typ=itype state=istate])
5520 $(sh body.u.found, state state.u.args(active [n active.state.u.args], in-mold &, params u.params))
5570 $(sh body.u.found, state state.u.args(active [n active.state.u.args], in-mold &, params u.params))
5521 ?~ out ~
5571 ?~ out ~
5572+ ?: ?=(%union -.typ.u.out) ~
5522 `[typ.u.out state.u.out(active active.state.u.args, in-mold in-mold.state.u.args, params params.state.u.args)]
5573 `[typ.u.out state.u.out(active active.state.u.args, in-mold in-mold.state.u.args, params params.state.u.args)]
5523 %tvar
5574 %tvar
5524 =/ param=(unit itype) (iparam-lookup name.sh params.state)
5575 =/ param=(unit itype) (iparam-lookup name.sh params.state)
@@ -5759,6 +5810,7 @@
5759 ?~ iface (infer-field-wing names.e env state)
5810 ?~ iface (infer-field-wing names.e env state)
5760 =/ member=(unit ischeme) (ienv-lookup i.names.e values.u.iface)
5811 =/ member=(unit ischeme) (ienv-lookup i.names.e values.u.iface)
5761 ?~ member [%| ["module member is not available to partial inference" ~]]
5812 ?~ member [%| ["module member is not available to partial inference" ~]]
5813+ =. typ.u.member (itype-in-import typ.u.member u.iface i.t.names.e)
5762 =/ instance=[typ=itype state=istate] (instantiate-scheme u.member state)
5814 =/ instance=[typ=itype state=istate] (instantiate-scheme u.member state)
5763 [%& typ.instance state.instance]
5815 [%& typ.instance state.instance]
5764 =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
5816 =/ scheme=(unit ischeme) (ienv-lookup i.names.e env)
@@ -5940,9 +5992,9 @@
5940 %flag "?"
5992 %flag "?"
5941 %tag (trip txt.literal.t)
5993 %tag (trip txt.literal.t)
5942 %const (trip txt.literal.t)
5994 %const (trip txt.literal.t)
5943− %union "<union>"
5995+ %union ?~(label.t (show-itype-cases cases.t sub) (trip u.label.t))
5944− %face "[{(trip name.t)}={$(t body.t)}]"
5996+ %face "[{(trip name.t)}={(show-itype-context body.t sub)}]"
5945− %fn "$-({$(t sample.t)} {$(t product.t)})"
5997+ %fn "$-({(show-itype-context sample.t sub)} {(show-itype-context product.t sub)})"
5946 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
5998 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
5947 ==
5999 ==
5948::
6000::
@@ -5950,9 +6002,23 @@
5950 |= [t=itype sub=isub]
6002 |= [t=itype sub=isub]
5951 ^- tape
6003 ^- tape
5952 =. t (itype-walk t sub)
6004 =. t (itype-walk t sub)
5953− ?: ?=(%face -.t) "{(trip name.t)}={(show-itype body.t sub)}"
6005+ ?: ?=(%face -.t) "{(trip name.t)}={(show-itype-context body.t sub)}"
6006+ (show-itype-context t sub)
6007+::
6008+++ show-itype-context
6009+ |= [t=itype sub=isub]
6010+ ^- tape
6011+ =. t (itype-walk t sub)
6012+ ?: &(?=(%union -.t) ?=(~ label.t)) "({(show-itype t sub)})"
5954 (show-itype t sub)
6013 (show-itype t sub)
5955::
6014::
6015+++ show-itype-cases
6016+ |= [cases=(list itype) sub=isub]
6017+ ^- tape
6018+ ?~ cases ""
6019+ ?~ t.cases (show-itype-context i.cases sub)
6020+ "{(show-itype-context i.cases sub)} {$(cases t.cases)}"
6021+::
5956:: Include the type at a conflicting site where it can be printed.
6022:: Include the type at a conflicting site where it can be printed.
5957:: A lone unresolved variable or decimal variable keeps the neutral label.
6023:: A lone unresolved variable or decimal variable keeps the neutral label.
5958::
6024::
@@ -6090,14 +6156,15 @@
6090 |
6156 |
6091::
6157::
6092++ add-supported-defs
6158++ add-supported-defs
6093− |= [ds=(list def) env=ienv molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term)]
6159+ |= [ds=(list def) env=ienv molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path]
6094 ^- ienv
6160 ^- ienv
6095 ?~ ds env
6161 ?~ ds env
6096 =/ d=def i.ds
6162 =/ d=def i.ds
6097 ?: ?=(%mold -.d) $(ds t.ds)
6163 ?: ?=(%mold -.d) $(ds t.ds)
6098 ?. (unique-value-name name.d globals) $(ds t.ds)
6164 ?. (unique-value-name name.d globals) $(ds t.ds)
6099 ?^ (ienv-lookup name.d env) $(ds t.ds)
6165 ?^ (ienv-lookup name.d env) $(ds t.ds)
6166+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
6100− =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ |])
6167+ =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | at top])
6101 ?: ?=(%| -.result) $(ds t.ds)
6168 ?: ?=(%| -.result) $(ds t.ds)
6102 ?: (constrained-capitals caps.state.p.result sub.state.p.result) $(ds t.ds)
6169 ?: (constrained-capitals caps.state.p.result sub.state.p.result) $(ds t.ds)
6103 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6170 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
@@ -6108,11 +6175,11 @@
6108 $(ds t.ds, env [[name.d [typ vars]] env])
6175 $(ds t.ds, env [[name.d [typ vars]] env])
6109::
6176::
6110++ resolve-supported-defs
6177++ resolve-supported-defs
6111− |= [ds=(list def) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term)]
6178+ |= [ds=(list def) molds=imolds globals=(list term) externals=iexternals surs=(list term) mark-externals=imark-externals marks=(list term) jimports=ijimports reserved-molds=(list term) at=path]
6112 ^- ienv
6179 ^- ienv
6113 =/ env=ienv ~
6180 =/ env=ienv ~
6114 |-
6181 |-
6115− =/ next=ienv (add-supported-defs ds env molds globals externals surs mark-externals marks jimports reserved-molds)
6182+ =/ next=ienv (add-supported-defs ds env molds globals externals surs mark-externals marks jimports reserved-molds at)
6116 ?: =(next env) env
6183 ?: =(next env) env
6117 $(env next)
6184 $(env next)
6118::
6185::
@@ -6345,6 +6412,7 @@
6345 =/ t=(unit [template=ischeme state=istate])
6412 =/ t=(unit [template=ischeme state=istate])
6346 (infer-mold-template body.m state(active [name.m active.state], in-mold &))
6413 (infer-mold-template body.m state(active [name.m active.state], in-mold &))
6347 ?~ t [%| 'module mold needs unsupported inference']
6414 ?~ t [%| 'module mold needs unsupported inference']
6415+ =. typ.template.u.t (label-direct-union typ.template.u.t body.m name.m state)
6348 =/ rest=(each imold-types @t) $(molds t.molds)
6416 =/ rest=(each imold-types @t) $(molds t.molds)
6349 ?: ?=(%| -.rest) rest
6417 ?: ?=(%| -.rest) rest
6350 [%& [[name.m template.u.t] p.rest]]
6418 [%& [[name.m template.u.t] p.rest]]
@@ -6407,13 +6475,14 @@
6407 =/ surs=(list term) (collect-sur-imports imports.mod)
6475 =/ surs=(list term) (collect-sur-imports imports.mod)
6408 =/ marks=(list term) (collect-mark-imports imports.mod)
6476 =/ marks=(list term) (collect-mark-imports imports.mod)
6409 =/ reserved=(list term) (weld prelude-molds (turn resolved.p.js |=(j=[face=term interface=ifile] face.j)))
6477 =/ reserved=(list term) (weld prelude-molds (turn resolved.p.js |=(j=[face=term interface=ifile] face.j)))
6478+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
6410− =/ state=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks resolved.p.js reserved ~ ~ ~ |]
6479+ =/ state=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks resolved.p.js reserved ~ ~ ~ | at top]
6411 =/ mts=(each imold-types @t) (module-mold-types molds state)
6480 =/ mts=(each imold-types @t) (module-mold-types molds state)
6412 ?: ?=(%| -.mts) [%| (crip "{(trip p.mts)}: {(spud at)}")]
6481 ?: ?=(%| -.mts) [%| (crip "{(trip p.mts)}: {(spud at)}")]
6413− =/ env=ienv (resolve-supported-defs defs.mod molds globals externals surs mark-externals marks resolved.p.js reserved)
6482+ =/ env=ienv (resolve-supported-defs defs.mod molds globals externals surs mark-externals marks resolved.p.js reserved at)
6414 ?. (module-values-complete defs.mod env)
6483 ?. (module-values-complete defs.mod env)
6415 [%| (crip "module definitions need unsupported inference: {(spud at)}")]
6484 [%| (crip "module definitions need unsupported inference: {(spud at)}")]
6416− [%& [[env p.mts] [[at [env p.mts]] cache.p.js]]]
6485+ [%& [[env p.mts at] [[at [env p.mts at]] cache.p.js]]]
6417::
6486::
6418:: +golden-types-with-modules fails closed for imports without prelude
6487:: +golden-types-with-modules fails closed for imports without prelude
6419:: scope. +golden-types-with-prelude resolves supported library graphs;
6488:: scope. +golden-types-with-prelude resolves supported library graphs;
@@ -6471,7 +6540,7 @@
6471 =/ globals=(list term) (weld prelude-values (weld (turn jimports |=(j=[face=term interface=ifile] face.j)) (global-value-names ds)))
6540 =/ globals=(list term) (weld prelude-values (weld (turn jimports |=(j=[face=term interface=ifile] face.j)) (global-value-names ds)))
6472 =/ surs=(list term) (collect-sur-imports imports.p.parsed)
6541 =/ surs=(list term) (collect-sur-imports imports.p.parsed)
6473 =/ marks=(list term) (collect-mark-imports imports.p.parsed)
6542 =/ marks=(list term) (collect-mark-imports imports.p.parsed)
6474− =/ env=ienv (resolve-supported-defs ds molds globals externals surs mark-externals marks jimports reserved-molds)
6543+ =/ env=ienv (resolve-supported-defs ds molds globals externals surs mark-externals marks jimports reserved-molds file)
6475 =/ lines=(list @t) ~
6544 =/ lines=(list @t) ~
6476 |-
6545 |-
6477 ?~ ds (of-wain:format ['partial inference; module not checked' (flop lines)])
6546 ?~ ds (of-wain:format ['partial inference; module not checked' (flop lines)])
@@ -6480,7 +6549,8 @@
6480 $(ds t.ds, lines [(show-partial-mold file src d molds) lines])
6549 $(ds t.ds, lines [(show-partial-mold file src d molds) lines])
6481 ?. (unique-value-name name.d globals)
6550 ?. (unique-value-name name.d globals)
6482 $(ds t.ds, lines [(crip "++ {(trip name.d)}: name already in scope") lines])
6551 $(ds t.ds, lines [(crip "++ {(trip name.d)}: name already in scope") lines])
6552+ =/ top=(list term) (turn molds |=(m=[name=term body=shape] name.m))
6483− =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ |])
6553+ =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ | file top])
6484 ?: ?=(%| -.result)
6554 ?: ?=(%| -.result)
6485 $(ds t.ds, lines [(show-inference-diagnostic file src name.d p.result) lines])
6555 $(ds t.ds, lines [(show-inference-diagnostic file src name.d p.result) lines])
6486 ?: (constrained-capitals caps.state.p.result sub.state.p.result)
6556 ?: (constrained-capitals caps.state.p.result sub.state.p.result)
@@ -6488,8 +6558,6 @@
6488 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6558 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6489 ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ))
6559 ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ))
6490 $(ds t.ds, lines [(crip "++ {(trip name.d)}: tag needs context in partial inference") lines])
6560 $(ds t.ds, lines [(crip "++ {(trip name.d)}: tag needs context in partial inference") lines])
6491− ?: (itype-has-union typ)
6492− $(ds t.ds, lines [(crip "++ {(trip name.d)}: union type printing is not supported by partial inference") lines])
6493 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
6561 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
6494 $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
6562 $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
6495 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
6563 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
tests/golden/types-union-alias/types.txt+1−1
@@ -1,4 +1,4 @@
1partial inference; module not checked
1partial inference; module not checked
2+$ msg: cases proven disjoint; mold not checked
2+$ msg: cases proven disjoint; mold not checked
3+$ alias: not checked
3+$ alias: not checked
4−++ via: union type printing is not supported by partial inference
4+++ via: msg
tests/golden/types-union-constructor-shape/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: union cases must differ as nouns; tags take their union from context.
2+tests: A constructor can resolve inside a typed record, but cannot use a tag that is not at the case head.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-constructor-shape/source.jibbnew file+5
@@ -0,0 +1,5 @@
1++$ typed [%typed text=@t]
2++$ wrapper [make=$-(@t typed) id=@ud]
3++$ reversed [text=@t tag=%typed]
4+++ value ^- wrapper [make=|=%typed id=1]
5+++ bad ^- $-(@t reversed) |=%typed
tests/golden/types-union-constructor-shape/tokens.txtnew file+58
@@ -0,0 +1,58 @@
1+1:1 glyph +$
2+1:4 name typed
3+1:10 glyph [
4+1:11 tight lit %typed
5+1:18 name text
6+1:22 tight glyph =
7+1:23 tight aura @t
8+1:25 tight glyph ]
9+2:1 NEWLINE
10+2:1 glyph +$
11+2:4 name wrapper
12+2:12 glyph [
13+2:13 tight name make
14+2:17 tight glyph =
15+2:18 tight glyph $-(
16+2:21 tight aura @t
17+2:24 name typed
18+2:29 tight glyph )
19+2:31 name id
20+2:33 tight glyph =
21+2:34 tight aura @ud
22+2:37 tight glyph ]
23+3:1 NEWLINE
24+3:1 glyph +$
25+3:4 name reversed
26+3:13 glyph [
27+3:14 tight name text
28+3:18 tight glyph =
29+3:19 tight aura @t
30+3:22 name tag
31+3:25 tight glyph =
32+3:26 tight lit %typed
33+3:32 tight glyph ]
34+4:1 NEWLINE
35+4:1 glyph ++
36+4:4 name value
37+4:10 glyph ^-
38+4:13 name wrapper
39+4:21 glyph [
40+4:22 tight name make
41+4:26 tight glyph =
42+4:27 tight glyph |=
43+4:29 tight lit %typed
44+4:36 name id
45+4:38 tight glyph =
46+4:39 tight lit 1
47+4:40 tight glyph ]
48+5:1 NEWLINE
49+5:1 glyph ++
50+5:4 name bad
51+5:8 glyph ^-
52+5:11 glyph $-(
53+5:14 tight aura @t
54+5:17 name reversed
55+5:25 tight glyph )
56+5:27 glyph |=
57+5:29 tight lit %typed
58+5:35 NEWLINE
tests/golden/types-union-constructor-shape/tree.txtnew file+24
@@ -0,0 +1,24 @@
1+(module
2+ (mold 1:1 typed
3+ (cell 1:10
4+ (const 1:11 %typed)
5+ (face 1:18 text (aura 1:23 @t))))
6+ (mold 2:1 wrapper
7+ (cell 2:12
8+ (face 2:13 make
9+ (fn 2:18 (aura 2:21 @t) (ref 2:24 typed)))
10+ (face 2:31 id (aura 2:34 @ud))))
11+ (mold 3:1 reversed
12+ (cell 3:13
13+ (face 3:14 text (aura 3:19 @t))
14+ (face 3:22 tag (const 3:26 %typed))))
15+ (value 4:1 value
16+ (cast 4:10
17+ (ref 4:13 wrapper)
18+ (tuple 4:21
19+ (face 4:22 make (ctor 4:27 %typed))
20+ (face 4:36 id (lit 4:39 1)))))
21+ (value 5:1 bad
22+ (cast 5:8
23+ (fn 5:11 (aura 5:14 @t) (ref 5:17 reversed))
24+ (ctor 5:27 %typed))))
tests/golden/types-union-constructor-shape/types.txtnew file+12
@@ -0,0 +1,12 @@
1+partial inference; module not checked
2++$ typed: not checked
3++$ wrapper: not checked
4++$ reversed: not checked
5+++ value: [make=$-(@t [%typed text=@t]) id=@ud]
6+++ bad: cast mold and expression type do not unify
7+/tests/golden/types-union-constructor-shape/source.jibb:5:11: cast mold has type $-(@t [text=@t tag=%typed])
8+++ bad ^- $-(@t reversed) |=%typed
9+ ^
10+/tests/golden/types-union-constructor-shape/source.jibb:5:27: expression
11+++ bad ^- $-(@t reversed) |=%typed
12+ ^
tests/golden/types-union-context-flow/types.txt+1−1
@@ -3,4 +3,4 @@ partial inference; module not checked
3++ only-one: tag needs context in partial inference
3++ only-one: tag needs context in partial inference
4++ choose: branch tag or union context is not supported by partial inference
4++ choose: branch tag or union context is not supported by partial inference
5++ id: $-(A A)
5++ id: $-(A A)
6−++ through: union type printing is not supported by partial inference
6+++ through: msg
tests/golden/types-union-import/types.txt+1−1
@@ -1,2 +1,2 @@
1partial inference; module not checked
1partial inference; module not checked
2−++ selected: union type printing is not supported by partial inference
2+++ selected: msg.lib
tests/golden/types-union-local-pending/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: union cases must differ as nouns; tags take their union from context.
2+tests: A tag left unresolved in a discarded local definition does not disappear.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-local-pending/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+++ outer
2+ ++ hidden %add
3+ 1
tests/golden/types-union-local-pending/tokens.txtnew file+10
@@ -0,0 +1,10 @@
1+1:1 glyph ++
2+1:4 name outer
3+2:3 INDENT
4+2:3 glyph ++
5+2:6 name hidden
6+2:13 lit %add
7+3:3 NEWLINE
8+3:3 lit 1
9+3:4 DEDENT
10+3:4 NEWLINE
tests/golden/types-union-local-pending/tree.txtnew file+5
@@ -0,0 +1,5 @@
1+(module
2+ (value 1:1 outer
3+ (body 2:3
4+ (value 2:3 hidden (lit 2:13 %add))
5+ (lit 3:3 1))))
tests/golden/types-union-local-pending/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+++ outer: local definitions need unsupported inference
tests/golden/types-union-overlap-nested/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: union cases must differ as nouns; tags take their union from context.
2+tests: Two cases with the same head tag and overlapping atom payloads are detected as overlapping.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-overlap-nested/source.jibbnew file+4
@@ -0,0 +1,4 @@
1++$ broken
2+ [%same @t]
3+ [%same @ud]
4+++ identity |=(x x)
tests/golden/types-union-overlap-nested/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph +$
2+1:4 name broken
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %same
6+2:10 aura @t
7+2:12 tight glyph ]
8+3:3 NEWLINE
9+3:3 glyph [
10+3:4 tight lit %same
11+3:10 aura @ud
12+3:13 tight glyph ]
13+4:1 DEDENT
14+4:1 NEWLINE
15+4:1 glyph ++
16+4:4 name identity
17+4:13 glyph |=(
18+4:16 tight name x
19+4:18 name x
20+4:19 tight glyph )
21+4:20 NEWLINE
tests/golden/types-union-overlap-nested/tree.txtnew file+7
@@ -0,0 +1,7 @@
1+(module
2+ (mold 1:1 broken
3+ (union 2:3
4+ (cell 2:3 (const 2:4 %same) (aura 2:10 @t))
5+ (cell 3:3 (const 3:4 %same) (aura 3:10 @ud))))
6+ (value 4:1 identity
7+ (gate-wide 4:13 (bind 4:16 x) (wing 4:18 x))))
tests/golden/types-union-overlap-nested/types.txtnew file+9
@@ -0,0 +1,9 @@
1+partial inference; module not checked
2++$ broken: overlapping cases; mold not checked
3+/tests/golden/types-union-overlap-nested/source.jibb:2:3: first union case
4+ [%same @t]
5+ ^
6+/tests/golden/types-union-overlap-nested/source.jibb:3:3: overlapping case
7+ [%same @ud]
8+ ^
9+++ identity: $-(A A)
tests/golden/types-union-phantom-generic/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds: a generic mold declares its parameters after `|$`, and a union takes its cases below its name.
2+tests: A generic union remains unsupported even when its parameter is unused, until its type identity retains the arguments.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-phantom-generic/source.jibbnew file+4
@@ -0,0 +1,4 @@
1++$ phantom |$ [A]
2+ %add
3+ %remove
4+++ example ^- (phantom @t) %add
tests/golden/types-union-phantom-generic/tokens.txtnew file+21
@@ -0,0 +1,21 @@
1+1:1 glyph +$
2+1:4 name phantom
3+1:12 glyph |$
4+1:15 glyph [
5+1:16 tight tvar A
6+1:17 tight glyph ]
7+2:3 INDENT
8+2:3 lit %add
9+3:3 NEWLINE
10+3:3 lit %remove
11+4:1 DEDENT
12+4:1 NEWLINE
13+4:1 glyph ++
14+4:4 name example
15+4:12 glyph ^-
16+4:15 glyph (
17+4:16 tight name phantom
18+4:24 aura @t
19+4:26 tight glyph )
20+4:28 lit %add
21+4:32 NEWLINE
tests/golden/types-union-phantom-generic/tree.txtnew file+8
@@ -0,0 +1,8 @@
1+(module
2+ (mold 1:1 phantom
3+ (generic 1:12 A
4+ (union 2:3 (const 2:3 %add) (const 3:3 %remove))))
5+ (value 4:1 example
6+ (cast 4:12
7+ (apply 4:15 phantom (aura 4:24 @t))
8+ (lit 4:28 %add))))
tests/golden/types-union-phantom-generic/types.txtnew file+3
@@ -0,0 +1,3 @@
1+partial inference; module not checked
2++$ phantom: cases proven disjoint; mold not checked
3+++ example: cast mold is not supported by partial inference
tests/golden/types-union-print-cross-namespace/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: every Jibb union has a name and names are read through module faces; unnamed unions print their cases.
2+tests: A module may export a union mold and a value with the same name; printing uses the mold namespace.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-print-cross-namespace/module-trees.txtnew file+6
@@ -0,0 +1,6 @@
1+/ui/lib.jibb
2+(module
3+ (mold 1:1 msg
4+ (union 2:3 (const 2:3 %add) (const 3:3 %remove)))
5+ (value 4:1 msg
6+ (gate-wide 4:8 (bind 4:11 x) (wing 4:13 x))))
tests/golden/types-union-print-cross-namespace/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/types-union-print-cross-namespace/modules/ui/lib.jibbnew file+4
@@ -0,0 +1,4 @@
1++$ msg
2+ %add
3+ %remove
4+++ msg |=(x x)
tests/golden/types-union-print-cross-namespace/source.jibbnew file+3
@@ -0,0 +1,3 @@
1+/= lib /ui/lib
2+++ by-type |= x=msg.lib x
3+++ by-value (msg.lib ~zod)
tests/golden/types-union-print-cross-namespace/tokens.txtnew file+22
@@ -0,0 +1,22 @@
1+1:1 glyph /=
2+1:5 name lib
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot lib
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name by-type
10+2:12 glyph |=
11+2:15 name x
12+2:16 tight glyph =
13+2:17 tight wing msg.lib
14+2:25 name x
15+3:1 NEWLINE
16+3:1 glyph ++
17+3:4 name by-value
18+3:13 glyph (
19+3:14 tight wing msg.lib
20+3:22 lit ~zod
21+3:26 tight glyph )
22+3:27 NEWLINE
tests/golden/types-union-print-cross-namespace/tree.txtnew file+9
@@ -0,0 +1,9 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (value 2:1 by-type
4+ (gate 2:12
5+ (face 2:15 x (ref 2:17 msg.lib))
6+ (wing 2:25 x)))
7+ (value 3:1 by-value
8+ (group 3:13
9+ (call 3:14 (wing 3:14 msg.lib) (lit 3:22 ~zod)))))
tests/golden/types-union-print-cross-namespace/types.txtnew file+3
@@ -0,0 +1,3 @@
1+partial inference; module not checked
2+++ by-type: $-(msg.lib msg.lib)
3+++ by-value: @p
tests/golden/types-union-print-distinct/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: every Jibb union has a name and names are read through module faces; unnamed unions print their cases.
2+tests: Imported union molds with the same local name remain distinguishable in printed types; equal cases from different modules are not silently equated, including in higher-order gate arguments.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-print-distinct/module-trees.txtnew file+12
@@ -0,0 +1,12 @@
1+/ui/left.jibb
2+(module
3+ (mold 1:1 msg
4+ (union 2:3 (const 2:3 %add) (const 3:3 %remove))))
5+/ui/right.jibb
6+(module
7+ (mold 1:1 msg
8+ (union 2:3 (const 2:3 %start) (const 3:3 %stop))))
9+/ui/twin.jibb
10+(module
11+ (mold 1:1 msg
12+ (union 2:3 (const 2:3 %add) (const 3:3 %remove))))
tests/golden/types-union-print-distinct/modules.txtnew file+3
@@ -0,0 +1,3 @@
1+/ui/left.jibb
2+/ui/right.jibb
3+/ui/twin.jibb
tests/golden/types-union-print-distinct/modules/ui/left.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ msg
2+ %add
3+ %remove
tests/golden/types-union-print-distinct/modules/ui/right.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ msg
2+ %start
3+ %stop
tests/golden/types-union-print-distinct/modules/ui/twin.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ msg
2+ %add
3+ %remove
tests/golden/types-union-print-distinct/source.jibbnew file+11
@@ -0,0 +1,11 @@
1+/= left /ui/left
2+/= right /ui/right
3+/= twin /ui/twin
4+++ a |= x=msg.left x
5+++ b |= x=msg.right x
6+++ c |= x=msg.twin x
7+++ from-left ^- msg.left %add
8+++ cross (c from-left)
9+++ apply |= f=$-(msg.left @t) (f from-left)
10+++ other |= x=msg.twin "hi"
11+++ higher (apply other)
tests/golden/types-union-print-distinct/tokens.txtnew file+87
@@ -0,0 +1,87 @@
1+1:1 glyph /=
2+1:5 name left
3+1:10 glyph /
4+1:11 tight knot ui
5+1:13 tight glyph /
6+1:14 tight knot left
7+2:1 NEWLINE
8+2:1 glyph /=
9+2:5 name right
10+2:11 glyph /
11+2:12 tight knot ui
12+2:14 tight glyph /
13+2:15 tight knot right
14+3:1 NEWLINE
15+3:1 glyph /=
16+3:5 name twin
17+3:10 glyph /
18+3:11 tight knot ui
19+3:13 tight glyph /
20+3:14 tight knot twin
21+4:1 NEWLINE
22+4:1 glyph ++
23+4:4 name a
24+4:6 glyph |=
25+4:9 name x
26+4:10 tight glyph =
27+4:11 tight wing msg.left
28+4:20 name x
29+5:1 NEWLINE
30+5:1 glyph ++
31+5:4 name b
32+5:6 glyph |=
33+5:9 name x
34+5:10 tight glyph =
35+5:11 tight wing msg.right
36+5:21 name x
37+6:1 NEWLINE
38+6:1 glyph ++
39+6:4 name c
40+6:6 glyph |=
41+6:9 name x
42+6:10 tight glyph =
43+6:11 tight wing msg.twin
44+6:20 name x
45+7:1 NEWLINE
46+7:1 glyph ++
47+7:4 name from-left
48+7:14 glyph ^-
49+7:17 wing msg.left
50+7:26 lit %add
51+8:1 NEWLINE
52+8:1 glyph ++
53+8:4 name cross
54+8:10 glyph (
55+8:11 tight name c
56+8:13 name from-left
57+8:22 tight glyph )
58+9:1 NEWLINE
59+9:1 glyph ++
60+9:4 name apply
61+9:10 glyph |=
62+9:13 name f
63+9:14 tight glyph =
64+9:15 tight glyph $-(
65+9:18 tight wing msg.left
66+9:27 aura @t
67+9:29 tight glyph )
68+9:31 glyph (
69+9:32 tight name f
70+9:34 name from-left
71+9:43 tight glyph )
72+10:1 NEWLINE
73+10:1 glyph ++
74+10:4 name other
75+10:10 glyph |=
76+10:13 name x
77+10:14 tight glyph =
78+10:15 tight wing msg.twin
79+10:24 str "hi"
80+11:1 NEWLINE
81+11:1 glyph ++
82+11:4 name higher
83+11:11 glyph (
84+11:12 tight name apply
85+11:18 name other
86+11:23 tight glyph )
87+11:24 NEWLINE
tests/golden/types-union-print-distinct/tree.txtnew file+34
@@ -0,0 +1,34 @@
1+(module
2+ (jibb 1:1 left /ui/left)
3+ (jibb 2:1 right /ui/right)
4+ (jibb 3:1 twin /ui/twin)
5+ (value 4:1 a
6+ (gate 4:6
7+ (face 4:9 x (ref 4:11 msg.left))
8+ (wing 4:20 x)))
9+ (value 5:1 b
10+ (gate 5:6
11+ (face 5:9 x (ref 5:11 msg.right))
12+ (wing 5:21 x)))
13+ (value 6:1 c
14+ (gate 6:6
15+ (face 6:9 x (ref 6:11 msg.twin))
16+ (wing 6:20 x)))
17+ (value 7:1 from-left
18+ (cast 7:14 (ref 7:17 msg.left) (lit 7:26 %add)))
19+ (value 8:1 cross
20+ (group 8:10
21+ (call 8:11 (wing 8:11 c) (wing 8:13 from-left))))
22+ (value 9:1 apply
23+ (gate 9:10
24+ (face 9:13 f
25+ (fn 9:15 (ref 9:18 msg.left) (aura 9:27 @t)))
26+ (group 9:31
27+ (call 9:32 (wing 9:32 f) (wing 9:34 from-left)))))
28+ (value 10:1 other
29+ (gate 10:10
30+ (face 10:13 x (ref 10:15 msg.twin))
31+ (str 10:24 "hi")))
32+ (value 11:1 higher
33+ (group 11:11
34+ (call 11:12 (wing 11:12 apply) (wing 11:18 other)))))
tests/golden/types-union-print-distinct/types.txtnew file+9
@@ -0,0 +1,9 @@
1+partial inference; module not checked
2+++ a: $-(msg.left msg.left)
3+++ b: $-(msg.right msg.right)
4+++ c: $-(msg.twin msg.twin)
5+++ from-left: msg.left
6+++ cross: call constraint is not supported by partial inference
7+++ apply: $-($-(msg.left @t) @t)
8+++ other: $-(msg.twin @t)
9+++ higher: call constraint is not supported by partial inference
tests/golden/types-union-print-escape/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: every Jibb union has a name and names are read through module faces; unnamed unions print their cases.
2+tests: A body-local union that escapes a gate must not print an out-of-scope mold name.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-print-escape/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ create |= x=?
2+ +$ local-state
3+ %add
4+ %remove
5+ ^- local-state %add
tests/golden/types-union-print-escape/tokens.txtnew file+20
@@ -0,0 +1,20 @@
1+1:1 glyph ++
2+1:4 name create
3+1:11 glyph |=
4+1:14 name x
5+1:15 tight glyph =
6+1:16 tight glyph ?
7+2:3 INDENT
8+2:3 glyph +$
9+2:6 name local-state
10+3:5 INDENT
11+3:5 lit %add
12+4:5 NEWLINE
13+4:5 lit %remove
14+5:3 DEDENT
15+5:3 NEWLINE
16+5:3 glyph ^-
17+5:6 name local-state
18+5:18 lit %add
19+5:22 DEDENT
20+5:22 NEWLINE
tests/golden/types-union-print-escape/tree.txtnew file+8
@@ -0,0 +1,8 @@
1+(module
2+ (value 1:1 create
3+ (gate 1:11
4+ (face 1:14 x (flag 1:16))
5+ (body 2:3
6+ (mold 2:3 local-state
7+ (union 3:5 (const 3:5 %add) (const 4:5 %remove)))
8+ (cast 5:3 (ref 5:6 local-state) (lit 5:18 %add))))))
tests/golden/types-union-print-escape/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+++ create: $-(? (%add %remove))
tests/golden/types-union-print-local/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: every Jibb union has a name and names are read through module faces; unnamed unions print their cases.
2+tests: Direct and aliased uses of a local named union print as usable types.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-print-local/source.jibbnew file+6
@@ -0,0 +1,6 @@
1++$ msg
2+ %add
3+ %remove
4++$ alias msg
5+++ direct |= x=msg x
6+++ via |= x=alias x
tests/golden/types-union-print-local/tokens.txtnew file+28
@@ -0,0 +1,28 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 lit %add
5+3:3 NEWLINE
6+3:3 lit %remove
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph +$
10+4:4 name alias
11+4:10 name msg
12+5:1 NEWLINE
13+5:1 glyph ++
14+5:4 name direct
15+5:11 glyph |=
16+5:14 name x
17+5:15 tight glyph =
18+5:16 tight name msg
19+5:20 name x
20+6:1 NEWLINE
21+6:1 glyph ++
22+6:4 name via
23+6:8 glyph |=
24+6:11 name x
25+6:12 tight glyph =
26+6:13 tight name alias
27+6:19 name x
28+6:20 NEWLINE
tests/golden/types-union-print-local/tree.txtnew file+12
@@ -0,0 +1,12 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3 (const 2:3 %add) (const 3:3 %remove)))
4+ (mold 4:1 alias (ref 4:10 msg))
5+ (value 5:1 direct
6+ (gate 5:11
7+ (face 5:14 x (ref 5:16 msg))
8+ (wing 5:20 x)))
9+ (value 6:1 via
10+ (gate 6:8
11+ (face 6:11 x (ref 6:13 alias))
12+ (wing 6:19 x))))
tests/golden/types-union-print-local/types.txtnew file+5
@@ -0,0 +1,5 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3++$ alias: not checked
4+++ direct: $-(msg msg)
5+++ via: $-(msg msg)
tests/golden/types-union-print-nested/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: every Jibb union has a name and names are read through module faces; unnamed unions print their cases.
2+tests: A named union inside a record and a gate prints without losing its context.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-print-nested/source.jibbnew file+7
@@ -0,0 +1,7 @@
1++$ msg
2+ %add
3+ %remove
4++$ wrapped [state=msg title=@t]
5++$ handler $-(msg msg)
6+++ echo |= x=wrapped x
7+++ keep |= x=handler x
tests/golden/types-union-print-nested/tokens.txtnew file+42
@@ -0,0 +1,42 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 lit %add
5+3:3 NEWLINE
6+3:3 lit %remove
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph +$
10+4:4 name wrapped
11+4:12 glyph [
12+4:13 tight name state
13+4:18 tight glyph =
14+4:19 tight name msg
15+4:23 name title
16+4:28 tight glyph =
17+4:29 tight aura @t
18+4:31 tight glyph ]
19+5:1 NEWLINE
20+5:1 glyph +$
21+5:4 name handler
22+5:12 glyph $-(
23+5:15 tight name msg
24+5:19 name msg
25+5:22 tight glyph )
26+6:1 NEWLINE
27+6:1 glyph ++
28+6:4 name echo
29+6:9 glyph |=
30+6:12 name x
31+6:13 tight glyph =
32+6:14 tight name wrapped
33+6:22 name x
34+7:1 NEWLINE
35+7:1 glyph ++
36+7:4 name keep
37+7:9 glyph |=
38+7:12 name x
39+7:13 tight glyph =
40+7:14 tight name handler
41+7:22 name x
42+7:23 NEWLINE
tests/golden/types-union-print-nested/tree.txtnew file+17
@@ -0,0 +1,17 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3 (const 2:3 %add) (const 3:3 %remove)))
4+ (mold 4:1 wrapped
5+ (cell 4:12
6+ (face 4:13 state (ref 4:19 msg))
7+ (face 4:23 title (aura 4:29 @t))))
8+ (mold 5:1 handler
9+ (fn 5:12 (ref 5:15 msg) (ref 5:19 msg)))
10+ (value 6:1 echo
11+ (gate 6:9
12+ (face 6:12 x (ref 6:14 wrapped))
13+ (wing 6:22 x)))
14+ (value 7:1 keep
15+ (gate 7:9
16+ (face 7:12 x (ref 7:14 handler))
17+ (wing 7:22 x))))
tests/golden/types-union-print-nested/types.txtnew file+6
@@ -0,0 +1,6 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3++$ wrapped: not checked
4++$ handler: not checked
5+++ echo: $-([state=msg title=@t] [state=msg title=@t])
6+++ keep: $-($-(msg msg) $-(msg msg))
tests/golden/types-union-print-same-origin/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Modules: "Everything is exported and read through the import's face"; recursive mold identity uses name and module.
2+tests: Two faces import the same module; its named union may print through either face but the type remains compatible.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-print-same-origin/module-trees.txtnew file+4
@@ -0,0 +1,4 @@
1+/ui/shared.jibb
2+(module
3+ (mold 1:1 msg
4+ (union 2:3 (const 2:3 %add) (const 3:3 %remove))))
tests/golden/types-union-print-same-origin/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/shared.jibb
tests/golden/types-union-print-same-origin/modules/ui/shared.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ msg
2+ %add
3+ %remove
tests/golden/types-union-print-same-origin/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+/= first /ui/shared
2+/= second /ui/shared
3+++ selected ^- msg.first %add
4+++ consume |= x=msg.second x
5+++ passed (consume selected)
tests/golden/types-union-print-same-origin/tokens.txtnew file+35
@@ -0,0 +1,35 @@
1+1:1 glyph /=
2+1:5 name first
3+1:11 glyph /
4+1:12 tight knot ui
5+1:14 tight glyph /
6+1:15 tight knot shared
7+2:1 NEWLINE
8+2:1 glyph /=
9+2:5 name second
10+2:12 glyph /
11+2:13 tight knot ui
12+2:15 tight glyph /
13+2:16 tight knot shared
14+3:1 NEWLINE
15+3:1 glyph ++
16+3:4 name selected
17+3:13 glyph ^-
18+3:16 wing msg.first
19+3:26 lit %add
20+4:1 NEWLINE
21+4:1 glyph ++
22+4:4 name consume
23+4:12 glyph |=
24+4:15 name x
25+4:16 tight glyph =
26+4:17 tight wing msg.second
27+4:28 name x
28+5:1 NEWLINE
29+5:1 glyph ++
30+5:4 name passed
31+5:11 glyph (
32+5:12 tight name consume
33+5:20 name selected
34+5:28 tight glyph )
35+5:29 NEWLINE
tests/golden/types-union-print-same-origin/tree.txtnew file+12
@@ -0,0 +1,12 @@
1+(module
2+ (jibb 1:1 first /ui/shared)
3+ (jibb 2:1 second /ui/shared)
4+ (value 3:1 selected
5+ (cast 3:13 (ref 3:16 msg.first) (lit 3:26 %add)))
6+ (value 4:1 consume
7+ (gate 4:12
8+ (face 4:15 x (ref 4:17 msg.second))
9+ (wing 4:28 x)))
10+ (value 5:1 passed
11+ (group 5:11
12+ (call 5:12 (wing 5:12 consume) (wing 5:20 selected)))))
tests/golden/types-union-print-same-origin/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2+++ selected: msg.first
3+++ consume: $-(msg.second msg.second)
4+++ passed: msg.second
tests/golden/types-union-print-transitive/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: every Jibb union has a name and names are read through module faces; unnamed unions print their cases.
2+tests: A transitive imported union alias prints without referencing an inaccessible import face.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-print-transitive/module-trees.txtnew file+8
@@ -0,0 +1,8 @@
1+/ui/mid.jibb
2+(module
3+ (jibb 1:1 base /ui/base)
4+ (mold 2:1 relay (ref 2:10 state.base)))
5+/ui/base.jibb
6+(module
7+ (mold 1:1 state
8+ (union 2:3 (const 2:3 %on) (const 3:3 %off))))
tests/golden/types-union-print-transitive/modules.txtnew file+2
@@ -0,0 +1,2 @@
1+/ui/mid.jibb
2+/ui/base.jibb
tests/golden/types-union-print-transitive/modules/ui/base.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ state
2+ %on
3+ %off
tests/golden/types-union-print-transitive/modules/ui/mid.jibbnew file+2
@@ -0,0 +1,2 @@
1+/= base /ui/base
2++$ relay state.base
tests/golden/types-union-print-transitive/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+/= mid /ui/mid
2+++ echo |= x=relay.mid x
tests/golden/types-union-print-transitive/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph /=
2+1:5 name mid
3+1:9 glyph /
4+1:10 tight knot ui
5+1:12 tight glyph /
6+1:13 tight knot mid
7+2:1 NEWLINE
8+2:1 glyph ++
9+2:4 name echo
10+2:9 glyph |=
11+2:12 name x
12+2:13 tight glyph =
13+2:14 tight wing relay.mid
14+2:24 name x
15+2:25 NEWLINE
tests/golden/types-union-print-transitive/tree.txtnew file+6
@@ -0,0 +1,6 @@
1+(module
2+ (jibb 1:1 mid /ui/mid)
3+ (value 2:1 echo
4+ (gate 2:9
5+ (face 2:12 x (ref 2:14 relay.mid))
6+ (wing 2:24 x))))
tests/golden/types-union-print-transitive/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+++ echo: $-(relay.mid relay.mid)
tests/golden/types-union-singleton/types.txt+1−1
@@ -4,7 +4,7 @@ partial inference; module not checked
4+$ msg: cases proven disjoint; mold not checked
4+$ msg: cases proven disjoint; mold not checked
5++ go-value: [%go url=@t]
5++ go-value: [%go url=@t]
6++ constructor: $-(@t [%typed text=@t])
6++ constructor: $-(@t [%typed text=@t])
7−++ union-constructor: union type printing is not supported by partial inference
7+++ union-constructor: $-(@t msg)
8++ wrong-input: cast mold and expression type do not unify
8++ wrong-input: cast mold and expression type do not unify
9/tests/golden/types-union-singleton/source.jibb:9:19: cast mold has type $-(@ud [%typed text=@t])
9/tests/golden/types-union-singleton/source.jibb:9:19: cast mold has type $-(@ud [%typed text=@t])
10++ wrong-input ^- $-(@ud typed) |=%typed
10++ wrong-input ^- $-(@ud typed) |=%typed
tests/golden/types-union-tags/types.txt+2−2
@@ -1,7 +1,7 @@
1partial inference; module not checked
1partial inference; module not checked
2+$ msg: cases proven disjoint; mold not checked
2+$ msg: cases proven disjoint; mold not checked
3−++ simple: union type printing is not supported by partial inference
3+++ simple: msg
4−++ record: union type printing is not supported by partial inference
4+++ record: msg
5++ wrong: cast mold and expression type do not unify
5++ wrong: cast mold and expression type do not unify
6/tests/golden/types-union-tags/source.jibb:6:13: cast mold
6/tests/golden/types-union-tags/source.jibb:6:13: cast mold
7++ wrong ^- msg %missing
7++ wrong ^- msg %missing
tests/lib/jibb.hoon+119−42
@@ -1566,40 +1566,95 @@
1566/* tok-460 %txt /tests/golden/types-union-alias/tokens/txt
1566/* tok-460 %txt /tests/golden/types-union-alias/tokens/txt
1567/* tre-460 %txt /tests/golden/types-union-alias/tree/txt
1567/* tre-460 %txt /tests/golden/types-union-alias/tree/txt
1568/* typ-460 %txt /tests/golden/types-union-alias/types/txt
1568/* typ-460 %txt /tests/golden/types-union-alias/types/txt
1569−/* src-461 %jibb /tests/golden/types-union-context-flow/source/jibb
1569+/* src-461 %jibb /tests/golden/types-union-constructor-shape/source/jibb
1570+/* tok-461 %txt /tests/golden/types-union-constructor-shape/tokens/txt
1571+/* tre-461 %txt /tests/golden/types-union-constructor-shape/tree/txt
1572+/* typ-461 %txt /tests/golden/types-union-constructor-shape/types/txt
1573+/* src-462 %jibb /tests/golden/types-union-context-flow/source/jibb
1574+/* tok-462 %txt /tests/golden/types-union-context-flow/tokens/txt
1575+/* tre-462 %txt /tests/golden/types-union-context-flow/tree/txt
1576+/* typ-462 %txt /tests/golden/types-union-context-flow/types/txt
1577+/* src-463 %jibb /tests/golden/types-union-import/source/jibb
1578+/* tok-463 %txt /tests/golden/types-union-import/tokens/txt
1579+/* tre-463 %txt /tests/golden/types-union-import/tree/txt
1580+/* mod-463-1 %jibb /tests/golden/types-union-import/modules/ui/lib/jibb
1581+/* typ-463 %txt /tests/golden/types-union-import/types/txt
1582+/* mtre-463 %txt /tests/golden/types-union-import/module-trees/txt
1583+/* src-464 %jibb /tests/golden/types-union-local-pending/source/jibb
1584+/* tok-464 %txt /tests/golden/types-union-local-pending/tokens/txt
1585+/* tre-464 %txt /tests/golden/types-union-local-pending/tree/txt
1586+/* typ-464 %txt /tests/golden/types-union-local-pending/types/txt
1587+/* src-465 %jibb /tests/golden/types-union-overlap/source/jibb
1588+/* tok-465 %txt /tests/golden/types-union-overlap/tokens/txt
1589+/* tre-465 %txt /tests/golden/types-union-overlap/tree/txt
1590+/* typ-465 %txt /tests/golden/types-union-overlap/types/txt
1591+/* src-466 %jibb /tests/golden/types-union-overlap-nested/source/jibb
1592+/* tok-466 %txt /tests/golden/types-union-overlap-nested/tokens/txt
1593+/* tre-466 %txt /tests/golden/types-union-overlap-nested/tree/txt
1594+/* typ-466 %txt /tests/golden/types-union-overlap-nested/types/txt
1595+/* src-467 %jibb /tests/golden/types-union-phantom-generic/source/jibb
1596+/* tok-467 %txt /tests/golden/types-union-phantom-generic/tokens/txt
1597+/* tre-467 %txt /tests/golden/types-union-phantom-generic/tree/txt
1598+/* typ-467 %txt /tests/golden/types-union-phantom-generic/types/txt
1599+/* src-468 %jibb /tests/golden/types-union-print-cross-namespace/source/jibb
1600+/* tok-468 %txt /tests/golden/types-union-print-cross-namespace/tokens/txt
1601+/* tre-468 %txt /tests/golden/types-union-print-cross-namespace/tree/txt
1602+/* mod-468-1 %jibb /tests/golden/types-union-print-cross-namespace/modules/ui/lib/jibb
1603+/* typ-468 %txt /tests/golden/types-union-print-cross-namespace/types/txt
1604+/* mtre-468 %txt /tests/golden/types-union-print-cross-namespace/module-trees/txt
1605+/* src-469 %jibb /tests/golden/types-union-print-distinct/source/jibb
1606+/* tok-469 %txt /tests/golden/types-union-print-distinct/tokens/txt
1607+/* tre-469 %txt /tests/golden/types-union-print-distinct/tree/txt
1608+/* mod-469-1 %jibb /tests/golden/types-union-print-distinct/modules/ui/left/jibb
1609+/* mod-469-2 %jibb /tests/golden/types-union-print-distinct/modules/ui/right/jibb
1610+/* mod-469-3 %jibb /tests/golden/types-union-print-distinct/modules/ui/twin/jibb
1611+/* typ-469 %txt /tests/golden/types-union-print-distinct/types/txt
1612+/* mtre-469 %txt /tests/golden/types-union-print-distinct/module-trees/txt
1613+/* src-470 %jibb /tests/golden/types-union-print-escape/source/jibb
1614+/* tok-470 %txt /tests/golden/types-union-print-escape/tokens/txt
1615+/* tre-470 %txt /tests/golden/types-union-print-escape/tree/txt
1616+/* typ-470 %txt /tests/golden/types-union-print-escape/types/txt
1617+/* src-471 %jibb /tests/golden/types-union-print-local/source/jibb
1618+/* tok-471 %txt /tests/golden/types-union-print-local/tokens/txt
1619+/* tre-471 %txt /tests/golden/types-union-print-local/tree/txt
1620+/* typ-471 %txt /tests/golden/types-union-print-local/types/txt
1621+/* src-472 %jibb /tests/golden/types-union-print-nested/source/jibb
1570−/* tok-461 %txt /tests/golden/types-union-context-flow/tokens/txt
1622+/* tok-472 %txt /tests/golden/types-union-print-nested/tokens/txt
1571−/* tre-461 %txt /tests/golden/types-union-context-flow/tree/txt
1623+/* tre-472 %txt /tests/golden/types-union-print-nested/tree/txt
1572−/* typ-461 %txt /tests/golden/types-union-context-flow/types/txt
1624+/* typ-472 %txt /tests/golden/types-union-print-nested/types/txt
1573−/* src-462 %jibb /tests/golden/types-union-import/source/jibb
1625+/* src-473 %jibb /tests/golden/types-union-print-same-origin/source/jibb
1574−/* tok-462 %txt /tests/golden/types-union-import/tokens/txt
1626+/* tok-473 %txt /tests/golden/types-union-print-same-origin/tokens/txt
1575−/* tre-462 %txt /tests/golden/types-union-import/tree/txt
1627+/* tre-473 %txt /tests/golden/types-union-print-same-origin/tree/txt
1576−/* mod-462-1 %jibb /tests/golden/types-union-import/modules/ui/lib/jibb
1628+/* mod-473-1 %jibb /tests/golden/types-union-print-same-origin/modules/ui/shared/jibb
1577−/* typ-462 %txt /tests/golden/types-union-import/types/txt
1629+/* typ-473 %txt /tests/golden/types-union-print-same-origin/types/txt
1578−/* mtre-462 %txt /tests/golden/types-union-import/module-trees/txt
1630+/* mtre-473 %txt /tests/golden/types-union-print-same-origin/module-trees/txt
1579−/* src-463 %jibb /tests/golden/types-union-overlap/source/jibb
1631+/* src-474 %jibb /tests/golden/types-union-print-transitive/source/jibb
1580−/* tok-463 %txt /tests/golden/types-union-overlap/tokens/txt
1632+/* tok-474 %txt /tests/golden/types-union-print-transitive/tokens/txt
1581−/* tre-463 %txt /tests/golden/types-union-overlap/tree/txt
1633+/* tre-474 %txt /tests/golden/types-union-print-transitive/tree/txt
1634+/* mod-474-1 %jibb /tests/golden/types-union-print-transitive/modules/ui/mid/jibb
1635+/* mod-474-2 %jibb /tests/golden/types-union-print-transitive/modules/ui/base/jibb
1582−/* typ-463 %txt /tests/golden/types-union-overlap/types/txt
1636+/* typ-474 %txt /tests/golden/types-union-print-transitive/types/txt
1637+/* mtre-474 %txt /tests/golden/types-union-print-transitive/module-trees/txt
1583−/* src-464 %jibb /tests/golden/types-union-singleton/source/jibb
1638+/* src-475 %jibb /tests/golden/types-union-singleton/source/jibb
1584−/* tok-464 %txt /tests/golden/types-union-singleton/tokens/txt
1639+/* tok-475 %txt /tests/golden/types-union-singleton/tokens/txt
1585−/* tre-464 %txt /tests/golden/types-union-singleton/tree/txt
1640+/* tre-475 %txt /tests/golden/types-union-singleton/tree/txt
1586−/* typ-464 %txt /tests/golden/types-union-singleton/types/txt
1641+/* typ-475 %txt /tests/golden/types-union-singleton/types/txt
1587−/* src-465 %jibb /tests/golden/types-union-tag-atoms/source/jibb
1642+/* src-476 %jibb /tests/golden/types-union-tag-atoms/source/jibb
1588−/* tok-465 %txt /tests/golden/types-union-tag-atoms/tokens/txt
1643+/* tok-476 %txt /tests/golden/types-union-tag-atoms/tokens/txt
1589−/* tre-465 %txt /tests/golden/types-union-tag-atoms/tree/txt
1644+/* tre-476 %txt /tests/golden/types-union-tag-atoms/tree/txt
1590−/* typ-465 %txt /tests/golden/types-union-tag-atoms/types/txt
1645+/* typ-476 %txt /tests/golden/types-union-tag-atoms/types/txt
1591−/* src-466 %jibb /tests/golden/types-union-tags/source/jibb
1646+/* src-477 %jibb /tests/golden/types-union-tags/source/jibb
1592−/* tok-466 %txt /tests/golden/types-union-tags/tokens/txt
1647+/* tok-477 %txt /tests/golden/types-union-tags/tokens/txt
1593−/* tre-466 %txt /tests/golden/types-union-tags/tree/txt
1648+/* tre-477 %txt /tests/golden/types-union-tags/tree/txt
1594−/* typ-466 %txt /tests/golden/types-union-tags/types/txt
1649+/* typ-477 %txt /tests/golden/types-union-tags/types/txt
1595−/* src-467 %jibb /tests/golden/types-union-unresolved/source/jibb
1650+/* src-478 %jibb /tests/golden/types-union-unresolved/source/jibb
1596−/* tok-467 %txt /tests/golden/types-union-unresolved/tokens/txt
1651+/* tok-478 %txt /tests/golden/types-union-unresolved/tokens/txt
1597−/* tre-467 %txt /tests/golden/types-union-unresolved/tree/txt
1652+/* tre-478 %txt /tests/golden/types-union-unresolved/tree/txt
1598−/* typ-467 %txt /tests/golden/types-union-unresolved/types/txt
1653+/* typ-478 %txt /tests/golden/types-union-unresolved/types/txt
1599−/* src-468 %jibb /tests/golden/types-union-unresolved-flow/source/jibb
1654+/* src-479 %jibb /tests/golden/types-union-unresolved-flow/source/jibb
1600−/* tok-468 %txt /tests/golden/types-union-unresolved-flow/tokens/txt
1655+/* tok-479 %txt /tests/golden/types-union-unresolved-flow/tokens/txt
1601−/* tre-468 %txt /tests/golden/types-union-unresolved-flow/tree/txt
1656+/* tre-479 %txt /tests/golden/types-union-unresolved-flow/tree/txt
1602−/* typ-468 %txt /tests/golden/types-union-unresolved-flow/types/txt
1657+/* typ-479 %txt /tests/golden/types-union-unresolved-flow/types/txt
1603|%
1658|%
1604:: one arm per case
1659:: one arm per case
1605::
1660::
@@ -2523,22 +2578,44 @@
2523 (weld (check ~.types-record-to-tuple src-459 `tok-459 `tre-459) (check-types ~.types-record-to-tuple ~[%tests %golden ~.types-record-to-tuple %source %jibb] src-459 `typ-459))
2578 (weld (check ~.types-record-to-tuple src-459 `tok-459 `tre-459) (check-types ~.types-record-to-tuple ~[%tests %golden ~.types-record-to-tuple %source %jibb] src-459 `typ-459))
2524++ test-types-union-alias
2579++ test-types-union-alias
2525 (weld (check ~.types-union-alias src-460 `tok-460 `tre-460) (check-types ~.types-union-alias ~[%tests %golden ~.types-union-alias %source %jibb] src-460 `typ-460))
2580 (weld (check ~.types-union-alias src-460 `tok-460 `tre-460) (check-types ~.types-union-alias ~[%tests %golden ~.types-union-alias %source %jibb] src-460 `typ-460))
2581+++ test-types-union-constructor-shape
2582+ (weld (check ~.types-union-constructor-shape src-461 `tok-461 `tre-461) (check-types ~.types-union-constructor-shape ~[%tests %golden ~.types-union-constructor-shape %source %jibb] src-461 `typ-461))
2526++ test-types-union-context-flow
2583++ test-types-union-context-flow
2527− (weld (check ~.types-union-context-flow src-461 `tok-461 `tre-461) (check-types ~.types-union-context-flow ~[%tests %golden ~.types-union-context-flow %source %jibb] src-461 `typ-461))
2584+ (weld (check ~.types-union-context-flow src-462 `tok-462 `tre-462) (check-types ~.types-union-context-flow ~[%tests %golden ~.types-union-context-flow %source %jibb] src-462 `typ-462))
2528++ test-types-union-import
2585++ test-types-union-import
2529− (weld (weld (check ~.types-union-import src-462 `tok-462 `tre-462) (check-module-types ~.types-union-import ~[%tests %golden ~.types-union-import %source %jibb] src-462 `typ-462 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-462-1]])) (check-module-trees ~.types-union-import `mtre-462 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-462-1]]))
2586+ (weld (weld (check ~.types-union-import src-463 `tok-463 `tre-463) (check-module-types ~.types-union-import ~[%tests %golden ~.types-union-import %source %jibb] src-463 `typ-463 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-463-1]])) (check-module-trees ~.types-union-import `mtre-463 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-463-1]]))
2587+++ test-types-union-local-pending
2588+ (weld (check ~.types-union-local-pending src-464 `tok-464 `tre-464) (check-types ~.types-union-local-pending ~[%tests %golden ~.types-union-local-pending %source %jibb] src-464 `typ-464))
2530++ test-types-union-overlap
2589++ test-types-union-overlap
2531− (weld (check ~.types-union-overlap src-463 `tok-463 `tre-463) (check-types ~.types-union-overlap ~[%tests %golden ~.types-union-overlap %source %jibb] src-463 `typ-463))
2590+ (weld (check ~.types-union-overlap src-465 `tok-465 `tre-465) (check-types ~.types-union-overlap ~[%tests %golden ~.types-union-overlap %source %jibb] src-465 `typ-465))
2591+++ test-types-union-overlap-nested
2592+ (weld (check ~.types-union-overlap-nested src-466 `tok-466 `tre-466) (check-types ~.types-union-overlap-nested ~[%tests %golden ~.types-union-overlap-nested %source %jibb] src-466 `typ-466))
2593+++ test-types-union-phantom-generic
2594+ (weld (check ~.types-union-phantom-generic src-467 `tok-467 `tre-467) (check-types ~.types-union-phantom-generic ~[%tests %golden ~.types-union-phantom-generic %source %jibb] src-467 `typ-467))
2595+++ test-types-union-print-cross-namespace
2596+ (weld (weld (check ~.types-union-print-cross-namespace src-468 `tok-468 `tre-468) (check-module-types ~.types-union-print-cross-namespace ~[%tests %golden ~.types-union-print-cross-namespace %source %jibb] src-468 `typ-468 ~ ~ ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-468-1]])) (check-module-trees ~.types-union-print-cross-namespace `mtre-468 ~[['/ui/lib.jibb' ~[~.ui ~.lib ~.jibb] mod-468-1]]))
2597+++ test-types-union-print-distinct
2598+ (weld (weld (check ~.types-union-print-distinct src-469 `tok-469 `tre-469) (check-module-types ~.types-union-print-distinct ~[%tests %golden ~.types-union-print-distinct %source %jibb] src-469 `typ-469 ~ ~ ~[['/ui/left.jibb' ~[~.ui ~.left ~.jibb] mod-469-1] ['/ui/right.jibb' ~[~.ui ~.right ~.jibb] mod-469-2] ['/ui/twin.jibb' ~[~.ui ~.twin ~.jibb] mod-469-3]])) (check-module-trees ~.types-union-print-distinct `mtre-469 ~[['/ui/left.jibb' ~[~.ui ~.left ~.jibb] mod-469-1] ['/ui/right.jibb' ~[~.ui ~.right ~.jibb] mod-469-2] ['/ui/twin.jibb' ~[~.ui ~.twin ~.jibb] mod-469-3]]))
2599+++ test-types-union-print-escape
2600+ (weld (check ~.types-union-print-escape src-470 `tok-470 `tre-470) (check-types ~.types-union-print-escape ~[%tests %golden ~.types-union-print-escape %source %jibb] src-470 `typ-470))
2601+++ test-types-union-print-local
2602+ (weld (check ~.types-union-print-local src-471 `tok-471 `tre-471) (check-types ~.types-union-print-local ~[%tests %golden ~.types-union-print-local %source %jibb] src-471 `typ-471))
2603+++ test-types-union-print-nested
2604+ (weld (check ~.types-union-print-nested src-472 `tok-472 `tre-472) (check-types ~.types-union-print-nested ~[%tests %golden ~.types-union-print-nested %source %jibb] src-472 `typ-472))
2605+++ test-types-union-print-same-origin
2606+ (weld (weld (check ~.types-union-print-same-origin src-473 `tok-473 `tre-473) (check-module-types ~.types-union-print-same-origin ~[%tests %golden ~.types-union-print-same-origin %source %jibb] src-473 `typ-473 ~ ~ ~[['/ui/shared.jibb' ~[~.ui ~.shared ~.jibb] mod-473-1]])) (check-module-trees ~.types-union-print-same-origin `mtre-473 ~[['/ui/shared.jibb' ~[~.ui ~.shared ~.jibb] mod-473-1]]))
2607+++ test-types-union-print-transitive
2608+ (weld (weld (check ~.types-union-print-transitive src-474 `tok-474 `tre-474) (check-module-types ~.types-union-print-transitive ~[%tests %golden ~.types-union-print-transitive %source %jibb] src-474 `typ-474 ~ ~ ~[['/ui/mid.jibb' ~[~.ui ~.mid ~.jibb] mod-474-1] ['/ui/base.jibb' ~[~.ui ~.base ~.jibb] mod-474-2]])) (check-module-trees ~.types-union-print-transitive `mtre-474 ~[['/ui/mid.jibb' ~[~.ui ~.mid ~.jibb] mod-474-1] ['/ui/base.jibb' ~[~.ui ~.base ~.jibb] mod-474-2]]))
2532++ test-types-union-singleton
2609++ test-types-union-singleton
2533− (weld (check ~.types-union-singleton src-464 `tok-464 `tre-464) (check-types ~.types-union-singleton ~[%tests %golden ~.types-union-singleton %source %jibb] src-464 `typ-464))
2610+ (weld (check ~.types-union-singleton src-475 `tok-475 `tre-475) (check-types ~.types-union-singleton ~[%tests %golden ~.types-union-singleton %source %jibb] src-475 `typ-475))
2534++ test-types-union-tag-atoms
2611++ test-types-union-tag-atoms
2535− (weld (check ~.types-union-tag-atoms src-465 `tok-465 `tre-465) (check-types ~.types-union-tag-atoms ~[%tests %golden ~.types-union-tag-atoms %source %jibb] src-465 `typ-465))
2612+ (weld (check ~.types-union-tag-atoms src-476 `tok-476 `tre-476) (check-types ~.types-union-tag-atoms ~[%tests %golden ~.types-union-tag-atoms %source %jibb] src-476 `typ-476))
2536++ test-types-union-tags
2613++ test-types-union-tags
2537− (weld (check ~.types-union-tags src-466 `tok-466 `tre-466) (check-types ~.types-union-tags ~[%tests %golden ~.types-union-tags %source %jibb] src-466 `typ-466))
2614+ (weld (check ~.types-union-tags src-477 `tok-477 `tre-477) (check-types ~.types-union-tags ~[%tests %golden ~.types-union-tags %source %jibb] src-477 `typ-477))
2538++ test-types-union-unresolved
2615++ test-types-union-unresolved
2539− (weld (check ~.types-union-unresolved src-467 `tok-467 `tre-467) (check-types ~.types-union-unresolved ~[%tests %golden ~.types-union-unresolved %source %jibb] src-467 `typ-467))
2616+ (weld (check ~.types-union-unresolved src-478 `tok-478 `tre-478) (check-types ~.types-union-unresolved ~[%tests %golden ~.types-union-unresolved %source %jibb] src-478 `typ-478))
2540++ test-types-union-unresolved-flow
2617++ test-types-union-unresolved-flow
2541− (weld (check ~.types-union-unresolved-flow src-468 `tok-468 `tre-468) (check-types ~.types-union-unresolved-flow ~[%tests %golden ~.types-union-unresolved-flow %source %jibb] src-468 `typ-468))
2618+ (weld (check ~.types-union-unresolved-flow src-479 `tok-479 `tre-479) (check-types ~.types-union-unresolved-flow ~[%tests %golden ~.types-union-unresolved-flow %source %jibb] src-479 `typ-479))
2542::
2619::
2543:: +check: run golden:jibb on a case and compare both outputs
2620:: +check: run golden:jibb on a case and compare both outputs
2544::
2621::