on master help sign in
Resolve contextual tags and check Hoon union cases
commit4406f6fa95698558b8a2182e602e9eb6f920e4e3 authoriko <mail@iko.soy> dateFri 30 Oct 2026, 19:45 (6 hours ago) parentedd9277
72 files changed+1120−42
docs/compiler.md+2−2 docs/development.md+1−1 docs/open-questions.md+1−1 docs/status.md+7−6 jibb-dev/lib/jibb-import.hoon+126−9 jibb-dev/lib/jibb.hoon+185−7 tests/golden/module-cache-incomplete/about.txt+1−1 tests/golden/module-cache-incomplete/module-trees.txt+6−1 tests/golden/module-cache-incomplete/modules/ui/bad.jibb+3−3 tests/golden/types-partial-local-molds/about.txt+2−1 tests/golden/types-partial-local-molds/types.txt+1−1 tests/golden/types-partial-unresolved-tag/about.txt+1−1 tests/golden/types-partial-unresolved-tag/types.txt+1−1 tests/golden/types-union-alias/about.txt+4 tests/golden/types-union-alias/source.jibb+5 tests/golden/types-union-alias/tokens.txt+23 tests/golden/types-union-alias/tree.txt+10 tests/golden/types-union-alias/types.txt+4 tests/golden/types-union-context-flow/about.txt+4 tests/golden/types-union-context-flow/source.jibb+13 tests/golden/types-union-context-flow/tokens.txt+58 tests/golden/types-union-context-flow/tree.txt+26 tests/golden/types-union-context-flow/types.txt+6 tests/golden/types-union-import/about.txt+4 tests/golden/types-union-import/module-trees.txt+8 tests/golden/types-union-import/modules.txt+1 tests/golden/types-union-import/modules/ui/lib.jibb+3 tests/golden/types-union-import/source.jibb+2 tests/golden/types-union-import/tokens.txt+13 tests/golden/types-union-import/tree.txt+4 tests/golden/types-union-import/types.txt+2 tests/golden/types-union-overlap/about.txt+4 tests/golden/types-union-overlap/source.jibb+4 tests/golden/types-union-overlap/tokens.txt+15 tests/golden/types-union-overlap/tree.txt+5 tests/golden/types-union-overlap/types.txt+9 tests/golden/types-union-singleton/about.txt+4 tests/golden/types-union-singleton/source.jibb+16 tests/golden/types-union-singleton/tokens.txt+130 tests/golden/types-union-singleton/tree.txt+53 tests/golden/types-union-singleton/types.txt+33 tests/golden/types-union-tag-atoms/about.txt+4 tests/golden/types-union-tag-atoms/source.jibb+5 tests/golden/types-union-tag-atoms/tokens.txt+30 tests/golden/types-union-tag-atoms/tree.txt+11 tests/golden/types-union-tag-atoms/types.txt+12 tests/golden/types-union-tags/about.txt+4 tests/golden/types-union-tags/source.jibb+6 tests/golden/types-union-tags/tokens.txt+34 tests/golden/types-union-tags/tree.txt+15 tests/golden/types-union-tags/types.txt+11 tests/golden/types-union-unresolved-flow/about.txt+4 tests/golden/types-union-unresolved-flow/source.jibb+7 tests/golden/types-union-unresolved-flow/tokens.txt+31 tests/golden/types-union-unresolved-flow/tree.txt+12 tests/golden/types-union-unresolved-flow/types.txt+6 tests/golden/types-union-unresolved/about.txt+4 tests/golden/types-union-unresolved/source.jibb+1 tests/golden/types-union-unresolved/tokens.txt+4 tests/golden/types-union-unresolved/tree.txt+2 tests/golden/types-union-unresolved/types.txt+2 tests/importer/about.txt+5−4 tests/importer/ford.txt+1 tests/importer/origin-transitive.txt+1 tests/importer/shadow-static.txt+2 tests/importer/small.txt+12 tests/importer/tree.txt+21−1 tests/lib/jibb-module-scope.hoon+10−1 tests/lib/jibb.hoon+56 tests/type-module-scope/about.txt+2 tests/type-module-scope/expected.txt+4 tools/importer-test+1−1
docs/compiler.md+2−2
@@ -56,9 +56,9 @@ The core is split into chapters, `+| %name`, in this order:
5656| `%span-check` | `+check-spans`, which `+golden` runs on every tree, and `+check-spans-test` |
5757| `%type-inference` | The initial inference fragment and its unification helpers; not yet a module type checker |
5858
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. Recursive local groups and recursive or union molds 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, deferred constraints, recursive or union 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 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, 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.
6060
61−The 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. A single nested `$^` in a record is checked when its branches and sibling fields use only aura atom molds such as `@ud`, constant tags and records built from them; both source branches are re-evaluated, unchanged siblings are verified and overlapping cases are rejected. Other nested `$^`, including `$^` in collection arguments, is rejected; 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.
61+The 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.
6262
6363Callers that have a `/sur` core and a name can use `+read-named`: it checks for a locally declared arm before asking Hoon to evaluate the mold, and reports evaluation failures with the final Hoon trace line. `+read-mold-in` remains available when the caller already has the selected type. The checker currently treats a failed import as unsupported rather than rendering the importer's error.
6464
docs/development.md+1−1
@@ -62,7 +62,7 @@ git clone https://github.com/urbit/tools /root/src/tools
6262| `tools/importer-test` | Compares the partial Hoon importer's diagnostic trees and errors with `tests/importer/tree.txt` under `urbit eval` |
6363| `tools/type-import-test` | Composes the Hoon importer with the partial checker and compares `tests/type-import/expected.txt` under eval |
6464| `tools/type-mark-test` | Checks the partial checker’s mark import boundary against `tests/type-mark/expected.txt` under eval |
65−| `tools/type-module-scope-test` | Checks the partial module checker’s prelude boundary against `tests/type-module-scope/expected.txt` under eval |
65+| `tools/type-module-scope-test` | Checks the partial module checker’s prelude boundary and duplicate-source rejection against `tests/type-module-scope/expected.txt` under eval |
6666| `tools/clay-fixtures` | Syncs `my-app`, builds its example `/sur` files and marks through Clay, checks selected mold and mark projections and the partial checker, and records Ford and mark subject shapes on the fake ship |
6767| `tools/hoon` | Evaluates Hoon with the library in scope, as `tools/hoon '(golden /a/b/jibb (crip "++ main view"))'`; `--cord name=file` binds a file's text, `-f` reads the expression from a file |
6868| `tools/doc-blocks` | Checks the doc's `jibb` blocks against the `doc-*` golden cases: `tools/doc-blocks docs/spec` |
docs/open-questions.md+1−1
@@ -41,7 +41,7 @@ Found while writing [prompts/milestone-2.md](prompts/milestone-2.md) and checkin
414119. **Settled: Hoon aura families and `step.hoon`.** On 2026-10-30, @iko chose `step.hoon` for Hoon 1c `step`, avoiding a clash with the Grammar example's `step`, and chose one-way widening across Hoon aura families: for example, `@ud` and `@ux` fit `@u`, and `@tD` fits `@t`. The reverse needs a check. The `step.hoon` group representation is not implemented yet.
424220. **The type of Hoon `clap`.** Hoon allows its two input units and combining gate's result to have different types. If only one unit is present it returns that unit; when both are present it returns the combining gate's result. Jibb branches normally need a common type, while every union written in Jibb has a name. Should the Jibb gate require a shared type, infer an unnamed union of the possible values, or wait for a different typing design? Asked @iko on 2026-10-30. `clap` is not implemented while this is open.
434321. **Duplicate faces in imported Hoon records.** Hoon permits `[a=@ud a=@t]`, and its lookup picks the first `a`. Should Jibb reject the imported type where it is used, use the first field, or permit the type but reject access to the ambiguous field? Asked @iko on 2026-10-30. The inference fragment currently permits the type but declines ambiguous field access (doc question).
44−22. **Overlapping imported `$%` and `$?` cases.** The Grammar says a union whose cases don't all differ as nouns is rejected, while the import table explicitly mentions that condition only for `$^`; its `$%` and `$?` row says they become a union. Does the general disjointness rule reject imported `$%` and `$?` cases such as `[%x @ud]` and `[%x @t]` where the type is used? Asked @iko on 2026-10-30. The general rule is the provisional reading (doc question); the importer currently accepts some overlaps, and a fix is in progress.
44+22. **Overlapping imported `$%` and `$?` cases.** The Grammar says a union whose cases don't all differ as nouns is rejected, while the import table explicitly mentions that condition only for `$^`; its `$%` and `$?` row says they become a union. Does the general disjointness rule reject imported `$%` and `$?` cases such as `[%x @ud]` and `[%x @t]` where the type is used? Asked @iko on 2026-10-30. The general rule is the provisional reading (doc question); the importer rejects recognizable overlaps and fails closed when it cannot verify them.
4545
4646## Grammar questions never put to the doc's author
4747
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
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 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; one nested `$^` in a static record of aura and constant-tag molds is checked, while other nested `$^`, 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, and selected faced record casts and field reads. 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, 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. 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.
2323
2424## Milestone 1: parser and mark
2525
@@ -37,8 +37,8 @@ What the plan asks for, and where it is:
3737
3838Besides the plan's list:
3939
40−- 459 golden cases: 243 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 459-case corpus passed under `urbit eval` in 33.6 s. The fake ship passed all 464 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 24.0 s for sync and 29.8 s for tests. The importer golden compares 110 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.
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.
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.
4242- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
4343- 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.
4444- 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).
@@ -67,14 +67,15 @@ Besides the plan's list:
6767| 529736a | 2026-10-30 | Infer supported library import graphs and guard nested Hoon `$^` in collections |
6868| 8bf1b12 | 2026-10-30 | Infer selected record faces and check nested `$^` in static Hoon records |
6969| d8ac47d | 2026-10-30 | Cache library interfaces, preserve imported Hoon record faces, and check nested tagged unions |
70−| This change | 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 |
7172
7273## Checking it
7374
7475On a machine set up as [development.md](development.md) says:
7576
7677```
77−tools/golden # 459 cases under urbit eval
78+tools/golden # 468 cases under urbit eval
7879tools/importer-test # the Hoon importer fixture projection
7980tools/type-import-test # the importer/checker bridge fixture
8081tools/type-mark-test # the mark/checker bridge fixture
@@ -84,7 +85,7 @@ tools/testdata/selftest # the tools themselves
8485tools/doc-blocks docs/spec # the doc's examples are golden cases
8586tools/ship start
8687tools/ship gen-tests --check # tests/lib/jibb.hoon is up to date
87−tools/ship test # the same 459 cases as -test arms on the ship
88+tools/ship test # the same 468 cases as -test arms on the ship
8889tools/testdata/ship-selftest
8990tools/ship check-commit # |commit stores .jibb files
9091tools/clay-fixtures # example /sur files and marks build through Clay
jibb-dev/lib/jibb-import.hoon+126−9
@@ -383,6 +383,30 @@
383383 ?: ?=([%bckt ^ ^] h) &
384384 |($(h -.h) $(h +.h))
385385::
386+:: (doc question 22) The Grammar's disjointness rule is applied to
387+:: imported $% and $? too. The import table singles out $^, so @iko
388+:: has been asked whether that general rule also covers those unions.
389+++ has-spec-general-union
390+ |= h=*
391+ ^- ?
392+ ?@ h |
393+ ?: ?=([%bcwt [^ [^ *]]] h) &
394+ ?: ?=([%bccn [^ [^ *]]] h) &
395+ |($(h -.h) $(h +.h))
396+::
397+++ has-fits-union
398+ |= h=*
399+ ^- ?
400+ ?@ h |
401+ ?: ?=([%wtcl [%fits *] * *] h) &
402+ |($(h -.h) $(h +.h))
403+::
404+++ fits-union-at
405+ |= [h=hoon axis=@ud]
406+ ^- ?
407+ ?. ?=([%fits *] h) |
408+ |(=(q.h ~[[%.y axis]]) =(q.h ~[[%.y (mul 2 axis)]]))
409+::
386410++ has-cell-union
387411 |= h=hoon
388412 ^- ?
@@ -403,6 +427,7 @@
403427 |($(h -.h, axis (mul 2 axis)) $(h +.h, axis (add 1 (mul 2 axis))))
404428 ?+ h (has-cell-union-any h)
405429 [%note *] $(h q.h)
430+ [%dbug *] $(h q.h)
406431 [%ktts *] $(h q.h)
407432 [%wtcl *]
408433 ?: =(p.h [%dtwt [%$ (mul 2 axis)]]) &
@@ -438,9 +463,17 @@
438463 &($(h -.h, axis (mul 2 axis)) $(h +.h, axis (add 1 (mul 2 axis))))
439464 ?+ h |
440465 [%note *] $(h q.h)
466+ [%dbug *] $(h q.h)
441467 [%ktts *] $(h q.h)
442468 [%ktls *] ?=([%sand *] p.h)
469+ [%cncl *]
470+ ?: =(h [%cncl [%tsgr [%wing ~[[%.y 7]]] [%wing ~[%path]]] ~[[%$ axis]]]) &
471+ (static-collection h)
472+ [%wtcl *]
473+ ?. (fits-union-at p.h axis) |
474+ &($(h q.h) $(h r.h))
443475 [%wtgr *]
476+ ?: =(h [%wtgr [%dtts [%bust %noun] [%$ axis]] [%rock %n 0]]) &
444477 ?. ?=([%dtts [%$ *] [%rock %$ *]] p.h) |
445478 ?. ?=([%rock %tas *] q.h) |
446479 ?^ q.q.h |
@@ -466,12 +499,16 @@
466499 =/ out $(h q.h)
467500 ?~ out ~
468501 [~ [h(q one.u.out) h(q two.u.out)]]
502+ [%dbug *]
503+ =/ out $(h q.h)
504+ ?~ out ~
505+ [~ [h(q one.u.out) h(q two.u.out)]]
469506 [%ktts *]
470507 =/ out $(h q.h)
471508 ?~ out ~
472509 [~ [h(q one.u.out) h(q two.u.out)]]
473510 [%wtcl *]
474− ?. =(p.h [%dtwt [%$ (mul 2 axis)]]) ~
511+ ?. |(=(p.h [%dtwt [%$ (mul 2 axis)]]) (fits-union-at p.h axis)) ~
475512 ?. &((fixed-cell-mold q.h axis) (fixed-cell-mold r.h axis)) ~
476513 [~ [q.h r.h]]
477514 ==
@@ -493,6 +530,7 @@
493530 ?: =(a b) [%& a]
494531 [%| 'a nested Hoon $^ union needs a source-level disjointness check']
495532 [%note *] $(h q.h)
533+ [%dbug *] $(h q.h)
496534 [%ktts *]
497535 ?. &(?=([%face *] a) ?=([%face *] b))
498536 [%| 'a nested Hoon $^ union needs a source-level disjointness check']
@@ -502,11 +540,26 @@
502540 ?. ?=([%& *] child) child
503541 [%& [%face name.a p.child]]
504542 [%wtcl *]
505− ?. =(p.h [%dtwt [%$ (mul 2 axis)]])
506− [%| 'a nested Hoon $^ union needs a source-level disjointness check']
507− ?. (disjoint a b) [%| 'a Hoon $^ union has overlapping cases']
508− [%& [%fork (sort ~[a b] |=(pair=[imported imported] (dor -.pair +.pair)))]]
543+ ?. |(=(p.h [%dtwt [%$ (mul 2 axis)]]) (fits-union-at p.h axis))
544+ [%| 'a Hoon union needs a source-level disjointness check']
545+ ?. (disjoint a b)
546+ ?: ?=([%fits *] p.h) [%| 'a Hoon union has overlapping cases']
547+ [%| 'a Hoon $^ union has overlapping cases']
548+ [%& [%fork (sort (weld (union-cases a) (union-cases b)) |=(pair=[imported imported] (dor -.pair +.pair)))]]
509549 ==
550+++ union-cases
551+ |= a=imported
552+ ^- (list imported)
553+ ?. ?=([%fork *] a) ~[a]
554+ (zing (turn cases.a |=(item=imported (union-cases item))))
555+::
556+++ all-disjoint
557+ |= cases=(list imported)
558+ ^- ?
559+ ?~ cases &
560+ ?. (levy t.cases |=(item=imported (disjoint i.cases item))) |
561+ $(cases t.cases)
562+::
510563++ disjoint
511564 |= [a=imported b=imported]
512565 ^- ?
@@ -729,11 +782,16 @@
729782 [%fork *]
730783 =/ cases=(list imported)
731784 (turn ~(tap in:..zuse p.typ) |=(t=type ^$(typ t)))
785+ =/ err (first-bads cases)
786+ ?^ err [%bad u.err]
787+ ?. (all-disjoint cases) [%bad 'a Hoon union has overlapping cases']
732788 [%fork (sort cases |=(pair=[imported imported] (dor -.pair +.pair)))]
733789 [%hint *] $(typ q.typ)
734790 [%hold *]
735791 ?: &(?=([%tsls [%note * *] *] q.typ) (has-spec-cell-union q.typ))
736792 [%bad 'a Hoon $^ union needs a source-level disjointness check']
793+ ?: &(?=([%tsls [%note * *] *] q.typ) (has-spec-general-union q.typ))
794+ [%bad 'a Hoon union needs a source-level disjointness check']
737795 =/ named=(unit term) (match-signature q.typ sig)
738796 ?^ named
739797 =/ name u.named
@@ -799,17 +857,23 @@
799857 ?: (disjoint first second)
800858 [%fork (sort ~[first second] |=(pair=[imported imported] (dor -.pair +.pair)))]
801859 [%bad 'a Hoon $^ union has overlapping cases']
802− ?: (has-cell-union q.typ)
860+ ?: |((has-cell-union q.typ) (has-fits-union q.typ))
861+ =/ cannot=@t
862+ ?: (has-fits-union q.typ) 'a Hoon union needs a source-level disjointness check'
863+ 'a Hoon $^ union needs a source-level disjointness check'
864+ =/ checked-names=(list term) ~[%map %set %qeu %list %unit %jar %jug %path]
865+ ?: (lien checked-names |=(n=term &((source-uses q.typ n) !(alias-safe context n))))
866+ [%bad 'Hoon collection provenance is unavailable or shadowed']
803867 ?. ?=([%tsls [%note * *] *] q.typ)
804− [%bad 'a Hoon $^ union needs a source-level disjointness check']
868+ [%bad cannot]
805869 =/ original=hoon q.typ
806870 ?> ?=([%tsls [%note * *] *] original)
807871 =/ body=hoon q.p.original
808872 =/ split (split-cell-record body 6)
809− ?~ split [%bad 'a Hoon $^ union needs a source-level disjointness check']
873+ ?~ split [%bad cannot]
810874 =/ try=(each [type type] tang)
811875 (mule |.([(~(play ut p.typ) original(q.p one.u.split)) (~(play ut p.typ) original(q.p two.u.split))]))
812− ?. ?=([%& *] try) [%bad 'a Hoon $^ union needs a source-level disjointness check']
876+ ?. ?=([%& *] try) [%bad cannot]
813877 =/ first $(typ -.p.try, seen [[typ nm] seen])
814878 =/ second $(typ +.p.try, seen [[typ nm] seen])
815879 =/ err (first-bads ~[first second])
@@ -1021,6 +1085,39 @@
10211085 [%| *] "error: {(trip p.result)}"
10221086 ==
10231087::
1088+:: Clay includes debug spans around source nodes. Reproduce that
1089+:: shape without Clay so the same regression runs under eval and -test.
1090+++ decorate-union-source
1091+ |= h=hoon
1092+ ^- hoon
1093+ =/ at=spot [/tests/importer/synthetic/hoon [[1 1] [1 2]]]
1094+ ?^ -.h [%dbug at [$(h -.h) $(h +.h)]]
1095+ ?+ h [%dbug at h]
1096+ [%note *] [%dbug at h(q $(h q.h))]
1097+ [%ktts *] [%dbug at h(q $(h q.h))]
1098+ [%wtcl *] [%dbug at h(q $(h q.h), r $(h r.h))]
1099+ ==
1100+::
1101+++ debug-union-fixture
1102+ |= [cor=type name=term]
1103+ ^- (each imported @t)
1104+ =/ typ=type (~(play ut cor) (ream (cat 3 '*' name)))
1105+ ?. ?=([%hold *] typ) [%| 'synthetic union is not a hold']
1106+ =/ original=hoon q.typ
1107+ ?. ?=([%tsls [%note * *] *] original) [%| 'synthetic union source is unavailable']
1108+ =/ source=hoon original(q.p (decorate-union-source q.p.original))
1109+ (read-mold %small name typ(q source))
1110+::
1111+++ overlap-fork-fixture
1112+ ^- type
1113+ =/ nodes=(list type) ~[[%atom %ud ~] [%atom %t ~]]
1114+ [%fork (silt nodes)]
1115+::
1116+++ invalid-fork-fixture
1117+ ^- type
1118+ =/ nodes=(list type) ~[[%atom %ud ~] [%atom %sd ~]]
1119+ [%fork (silt nodes)]
1120+::
10241121++ fixture-output
10251122 |= [small=@t epic=@t presence=@t docs=@t shadow=@t shadow-static=@t ford=@t mark=@t mark-rec=@t mark-gate=@t mark-basic=@t origin-trans=@t origin-first=@t origin-other=@t]
10261123 ^- wain
@@ -1119,6 +1216,26 @@
11191216 (crip "gate: {(show-result (sample %gate-test))}")
11201217 (crip "vase: {(show-result vase)}")
11211218 (crip "failed-branch: {(show-result (read-mold %external %bad bad-branch-fixture))}")
1219+ (crip "debug-union: {(show-result (debug-union-fixture sc %action))}")
1220+ (crip "debug-union-overlap: {(show-result (debug-union-fixture sc %explicit-wut-overlap))}")
1221+ (crip "debug-nested-cell: {(show-result (debug-union-fixture sc %nested-valid-cell))}")
1222+ (crip "debug-nested-cell-overlap: {(show-result (debug-union-fixture sc %nested-invalid-cell))}")
1223+ (crip "explicit-graph: {(show-result (read-mold %raw %raw overlap-fork-fixture))}")
1224+ (crip "explicit-graph-unsupported: {(show-result (read-mold %raw %raw invalid-fork-fixture))}")
1225+ (crip "explicit-wut-safe: {(show-result (sample %explicit-wut-safe))}")
1226+ (crip "explicit-percent-overlap: {(show-result (sample %explicit-percent-overlap))}")
1227+ (crip "explicit-wut-overlap: {(show-result (sample %explicit-wut-overlap))}")
1228+ (crip "explicit-collapsed: {(show-result (sample %explicit-collapsed))}")
1229+ (crip "explicit-subsumed: {(show-result (sample %explicit-subsumed))}")
1230+ (crip "explicit-three: {(show-result (sample %explicit-three))}")
1231+ (crip "explicit-unknown: {(show-result (sample %explicit-unknown))}")
1232+ (crip "explicit-nested: {(show-result (sample %explicit-nested))}")
1233+ (crip "explicit-list: {(show-result (sample %explicit-list))}")
1234+ (crip "explicit-set: {(show-result (sample %explicit-set))}")
1235+ (crip "explicit-faces: {(show-result (sample %explicit-faces))}")
1236+ (crip "explicit-alias: {(show-result (sample %explicit-alias))}")
1237+ (crip "explicit-ford: {(show-result (read-named %outer %bad-union trans))}")
1238+ (crip "explicit-shadow-path: {(show-result (read-named %shadow %path-shadow xc))}")
11221239 (crip "list-bckt-field: {(show-result (sample %list-bckt-field))}")
11231240 (crip "list-noun-overlap: {(show-result (sample %list-noun-overlap))}")
11241241 (crip "list-null-overlap: {(show-result (sample %list-null-overlap))}")
jibb-dev/lib/jibb.hoon+185−7
@@ -4606,6 +4606,9 @@
46064606 [%atom aura=@ta]
46074607 [%any-atom ~]
46084608 [%flag ~]
4609+ [%tag id=@ud literal=lit constructor=?]
4610+ [%const literal=lit]
4611+ [%union cases=(list itype)]
46094612 [%face name=term body=itype]
46104613 [%fn sample=itype product=itype]
46114614 [%cell hed=itype tal=itype]
@@ -4636,6 +4639,10 @@
46364639 =/ found=(unit itype) (itype-lookup id.t sub)
46374640 ?~ found t
46384641 $(t u.found)
4642+ %tag
4643+ =/ found=(unit itype) (itype-lookup id.t sub)
4644+ ?~ found t
4645+ $(t u.found)
46394646 ==
46404647::
46414648++ itype-occurs
@@ -4649,6 +4656,9 @@
46494656 %atom |
46504657 %any-atom |
46514658 %flag |
4659+ %tag =(n id.t)
4660+ %const |
4661+ %union (lien cases.t |=(c=itype (itype-occurs n c sub)))
46524662 %face $(t body.t)
46534663 %fn |($(t sample.t) $(t product.t))
46544664 %cell |($(t hed.t) $(t tal.t))
@@ -4688,6 +4698,8 @@
46884698 ?: ?=(%avar -.b)
46894699 ?. |(?=(%atom -.a) ?=(%any-atom -.a) ?=(%flag -.a)) ~
46904700 `[[id.b a] sub]
4701+ ?: &(?=(%const -.a) ?=(%const -.b))
4702+ ?:(=(val.literal.a val.literal.b) `sub ~)
46914703 ?: &(?=(%atom -.a) ?=(%atom -.b)) ~
46924704 ?: &(?=(%face -.a) ?=(%face -.b))
46934705 ?. =(name.a name.b) ~
@@ -4719,6 +4731,9 @@
47194731 %atom |
47204732 %any-atom &
47214733 %flag |
4734+ %tag |
4735+ %const |
4736+ %union (lien cases.t |=(c=itype (itype-has-any-atom c sub)))
47224737 %face $(t body.t)
47234738 %fn |($(t sample.t) $(t product.t))
47244739 %cell |($(t hed.t) $(t tal.t))
@@ -4773,6 +4788,9 @@
47734788 %atom &
47744789 %any-atom &
47754790 %flag &
4791+ %tag &
4792+ %const &
4793+ %union (lien cases.typ |=(c=itype (itype-has-fixed-atom c)))
47764794 %face $(typ body.typ)
47774795 %fn |($(typ sample.typ) $(typ product.typ))
47784796 %cell |($(typ hed.typ) $(typ tal.typ))
@@ -4843,11 +4861,83 @@
48434861 ?- -.t
48444862 %var &
48454863 %cell &
4864+ %union &
48464865 %face $(t body.t)
48474866 %fn |($(t sample.t) $(t product.t))
48484867 * |
48494868 ==
48504869::
4870+++ pending-tags
4871+ |= [tags=(list @ud) sub=isub]
4872+ ^- ?
4873+ ?~ tags |
4874+ ?~ (itype-lookup i.tags sub) &
4875+ $(tags t.tags)
4876+::
4877+:: Tags remain constrained until a mold selects a case or permitted atom
4878+:: type. Never generalize an unresolved tag through aliases or cells.
4879+::
4880+++ itype-has-tag
4881+ |= t=itype
4882+ ^- ?
4883+ ?- -.t
4884+ %tag &
4885+ %face $(t body.t)
4886+ %fn |($(t sample.t) $(t product.t))
4887+ %cell |($(t hed.t) $(t tal.t))
4888+ %union (lien cases.t |=(c=itype (itype-has-tag c)))
4889+ * |
4890+ ==
4891+::
4892+++ itype-has-union
4893+ |= t=itype
4894+ ^- ?
4895+ ?- -.t
4896+ %union &
4897+ %face $(t body.t)
4898+ %fn |($(t sample.t) $(t product.t))
4899+ %cell |($(t hed.t) $(t tal.t))
4900+ * |
4901+ ==
4902+::
4903+++ itype-fit-cases
4904+ |= [actual=itype cases=(list itype) sub=isub next=@ud]
4905+ ^- ifit
4906+ =/ good=(unit ifit) ~
4907+ =/ pending=? |
4908+ |-
4909+ ?~ cases
4910+ ?: pending [%unknown ~]
4911+ ?~ good [%bad ~]
4912+ u.good
4913+ =/ trial=ifit (itype-fit actual i.cases sub next)
4914+ ?- -.trial
4915+ %unknown $(cases t.cases, pending &)
4916+ %bad $(cases t.cases)
4917+ %ok
4918+ ?^ good [%unknown ~]
4919+ $(cases t.cases, good `trial)
4920+ ==
4921+::
4922+:: A constructor needs a case with its tag at the head and a payload
4923+:: compatible with the expected gate sample. Other case forms do not
4924+:: identify a constructor.
4925+::
4926+++ itype-fit-ctor-cases
4927+ |= [tag=lit sample=itype cases=(list itype) sub=isub next=@ud]
4928+ ^- ifit
4929+ =/ found=(unit ifit) ~
4930+ |-
4931+ ?~ cases ?~(found [%bad ~] u.found)
4932+ =/ c=itype (itype-walk i.cases sub)
4933+ ?. ?=(%cell -.c) $(cases t.cases)
4934+ =/ head=itype (itype-walk hed.c sub)
4935+ ?. ?=(%const -.head) $(cases t.cases)
4936+ ?. =(val.literal.head val.tag) $(cases t.cases)
4937+ ?^ found [%unknown ~]
4938+ =/ trial=ifit (itype-fit sample tal.c sub next)
4939+ $(cases t.cases, found `trial)
4940+::
48514941++ itype-fit
48524942 |= [actual=itype expected=itype sub=isub next=@ud]
48534943 ^- ifit
@@ -4856,6 +4946,51 @@
48564946 =. actual (itype-walk actual sub)
48574947 =. expected (itype-walk expected sub)
48584948 ?: =(actual expected) [%ok sub next]
4949+ ?: &(?=(%union -.actual) ?=(%union -.expected)) [%unknown ~]
4950+ ?: ?=(%union -.actual) [%unknown ~]
4951+ ?: &(?=(%union -.expected) |(?=(%avar -.actual) ?=(%nvar -.actual))) [%unknown ~]
4952+ ?: &(?=(%union -.expected) !?=(%var -.actual))
4953+ (itype-fit-cases actual cases.expected sub next)
4954+ ?: ?=(%tag -.actual)
4955+ ?: ?=(%var -.expected)
4956+ =/ u=(unit isub) (itype-unify actual expected sub)
4957+ ?~ u [%bad ~]
4958+ [%ok u.u next]
4959+ ?: |(?=(%avar -.expected) ?=(%nvar -.expected)) [%unknown ~]
4960+ ?: ?=(%face -.expected) $(expected body.expected)
4961+ ?: constructor.actual
4962+ ?. ?=(%fn -.expected) [%bad ~]
4963+ =/ product=itype (itype-walk product.expected sub)
4964+ =/ cases=(list itype) ?:(?=(%union -.product) cases.product ~[product])
4965+ =/ trial=ifit (itype-fit-ctor-cases literal.actual sample.expected cases sub next)
4966+ ?. ?=(%ok -.trial) trial
4967+ [%ok [[id.actual expected] sub.trial] next.trial]
4968+ ?: ?=(%const -.expected)
4969+ ?:(=(val.literal.actual val.literal.expected) [%ok [[id.actual expected] sub] next] [%bad ~])
4970+ ?: ?=(%atom -.expected)
4971+ ?: |(=(%tas aura.expected) =(%ta aura.expected))
4972+ [%ok [[id.actual expected] sub] next]
4973+ [%bad ~]
4974+ ?: ?=(%flag -.expected)
4975+ ?:(|(=(0 val.literal.actual) =(1 val.literal.actual)) [%ok [[id.actual expected] sub] next] [%bad ~])
4976+ ?: ?=(%any-atom -.expected) [%ok [[id.actual expected] sub] next]
4977+ [%bad ~]
4978+ ?: ?=(%const -.actual)
4979+ ?: ?=(%var -.expected)
4980+ =/ u=(unit isub) (itype-unify actual expected sub)
4981+ ?~ u [%bad ~]
4982+ [%ok u.u next]
4983+ ?: |(?=(%avar -.expected) ?=(%nvar -.expected)) [%unknown ~]
4984+ ?: ?=(%face -.expected) $(expected body.expected)
4985+ ?: ?=(%const -.expected)
4986+ ?:(=(val.literal.actual val.literal.expected) [%ok sub next] [%bad ~])
4987+ ?: ?=(%atom -.expected)
4988+ ?: |(=(%tas aura.expected) =(%ta aura.expected)) [%ok sub next]
4989+ [%bad ~]
4990+ ?: ?=(%flag -.expected)
4991+ ?:(|(=(0 val.literal.actual) =(1 val.literal.actual)) [%ok sub next] [%bad ~])
4992+ ?: ?=(%any-atom -.expected) [%ok sub next]
4993+ [%bad ~]
48594994 ?: &(uncertain (itype-face-asym actual expected sub)) [%unknown ~]
48604995 ?: ?=(%any-atom -.expected)
48614996 ?: |(?=(%atom -.actual) ?=(%avar -.actual) ?=(%nvar -.actual) ?=(%flag -.actual)) [%ok sub next]
@@ -4943,7 +5078,7 @@
49435078:: This core has no Ford dependencies; unrecognized payloads fail closed.
49445079+$ iexternals (list [module=term name=term result=*])
49455080+$ imark-externals (list [mark=term result=*])
4946−+$ 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) in-mold=?]
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=?]
49475082+$ idiag [msg=tape sites=(list [at=span note=tape])]
49485083+$ iresult (each [typ=itype state=istate] idiag)
49495084+$ isample-result (each [typ=itype env=ienv state=istate] tape)
@@ -4963,6 +5098,8 @@
49635098 |= [t=itype sub=isub]
49645099 ^- itype
49655100 =. t (itype-walk t sub)
5101+ ?: ?=(%union -.t)
5102+ [%union (turn cases.t |=(c=itype (itype-normalize c sub)))]
49665103 ?: ?=(%face -.t)
49675104 [%face name.t $(t body.t)]
49685105 ?: ?=(%fn -.t)
@@ -4983,6 +5120,9 @@
49835120 %fn &
49845121 %cell |($(t hed.t) $(t tal.t))
49855122 %face $(t body.t)
5123+ %union (lien cases.t |=(c=itype (itype-has-gate c)))
5124+ %tag |
5125+ %const |
49865126 %var |
49875127 %avar |
49885128 %nvar |
@@ -5012,6 +5152,9 @@
50125152 %atom ~
50135153 %any-atom ~
50145154 %flag ~
5155+ %tag ~
5156+ %const ~
5157+ %union (zing (turn cases.t |=(c=itype (itype-vars c))))
50155158 %face $(t body.t)
50165159 %fn (weld $(t sample.t) $(t product.t))
50175160 %cell (weld $(t hed.t) $(t tal.t))
@@ -5045,6 +5188,9 @@
50455188 %atom t
50465189 %any-atom t
50475190 %flag t
5191+ %tag t
5192+ %const t
5193+ %union [%union (turn cases.t |=(c=itype (itype-rename c ren)))]
50485194 %face [%face name.t $(t body.t)]
50495195 %fn [%fn $(t sample.t) $(t product.t)]
50505196 %cell [%cell $(t hed.t) $(t tal.t)]
@@ -5063,6 +5209,9 @@
50635209 %atom |
50645210 %any-atom |
50655211 %flag |
5212+ %tag |
5213+ %const |
5214+ %union (lien cases.t |=(c=itype (itype-var-is-atom n c)))
50665215 %face $(t body.t)
50675216 %fn |($(t sample.t) $(t product.t))
50685217 %cell |($(t hed.t) $(t tal.t))
@@ -5301,6 +5450,16 @@
53015450 ?: =(0 aura.sh) `[[%any-atom ~] state]
53025451 `[[%atom aura.sh] state]
53035452 %flag `[[%flag ~] state]
5453+ %const
5454+ ?. =(%term form.lit.sh) ~
5455+ `[[%const lit.sh] state]
5456+ %union
5457+ =/ pairs=(list upair) (union-pairs cases.sh molds.state)
5458+ ?. (levy pairs |=(p=upair =(%disjoint relation.p))) ~
5459+ =/ cs=(unit [types=(list itype) state=istate]) (infer-shape-args cases.sh state)
5460+ ?~ cs ~
5461+ ?: (lien types.u.cs |=(t=itype ?=(^ (itype-vars t)))) ~
5462+ `[[%union types.u.cs] state.u.cs]
53045463 %cell (infer-simple-fields fields.sh state)
53055464 %fn
53065465 =/ arg=(unit [typ=itype state=istate]) $(sh sample.sh)
@@ -5528,6 +5687,8 @@
55285687 =/ inferred=iresult (infer-fragment val.d env state)
55295688 ?: ?=(%| -.inferred) $(ds t.ds, remaining [d remaining])
55305689 =/ typ=itype (itype-normalize typ.p.inferred sub.state.p.inferred)
5690+ ?: |((pending-tags tags.state.p.inferred sub.state.p.inferred) (itype-has-tag typ))
5691+ $(ds t.ds, remaining [d remaining])
55315692 ?: (unsupported-atom-vars typ caps.state.p.inferred binders.state.p.inferred sub.state.p.inferred)
55325693 $(ds t.ds, remaining [d remaining])
55335694 =/ free=(list @ud)
@@ -5583,6 +5744,7 @@
55835744 %duration [%& [%atom %dr] state]
55845745 %knot [%& [%atom %ta] state]
55855746 %loobean [%& [%flag ~] state]
5747+ %term [%& [%tag next.state lit.e |] state(next +(next.state), tags [next.state tags.state])]
55865748 * [%| ["literal needs contextual inference" ~]]
55875749 ==
55885750 %str
@@ -5604,6 +5766,7 @@
56045766 =/ instance=[typ=itype state=istate] (instantiate-scheme u.scheme state)
56055767 [%& typ.instance state.instance]
56065768 %group $(e inner.e)
5769+ %ctor [%& [%tag next.state tag.e &] state(next +(next.state), tags [next.state tags.state])]
56075770 %trace
56085771 =/ traced=iresult $(e val.e)
56095772 ?: ?=(%| -.traced) traced
@@ -5653,6 +5816,8 @@
56535816 [%| ["branch widening is not supported by partial inference" ~]]
56545817 =/ joined=(unit isub) (itype-unify typ.p.left typ.p.right sub.state.p.right)
56555818 ?~ joined
5819+ ?: |((itype-has-tag ltype) (itype-has-tag rtype) (itype-has-union ltype) (itype-has-union rtype))
5820+ [%| ["branch tag or union context is not supported by partial inference" ~]]
56565821 =/ common=(unit itype) (itype-concrete-join typ.p.left typ.p.right sub.state.p.right)
56575822 ?^ common [%& u.common state.p.right]
56585823 ?: |((itype-has-face typ.p.left sub.state.p.right) (itype-has-face typ.p.right sub.state.p.right))
@@ -5710,8 +5875,7 @@
57105875 * [%| ["expression is not supported by partial inference" ~]]
57115876 ==
57125877::
5713−:: Unfaced tuple expressions are the one supported cell construction.
5714−:: Faced cells wait for the representation to preserve record faces.
5878+:: Tuple and record expressions preserve their explicitly written faces.
57155879::
57165880++ infer-simple-items
57175881 |= [items=(list item) env=ienv state=istate]
@@ -5774,6 +5938,9 @@
57745938 %atom "@{(trip aura.t)}"
57755939 %any-atom "@"
57765940 %flag "?"
5941+ %tag (trip txt.literal.t)
5942+ %const (trip txt.literal.t)
5943+ %union "<union>"
57775944 %face "[{(trip name.t)}={$(t body.t)}]"
57785945 %fn "$-({$(t sample.t)} {$(t product.t)})"
57795946 %cell "[{(show-itype-item hed.t sub)} {(show-itype-item tal.t sub)}]"
@@ -5799,6 +5966,9 @@
57995966 %atom |
58005967 %any-atom |
58015968 %flag |
5969+ %tag |
5970+ %const |
5971+ %union (lien cases.typ |=(c=itype (itype-has-nvar c)))
58025972 %face $(typ body.typ)
58035973 %fn |($(typ sample.typ) $(typ product.typ))
58045974 %cell |($(typ hed.typ) $(typ tal.typ))
@@ -5808,7 +5978,7 @@
58085978 |= [label=tape typ=itype sub=isub]
58095979 ^- tape
58105980 =/ normalized=itype (itype-normalize typ sub)
5811− ?: |(?=(%var -.normalized) ?=(%avar -.normalized) (itype-has-nvar normalized)) label
5981+ ?: |(?=(%var -.normalized) ?=(%avar -.normalized) (itype-has-nvar normalized) (itype-has-tag normalized) (itype-has-union normalized)) label
58125982 =/ vars=(list @ud) (unique-type-vars (itype-vars normalized))
58135983 ?: (gth (lent vars) 26) label
58145984 =/ printable=itype (canonical-itype normalized vars)
@@ -5850,6 +6020,9 @@
58506020 %atom |
58516021 %any-atom |
58526022 %flag |
6023+ %tag |
6024+ %const |
6025+ %union (lien cases.t |=(c=itype (has-atom-var n c)))
58536026 %face $(t body.t)
58546027 %fn |($(t sample.t) $(t product.t))
58556028 %cell |($(t hed.t) $(t tal.t))
@@ -5924,10 +6097,11 @@
59246097 ?: ?=(%mold -.d) $(ds t.ds)
59256098 ?. (unique-value-name name.d globals) $(ds t.ds)
59266099 ?^ (ienv-lookup name.d env) $(ds t.ds)
5927− =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ |])
6100+ =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ |])
59286101 ?: ?=(%| -.result) $(ds t.ds)
59296102 ?: (constrained-capitals caps.state.p.result sub.state.p.result) $(ds t.ds)
59306103 =/ typ=itype (default-decimals (itype-normalize typ.p.result sub.state.p.result))
6104+ ?: |((pending-tags tags.state.p.result sub.state.p.result) (itype-has-tag typ)) $(ds t.ds)
59316105 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result) $(ds t.ds)
59326106 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
59336107 ?: (gth (lent vars) 26) $(ds t.ds)
@@ -6233,7 +6407,7 @@
62336407 =/ surs=(list term) (collect-sur-imports imports.mod)
62346408 =/ marks=(list term) (collect-mark-imports imports.mod)
62356409 =/ reserved=(list term) (weld prelude-molds (turn resolved.p.js |=(j=[face=term interface=ifile] face.j)))
6236− =/ state=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks resolved.p.js reserved ~ ~ |]
6410+ =/ state=istate [0 ~ ~ ~ molds globals externals surs mark-externals marks resolved.p.js reserved ~ ~ ~ |]
62376411 =/ mts=(each imold-types @t) (module-mold-types molds state)
62386412 ?: ?=(%| -.mts) [%| (crip "{(trip p.mts)}: {(spud at)}")]
62396413 =/ env=ienv (resolve-supported-defs defs.mod molds globals externals surs mark-externals marks resolved.p.js reserved)
@@ -6306,12 +6480,16 @@
63066480 $(ds t.ds, lines [(show-partial-mold file src d molds) lines])
63076481 ?. (unique-value-name name.d globals)
63086482 $(ds t.ds, lines [(crip "++ {(trip name.d)}: name already in scope") lines])
6309− =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ |])
6483+ =/ result=iresult (infer-fragment val.d env [0 ~ ~ ~ molds globals externals surs mark-externals marks jimports reserved-molds ~ ~ ~ |])
63106484 ?: ?=(%| -.result)
63116485 $(ds t.ds, lines [(show-inference-diagnostic file src name.d p.result) lines])
63126486 ?: (constrained-capitals caps.state.p.result sub.state.p.result)
63136487 $(ds t.ds, lines [(crip "++ {(trip name.d)}: explicit capital constraints are not supported by partial inference") lines])
63146488 =/ 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))
6490+ $(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])
63156493 ?: (unsupported-atom-vars typ caps.state.p.result binders.state.p.result sub.state.p.result)
63166494 $(ds t.ds, lines [(crip "++ {(trip name.d)}: unresolved aura-variable inference") lines])
63176495 =/ vars=(list @ud) (unique-type-vars (itype-vars typ))
tests/golden/module-cache-incomplete/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Grammar, Modules: "Everything is exported and read through the import's face"; Imports: "Import cycles are errors".
2−tests: A shared library with an unsupported mold yields no partial interface, even though one value could be inferred.
2+tests: A shared library with a generic union mold, which partial inference does not yet support, yields no interface even though one value could be inferred.
33expect: parses
44expect-types: a partial inference report
tests/golden/module-cache-incomplete/module-trees.txt+6−1
@@ -1,6 +1,11 @@
11/ui/bad.jibb
22(module
33 (mold 1:1 choice
4− (union 2:3 (const 2:3 %a) (const 3:3 %b)))
4+ (generic 1:11 A
5+ (union 2:3
6+ (cell 2:3
7+ (const 2:4 %some)
8+ (face 2:10 value (tvar 2:16 A)))
9+ (const 3:3 %none))))
510 (value 4:1 id
611 (gate-wide 4:7 (bind 4:10 x) (wing 4:12 x))))
tests/golden/module-cache-incomplete/modules/ui/bad.jibb+3−3
@@ -1,4 +1,4 @@
1−+$ choice
2− %a
3− %b
1++$ choice |$ [A]
2+ [%some value=A]
3+ %none
44++ id |=(x x)
tests/golden/types-partial-local-molds/about.txt+2−1
@@ -2,7 +2,8 @@ Grammar, Modules: "Local definitions may start any body, visible to each
22other and the final expression"; a gate's sample cannot see a mold in that
33gate's body. Partial inference supports acyclic local aliases of simple
44molds and resolves them in any order. It rejects duplicate or shadowed molds
5−and leaves recursive or union molds unsupported, even if unused. Mold and
5+and leaves recursive molds unsupported, even if unused. A closed disjoint
6+union mold is accepted, including when unused. Mold and
67value namespaces remain separate. The report does not claim the module is
78checked.
89expect: parses
tests/golden/types-partial-local-molds/types.txt+1−1
@@ -5,7 +5,7 @@ partial inference; module not checked
55++ duplicate: local molds shadow a name
66++ shadow: local molds shadow a name
77++ recursive: local molds need unsupported inference
8−++ unused-union: local molds need unsupported inference
8+++ unused-union: $-(A A)
99++ same-names: $-(@t @t)
1010++ no-leak: cast mold is not supported by partial inference
1111++ nested-shadow: local definitions need unsupported inference
tests/golden/types-partial-unresolved-tag/about.txt+1−1
@@ -1,4 +1,4 @@
11source: Grammar tab, Molds: "every expression has a principal type, and there is no general subtyping".
2−tests: partial inference reports a tag whose contextual inference is not implemented; the report does not claim the module checks.
2+tests: Partial inference reports a tag whose type is not fixed by context; the report does not claim the module checks.
33expect: parses
44expect-types: a partial inference report, not a checked module
tests/golden/types-partial-unresolved-tag/types.txt+1−1
@@ -1,2 +1,2 @@
11partial inference; module not checked
2−++ message: literal needs contextual inference
2+++ message: tag needs context in partial inference
tests/golden/types-union-alias/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A local alias retains the named union context for a bare tag.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-alias/source.jibbnew file+5
@@ -0,0 +1,5 @@
1++$ msg
2+ [%noted text=@t]
3+ %add
4++$ alias msg
5+++ via ^- alias %add
tests/golden/types-union-alias/tokens.txtnew file+23
@@ -0,0 +1,23 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %noted
6+2:11 name text
7+2:15 tight glyph =
8+2:16 tight aura @t
9+2:18 tight glyph ]
10+3:3 NEWLINE
11+3:3 lit %add
12+4:1 DEDENT
13+4:1 NEWLINE
14+4:1 glyph +$
15+4:4 name alias
16+4:10 name msg
17+5:1 NEWLINE
18+5:1 glyph ++
19+5:4 name via
20+5:8 glyph ^-
21+5:11 name alias
22+5:17 lit %add
23+5:21 NEWLINE
tests/golden/types-union-alias/tree.txtnew file+10
@@ -0,0 +1,10 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %noted)
6+ (face 2:11 text (aura 2:16 @t)))
7+ (const 3:3 %add)))
8+ (mold 4:1 alias (ref 4:10 msg))
9+ (value 5:1 via
10+ (cast 5:8 (ref 5:11 alias) (lit 5:17 %add))))
tests/golden/types-union-alias/types.txtnew file+4
@@ -0,0 +1,4 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3++$ alias: not checked
4+++ via: union type printing is not supported by partial inference
tests/golden/types-union-context-flow/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Tag resolution: tags take their union from context and constrained variables do not generalize.
2+tests: Resolving one tag does not resolve another; union context can reach tags in a branch and through a generic call when supported.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-context-flow/source.jibbnew file+13
@@ -0,0 +1,13 @@
1++$ msg
2+ %add
3+ %remove
4+++ only-one
5+ ~& ^- msg %add
6+ %unknown
7+++ choose |= b=?
8+ ^- msg
9+ ?- b
10+ %.y %add
11+ %.n %remove
12+++ id |=(x x)
13+++ through ^- msg (id %add)
tests/golden/types-union-context-flow/tokens.txtnew file+58
@@ -0,0 +1,58 @@
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 only-one
11+5:3 INDENT
12+5:3 glyph ~&
13+5:6 glyph ^-
14+5:9 name msg
15+5:13 lit %add
16+6:5 INDENT
17+6:5 lit %unknown
18+7:1 DEDENT
19+7:1 DEDENT
20+7:1 NEWLINE
21+7:1 glyph ++
22+7:4 name choose
23+7:11 glyph |=
24+7:14 name b
25+7:15 tight glyph =
26+7:16 tight glyph ?
27+8:3 INDENT
28+8:3 glyph ^-
29+8:6 name msg
30+9:5 INDENT
31+9:5 glyph ?-
32+9:8 name b
33+10:7 INDENT
34+10:7 lit %.y
35+10:11 lit %add
36+11:7 NEWLINE
37+11:7 lit %.n
38+11:11 lit %remove
39+12:1 DEDENT
40+12:1 DEDENT
41+12:1 DEDENT
42+12:1 NEWLINE
43+12:1 glyph ++
44+12:4 name id
45+12:7 glyph |=(
46+12:10 tight name x
47+12:12 name x
48+12:13 tight glyph )
49+13:1 NEWLINE
50+13:1 glyph ++
51+13:4 name through
52+13:12 glyph ^-
53+13:15 name msg
54+13:19 glyph (
55+13:20 tight name id
56+13:23 lit %add
57+13:27 tight glyph )
58+13:28 NEWLINE
tests/golden/types-union-context-flow/tree.txtnew file+26
@@ -0,0 +1,26 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3 (const 2:3 %add) (const 3:3 %remove)))
4+ (value 4:1 only-one
5+ (body 5:3
6+ (trace 5:3
7+ (cast 5:6 (ref 5:9 msg) (lit 5:13 %add))
8+ (body 6:5 (lit 6:5 %unknown)))))
9+ (value 7:1 choose
10+ (gate 7:11
11+ (face 7:14 b (flag 7:16))
12+ (body 8:3
13+ (cast 8:3
14+ (ref 8:6 msg)
15+ (body 9:5
16+ (branch 9:5
17+ (wing 9:8 b)
18+ (arm 10:7 (lit 10:7 %.y) (lit 10:11 %add))
19+ (arm 11:7 (lit 11:7 %.n) (lit 11:11 %remove))))))))
20+ (value 12:1 id
21+ (gate-wide 12:7 (bind 12:10 x) (wing 12:12 x)))
22+ (value 13:1 through
23+ (cast 13:12
24+ (ref 13:15 msg)
25+ (group 13:19
26+ (call 13:20 (wing 13:20 id) (lit 13:23 %add))))))
tests/golden/types-union-context-flow/types.txtnew file+6
@@ -0,0 +1,6 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ only-one: tag needs context in partial inference
4+++ choose: branch tag or union context is not supported by partial inference
5+++ id: $-(A A)
6+++ through: union type printing is not supported by partial inference
tests/golden/types-union-import/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Modules: tags take their union from context and modules export their definitions through an import face.
2+tests: A closed union exported by a Jibb library supplies the context of a tag in its caller.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-import/module-trees.txtnew file+8
@@ -0,0 +1,8 @@
1+/ui/lib.jibb
2+(module
3+ (mold 1:1 msg
4+ (union 2:3
5+ (cell 2:3
6+ (const 2:4 %noted)
7+ (face 2:11 text (aura 2:16 @t)))
8+ (const 3:3 %add))))
tests/golden/types-union-import/modules.txtnew file+1
@@ -0,0 +1 @@
1+/ui/lib.jibb
tests/golden/types-union-import/modules/ui/lib.jibbnew file+3
@@ -0,0 +1,3 @@
1++$ msg
2+ [%noted text=@t]
3+ %add
tests/golden/types-union-import/source.jibbnew file+2
@@ -0,0 +1,2 @@
1+/= lib /ui/lib
2+++ selected ^- msg.lib %add
tests/golden/types-union-import/tokens.txtnew file+13
@@ -0,0 +1,13 @@
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 selected
10+2:13 glyph ^-
11+2:16 wing msg.lib
12+2:24 lit %add
13+2:28 NEWLINE
tests/golden/types-union-import/tree.txtnew file+4
@@ -0,0 +1,4 @@
1+(module
2+ (jibb 1:1 lib /ui/lib)
3+ (value 2:1 selected
4+ (cast 2:13 (ref 2:16 msg.lib) (lit 2:24 %add))))
tests/golden/types-union-import/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+++ selected: union type printing is not supported by partial inference
tests/golden/types-union-overlap/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A union whose atom cases overlap is reported and cannot be treated as a valid type.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-overlap/source.jibbnew file+4
@@ -0,0 +1,4 @@
1++$ overlap
2+ @t
3+ @ud
4+++ identity |=(x x)
tests/golden/types-union-overlap/tokens.txtnew file+15
@@ -0,0 +1,15 @@
1+1:1 glyph +$
2+1:4 name overlap
3+2:3 INDENT
4+2:3 aura @t
5+3:3 NEWLINE
6+3:3 aura @ud
7+4:1 DEDENT
8+4:1 NEWLINE
9+4:1 glyph ++
10+4:4 name identity
11+4:13 glyph |=(
12+4:16 tight name x
13+4:18 name x
14+4:19 tight glyph )
15+4:20 NEWLINE
tests/golden/types-union-overlap/tree.txtnew file+5
@@ -0,0 +1,5 @@
1+(module
2+ (mold 1:1 overlap
3+ (union 2:3 (aura 2:3 @t) (aura 3:3 @ud)))
4+ (value 4:1 identity
5+ (gate-wide 4:13 (bind 4:16 x) (wing 4:18 x))))
tests/golden/types-union-overlap/types.txtnew file+9
@@ -0,0 +1,9 @@
1+partial inference; module not checked
2++$ overlap: overlapping cases; mold not checked
3+/tests/golden/types-union-overlap/source.jibb:2:3: first union case
4+ @t
5+ ^
6+/tests/golden/types-union-overlap/source.jibb:3:3: overlapping case
7+ @ud
8+ ^
9+++ identity: $-(A A)
tests/golden/types-union-singleton/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A nonunion mold counts as a union of one for tagged cells and a tagged constructor. A constructor also works against a union or as a typed argument; wrong input, missing tag and missing context fail, including through a polymorphic identity.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-singleton/source.jibbnew file+16
@@ -0,0 +1,16 @@
1++$ go [%go url=@t]
2++$ typed [%typed text=@t]
3++$ msg
4+ [%noted text=@t]
5+ %add
6+++ go-value ^- go [%go "hi"]
7+++ constructor ^- $-(@t typed) |=%typed
8+++ union-constructor ^- $-(@t msg) |=%noted
9+++ wrong-input ^- $-(@ud typed) |=%typed
10+++ missing ^- $-(@t typed) |=%missing
11+++ no-context |=%typed
12+++ use |= f=$-(@t typed) (f "hi")
13+++ test (use |=%typed)
14+++ bad-call (use |=%nope)
15+++ id |=(x x)
16+++ through (id |=%typed)
tests/golden/types-union-singleton/tokens.txtnew file+130
@@ -0,0 +1,130 @@
1+1:1 glyph +$
2+1:4 name go
3+1:7 glyph [
4+1:8 tight lit %go
5+1:12 name url
6+1:15 tight glyph =
7+1:16 tight aura @t
8+1:18 tight glyph ]
9+2:1 NEWLINE
10+2:1 glyph +$
11+2:4 name typed
12+2:10 glyph [
13+2:11 tight lit %typed
14+2:18 name text
15+2:22 tight glyph =
16+2:23 tight aura @t
17+2:25 tight glyph ]
18+3:1 NEWLINE
19+3:1 glyph +$
20+3:4 name msg
21+4:3 INDENT
22+4:3 glyph [
23+4:4 tight lit %noted
24+4:11 name text
25+4:15 tight glyph =
26+4:16 tight aura @t
27+4:18 tight glyph ]
28+5:3 NEWLINE
29+5:3 lit %add
30+6:1 DEDENT
31+6:1 NEWLINE
32+6:1 glyph ++
33+6:4 name go-value
34+6:13 glyph ^-
35+6:16 name go
36+6:19 glyph [
37+6:20 tight lit %go
38+6:24 str "hi"
39+6:28 tight glyph ]
40+7:1 NEWLINE
41+7:1 glyph ++
42+7:4 name constructor
43+7:16 glyph ^-
44+7:19 glyph $-(
45+7:22 tight aura @t
46+7:25 name typed
47+7:30 tight glyph )
48+7:32 glyph |=
49+7:34 tight lit %typed
50+8:1 NEWLINE
51+8:1 glyph ++
52+8:4 name union-constructor
53+8:22 glyph ^-
54+8:25 glyph $-(
55+8:28 tight aura @t
56+8:31 name msg
57+8:34 tight glyph )
58+8:36 glyph |=
59+8:38 tight lit %noted
60+9:1 NEWLINE
61+9:1 glyph ++
62+9:4 name wrong-input
63+9:16 glyph ^-
64+9:19 glyph $-(
65+9:22 tight aura @ud
66+9:26 name typed
67+9:31 tight glyph )
68+9:33 glyph |=
69+9:35 tight lit %typed
70+10:1 NEWLINE
71+10:1 glyph ++
72+10:4 name missing
73+10:12 glyph ^-
74+10:15 glyph $-(
75+10:18 tight aura @t
76+10:21 name typed
77+10:26 tight glyph )
78+10:28 glyph |=
79+10:30 tight lit %missing
80+11:1 NEWLINE
81+11:1 glyph ++
82+11:4 name no-context
83+11:15 glyph |=
84+11:17 tight lit %typed
85+12:1 NEWLINE
86+12:1 glyph ++
87+12:4 name use
88+12:8 glyph |=
89+12:11 name f
90+12:12 tight glyph =
91+12:13 tight glyph $-(
92+12:16 tight aura @t
93+12:19 name typed
94+12:24 tight glyph )
95+12:26 glyph (
96+12:27 tight name f
97+12:29 str "hi"
98+12:33 tight glyph )
99+13:1 NEWLINE
100+13:1 glyph ++
101+13:4 name test
102+13:9 glyph (
103+13:10 tight name use
104+13:14 glyph |=
105+13:16 tight lit %typed
106+13:22 tight glyph )
107+14:1 NEWLINE
108+14:1 glyph ++
109+14:4 name bad-call
110+14:13 glyph (
111+14:14 tight name use
112+14:18 glyph |=
113+14:20 tight lit %nope
114+14:25 tight glyph )
115+15:1 NEWLINE
116+15:1 glyph ++
117+15:4 name id
118+15:7 glyph |=(
119+15:10 tight name x
120+15:12 name x
121+15:13 tight glyph )
122+16:1 NEWLINE
123+16:1 glyph ++
124+16:4 name through
125+16:12 glyph (
126+16:13 tight name id
127+16:16 glyph |=
128+16:18 tight lit %typed
129+16:24 tight glyph )
130+16:25 NEWLINE
tests/golden/types-union-singleton/tree.txtnew file+53
@@ -0,0 +1,53 @@
1+(module
2+ (mold 1:1 go
3+ (cell 1:7
4+ (const 1:8 %go)
5+ (face 1:12 url (aura 1:16 @t))))
6+ (mold 2:1 typed
7+ (cell 2:10
8+ (const 2:11 %typed)
9+ (face 2:18 text (aura 2:23 @t))))
10+ (mold 3:1 msg
11+ (union 4:3
12+ (cell 4:3
13+ (const 4:4 %noted)
14+ (face 4:11 text (aura 4:16 @t)))
15+ (const 5:3 %add)))
16+ (value 6:1 go-value
17+ (cast 6:13
18+ (ref 6:16 go)
19+ (tuple 6:19 (lit 6:20 %go) (str 6:24 "hi"))))
20+ (value 7:1 constructor
21+ (cast 7:16
22+ (fn 7:19 (aura 7:22 @t) (ref 7:25 typed))
23+ (ctor 7:32 %typed)))
24+ (value 8:1 union-constructor
25+ (cast 8:22
26+ (fn 8:25 (aura 8:28 @t) (ref 8:31 msg))
27+ (ctor 8:36 %noted)))
28+ (value 9:1 wrong-input
29+ (cast 9:16
30+ (fn 9:19 (aura 9:22 @ud) (ref 9:26 typed))
31+ (ctor 9:33 %typed)))
32+ (value 10:1 missing
33+ (cast 10:12
34+ (fn 10:15 (aura 10:18 @t) (ref 10:21 typed))
35+ (ctor 10:28 %missing)))
36+ (value 11:1 no-context (ctor 11:15 %typed))
37+ (value 12:1 use
38+ (gate 12:8
39+ (face 12:11 f
40+ (fn 12:13 (aura 12:16 @t) (ref 12:19 typed)))
41+ (group 12:26
42+ (call 12:27 (wing 12:27 f) (str 12:29 "hi")))))
43+ (value 13:1 test
44+ (group 13:9
45+ (call 13:10 (wing 13:10 use) (ctor 13:14 %typed))))
46+ (value 14:1 bad-call
47+ (group 14:13
48+ (call 14:14 (wing 14:14 use) (ctor 14:18 %nope))))
49+ (value 15:1 id
50+ (gate-wide 15:7 (bind 15:10 x) (wing 15:12 x)))
51+ (value 16:1 through
52+ (group 16:12
53+ (call 16:13 (wing 16:13 id) (ctor 16:16 %typed)))))
tests/golden/types-union-singleton/types.txtnew file+33
@@ -0,0 +1,33 @@
1+partial inference; module not checked
2++$ go: not checked
3++$ typed: not checked
4++$ msg: cases proven disjoint; mold not checked
5+++ go-value: [%go url=@t]
6+++ constructor: $-(@t [%typed text=@t])
7+++ union-constructor: union type printing is not supported by partial inference
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])
10+++ wrong-input ^- $-(@ud typed) |=%typed
11+ ^
12+/tests/golden/types-union-singleton/source.jibb:9:33: expression
13+++ wrong-input ^- $-(@ud typed) |=%typed
14+ ^
15+++ missing: cast mold and expression type do not unify
16+/tests/golden/types-union-singleton/source.jibb:10:15: cast mold has type $-(@t [%typed text=@t])
17+++ missing ^- $-(@t typed) |=%missing
18+ ^
19+/tests/golden/types-union-singleton/source.jibb:10:28: expression
20+++ missing ^- $-(@t typed) |=%missing
21+ ^
22+++ no-context: tag needs context in partial inference
23+++ use: $-($-(@t [%typed text=@t]) [%typed text=@t])
24+++ test: [%typed text=@t]
25+++ bad-call: call's sample and argument types do not unify
26+/tests/golden/types-union-singleton/source.jibb:14:14: called gate has type $-($-(@t [%typed text=@t]) [%typed text=@t])
27+++ bad-call (use |=%nope)
28+ ^
29+/tests/golden/types-union-singleton/source.jibb:14:18: argument
30+++ bad-call (use |=%nope)
31+ ^
32+++ id: $-(A A)
33+++ through: tag needs context in partial inference
tests/golden/types-union-tag-atoms/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Tag resolution: a tag may fit an atom type by its noun value; a loobean has the two atoms `%.y` and `%.n`.
2+tests: `%$` and `%1` fit a loobean by value, `%2` does not, and `%1` and `%&` fit the requested atom auras.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-tag-atoms/source.jibbnew file+5
@@ -0,0 +1,5 @@
1+++ zero ^- ? %$
2+++ one ^- ? %1
3+++ two ^- ? %2
4+++ numeric ^- @tas %1
5+++ bit ^- @ta %&
tests/golden/types-union-tag-atoms/tokens.txtnew file+30
@@ -0,0 +1,30 @@
1+1:1 glyph ++
2+1:4 name zero
3+1:9 glyph ^-
4+1:12 glyph ?
5+1:14 lit %$
6+2:1 NEWLINE
7+2:1 glyph ++
8+2:4 name one
9+2:8 glyph ^-
10+2:11 glyph ?
11+2:13 lit %1
12+3:1 NEWLINE
13+3:1 glyph ++
14+3:4 name two
15+3:8 glyph ^-
16+3:11 glyph ?
17+3:13 lit %2
18+4:1 NEWLINE
19+4:1 glyph ++
20+4:4 name numeric
21+4:12 glyph ^-
22+4:15 aura @tas
23+4:20 lit %1
24+5:1 NEWLINE
25+5:1 glyph ++
26+5:4 name bit
27+5:8 glyph ^-
28+5:11 aura @ta
29+5:15 lit %&
30+5:17 NEWLINE
tests/golden/types-union-tag-atoms/tree.txtnew file+11
@@ -0,0 +1,11 @@
1+(module
2+ (value 1:1 zero
3+ (cast 1:9 (flag 1:12) (lit 1:14 %$)))
4+ (value 2:1 one
5+ (cast 2:8 (flag 2:11) (lit 2:13 %1)))
6+ (value 3:1 two
7+ (cast 3:8 (flag 3:11) (lit 3:13 %2)))
8+ (value 4:1 numeric
9+ (cast 4:12 (aura 4:15 @tas) (lit 4:20 %1)))
10+ (value 5:1 bit
11+ (cast 5:8 (aura 5:11 @ta) (lit 5:15 %&))))
tests/golden/types-union-tag-atoms/types.txtnew file+12
@@ -0,0 +1,12 @@
1+partial inference; module not checked
2+++ zero: ?
3+++ one: ?
4+++ two: cast mold and expression type do not unify
5+/tests/golden/types-union-tag-atoms/source.jibb:3:11: cast mold has type ?
6+++ two ^- ? %2
7+ ^
8+/tests/golden/types-union-tag-atoms/source.jibb:3:13: expression
9+++ two ^- ? %2
10+ ^
11+++ numeric: @tas
12+++ bit: @ta
tests/golden/types-union-tags/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A closed disjoint union resolves bare and record tags in context; an absent tag remains an error.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-tags/source.jibbnew file+6
@@ -0,0 +1,6 @@
1++$ msg
2+ [%noted text=@t]
3+ %add
4+++ simple ^- msg %add
5+++ record ^- msg [%noted "hi"]
6+++ wrong ^- msg %missing
tests/golden/types-union-tags/tokens.txtnew file+34
@@ -0,0 +1,34 @@
1+1:1 glyph +$
2+1:4 name msg
3+2:3 INDENT
4+2:3 glyph [
5+2:4 tight lit %noted
6+2:11 name text
7+2:15 tight glyph =
8+2:16 tight aura @t
9+2:18 tight glyph ]
10+3:3 NEWLINE
11+3:3 lit %add
12+4:1 DEDENT
13+4:1 NEWLINE
14+4:1 glyph ++
15+4:4 name simple
16+4:11 glyph ^-
17+4:14 name msg
18+4:18 lit %add
19+5:1 NEWLINE
20+5:1 glyph ++
21+5:4 name record
22+5:11 glyph ^-
23+5:14 name msg
24+5:18 glyph [
25+5:19 tight lit %noted
26+5:26 str "hi"
27+5:30 tight glyph ]
28+6:1 NEWLINE
29+6:1 glyph ++
30+6:4 name wrong
31+6:10 glyph ^-
32+6:13 name msg
33+6:17 lit %missing
34+6:25 NEWLINE
tests/golden/types-union-tags/tree.txtnew file+15
@@ -0,0 +1,15 @@
1+(module
2+ (mold 1:1 msg
3+ (union 2:3
4+ (cell 2:3
5+ (const 2:4 %noted)
6+ (face 2:11 text (aura 2:16 @t)))
7+ (const 3:3 %add)))
8+ (value 4:1 simple
9+ (cast 4:11 (ref 4:14 msg) (lit 4:18 %add)))
10+ (value 5:1 record
11+ (cast 5:11
12+ (ref 5:14 msg)
13+ (tuple 5:18 (lit 5:19 %noted) (str 5:26 "hi"))))
14+ (value 6:1 wrong
15+ (cast 6:10 (ref 6:13 msg) (lit 6:17 %missing))))
tests/golden/types-union-tags/types.txtnew file+11
@@ -0,0 +1,11 @@
1+partial inference; module not checked
2++$ msg: cases proven disjoint; mold not checked
3+++ simple: union type printing is not supported by partial inference
4+++ record: union type printing is not supported by partial inference
5+++ wrong: cast mold and expression type do not unify
6+/tests/golden/types-union-tags/source.jibb:6:13: cast mold
7+++ wrong ^- msg %missing
8+ ^
9+/tests/golden/types-union-tags/source.jibb:6:17: expression
10+++ wrong ^- msg %missing
11+ ^
tests/golden/types-union-unresolved-flow/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Tag resolution: "A constrained variable, and any it mentions, doesn't generalize" and an unresolved tag needs context.
2+tests: An unresolved tag remains unresolved through an alias, a cell, a gate and a discarded trace; partial inference must not guess a type.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-unresolved-flow/source.jibbnew file+7
@@ -0,0 +1,7 @@
1+++ first %add
2+++ alias first
3+++ cell [%add 1]
4+++ gate |= x %add
5+++ traced
6+ ~& %add
7+ 1
tests/golden/types-union-unresolved-flow/tokens.txtnew file+31
@@ -0,0 +1,31 @@
1+1:1 glyph ++
2+1:4 name first
3+1:10 lit %add
4+2:1 NEWLINE
5+2:1 glyph ++
6+2:4 name alias
7+2:10 name first
8+3:1 NEWLINE
9+3:1 glyph ++
10+3:4 name cell
11+3:9 glyph [
12+3:10 tight lit %add
13+3:15 lit 1
14+3:16 tight glyph ]
15+4:1 NEWLINE
16+4:1 glyph ++
17+4:4 name gate
18+4:9 glyph |=
19+4:12 name x
20+4:14 lit %add
21+5:1 NEWLINE
22+5:1 glyph ++
23+5:4 name traced
24+6:3 INDENT
25+6:3 glyph ~&
26+6:6 lit %add
27+7:5 INDENT
28+7:5 lit 1
29+7:6 DEDENT
30+7:6 DEDENT
31+7:6 NEWLINE
tests/golden/types-union-unresolved-flow/tree.txtnew file+12
@@ -0,0 +1,12 @@
1+(module
2+ (value 1:1 first (lit 1:10 %add))
3+ (value 2:1 alias (wing 2:10 first))
4+ (value 3:1 cell
5+ (tuple 3:9 (lit 3:10 %add) (lit 3:15 1)))
6+ (value 4:1 gate
7+ (gate 4:9 (bind 4:12 x) (lit 4:14 %add)))
8+ (value 5:1 traced
9+ (body 6:3
10+ (trace 6:3
11+ (lit 6:6 %add)
12+ (body 7:5 (lit 7:5 1))))))
tests/golden/types-union-unresolved-flow/types.txtnew file+6
@@ -0,0 +1,6 @@
1+partial inference; module not checked
2+++ first: tag needs context in partial inference
3+++ alias: name is not available to partial inference
4+++ cell: tag needs context in partial inference
5+++ gate: tag needs context in partial inference
6+++ traced: tag needs context in partial inference
tests/golden/types-union-unresolved/about.txtnew file+4
@@ -0,0 +1,4 @@
1+source: Grammar, Molds and Tag resolution: a `+$` with cases forms a union; tags take their union from context.
2+tests: A tag with no context stays unresolved and asks for a type rather than being guessed.
3+expect: parses
4+expect-types: a partial inference report
tests/golden/types-union-unresolved/source.jibbnew file+1
@@ -0,0 +1 @@
1+++ alone %add
tests/golden/types-union-unresolved/tokens.txtnew file+4
@@ -0,0 +1,4 @@
1+1:1 glyph ++
2+1:4 name alone
3+1:10 lit %add
4+1:14 NEWLINE
tests/golden/types-union-unresolved/tree.txtnew file+2
@@ -0,0 +1,2 @@
1+(module
2+ (value 1:1 alone (lit 1:10 %add)))
tests/golden/types-union-unresolved/types.txtnew file+2
@@ -0,0 +1,2 @@
1+partial inference; module not checked
2+++ alone: tag needs context in partial inference
tests/importer/about.txt+5−4
@@ -2,10 +2,11 @@
22recursion, and unsupported forms. `shadow.txt` checks local generator
33shadowing and missing provenance. `shadow-static.txt` checks that a local
44list shadow alongside a nested ordered map is rejected. Static sibling
5−collections and dependent sibling molds are tested separately. A single nested `$^` in a record of aura atom molds, constant tags and records is checked
6−from its source branches. Named or validated siblings and branches, multiple `$^` cases,
7−and `$^` in collection arguments fail closed before Hoon can collapse
8−overlapping branches; nested `$@` cases remain supported. `ford.txt`
5+collections and dependent sibling molds are tested separately. Explicit Hoon `$%`, `$?` and `$^` unions are checked from source where
6+their branches are static, including cases Hoon would collapse. Materialized
7+forks are checked too. Named or validated branches, multiple nested unions,
8+and explicit unions in collection arguments fail closed; nested `$@` cases
9+remain supported. The provisional reading is recorded in doc question 22. `ford.txt`
910checks a synthetic imported subject and selected mold; other cases check
1011transitive imports, named mold lookup, missing names, shadowing, unprovenanced
1112recursive holds, malformed
tests/importer/ford.txt+1
@@ -2,6 +2,7 @@
22+$ lists (list @ud)
33+$ wrapped item:small
44+$ recursive chain:small
5++$ bad-union explicit-wut-overlap:small
56+$ tagged-record nested-tagged:small
67+$ nested-record nested-valid-cell:small
78+$ local $@(~ [v=@ud next=local])
tests/importer/origin-transitive.txt+1
@@ -1,5 +1,6 @@
11|%
22+$ wrapped recursive:intermediate
3++$ bad-union bad-union:intermediate
34+$ tagged tagged-record:intermediate
45+$ nested nested-record:intermediate
56--
tests/importer/shadow-static.txt+2
@@ -1,4 +1,6 @@
11|%
22++ list list:..zuse
3+++ path path:..zuse
4++$ path-shadow [?(%fil %dir) pa=path nam=@t]
35+$ bad [a=((mop @ud @t) lte) b=(list @ud)]
46--
tests/importer/small.txt+12
@@ -26,6 +26,18 @@
2626+$ signed @sd
2727+$ float @rd
2828+$ gate-test $-(@ud @ud)
29++$ explicit-wut-safe $?([%ok @ud] [%err @t])
30++$ explicit-percent-overlap $%([%x @ud] [%x @t])
31++$ explicit-wut-overlap $?([%x @ud] [%x @t])
32++$ explicit-collapsed $?([%x @ud] [%x @ud])
33++$ explicit-subsumed $?(@u @ud)
34++$ explicit-three $?([%a @ud] [%b @t] [%c @p])
35++$ explicit-unknown $?([%x word] [%y @t])
36++$ explicit-nested [value=$?([%x @ud] [%x @t]) other=@ud]
37++$ explicit-list (list $?([%x @ud] [%x @t]))
38++$ explicit-set (set $%([%x @ud] [%x @ud]))
39++$ explicit-faces (list [bcwt=@t bccn=@ud])
40++$ explicit-alias explicit-wut-overlap
2941+$ list-bckt-field (list [bckt=@ud value=@t])
3042+$ list-noun-overlap (list $^(* @ud))
3143+$ list-null-overlap (list $^(~ @ud))
tests/importer/tree.txt+21−1
@@ -46,6 +46,26 @@ float: error: signed and float auras cannot be imported
4646gate: error: cores and gates cannot be imported
4747vase: error: vases cannot be imported
4848failed-branch: error: a Hoon $^ union needs a source-level disjointness check
49+debug-union: (union [add text=@t] [remove id=@ud])
50+debug-union-overlap: error: a Hoon union has overlapping cases
51+debug-nested-cell: [id=@ud value=(union [a=@ud b=@t] @ud)]
52+debug-nested-cell-overlap: error: a Hoon $^ union has overlapping cases
53+explicit-graph: error: a Hoon union has overlapping cases
54+explicit-graph-unsupported: error: signed and float auras cannot be imported
55+explicit-wut-safe: (union [ok @ud] [err @t])
56+explicit-percent-overlap: error: a Hoon union has overlapping cases
57+explicit-wut-overlap: error: a Hoon union has overlapping cases
58+explicit-collapsed: error: a Hoon union has overlapping cases
59+explicit-subsumed: error: a Hoon union has overlapping cases
60+explicit-three: (union [a @ud] [b @t] [c @p])
61+explicit-unknown: error: a Hoon union needs a source-level disjointness check
62+explicit-nested: error: a Hoon union has overlapping cases
63+explicit-list: error: a Hoon union needs a source-level disjointness check
64+explicit-set: error: a Hoon union needs a source-level disjointness check
65+explicit-faces: (list [bcwt=@t bccn=@ud])
66+explicit-alias: error: a Hoon union has overlapping cases
67+explicit-ford: error: a Hoon union has overlapping cases
68+explicit-shadow-path: error: Hoon collection provenance is unavailable or shadowed
4969list-bckt-field: (list [bckt=@ud value=@t])
5070list-noun-overlap: error: a Hoon $^ union needs a source-level disjointness check
5171list-null-overlap: error: a Hoon $^ union needs a source-level disjointness check
@@ -71,7 +91,7 @@ nested-first-cell: [value=(union [a=@ud b=@t] @ud) id=@t]
7191nested-alias-cell: [id=@ud value=(union [a=@ud b=@t] @ud)]
7292nested-multiple-cell: error: a Hoon $^ union needs a source-level disjointness check
7393nested-named-sibling: error: a Hoon $^ union needs a source-level disjointness check
74−nested-list-sibling: error: a Hoon $^ union needs a source-level disjointness check
94+nested-list-sibling: [id=(list @ud) value=(union [a=@ud b=@t] @ud)]
7595nested-validated-sibling: error: a Hoon $^ union needs a source-level disjointness check
7696nested-validated-branch: error: a Hoon $^ union needs a source-level disjointness check
7797nested-named-branch: error: a Hoon $^ union needs a source-level disjointness check
tests/lib/jibb-module-scope.hoon+10−1
@@ -20,5 +20,14 @@
2020 =/ bad (golden-types-with-prelude:jibb /ui/main/jibb source ~ ~ fixtures (crip "+$"))
2121 =/ conflict=@t (crip "/= value /ui/dep\0a++ identity |= x x\0a")
2222 =/ collision (golden-types-with-prelude:jibb /ui/main/jibb conflict ~ ~ fixtures prelude)
23− (of-wain:format ~[okay empty bad collision])
23+ =/ library=@t (crip "++ pass |=(x x)\0a")
24+ =/ duplicate-source=@t (crip "/= dep /ui/dup\0a++ main-value 1\0a")
25+ =/ duplicates=(list [at=path source=@t])
26+ ~[[~[%ui %dup %jibb] library] [~[%ui %dup %jibb] library]]
27+ =/ duplicate (golden-types-with-prelude:jibb /ui/main/jibb duplicate-source ~ ~ duplicates prelude)
28+ =/ after-source=@t (crip "/= first /ui/safe\0a/= second /ui/dup\0a++ main-value 1\0a")
29+ =/ after-fixtures=(list [at=path source=@t])
30+ [[~[%ui %safe %jibb] library] duplicates]
31+ =/ after (golden-types-with-prelude:jibb /ui/main/jibb after-source ~ ~ after-fixtures prelude)
32+ (of-wain:format ~[okay empty bad collision duplicate after])
2433--
tests/lib/jibb.hoon+56
@@ -1562,6 +1562,44 @@
15621562/* tok-459 %txt /tests/golden/types-record-to-tuple/tokens/txt
15631563/* tre-459 %txt /tests/golden/types-record-to-tuple/tree/txt
15641564/* typ-459 %txt /tests/golden/types-record-to-tuple/types/txt
1565+/* src-460 %jibb /tests/golden/types-union-alias/source/jibb
1566+/* tok-460 %txt /tests/golden/types-union-alias/tokens/txt
1567+/* tre-460 %txt /tests/golden/types-union-alias/tree/txt
1568+/* typ-460 %txt /tests/golden/types-union-alias/types/txt
1569+/* src-461 %jibb /tests/golden/types-union-context-flow/source/jibb
1570+/* tok-461 %txt /tests/golden/types-union-context-flow/tokens/txt
1571+/* tre-461 %txt /tests/golden/types-union-context-flow/tree/txt
1572+/* typ-461 %txt /tests/golden/types-union-context-flow/types/txt
1573+/* src-462 %jibb /tests/golden/types-union-import/source/jibb
1574+/* tok-462 %txt /tests/golden/types-union-import/tokens/txt
1575+/* tre-462 %txt /tests/golden/types-union-import/tree/txt
1576+/* mod-462-1 %jibb /tests/golden/types-union-import/modules/ui/lib/jibb
1577+/* typ-462 %txt /tests/golden/types-union-import/types/txt
1578+/* mtre-462 %txt /tests/golden/types-union-import/module-trees/txt
1579+/* src-463 %jibb /tests/golden/types-union-overlap/source/jibb
1580+/* tok-463 %txt /tests/golden/types-union-overlap/tokens/txt
1581+/* tre-463 %txt /tests/golden/types-union-overlap/tree/txt
1582+/* typ-463 %txt /tests/golden/types-union-overlap/types/txt
1583+/* src-464 %jibb /tests/golden/types-union-singleton/source/jibb
1584+/* tok-464 %txt /tests/golden/types-union-singleton/tokens/txt
1585+/* tre-464 %txt /tests/golden/types-union-singleton/tree/txt
1586+/* typ-464 %txt /tests/golden/types-union-singleton/types/txt
1587+/* src-465 %jibb /tests/golden/types-union-tag-atoms/source/jibb
1588+/* tok-465 %txt /tests/golden/types-union-tag-atoms/tokens/txt
1589+/* tre-465 %txt /tests/golden/types-union-tag-atoms/tree/txt
1590+/* typ-465 %txt /tests/golden/types-union-tag-atoms/types/txt
1591+/* src-466 %jibb /tests/golden/types-union-tags/source/jibb
1592+/* tok-466 %txt /tests/golden/types-union-tags/tokens/txt
1593+/* tre-466 %txt /tests/golden/types-union-tags/tree/txt
1594+/* typ-466 %txt /tests/golden/types-union-tags/types/txt
1595+/* src-467 %jibb /tests/golden/types-union-unresolved/source/jibb
1596+/* tok-467 %txt /tests/golden/types-union-unresolved/tokens/txt
1597+/* tre-467 %txt /tests/golden/types-union-unresolved/tree/txt
1598+/* typ-467 %txt /tests/golden/types-union-unresolved/types/txt
1599+/* src-468 %jibb /tests/golden/types-union-unresolved-flow/source/jibb
1600+/* tok-468 %txt /tests/golden/types-union-unresolved-flow/tokens/txt
1601+/* tre-468 %txt /tests/golden/types-union-unresolved-flow/tree/txt
1602+/* typ-468 %txt /tests/golden/types-union-unresolved-flow/types/txt
15651603|%
15661604:: one arm per case
15671605::
@@ -2483,6 +2521,24 @@
24832521 (weld (check ~.types-record-nested src-458 `tok-458 `tre-458) (check-types ~.types-record-nested ~[%tests %golden ~.types-record-nested %source %jibb] src-458 `typ-458))
24842522++ test-types-record-to-tuple
24852523 (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
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))
2526+++ 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))
2528+++ 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]]))
2530+++ 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))
2532+++ 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))
2534+++ 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))
2536+++ 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))
2538+++ 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))
2540+++ 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))
24862542::
24872543:: +check: run golden:jibb on a case and compare both outputs
24882544::
tests/type-module-scope/about.txt+2
@@ -3,3 +3,5 @@ source. Names from the prelude occupy separate value and mold namespaces;
33import faces cannot shadow either. This synthetic prelude exercises a value
44whose name is used as an imported mold and a mold whose name is used as an
55imported value. Empty and malformed prelude sources fail closed.
6+Duplicate module sources are rejected both directly and after a distinct
7+sibling module has been cached; they cannot produce an interface.
tests/type-module-scope/expected.txt+4
@@ -7,3 +7,7 @@ partial inference; module not checked
77prelude source does not parse; module import inference unsupported
88partial inference; module not checked
99module has conflicting names
10+partial inference; module not checked
11+duplicate module sources: /ui/dup/jibb
12+partial inference; module not checked
13+duplicate module sources: /ui/dup/jibb
tools/importer-test+1−1
@@ -34,4 +34,4 @@ if result.stdout != expected:
3434 result.stdout.decode().splitlines(keepends=True),
3535 fromfile='expected tree.txt', tofile='actual types'))
3636 sys.exit(1)
37−print('importer golden: 110 projections passed')
37+print('importer golden: 130 projections passed')