on master help sign in
Infer contextual unit payloads
264a436iko
docs/compiler.md+1−1
@@ -68,7 +68,7 @@ Multi-argument calls form one right-nested sample: `f a b c` supplies `[a [b c]]
68
68
69A list literal can be inferred when a cast or known gate sample supplies a list type and the supplied prelude has the validated standard list definition. Empty, nonempty and nested literals work, including contextual union tags in elements; mismatched elements report the item and expected type. Imported Hoon lists share this representation. Under the same known context, `~` and zero-valued term literals fit an empty list, and a two-item unfaced cell `[head tail]` is a cons; cons cells and list literals can be nested. Mismatched heads or tails report both sites. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. A known gate sample also supplies context to corresponding positions of a single tuple or record argument, including nested cells; a zero literal can therefore fit a list position. A bound zero constant still remains unsupported rather than a definite mismatch, and an unknown callee does not supply context. Faced or longer cells, uncontextualized construction, and a missing or altered prelude list remain unsupported. For a known standard list with a supported element type, it also infers a complete two-arm branch using `~` and `[item rest]`, in either order. The binders have the element and list types and cannot shadow or duplicate names. Unknown subjects, unsupported element types, other patterns and incomplete arms remain unsupported.
69A list literal can be inferred when a cast or known gate sample supplies a list type and the supplied prelude has the validated standard list definition. Empty, nonempty and nested literals work, including contextual union tags in elements; mismatched elements report the item and expected type. Imported Hoon lists share this representation. Under the same known context, `~` and zero-valued term literals fit an empty list, and a two-item unfaced cell `[head tail]` is a cons; cons cells and list literals can be nested. Mismatched heads or tails report both sites. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. A known gate sample also supplies context to corresponding positions of a single tuple or record argument, including nested cells; a zero literal can therefore fit a list position. A bound zero constant still remains unsupported rather than a definite mismatch, and an unknown callee does not supply context. Faced or longer cells, uncontextualized construction, and a missing or altered prelude list remain unsupported. For a known standard list with a supported element type, it also infers a complete two-arm branch using `~` and `[item rest]`, in either order. The binders have the element and list types and cannot shadow or duplicate names. Unknown subjects, unsupported element types, other patterns and incomplete arms remain unsupported.
70
70
71−A backtick constructs a unit when the supplied prelude has the validated standard `unit` template. Its payload is inferred normally, retaining pending literals and generic variables; nested units work and the prelude’s `some` becomes available. Unit payloads that require contextual matching, unrelated union identities, and missing or altered prelude templates remain unsupported.
71+A backtick constructs a unit when the supplied prelude has the validated standard `unit` template. Its payload is inferred normally, retaining pending literals and generic variables; nested units work and the prelude’s `some` becomes available. A known unit in a cast, call, list item or record field supplies its payload context, including nested units and lists; definite mismatches identify the payload and context. Unrelated union identities, some variable-dependent fits, and missing or altered prelude templates remain unsupported.
72
72
73A known union of `~` and a null-headed cell can be matched by `~` and `[~ value]` arms in either order. The payload binder is checked for shadowing. Unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported; this fragment infers the prelude’s `fall` and `need` signatures.
73A known union of `~` and a null-headed cell can be matched by `~` and `[~ value]` arms in either order. The payload binder is checked for shadowing. Unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported; this fragment infers the prelude’s `fall` and `need` signatures.
74
74
docs/status.md+4−3
@@ -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, term singletons, nested faced or unfaced cells, supported disjoint unions and opaque standard collections from `/sur` molds and marks into inference. Collections retain their names and supported arguments for printing and unification; nested supported union arguments are retained too. The bridge trusts unchanged results from the source-aware reader; a materialized type graph alone cannot reveal cases Hoon already collapsed. The source-validated standard prelude `list` mold shares this representation with imported lists; other Jibb-written collection molds and most prelude collection operations remain unsupported; malformed names and arities fail closed. Selected self-recursive `/sur` molds cross as opaque module-and-name identities; aliases, foreign references, recursive marks, unfolding and construction remain unsupported. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, direct `$^` unions whose cases can be proved disjoint, and one verified explicit union argument in a list, set, map or unit. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases, as @iko confirmed for imported `$%`, `$?` and `$^`, while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. Opt-in structured reader APIs preserve successful graphs and distinguish definite unsupported-aura and core evidence from failures the reader cannot prove; unverified union disjointness and name-only vase recognition remain unsupported. They revalidate and re-walk failed types. An opt-in partial checker entry point consumes unchanged reader results and reports definite aura or core errors at imported mold use sites when their inputs are unique. Ordered replay covers nested cell samples, record and function casts, and non-generic same-module aliases; unsupported prefixes, cycles and shadowing stop it. Union molds, generic applications, transitive modules and unsupported reader outcomes remain generic. Replay repeats inference and may add work. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and a source-derived partial prelude interface, caches completed interfaces per run, and detects missing sources and cycles. It does not yet check API or kind semantics, and the prelude inventory is incomplete. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, acyclic local value definitions with captures, selected single self-recursive top-level and local gates, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags, `~` and constructors for closed disjoint unions, including direct nonrecursive generic unions and propagation through complete loobean and unit-shaped branches in casts and known union-sample calls, including nested branches. Multi-argument calls form a right-nested sample, retain known faces and shared type variables, and can use known sample positions to contextualize list and union arguments. A definite mismatch points to the failing argument when the fragment can establish it, otherwise to the combined sample; unsupported contextual forms still fail closed. For a supported recursive gate, the checker infers the sample first and uses its exact type, including field faces, for one monomorphic self reference. It generalizes after the body is checked; subsequent uses instantiate it independently. Incompatible recursive arguments can report the gate and argument sites. For a complete loobean branch with one direct self-call arm, a separately inferred closed base type can seed the recursive result before the whole body is checked. Open or pending base types do not seed it; other branch shapes remain subject to the fragment’s existing limits. A supported single local recursive gate also uses a monomorphic self reference and generalizes variables free of the enclosing environment after checking its body; captured variables remain shared. The checker collects written capitals per `++` before inference, excluding nested definitions: a capital used in an enclosing definition is shared with its locals even when written later, while a capital introduced only in a local definition is generalized there. Sibling locals can introduce independent capitals with the same spelling; generic mold parameters keep their own scope. Top-level groups of syntactic gates are inferred together with monomorphic placeholders and shared substitutions, then generalized only after the whole group checks; downstream uses and library interfaces instantiate those schemes independently. A dependency graph identifies groups with two iterative depth-first passes; its conservative local-reference edges can reject otherwise valid programs. Local mutual groups, polymorphic recursion, value cycles, unresolved literal constraints and unresolved branch joins remain unsupported. Reporting repeats inference for a single recursive gate outside a group; grouped reports use the stored schemes. Its performance cost remains unmeasured. String interpolation accepts known atom auras, unrestricted `@`, tapes and isolated decimal literals; a known cell asks for a printer, and an explicitly generic atom asks for an aura. Loobeans, term singletons, non-tape collections, open types and a type fixed only later remain unsupported. A known closed union with two or more arms supports patterns that provably cover or exclude each remaining case, including payload binders, imported and generic cases, and binder-free catch-alls. Partial boolean patterns can split known `?` positions into their two noun values, up to 64 alternatives across the union; binders retain their original case type. Missing alternatives and covered arms are reported. Other partial patterns, expansions above the limit, binders spanning distinct cases, differing arm result types, some complex two-arm subjects and contextual union-pattern branches remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked. Known faced records support uniquely named field changes, including nested wings, with field context passed to replacements and the original record type retained. Missing fields, empty changes and definite mismatches report sites; the expected-type site is the edit because the original field declaration location is not retained. Unknown or partly unfaced spines, ambiguous fields and repeated edits remain unsupported. A known record cast supplies field context to its tuple or record initializer, including nested list and union fields; mismatch diagnostics use the cast mold because the original field declaration location is not retained. The cart-store example’s `init` and `update` now infer, while its kind, declarations and full module remain unchecked. Backtick unit construction uses the validated standard prelude unit template, infers its payload without losing pending constraints, and makes the prelude’s `some` available. Context-dependent payload matching and missing or altered prelude unit templates remain unsupported. Contextual null-headed cells fit their cases, but do not supply a `|=%$` constructor; unresolved nulls remain pending and are reported separately from tags. A known union of `~` and a null-headed cell supports a complete `~` / `[~ value]` branch in either order, including shadow checks; unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported. This fragment infers the prelude’s `fall` and `need` signatures. With the validated prelude list and a known cast or gate sample, empty, nonempty and nested list literals infer their element types, including contextual union tags; a mismatched element names both sites. In that context `~` and zero-valued terms fit an empty list, and two-item unfaced cells form cons lists, including nested cons and imported-list contexts; invalid heads or tails name both sites. A known gate sample also supplies context to matching positions in a single tuple or record argument, including nested cells; zero literals can fit list positions. A bound zero constant remains unsupported rather than a definite mismatch, and an unknown callee does not supply context. Faced or longer cells and a missing or altered prelude list fail closed. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. For a known standard list with a supported element type, a complete `~` / `[item rest]` branch infers the element and tail types in either arm order and checks binders for shadowing. Uncontextualized list construction, unknown subjects, unsupported element types and other or incomplete list patterns remain unsupported. A value with type variable `A` can fit a field whose type is that same `A`, including in generic union payloads and nested or repeated record fields. Other variable-dependent face merges remain unsupported. Forced equality of distinct written capitals now reports both source sites, following @iko’s decision; forcing one to a concrete type remains unsupported. Imported record spines with repeated faces fail closed where used, but only with a generic unsupported diagnostic. Hoon may erase unfaced nested-cell boundaries, so the check can conservatively reject valid names in distinct erased scopes. Supported closed unions print using an in-scope name or imported alias; an unnamed nongeneric union prints its cases, parenthesized when nested. The latter is print-only. Generic union types retain all arguments in their printed name; if that name is unavailable, the partial printer reports the limitation. Different import faces for the same origin remain compatible; compatibility across distinct union origins and some generic-argument comparisons remain unsupported. Nonrecursive generic aliases can reorder, repeat or omit parameters while retaining a union’s origin, including through local scopes and library interfaces. A generic union declared directly inside a body remains unsupported, as do differing-variable face constraints in a union payload. A transitive generic union whose name is unavailable is reported as unsupported instead of hiding its arguments. Unfixed decimal literals default to `@ud` in gate-free inferred types; mutually recursive local groups and recursive molds, general branch tag context, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; a wrapper regression also rejects forged subjects, samples and tails. Its golden fixtures include three real Tlon files. A Clay test passes a Ford-built nested union through the reader into partial inference. The partial prelude includes `murn`, `join`, `snip`, `rear` and the newly agreed shared-type `clap`, parsed but still awaiting checker and backend validation, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
22+The repository spec records the subsequent type-system and prelude decisions; those changes also need synchronization to the Claude document. An initial inference fragment and a standalone Hoon type reader are being tested. The fragment explicitly reports that it does not check a module; partial bridges pass selected Hoon atoms, term singletons, nested faced or unfaced cells, supported disjoint unions and opaque standard collections from `/sur` molds and marks into inference. Collections retain their names and supported arguments for printing and unification; nested supported union arguments are retained too. The bridge trusts unchanged results from the source-aware reader; a materialized type graph alone cannot reveal cases Hoon already collapsed. The source-validated standard prelude `list` mold shares this representation with imported lists; other Jibb-written collection molds and most prelude collection operations remain unsupported; malformed names and arities fail closed. Selected self-recursive `/sur` molds cross as opaque module-and-name identities; aliases, foreign references, recursive marks, unfolding and construction remain unsupported. The reader handles mark samples, recursive molds whose origins can be verified through Ford imports, nested collections, direct ordered maps, certain ordered-map fields, direct `$^` unions whose cases can be proved disjoint, and one verified explicit union argument in a list, set, map or unit. Ambiguous recursive origins fail closed; recognizable explicit unions are checked from source before Hoon can collapse their cases, as @iko confirmed for imported `$%`, `$?` and `$^`, while other nested unions, nested ordered maps, general union disjointness and complete import integration remain unfinished. Opt-in structured reader APIs preserve successful graphs and distinguish definite unsupported-aura and core evidence from failures the reader cannot prove; unverified union disjointness and name-only vase recognition remain unsupported. They revalidate and re-walk failed types. An opt-in partial checker entry point consumes unchanged reader results and reports definite aura or core errors at imported mold use sites when their inputs are unique. Ordered replay covers nested cell samples, record and function casts, and non-generic same-module aliases; unsupported prefixes, cycles and shadowing stop it. Union molds, generic applications, transitive modules and unsupported reader outcomes remain generic. Replay repeats inference and may add work. The partial checker resolves a subset of ordinary library imports in dependency order using supplied Jibb sources and a source-derived partial prelude interface, caches completed interfaces per run, and detects missing sources and cycles. It does not yet check API or kind semantics, and the prelude inventory is incomplete. The inference fragment supports unrestricted `@`, selected one-way widenings including aura-family ancestors, generalized atom constraints arising from explicit capitals or bare sample binders, acyclic local value definitions with captures, selected single self-recursive top-level and local gates, simple and nonrecursive generic mold aliases, selected faced record casts and field reads, and contextual tags, `~` and constructors for closed disjoint unions, including direct nonrecursive generic unions and propagation through complete loobean and unit-shaped branches in casts and known union-sample calls, including nested branches. Multi-argument calls form a right-nested sample, retain known faces and shared type variables, and can use known sample positions to contextualize list and union arguments. A definite mismatch points to the failing argument when the fragment can establish it, otherwise to the combined sample; unsupported contextual forms still fail closed. For a supported recursive gate, the checker infers the sample first and uses its exact type, including field faces, for one monomorphic self reference. It generalizes after the body is checked; subsequent uses instantiate it independently. Incompatible recursive arguments can report the gate and argument sites. For a complete loobean branch with one direct self-call arm, a separately inferred closed base type can seed the recursive result before the whole body is checked. Open or pending base types do not seed it; other branch shapes remain subject to the fragment’s existing limits. A supported single local recursive gate also uses a monomorphic self reference and generalizes variables free of the enclosing environment after checking its body; captured variables remain shared. The checker collects written capitals per `++` before inference, excluding nested definitions: a capital used in an enclosing definition is shared with its locals even when written later, while a capital introduced only in a local definition is generalized there. Sibling locals can introduce independent capitals with the same spelling; generic mold parameters keep their own scope. Top-level groups of syntactic gates are inferred together with monomorphic placeholders and shared substitutions, then generalized only after the whole group checks; downstream uses and library interfaces instantiate those schemes independently. A dependency graph identifies groups with two iterative depth-first passes; its conservative local-reference edges can reject otherwise valid programs. Local mutual groups, polymorphic recursion, value cycles, unresolved literal constraints and unresolved branch joins remain unsupported. Reporting repeats inference for a single recursive gate outside a group; grouped reports use the stored schemes. Its performance cost remains unmeasured. String interpolation accepts known atom auras, unrestricted `@`, tapes and isolated decimal literals; a known cell asks for a printer, and an explicitly generic atom asks for an aura. Loobeans, term singletons, non-tape collections, open types and a type fixed only later remain unsupported. A known closed union with two or more arms supports patterns that provably cover or exclude each remaining case, including payload binders, imported and generic cases, and binder-free catch-alls. Partial boolean patterns can split known `?` positions into their two noun values, up to 64 alternatives across the union; binders retain their original case type. Missing alternatives and covered arms are reported. Other partial patterns, expansions above the limit, binders spanning distinct cases, differing arm result types, some complex two-arm subjects and contextual union-pattern branches remain unsupported. The Grammar’s `step` block infers in this fragment, but its module is not yet checked. Known faced records support uniquely named field changes, including nested wings, with field context passed to replacements and the original record type retained. Missing fields, empty changes and definite mismatches report sites; the expected-type site is the edit because the original field declaration location is not retained. Unknown or partly unfaced spines, ambiguous fields and repeated edits remain unsupported. A known record cast supplies field context to its tuple or record initializer, including nested list and union fields; mismatch diagnostics use the cast mold because the original field declaration location is not retained. The cart-store example’s `init` and `update` now infer, while its kind, declarations and full module remain unchecked. Backtick unit construction uses the validated standard prelude unit template, infers its payload without losing pending constraints, and makes the prelude’s `some` available. A known unit in a cast, call, list item or record field supplies context to its payload, including nested units and lists; mismatches identify the payload and context. Unrelated union identities, some variable-dependent fits, and missing or altered prelude unit templates remain unsupported. Contextual null-headed cells fit their cases, but do not supply a `|=%$` constructor; unresolved nulls remain pending and are reported separately from tags. A known union of `~` and a null-headed cell supports a complete `~` / `[~ value]` branch in either order, including shadow checks; unknown subjects, missing or duplicate arms, and unresolved branch results remain unsupported. This fragment infers the prelude’s `fall` and `need` signatures. With the validated prelude list and a known cast or gate sample, empty, nonempty and nested list literals infer their element types, including contextual union tags; a mismatched element names both sites. In that context `~` and zero-valued terms fit an empty list, and two-item unfaced cells form cons lists, including nested cons and imported-list contexts; invalid heads or tails name both sites. A known gate sample also supplies context to matching positions in a single tuple or record argument, including nested cells; zero literals can fit list positions. A bound zero constant remains unsupported rather than a definite mismatch, and an unknown callee does not supply context. Faced or longer cells and a missing or altered prelude list fail closed. A known list result also supplies context through complete loobean, unit-shaped and list-shaped branches, including recursive and nested branches. For a known standard list with a supported element type, a complete `~` / `[item rest]` branch infers the element and tail types in either arm order and checks binders for shadowing. Uncontextualized list construction, unknown subjects, unsupported element types and other or incomplete list patterns remain unsupported. A value with type variable `A` can fit a field whose type is that same `A`, including in generic union payloads and nested or repeated record fields. Other variable-dependent face merges remain unsupported. Forced equality of distinct written capitals now reports both source sites, following @iko’s decision; forcing one to a concrete type remains unsupported. Imported record spines with repeated faces fail closed where used, but only with a generic unsupported diagnostic. Hoon may erase unfaced nested-cell boundaries, so the check can conservatively reject valid names in distinct erased scopes. Supported closed unions print using an in-scope name or imported alias; an unnamed nongeneric union prints its cases, parenthesized when nested. The latter is print-only. Generic union types retain all arguments in their printed name; if that name is unavailable, the partial printer reports the limitation. Different import faces for the same origin remain compatible; compatibility across distinct union origins and some generic-argument comparisons remain unsupported. Nonrecursive generic aliases can reorder, repeat or omit parameters while retaining a union’s origin, including through local scopes and library interfaces. A generic union declared directly inside a body remains unsupported, as do differing-variable face constraints in a union payload. A transitive generic union whose name is unavailable is reported as unsupported instead of hiding its arguments. Unfixed decimal literals default to `@ud` in gate-free inferred types; mutually recursive local groups and recursive molds, general branch tag context, other constraint cases and defaulting inside gate types still need work. Collection recognition checks the originating core and fails closed on shadows or unsupported Ford subject shapes; a wrapper regression also rejects forged subjects, samples and tails. Its golden fixtures include three real Tlon files. A Clay test passes a Ford-built nested union through the reader into partial inference. The partial prelude includes `murn`, `join`, `snip`, `rear` and the newly agreed shared-type `clap`, parsed but still awaiting checker and backend validation, and [prelude-inventory.md](prelude-inventory.md) is a source audit, not the complete inventory or signatures. The milestone remains unfinished.
23
23
24The shared prelude interface reserves every name present in the supplied vendored source and makes only supported inferred entries available, including `list`, `unit`, `same`, `fall`, `need`, `lure`, `weld`, `snoc` and `turn`. The validated standard `list` mold is injected when the prelude’s own gates are inferred; `weld` and `turn` have ordinary explicit result casts. An absent or altered `list` is not injected, and an altered declaration cannot leak through direct or transitive mold aliases. List-dependent prelude mold aliases remain unsupported because their templates are prepared before injection. Unsupported entries such as most list helpers remain reserved but unavailable; backend validation of the helpers remains outstanding. All callers use the same prelude origin, so a library can export a type containing unqualified `(unit A)` to another module. Preparation rejects empty, malformed, conflicting or import-bearing source; the prepared value is trusted and must come unchanged from `+prepare-prelude`. The module-scope fixture compares the prepared and source-taking paths against the real prelude and a two-module golden under eval and on the ship. The source and checker remain incomplete, so this does not establish complete shadowing coverage or a checked module.
24The shared prelude interface reserves every name present in the supplied vendored source and makes only supported inferred entries available, including `list`, `unit`, `same`, `fall`, `need`, `lure`, `weld`, `snoc` and `turn`. The validated standard `list` mold is injected when the prelude’s own gates are inferred; `weld` and `turn` have ordinary explicit result casts. An absent or altered `list` is not injected, and an altered declaration cannot leak through direct or transitive mold aliases. List-dependent prelude mold aliases remain unsupported because their templates are prepared before injection. Unsupported entries such as most list helpers remain reserved but unavailable; backend validation of the helpers remains outstanding. All callers use the same prelude origin, so a library can export a type containing unqualified `(unit A)` to another module. Preparation rejects empty, malformed, conflicting or import-bearing source; the prepared value is trusted and must come unchanged from `+prepare-prelude`. The module-scope fixture compares the prepared and source-taking paths against the real prelude and a two-module golden under eval and on the ship. The source and checker remain incomplete, so this does not establish complete shadowing coverage or a checked module.
25
25
@@ -40,7 +40,7 @@ What the plan asks for, and where it is:
40Besides the plan's list:
40Besides the plan's list:
41
41
42- 535 golden cases: 319 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.
42- 535 golden cases: 319 that parse and 216 that fail, each failure at a stated line and column. One failing case has an unclear expectation (corpus question 3). The newer type-output cases exercise only the partial inference fragment. Each case's `about.txt` quotes the doc's words it tests.
43−- The 535-case corpus passed under `urbit eval` in 66.0 s. The fake ship passed all 541 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 33.4 s for sync and 40.8 s for tests. The importer golden compares 149 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
43+- The 535-case corpus passed under `urbit eval` in 62.4 s. The fake ship passed all 541 tests, including the importer, importer/checker and mark/checker bridges, module scope and unification checks, with 32.8 s for sync and 39.4 s for tests. The importer golden compares 149 projections; `tools/clay-fixtures` builds the example Hoon fixtures through Clay, checks a recursive Ford import's origin, and passes Clay-built types through the Clay-built importer and partial checker.
44- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
44- `tools/testdata/selftest` (22 checks) and `tools/testdata/ship-selftest` test the tools themselves.
45- 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.
45- 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.
46- 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).
46- 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).
@@ -97,7 +97,8 @@ Besides the plan's list:
97| 9f1517e | 2026-10-30 | Infer whole-case union patterns and prelude `turn` |
97| 9f1517e | 2026-10-30 | Infer whole-case union patterns and prelude `turn` |
98| 9dd35c8 | 2026-10-31 | Match finite boolean refinements of union cases |
98| 9dd35c8 | 2026-10-31 | Match finite boolean refinements of union cases |
99| 54852d4 | 2026-10-31 | Contextualize tuple calls and infer known record changes |
99| 54852d4 | 2026-10-31 | Contextualize tuple calls and infer known record changes |
100−| This change | 2026-10-31 | Contextualize record initializers and infer unit construction |
100+| 0bc5113 | 2026-10-31 | Contextualize record initializers and infer unit construction |
101+| This change | 2026-10-31 | Contextualize unit payloads in casts, calls and nested values |
101
102
102## Checking it
103## Checking it
103
104
jibb-dev/lib/jibb.hoon+35−8
@@ -5066,6 +5066,10 @@
5066 =/ unified=(unit isub) (itype-unify-args args.actual args.expected sub)
5066 =/ unified=(unit isub) (itype-unify-args args.actual args.expected sub)
5067 ?^ unified [%ok u.unified next]
5067 ?^ unified [%ok u.unified next]
5068 [%unknown ~]
5068 [%unknown ~]
5069+ :: A concrete union value in a tuple may acquire the expected field's
5070+ :: face. A variable-bound union still needs face propagation support.
5071+ ?: &(!uncertain ?=(%union -.actual) ?=(%face -.expected))
5072+ $(expected body.expected)
5069 ?: ?=(%union -.actual) [%unknown ~]
5073 ?: ?=(%union -.actual) [%unknown ~]
5070 ?: &(?=(%union -.expected) |(?=(%avar -.actual) ?=(%nvar -.actual))) [%unknown ~]
5074 ?: &(?=(%union -.expected) |(?=(%avar -.actual) ?=(%nvar -.actual))) [%unknown ~]
5071 ?: &(?=(%union -.expected) !?=(%var -.actual))
5075 ?: &(?=(%union -.expected) !?=(%var -.actual))
@@ -6521,14 +6525,7 @@
6521 ^- iresult
6525 ^- iresult
6522 ?~ items [%& expected state]
6526 ?~ items [%& expected state]
6523 =/ target=itype (itype-walk expected sub.state)
6527 =/ target=itype (itype-walk expected sub.state)
6524− =/ value=iresult
6525− ?: &(?=(%union -.target) (context-union-branch i.items))
6526− (infer-union-context i.items target env state context)
6527− ?: &(?=(%collection -.target) =(%list name.target) (context-union-branch i.items))
6528− (infer-union-context i.items target env state context)
6529− ?: &(?=(%collection -.target) =(%list name.target) (context-list-expression i.items))
6530− (infer-list-context i.items target env state context)
6528+ =/ value=iresult (infer-call-context-arg i.items target env state context)
6531− (infer-fragment i.items env state)
6532 ?: ?=(%| -.value) value
6529 ?: ?=(%| -.value) value
6533 =/ fit=ifit (itype-fit typ.p.value target sub.state.p.value next.state.p.value)
6530 =/ fit=ifit (itype-fit typ.p.value target sub.state.p.value next.state.p.value)
6534 ?: ?=(%unknown -.fit) [%| ["list item constraint is not supported by partial inference" ~]]
6531 ?: ?=(%unknown -.fit) [%| ["list item constraint is not supported by partial inference" ~]]
@@ -7177,12 +7174,42 @@
7177:: Context can help a call argument or cast value while the final fit
7174:: Context can help a call argument or cast value while the final fit
7178:: checks the complete right-nested type, including any written faces.
7175:: checks the complete right-nested type, including any written faces.
7179::
7176::
7177+:: Context can resolve the payload of a canonical prelude unit, but an
7178+:: unrelated union with a similar noun shape is not the same mold.
7179+++ infer-unit-context
7180+ |= [e=expr expected=itype env=ienv state=istate context=span]
7181+ ^- iresult
7182+ ?> ?=(%unit -.e)
7183+ ?> ?=(%union -.expected)
7184+ ?~ prelude.state (infer-fragment e env state)
7185+ =/ standard=(unit ischeme) (find-jibb-mold %unit u.prelude.state)
7186+ ?~ standard (infer-fragment e env state)
7187+ ?. (standard-unit-template u.standard at.u.prelude.state) (infer-fragment e env state)
7188+ ?. =(origin.expected `[at.u.prelude.state %unit]) (infer-fragment e env state)
7189+ ?~ args.expected (infer-fragment e env state)
7190+ ?^ t.args.expected (infer-fragment e env state)
7191+ =/ payload=itype i.args.expected
7192+ =/ canonical=(unit itype) (template-apply u.standard ~[payload])
7193+ ?~ canonical (infer-fragment e env state)
7194+ ?> ?=(%union -.u.canonical)
7195+ ?. =((itype-normalize expected(label ~) sub.state) (itype-normalize u.canonical(label ~) sub.state))
7196+ (infer-fragment e env state)
7197+ =/ value=iresult (infer-call-context-arg val.e payload env state context)
7198+ ?: ?=(%| -.value) value
7199+ =/ fit=ifit (itype-fit typ.p.value payload sub.state.p.value next.state.p.value)
7200+ ?: ?=(%unknown -.fit) [%| ["unit payload constraint is not supported by partial inference" ~]]
7201+ ?: ?=(%bad -.fit)
7202+ [%| ["unit payload does not fit its expected type" ~[[context (site-type-note "expected unit payload" payload sub.state.p.value)] [(span-of val.e) (site-type-note "payload" typ.p.value sub.state.p.value)]]]]
7203+ [%& expected state.p.value(sub sub.fit, next next.fit)]
7204+::
7180++ infer-call-context-arg
7205++ infer-call-context-arg
7181 |= [e=expr expected=itype env=ienv state=istate context=span]
7206 |= [e=expr expected=itype env=ienv state=istate context=span]
7182 ^- iresult
7207 ^- iresult
7183 =/ target=itype (itype-walk expected sub.state)
7208 =/ target=itype (itype-walk expected sub.state)
7184 |-
7209 |-
7185 ?: ?=(%face -.target) $(target (itype-walk body.target sub.state))
7210 ?: ?=(%face -.target) $(target (itype-walk body.target sub.state))
7211+ ?: &(?=(%union -.target) ?=(%unit -.e))
7212+ (infer-unit-context e target env state context)
7186 ?: &(?=(%union -.target) (context-union-branch e))
7213 ?: &(?=(%union -.target) (context-union-branch e))
7187 (infer-union-context e target env state context)
7214 (infer-union-context e target env state context)
7188 ?: &(?=(%collection -.target) =(%list name.target) (context-union-branch e))
7215 ?: &(?=(%collection -.target) =(%list name.target) (context-union-branch e))
tests/golden/types-unit-construction/about.txt+1−1
@@ -1,4 +1,4 @@
1source: Grammar, Literals: a backtick constructs a `(unit A)`; Tag resolution: tags and `~` take their type from context.
1source: Grammar, Literals: a backtick constructs a `(unit A)`; Tag resolution: tags and `~` take their type from context.
2−tests: Unit construction uses the validated prelude shape, preserves generic and nested payload types, and makes prelude some available at independent types. Unresolved payloads and discarded literals stay pending. Payload constraints and unrelated user-defined unions fail closed where their compatibility is not yet supported.
2+tests: Unit construction uses the validated prelude shape, preserves generic and nested payload types, and makes prelude some available at independent types. Unresolved payloads and discarded literals stay pending. Known payload contexts resolve tags and report definite mismatches; unrelated user-defined unions and forcing explicit capitals remain unsupported.
3expect: parses
3expect: parses
4expect-types: a partial inference report
4expect-types: a partial inference report
tests/golden/types-unit-construction/types.txt+16−4
@@ -8,13 +8,25 @@ partial inference; module not checked
8++ nested: (unit (unit @t))
8++ nested: (unit (unit @t))
9++ same-first: (unit @t)
9++ same-first: (unit @t)
10++ same-second: (unit @p)
10++ same-second: (unit @p)
11−++ ctx: cast constraint is not supported by partial inference
11+++ ctx: (unit msg)
12−++ bad-tag: cast constraint is not supported by partial inference
12+++ bad-tag: unit payload does not fit its expected type
13+/tests/golden/types-unit-construction/source.jibb:17:15: expected unit payload
14+++ bad-tag ^- (unit msg) `%bad
15+ ^
16+/tests/golden/types-unit-construction/source.jibb:17:27: payload
17+++ bad-tag ^- (unit msg) `%bad
18+ ^
13++ missing-tag: tag needs context in partial inference
19++ missing-tag: tag needs context in partial inference
14++ discarded-tag: tag needs context in partial inference
20++ discarded-tag: tag needs context in partial inference
15++ discarded-null: `~` needs context in partial inference
21++ discarded-null: `~` needs context in partial inference
16−++ mismatch: cast constraint is not supported by partial inference
22+++ mismatch: unit payload does not fit its expected type
23+/tests/golden/types-unit-construction/source.jibb:25:16: expected unit payload has type @p
24+++ mismatch ^- (unit @p) `"hi"
25+ ^
26+/tests/golden/types-unit-construction/source.jibb:25:27: payload has type @t
27+++ mismatch ^- (unit @p) `"hi"
28+ ^
17++ other-unit: cast constraint is not supported by partial inference
29++ other-unit: cast constraint is not supported by partial inference
18++ force: explicit capital constraints are not supported by partial inference
30++ force: explicit capital constraints are not supported by partial inference
19++ null-payload: `~` needs context in partial inference
31++ null-payload: `~` needs context in partial inference
20−++ tag-payload: cast constraint is not supported by partial inference
32+++ tag-payload: (unit @tas)
tests/golden/types-unit-context/about.txt+2−2
@@ -1,4 +1,4 @@
1−source: Grammar, Tag resolution: "A tag literal or `~` gets a fresh type variable and a pending constraint"; Patterns: "A name in a pattern always binds anew".
1+source: Grammar, Literals: a backtick constructs a `(unit A)`; Tag resolution: tags and `~` take their type from context; Literals by context: cells and lists take their type from context.
2−tests: A cast or known sample supplies union context to both unit branch arms, including nested unit and loobean branches; bad cases, unknown subjects, shadowing and unrelated pending tags or nulls fail closed.
2+tests: Known standard unit payloads supply context through casts, calls, nested units, lists and record fields. Invalid tags, auras and faces report errors; different union origins and concrete forcing of written capitals fail closed. Shared capitals and unrelated pending literals are preserved.
3expect: parses
3expect: parses
4expect-types: a partial inference report
4expect-types: a partial inference report
tests/golden/types-unit-context/modules.txtnew file+1
@@ -0,0 +1 @@
1+# Use the prepared prelude.
tests/golden/types-unit-context/source.jibb+44−68
@@ -1,70 +1,46 @@
1−+$ maybe
2− ~
3− [~ value=@t]
4+$ msg
1+$ msg
5− %add
2+ %go
6− [%note text=@t]
3+ %stay
7−++ cast |= x=maybe
4++$ mimic |$ [A]
8− ^- msg
5+ ~
9− ?- x
6+ [~ u=A]
10− ~ %add
7++$ record [u=(unit msg) xs=(list (unit @t))]
11− [~ text] [%note text]
8+++ valid ^- (unit msg) `%go
12−++ reversed |= x=maybe
9+++ invalid ^- (unit msg) `%bad
13− ^- msg
10+++ str ^- (unit @t) `"hi"
14− ?- x
11+++ wrong ^- (unit @t) `~zod
15− [~ text] [%note text]
12+++ nest ^- (unit (unit @t)) ``"hi"
16− ~ %add
13+++ nested-bad ^- (unit (unit @t)) ``~zod
17−++ consume |= x=msg "ok"
14+++ lis ^- (unit (list @t)) `~["hi"]
18−++ call |= x=maybe
15+++ list-bad ^- (unit (list @t)) `~[~zod]
19− (consume
16+++ accept |= x=(unit msg) x
20− ?- x
17+++ call (accept `%stay)
21− ~ %add
18+++ bad-call (accept `%bad)
22− [~ text] [%note text]
19+++ field ^- record [`%go ~[`"hi"]]
23−++ nested |= x=maybe
20+++ field-bad ^- record [`%bad ~[`"hi"]]
24− ^- msg
21+++ mimic-mismatch ^- (mimic @t) `"hi"
25− ?- x
22+++ without-context `%go
26− ~
27− ?- %.y
28− %.y %add
29− %.n [%note "hi"]
30− [~ text] [%note text]
31−++ bad-empty |= x=maybe
32− ^- msg
33− ?- x
34− ~ %missing
35− [~ text] [%note text]
36−++ bad-present |= x=maybe
37− ^- msg
38− ?- x
39− ~ %add
40− [~ text] %missing
41−++ unknown |= x
42− ^- msg
43− ?- x
44− ~ %add
45− [~ text] [%note text]
46−++ shadow |= x=maybe
47− ^- msg
48− ?- x
49− ~ %add
50− [~ x] [%note x]
51−++ pending |= x=maybe
23+++ pending
52− ~& %unknown
24+ ~& %other
53− ^- msg
54− ?- x
55− ~ %add
56− [~ text] [%note text]
57−++ nested-unit |= x=maybe
58− ^- msg
25+ ^- (unit msg) `%go
59− ?- x
60− ~
61− ?- x
62− ~ %add
63− [~ inner] [%note inner]
64− [~ text] [%note text]
65−++ pending-null |= x=maybe
26+++ pending-null
66 ~& ~
27 ~& ~
67− ^- msg
28+ ^- (unit @t) `"hi"
68− ?- x
29+++ preserve |= x=A ^- (unit A) `x
69− ~ %add
30+++ force |= x=A ^- (unit A) `"hi"
70− [~ text] [%note text]
31++$ alt
32+ %go
33+ %stay
34+++ field-wrong-payload ^- record [`%go ~[`~zod]]
35+++ wrong-name ^- record [wrong=`%go xs=~[`"hi"]]
36+++ wrong-union |= x=alt ^- record [`x ~[`"hi"]]
37+++ no-field-context |= x=A ^- [a=A] [wrong=x]
38+++ known-left |= x=msg ^- [a=msg] [a=x]
39+++ mismatch-left |= x=msg ^- [a=alt] [a=x]
40+++ contextual |= x=A ^- [a=A b=(unit A)] [a=x b=`x]
41+++ contextual-bad |= x=A ^- [a=A b=(unit A)] [a=x b=`"hi"]
42+++ nested-units ^- (list (unit msg)) ~[`%go `%stay]
43+++ nested-units-bad ^- (list (unit msg)) ~[`%go `%oops]
44+++ case-discarded
45+ ~& %pending
46+ ^- record [`%go ~[`"hi"]]
tests/golden/types-unit-context/tokens.txt+458−343
@@ -1,374 +1,489 @@
11:1 glyph +$
11:1 glyph +$
2−1:4 name maybe
2+1:4 name msg
32:3 INDENT
32:3 INDENT
4−2:3 lit ~
4+2:3 lit %go
53:3 NEWLINE
53:3 NEWLINE
6−3:3 glyph [
6+3:3 lit %stay
7−3:4 tight lit ~
8−3:6 name value
9−3:11 tight glyph =
10−3:12 tight aura @t
11−3:14 tight glyph ]
124:1 DEDENT
74:1 DEDENT
134:1 NEWLINE
84:1 NEWLINE
144:1 glyph +$
94:1 glyph +$
15−4:4 name msg
10+4:4 name mimic
11+4:10 glyph |$
12+4:13 glyph [
13+4:14 tight tvar A
14+4:15 tight glyph ]
165:3 INDENT
155:3 INDENT
17−5:3 lit %add
16+5:3 lit ~
186:3 NEWLINE
176:3 NEWLINE
196:3 glyph [
186:3 glyph [
20−6:4 tight lit %note
19+6:4 tight lit ~
21−6:10 name text
20+6:6 name u
22−6:14 tight glyph =
21+6:7 tight glyph =
23−6:15 tight aura @t
22+6:8 tight tvar A
24−6:17 tight glyph ]
23+6:9 tight glyph ]
257:1 DEDENT
247:1 DEDENT
267:1 NEWLINE
257:1 NEWLINE
27−7:1 glyph ++
26+7:1 glyph +$
28−7:4 name cast
27+7:4 name record
29−7:9 glyph |=
28+7:11 glyph [
30−7:12 name x
29+7:12 tight name u
317:13 tight glyph =
307:13 tight glyph =
32−7:14 tight name maybe
31+7:14 tight glyph (
33−8:3 INDENT
32+7:15 tight name unit
33+7:20 name msg
34−8:3 glyph ^-
34+7:23 tight glyph )
35−8:6 name msg
35+7:25 name xs
36−9:5 INDENT
36+7:27 tight glyph =
37−9:5 glyph ?-
37+7:28 tight glyph (
38−9:8 name x
38+7:29 tight name list
39−10:7 INDENT
39+7:34 glyph (
40−10:7 lit ~
40+7:35 tight name unit
41−10:9 lit %add
41+7:40 aura @t
42+7:42 tight glyph )
43+7:43 tight glyph )
44+7:44 tight glyph ]
42−11:7 NEWLINE
45+8:1 NEWLINE
46+8:1 glyph ++
47+8:4 name valid
48+8:10 glyph ^-
49+8:13 glyph (
50+8:14 tight name unit
51+8:19 name msg
43−11:7 glyph [
52+8:22 tight glyph )
53+8:24 glyph `
44−11:8 tight lit ~
54+8:25 tight lit %go
45−11:10 name text
55+9:1 NEWLINE
56+9:1 glyph ++
57+9:4 name invalid
58+9:12 glyph ^-
46−11:14 tight glyph ]
59+9:15 glyph (
60+9:16 tight name unit
61+9:21 name msg
47−11:16 glyph [
62+9:24 tight glyph )
48−11:17 tight lit %note
63+9:26 glyph `
64+9:27 tight lit %bad
65+10:1 NEWLINE
66+10:1 glyph ++
67+10:4 name str
68+10:8 glyph ^-
69+10:11 glyph (
70+10:12 tight name unit
71+10:17 aura @t
72+10:19 tight glyph )
73+10:21 glyph `
74+10:22 tight str "hi"
75+11:1 NEWLINE
76+11:1 glyph ++
49−11:23 name text
77+11:4 name wrong
78+11:10 glyph ^-
79+11:13 glyph (
50−11:27 tight glyph ]
80+11:14 tight name unit
51−12:1 DEDENT
81+11:19 aura @t
52−12:1 DEDENT
82+11:21 tight glyph )
53−12:1 DEDENT
83+11:23 glyph `
84+11:24 tight lit ~zod
5412:1 NEWLINE
8512:1 NEWLINE
5512:1 glyph ++
8612:1 glyph ++
56−12:4 name reversed
87+12:4 name nest
88+12:9 glyph ^-
89+12:12 glyph (
90+12:13 tight name unit
91+12:18 glyph (
92+12:19 tight name unit
93+12:24 aura @t
94+12:26 tight glyph )
95+12:27 tight glyph )
96+12:29 glyph `
97+12:30 tight glyph `
98+12:31 tight str "hi"
99+13:1 NEWLINE
100+13:1 glyph ++
101+13:4 name nested-bad
102+13:15 glyph ^-
103+13:18 glyph (
104+13:19 tight name unit
105+13:24 glyph (
106+13:25 tight name unit
107+13:30 aura @t
108+13:32 tight glyph )
109+13:33 tight glyph )
110+13:35 glyph `
111+13:36 tight glyph `
112+13:37 tight lit ~zod
113+14:1 NEWLINE
114+14:1 glyph ++
115+14:4 name lis
116+14:8 glyph ^-
117+14:11 glyph (
118+14:12 tight name unit
119+14:17 glyph (
120+14:18 tight name list
121+14:23 aura @t
122+14:25 tight glyph )
123+14:26 tight glyph )
124+14:28 glyph `
125+14:29 tight glyph ~[
126+14:31 tight str "hi"
127+14:35 tight glyph ]
128+15:1 NEWLINE
129+15:1 glyph ++
130+15:4 name list-bad
131+15:13 glyph ^-
132+15:16 glyph (
133+15:17 tight name unit
134+15:22 glyph (
135+15:23 tight name list
136+15:28 aura @t
137+15:30 tight glyph )
138+15:31 tight glyph )
139+15:33 glyph `
140+15:34 tight glyph ~[
141+15:36 tight lit ~zod
142+15:40 tight glyph ]
143+16:1 NEWLINE
144+16:1 glyph ++
145+16:4 name accept
57−12:13 glyph |=
146+16:11 glyph |=
58−12:16 name x
147+16:14 name x
59−12:17 tight glyph =
148+16:15 tight glyph =
60−12:18 tight name maybe
149+16:16 tight glyph (
61−13:3 INDENT
150+16:17 tight name unit
62−13:3 glyph ^-
63−13:6 name msg
151+16:22 name msg
64−14:5 INDENT
65−14:5 glyph ?-
66−14:8 name x
67−15:7 INDENT
68−15:7 glyph [
69−15:8 tight lit ~
70−15:10 name text
71−15:14 tight glyph ]
152+16:25 tight glyph )
72−15:16 glyph [
153+16:27 name x
73−15:17 tight lit %note
74−15:23 name text
75−15:27 tight glyph ]
76−16:7 NEWLINE
77−16:7 lit ~
78−16:9 lit %add
79−17:1 DEDENT
80−17:1 DEDENT
81−17:1 DEDENT
8217:1 NEWLINE
15417:1 NEWLINE
8317:1 glyph ++
15517:1 glyph ++
84−17:4 name consume
156+17:4 name call
85−17:12 glyph |=
157+17:9 glyph (
86−17:15 name x
158+17:10 tight name accept
87−17:16 tight glyph =
159+17:17 glyph `
88−17:17 tight name msg
160+17:18 tight lit %stay
89−17:21 str "ok"
161+17:23 tight glyph )
9018:1 NEWLINE
16218:1 NEWLINE
9118:1 glyph ++
16318:1 glyph ++
92−18:4 name call
164+18:4 name bad-call
93−18:9 glyph |=
94−18:12 name x
95−18:13 tight glyph =
165+18:13 glyph (
96−18:14 tight name maybe
166+18:14 tight name accept
97−19:3 INDENT
98−19:3 glyph (
167+18:21 glyph `
99−19:4 tight name consume
168+18:22 tight lit %bad
100−20:5 INDENT
101−20:5 glyph ?-
169+18:26 tight glyph )
102−20:8 name x
103−21:7 INDENT
104−21:7 lit ~
105−21:9 lit %add
106−22:7 NEWLINE
170+19:1 NEWLINE
107−22:7 glyph [
171+19:1 glyph ++
108−22:8 tight lit ~
172+19:4 name field
109−22:10 name text
173+19:10 glyph ^-
174+19:13 name record
175+19:20 glyph [
176+19:21 tight glyph `
177+19:22 tight lit %go
178+19:26 glyph ~[
179+19:28 tight glyph `
180+19:29 tight str "hi"
110−22:14 tight glyph ]
181+19:33 tight glyph ]
111−22:16 glyph [
182+19:34 tight glyph ]
183+20:1 NEWLINE
184+20:1 glyph ++
185+20:4 name field-bad
186+20:14 glyph ^-
187+20:17 name record
188+20:24 glyph [
189+20:25 tight glyph `
112−22:17 tight lit %note
190+20:26 tight lit %bad
113−22:23 name text
191+20:31 glyph ~[
114−22:27 tight glyph ]
192+20:33 tight glyph `
115−23:1 DEDENT
193+20:34 tight str "hi"
116−23:1 DEDENT
194+20:38 tight glyph ]
117−23:1 DEDENT
195+20:39 tight glyph ]
196+21:1 NEWLINE
197+21:1 glyph ++
198+21:4 name mimic-mismatch
199+21:19 glyph ^-
200+21:22 glyph (
201+21:23 tight name mimic
202+21:29 aura @t
203+21:31 tight glyph )
204+21:33 glyph `
205+21:34 tight str "hi"
206+22:1 NEWLINE
207+22:1 glyph ++
208+22:4 name without-context
209+22:20 glyph `
210+22:21 tight lit %go
11823:1 NEWLINE
21123:1 NEWLINE
11923:1 glyph ++
21223:1 glyph ++
120−23:4 name nested
213+23:4 name pending
121−23:11 glyph |=
122−23:14 name x
123−23:15 tight glyph =
124−23:16 tight name maybe
12524:3 INDENT
21424:3 INDENT
126−24:3 glyph ^-
215+24:3 glyph ~&
127−24:6 name msg
216+24:6 lit %other
12825:5 INDENT
21725:5 INDENT
129−25:5 glyph ?-
218+25:5 glyph ^-
219+25:8 glyph (
220+25:9 tight name unit
130−25:8 name x
221+25:14 name msg
131−26:7 INDENT
222+25:17 tight glyph )
132−26:7 lit ~
223+25:19 glyph `
224+25:20 tight lit %go
225+26:1 DEDENT
226+26:1 DEDENT
227+26:1 NEWLINE
228+26:1 glyph ++
229+26:4 name pending-null
133−27:9 INDENT
230+27:3 INDENT
134−27:9 glyph ?-
231+27:3 glyph ~&
135−27:12 lit %.y
232+27:6 lit ~
136−28:11 INDENT
233+28:5 INDENT
137−28:11 lit %.y
234+28:5 glyph ^-
138−28:15 lit %add
235+28:8 glyph (
139−29:11 NEWLINE
236+28:9 tight name unit
140−29:11 lit %.n
237+28:14 aura @t
141−29:15 glyph [
142−29:16 tight lit %note
238+28:16 tight glyph )
143−29:22 str "hi"
239+28:18 glyph `
144−29:26 tight glyph ]
240+28:19 tight str "hi"
145−30:7 DEDENT
241+29:1 DEDENT
146−30:7 DEDENT
242+29:1 DEDENT
147−30:7 NEWLINE
243+29:1 NEWLINE
148−30:7 glyph [
244+29:1 glyph ++
149−30:8 tight lit ~
245+29:4 name preserve
150−30:10 name text
246+29:13 glyph |=
247+29:16 name x
151−30:14 tight glyph ]
248+29:17 tight glyph =
152−30:16 glyph [
249+29:18 tight tvar A
153−30:17 tight lit %note
250+29:20 glyph ^-
154−30:23 name text
251+29:23 glyph (
252+29:24 tight name unit
253+29:29 tvar A
155−30:27 tight glyph ]
254+29:30 tight glyph )
156−31:1 DEDENT
255+29:32 glyph `
157−31:1 DEDENT
256+29:33 tight name x
158−31:1 DEDENT
257+30:1 NEWLINE
258+30:1 glyph ++
259+30:4 name force
260+30:10 glyph |=
261+30:13 name x
262+30:14 tight glyph =
263+30:15 tight tvar A
264+30:17 glyph ^-
265+30:20 glyph (
266+30:21 tight name unit
267+30:26 tvar A
268+30:27 tight glyph )
269+30:29 glyph `
270+30:30 tight str "hi"
15931:1 NEWLINE
27131:1 NEWLINE
160−31:1 glyph ++
272+31:1 glyph +$
161−31:4 name bad-empty
273+31:4 name alt
162−31:14 glyph |=
163−31:17 name x
164−31:18 tight glyph =
165−31:19 tight name maybe
16632:3 INDENT
27432:3 INDENT
167−32:3 glyph ^-
275+32:3 lit %go
168−32:6 name msg
276+33:3 NEWLINE
169−33:5 INDENT
277+33:3 lit %stay
170−33:5 glyph ?-
278+34:1 DEDENT
171−33:8 name x
172−34:7 INDENT
173−34:7 lit ~
174−34:9 lit %missing
175−35:7 NEWLINE
279+34:1 NEWLINE
176−35:7 glyph [
280+34:1 glyph ++
177−35:8 tight lit ~
281+34:4 name field-wrong-payload
178−35:10 name text
179−35:14 tight glyph ]
180−35:16 glyph [
282+34:24 glyph ^-
181−35:17 tight lit %note
283+34:27 name record
182−35:23 name text
284+34:34 glyph [
183−35:27 tight glyph ]
285+34:35 tight glyph `
184−36:1 DEDENT
286+34:36 tight lit %go
185−36:1 DEDENT
287+34:40 glyph ~[
186−36:1 DEDENT
288+34:42 tight glyph `
289+34:43 tight lit ~zod
290+34:47 tight glyph ]
291+34:48 tight glyph ]
292+35:1 NEWLINE
293+35:1 glyph ++
294+35:4 name wrong-name
295+35:15 glyph ^-
296+35:18 name record
297+35:25 glyph [
298+35:26 tight name wrong
299+35:31 tight glyph =
300+35:32 tight glyph `
301+35:33 tight lit %go
302+35:37 name xs
303+35:39 tight glyph =
304+35:40 tight glyph ~[
305+35:42 tight glyph `
306+35:43 tight str "hi"
307+35:47 tight glyph ]
308+35:48 tight glyph ]
18736:1 NEWLINE
30936:1 NEWLINE
18836:1 glyph ++
31036:1 glyph ++
189−36:4 name bad-present
311+36:4 name wrong-union
19036:16 glyph |=
31236:16 glyph |=
19136:19 name x
31336:19 name x
19236:20 tight glyph =
31436:20 tight glyph =
193−36:21 tight name maybe
315+36:21 tight name alt
194−37:3 INDENT
316+36:25 glyph ^-
317+36:28 name record
318+36:35 glyph [
319+36:36 tight glyph `
320+36:37 tight name x
321+36:39 glyph ~[
322+36:41 tight glyph `
323+36:42 tight str "hi"
324+36:46 tight glyph ]
325+36:47 tight glyph ]
326+37:1 NEWLINE
327+37:1 glyph ++
328+37:4 name no-field-context
329+37:21 glyph |=
330+37:24 name x
331+37:25 tight glyph =
332+37:26 tight tvar A
333+37:28 glyph ^-
334+37:31 glyph [
335+37:32 tight name a
336+37:33 tight glyph =
337+37:34 tight tvar A
338+37:35 tight glyph ]
339+37:37 glyph [
340+37:38 tight name wrong
341+37:43 tight glyph =
342+37:44 tight name x
343+37:45 tight glyph ]
344+38:1 NEWLINE
345+38:1 glyph ++
346+38:4 name known-left
347+38:15 glyph |=
348+38:18 name x
349+38:19 tight glyph =
350+38:20 tight name msg
351+38:24 glyph ^-
352+38:27 glyph [
353+38:28 tight name a
354+38:29 tight glyph =
355+38:30 tight name msg
356+38:33 tight glyph ]
357+38:35 glyph [
358+38:36 tight name a
359+38:37 tight glyph =
360+38:38 tight name x
361+38:39 tight glyph ]
362+39:1 NEWLINE
363+39:1 glyph ++
364+39:4 name mismatch-left
365+39:18 glyph |=
366+39:21 name x
367+39:22 tight glyph =
368+39:23 tight name msg
369+39:27 glyph ^-
370+39:30 glyph [
371+39:31 tight name a
372+39:32 tight glyph =
373+39:33 tight name alt
374+39:36 tight glyph ]
375+39:38 glyph [
376+39:39 tight name a
377+39:40 tight glyph =
378+39:41 tight name x
195−37:3 glyph ^-
379+39:42 tight glyph ]
196−37:6 name msg
380+40:1 NEWLINE
197−38:5 INDENT
381+40:1 glyph ++
382+40:4 name contextual
198−38:5 glyph ?-
383+40:15 glyph |=
199−38:8 name x
384+40:18 name x
200−39:7 INDENT
385+40:19 tight glyph =
201−39:7 lit ~
386+40:20 tight tvar A
202−39:9 lit %add
387+40:22 glyph ^-
203−40:7 NEWLINE
388+40:25 glyph [
389+40:26 tight name a
390+40:27 tight glyph =
391+40:28 tight tvar A
392+40:30 name b
204−40:7 glyph [
393+40:31 tight glyph =
205−40:8 tight lit ~
394+40:32 tight glyph (
206−40:10 name text
395+40:33 tight name unit
396+40:38 tvar A
397+40:39 tight glyph )
207−40:14 tight glyph ]
398+40:40 tight glyph ]
208−40:16 lit %missing
399+40:42 glyph [
209−41:1 DEDENT
400+40:43 tight name a
210−41:1 DEDENT
401+40:44 tight glyph =
211−41:1 DEDENT
402+40:45 tight name x
403+40:47 name b
404+40:48 tight glyph =
405+40:49 tight glyph `
406+40:50 tight name x
407+40:51 tight glyph ]
21241:1 NEWLINE
40841:1 NEWLINE
21341:1 glyph ++
40941:1 glyph ++
214−41:4 name unknown
410+41:4 name contextual-bad
215−41:12 glyph |=
411+41:19 glyph |=
216−41:15 name x
412+41:22 name x
217−42:3 INDENT
218−42:3 glyph ^-
413+41:23 tight glyph =
219−42:6 name msg
414+41:24 tight tvar A
220−43:5 INDENT
221−43:5 glyph ?-
415+41:26 glyph ^-
222−43:8 name x
223−44:7 INDENT
224−44:7 lit ~
225−44:9 lit %add
226−45:7 NEWLINE
227−45:7 glyph [
416+41:29 glyph [
228−45:8 tight lit ~
417+41:30 tight name a
229−45:10 name text
230−45:14 tight glyph ]
418+41:31 tight glyph =
231−45:16 glyph [
419+41:32 tight tvar A
232−45:17 tight lit %note
420+41:34 name b
233−45:23 name text
234−45:27 tight glyph ]
421+41:35 tight glyph =
235−46:1 DEDENT
236−46:1 DEDENT
237−46:1 DEDENT
238−46:1 NEWLINE
239−46:1 glyph ++
240−46:4 name shadow
241−46:11 glyph |=
242−46:14 name x
243−46:15 tight glyph =
422+41:36 tight glyph (
244−46:16 tight name maybe
423+41:37 tight name unit
245−47:3 INDENT
424+41:42 tvar A
246−47:3 glyph ^-
247−47:6 name msg
248−48:5 INDENT
249−48:5 glyph ?-
425+41:43 tight glyph )
250−48:8 name x
251−49:7 INDENT
252−49:7 lit ~
253−49:9 lit %add
254−50:7 NEWLINE
255−50:7 glyph [
256−50:8 tight lit ~
257−50:10 name x
258−50:11 tight glyph ]
426+41:44 tight glyph ]
259−50:13 glyph [
427+41:46 glyph [
260−50:14 tight lit %note
428+41:47 tight name a
261−50:20 name x
262−50:21 tight glyph ]
429+41:48 tight glyph =
263−51:1 DEDENT
430+41:49 tight name x
264−51:1 DEDENT
265−51:1 DEDENT
266−51:1 NEWLINE
267−51:1 glyph ++
268−51:4 name pending
269−51:12 glyph |=
270−51:15 name x
431+41:51 name b
271−51:16 tight glyph =
432+41:52 tight glyph =
272−51:17 tight name maybe
273−52:3 INDENT
274−52:3 glyph ~&
433+41:53 tight glyph `
275−52:6 lit %unknown
434+41:54 tight str "hi"
276−53:5 INDENT
277−53:5 glyph ^-
435+41:58 tight glyph ]
278−53:8 name msg
436+42:1 NEWLINE
279−54:7 INDENT
280−54:7 glyph ?-
437+42:1 glyph ++
281−54:10 name x
438+42:4 name nested-units
282−55:9 INDENT
439+42:17 glyph ^-
283−55:9 lit ~
440+42:20 glyph (
284−55:11 lit %add
441+42:21 tight name list
285−56:9 NEWLINE
286−56:9 glyph [
442+42:26 glyph (
287−56:10 tight lit ~
443+42:27 tight name unit
288−56:12 name text
444+42:32 name msg
445+42:35 tight glyph )
289−56:16 tight glyph ]
446+42:36 tight glyph )
290−56:18 glyph [
447+42:38 glyph ~[
448+42:40 tight glyph `
291−56:19 tight lit %note
449+42:41 tight lit %go
292−56:25 name text
450+42:45 glyph `
293−56:29 tight glyph ]
451+42:46 tight lit %stay
294−57:1 DEDENT
452+42:51 tight glyph ]
295−57:1 DEDENT
296−57:1 DEDENT
297−57:1 DEDENT
298−57:1 NEWLINE
453+43:1 NEWLINE
299−57:1 glyph ++
454+43:1 glyph ++
300−57:4 name nested-unit
455+43:4 name nested-units-bad
301−57:16 glyph |=
456+43:21 glyph ^-
302−57:19 name x
457+43:24 glyph (
458+43:25 tight name list
303−57:20 tight glyph =
459+43:30 glyph (
304−57:21 tight name maybe
460+43:31 tight name unit
305−58:3 INDENT
461+43:36 name msg
306−58:3 glyph ^-
462+43:39 tight glyph )
307−58:6 name msg
463+43:40 tight glyph )
308−59:5 INDENT
464+43:42 glyph ~[
309−59:5 glyph ?-
465+43:44 tight glyph `
310−59:8 name x
466+43:45 tight lit %go
311−60:7 INDENT
467+43:49 glyph `
312−60:7 lit ~
468+43:50 tight lit %oops
313−61:9 INDENT
469+43:55 tight glyph ]
470+44:1 NEWLINE
314−61:9 glyph ?-
471+44:1 glyph ++
315−61:12 name x
472+44:4 name case-discarded
316−62:11 INDENT
473+45:3 INDENT
317−62:11 lit ~
474+45:3 glyph ~&
318−62:13 lit %add
475+45:6 lit %pending
319−63:11 NEWLINE
476+46:5 INDENT
320−63:11 glyph [
477+46:5 glyph ^-
321−63:12 tight lit ~
478+46:8 name record
322−63:14 name inner
479+46:15 glyph [
323−63:19 tight glyph ]
480+46:16 tight glyph `
481+46:17 tight lit %go
324−63:21 glyph [
482+46:21 glyph ~[
325−63:22 tight lit %note
483+46:23 tight glyph `
326−63:28 name inner
484+46:24 tight str "hi"
327−63:33 tight glyph ]
328−64:7 DEDENT
329−64:7 DEDENT
330−64:7 NEWLINE
331−64:7 glyph [
332−64:8 tight lit ~
333−64:10 name text
334−64:14 tight glyph ]
335−64:16 glyph [
336−64:17 tight lit %note
337−64:23 name text
338−64:27 tight glyph ]
485+46:28 tight glyph ]
339−65:1 DEDENT
340−65:1 DEDENT
341−65:1 DEDENT
342−65:1 NEWLINE
343−65:1 glyph ++
344−65:4 name pending-null
345−65:17 glyph |=
346−65:20 name x
347−65:21 tight glyph =
348−65:22 tight name maybe
349−66:3 INDENT
350−66:3 glyph ~&
351−66:6 lit ~
352−67:5 INDENT
353−67:5 glyph ^-
354−67:8 name msg
355−68:7 INDENT
356−68:7 glyph ?-
357−68:10 name x
358−69:9 INDENT
359−69:9 lit ~
360−69:11 lit %add
361−70:9 NEWLINE
362−70:9 glyph [
363−70:10 tight lit ~
364−70:12 name text
365−70:16 tight glyph ]
366−70:18 glyph [
367−70:19 tight lit %note
368−70:25 name text
369−70:29 tight glyph ]
486+46:29 tight glyph ]
370−70:30 DEDENT
487+46:30 DEDENT
371−70:30 DEDENT
488+46:30 DEDENT
372−70:30 DEDENT
373−70:30 DEDENT
374−70:30 NEWLINE
489+46:30 NEWLINE
tests/golden/types-unit-context/tree.txt+218−180
@@ -1,182 +1,220 @@
1(module
1(module
2− (mold 1:1 maybe
2+ (mold 1:1 msg
3− (union 2:3
3+ (union 2:3 (const 2:3 %go) (const 3:3 %stay)))
4− (const 2:3 ~)
5− (cell 3:3
6− (const 3:4 ~)
7− (face 3:6 value (aura 3:12 @t)))))
8− (mold 4:1 msg
4+ (mold 4:1 mimic
5+ (generic 4:10 A
9− (union 5:3
6+ (union 5:3
10− (const 5:3 %add)
7+ (const 5:3 ~)
11− (cell 6:3
8+ (cell 6:3
12− (const 6:4 %note)
9+ (const 6:4 ~)
13− (face 6:10 text (aura 6:15 @t)))))
10+ (face 6:6 u (tvar 6:8 A))))))
14− (value 7:1 cast
11+ (mold 7:1 record
15− (gate 7:9
12+ (cell 7:11
16− (face 7:12 x (ref 7:14 maybe))
13+ (face 7:12 u
17− (body 8:3
18− (cast 8:3
19− (ref 8:6 msg)
14+ (apply 7:14 unit (ref 7:20 msg)))
20− (body 9:5
15+ (face 7:25 xs
21− (branch 9:5
16+ (apply 7:28 list
22− (wing 9:8 x)
17+ (apply 7:34 unit (aura 7:40 @t))))))
23− (arm 10:7 (lit 10:7 ~) (lit 10:9 %add))
24− (arm 11:7
25− (cell 11:7 (lit 11:8 ~) (bind 11:10 text))
26− (tuple 11:16 (lit 11:17 %note) (wing 11:23 text)))))))))
27− (value 12:1 reversed
18+ (value 8:1 valid
28− (gate 12:13
19+ (cast 8:10
29− (face 12:16 x (ref 12:18 maybe))
20+ (apply 8:13 unit (ref 8:19 msg))
30− (body 13:3
21+ (unit 8:24 (lit 8:25 %go))))
31− (cast 13:3
22+ (value 9:1 invalid
32− (ref 13:6 msg)
23+ (cast 9:12
33− (body 14:5
24+ (apply 9:15 unit (ref 9:21 msg))
34− (branch 14:5
25+ (unit 9:26 (lit 9:27 %bad))))
35− (wing 14:8 x)
36− (arm 15:7
37− (cell 15:7 (lit 15:8 ~) (bind 15:10 text))
38− (tuple 15:16 (lit 15:17 %note) (wing 15:23 text)))
39− (arm 16:7 (lit 16:7 ~) (lit 16:9 %add))))))))
40− (value 17:1 consume
26+ (value 10:1 str
41− (gate 17:12
27+ (cast 10:8
42− (face 17:15 x (ref 17:17 msg))
28+ (apply 10:11 unit (aura 10:17 @t))
43− (str 17:21 "ok")))
29+ (unit 10:21 (str 10:22 "hi"))))
44− (value 18:1 call
30+ (value 11:1 wrong
45− (gate 18:9
31+ (cast 11:10
46− (face 18:12 x (ref 18:14 maybe))
32+ (apply 11:13 unit (aura 11:19 @t))
47− (body 19:3
33+ (unit 11:23 (lit 11:24 ~zod))))
48− (group 19:3
34+ (value 12:1 nest
49− (call 19:4
35+ (cast 12:9
50− (wing 19:4 consume)
36+ (apply 12:12 unit
51− (branch 20:5
37+ (apply 12:18 unit (aura 12:24 @t)))
52− (wing 20:8 x)
38+ (unit 12:29
53− (arm 21:7 (lit 21:7 ~) (lit 21:9 %add))
39+ (unit 12:30 (str 12:31 "hi")))))
54− (arm 22:7
55− (cell 22:7 (lit 22:8 ~) (bind 22:10 text))
56− (tuple 22:16 (lit 22:17 %note) (wing 22:23 text)))))))))
57− (value 23:1 nested
40+ (value 13:1 nested-bad
58− (gate 23:11
41+ (cast 13:15
59− (face 23:14 x (ref 23:16 maybe))
42+ (apply 13:18 unit
43+ (apply 13:24 unit (aura 13:30 @t)))
44+ (unit 13:35
45+ (unit 13:36 (lit 13:37 ~zod)))))
46+ (value 14:1 lis
47+ (cast 14:8
48+ (apply 14:11 unit
49+ (apply 14:17 list (aura 14:23 @t)))
50+ (unit 14:28
51+ (list 14:29 (str 14:31 "hi")))))
52+ (value 15:1 list-bad
53+ (cast 15:13
54+ (apply 15:16 unit
55+ (apply 15:22 list (aura 15:28 @t)))
56+ (unit 15:33
57+ (list 15:34 (lit 15:36 ~zod)))))
58+ (value 16:1 accept
59+ (gate 16:11
60+ (face 16:14 x
61+ (apply 16:16 unit (ref 16:22 msg)))
62+ (wing 16:27 x)))
63+ (value 17:1 call
64+ (group 17:9
65+ (call 17:10
66+ (wing 17:10 accept)
67+ (unit 17:17 (lit 17:18 %stay)))))
68+ (value 18:1 bad-call
69+ (group 18:13
70+ (call 18:14
71+ (wing 18:14 accept)
72+ (unit 18:21 (lit 18:22 %bad)))))
73+ (value 19:1 field
74+ (cast 19:10
75+ (ref 19:13 record)
76+ (tuple 19:20
77+ (unit 19:21 (lit 19:22 %go))
78+ (list 19:26
79+ (unit 19:28 (str 19:29 "hi"))))))
80+ (value 20:1 field-bad
81+ (cast 20:14
82+ (ref 20:17 record)
83+ (tuple 20:24
84+ (unit 20:25 (lit 20:26 %bad))
85+ (list 20:31
86+ (unit 20:33 (str 20:34 "hi"))))))
87+ (value 21:1 mimic-mismatch
88+ (cast 21:19
89+ (apply 21:22 mimic (aura 21:29 @t))
90+ (unit 21:33 (str 21:34 "hi"))))
91+ (value 22:1 without-context
92+ (unit 22:20 (lit 22:21 %go)))
93+ (value 23:1 pending
94+ (body 24:3
95+ (trace 24:3
96+ (lit 24:6 %other)
97+ (body 25:5
98+ (cast 25:5
99+ (apply 25:8 unit (ref 25:14 msg))
100+ (unit 25:19 (lit 25:20 %go)))))))
101+ (value 26:1 pending-null
60− (body 24:3
102+ (body 27:3
61− (cast 24:3
103+ (trace 27:3
62− (ref 24:6 msg)
104+ (lit 27:6 ~)
63− (body 25:5
105+ (body 28:5
64− (branch 25:5
106+ (cast 28:5
65− (wing 25:8 x)
107+ (apply 28:8 unit (aura 28:14 @t))
66− (arm 26:7
108+ (unit 28:18 (str 28:19 "hi")))))))
67− (lit 26:7 ~)
109+ (value 29:1 preserve
68− (body 27:9
110+ (gate 29:13
69− (branch 27:9
111+ (face 29:16 x (tvar 29:18 A))
70− (lit 27:12 %.y)
112+ (cast 29:20
71− (arm 28:11 (lit 28:11 %.y) (lit 28:15 %add))
113+ (apply 29:23 unit (tvar 29:29 A))
72− (arm 29:11
114+ (unit 29:32 (wing 29:33 x)))))
73− (lit 29:11 %.n)
115+ (value 30:1 force
74− (tuple 29:15 (lit 29:16 %note) (str 29:22 "hi"))))))
116+ (gate 30:10
75− (arm 30:7
117+ (face 30:13 x (tvar 30:15 A))
76− (cell 30:7 (lit 30:8 ~) (bind 30:10 text))
118+ (cast 30:17
77− (tuple 30:16 (lit 30:17 %note) (wing 30:23 text)))))))))
119+ (apply 30:20 unit (tvar 30:26 A))
78− (value 31:1 bad-empty
120+ (unit 30:29 (str 30:30 "hi")))))
79− (gate 31:14
121+ (mold 31:1 alt
80− (face 31:17 x (ref 31:19 maybe))
122+ (union 32:3 (const 32:3 %go) (const 33:3 %stay)))
81− (body 32:3
123+ (value 34:1 field-wrong-payload
82− (cast 32:3
124+ (cast 34:24
83− (ref 32:6 msg)
125+ (ref 34:27 record)
84− (body 33:5
126+ (tuple 34:34
85− (branch 33:5
127+ (unit 34:35 (lit 34:36 %go))
86− (wing 33:8 x)
128+ (list 34:40
87− (arm 34:7 (lit 34:7 ~) (lit 34:9 %missing))
129+ (unit 34:42 (lit 34:43 ~zod))))))
88− (arm 35:7
130+ (value 35:1 wrong-name
89− (cell 35:7 (lit 35:8 ~) (bind 35:10 text))
131+ (cast 35:15
90− (tuple 35:16 (lit 35:17 %note) (wing 35:23 text)))))))))
132+ (ref 35:18 record)
133+ (tuple 35:25
134+ (face 35:26 wrong
135+ (unit 35:32 (lit 35:33 %go)))
136+ (face 35:37 xs
137+ (list 35:40
138+ (unit 35:42 (str 35:43 "hi")))))))
91− (value 36:1 bad-present
139+ (value 36:1 wrong-union
92 (gate 36:16
140 (gate 36:16
93− (face 36:19 x (ref 36:21 maybe))
141+ (face 36:19 x (ref 36:21 alt))
94− (body 37:3
142+ (cast 36:25
95− (cast 37:3
143+ (ref 36:28 record)
96− (ref 37:6 msg)
144+ (tuple 36:35
97− (body 38:5
98− (branch 38:5
99− (wing 38:8 x)
145+ (unit 36:36 (wing 36:37 x))
100− (arm 39:7 (lit 39:7 ~) (lit 39:9 %add))
146+ (list 36:39
101− (arm 40:7
147+ (unit 36:41 (str 36:42 "hi")))))))
102− (cell 40:7 (lit 40:8 ~) (bind 40:10 text))
148+ (value 37:1 no-field-context
103− (lit 40:16 %missing))))))))
104− (value 41:1 unknown
105− (gate 41:12
149+ (gate 37:21
106− (bind 41:15 x)
150+ (face 37:24 x (tvar 37:26 A))
107− (body 42:3
151+ (cast 37:28
108− (cast 42:3
152+ (cell 37:31
109− (ref 42:6 msg)
153+ (face 37:32 a (tvar 37:34 A)))
110− (body 43:5
154+ (tuple 37:37
111− (branch 43:5
155+ (face 37:38 wrong (wing 37:44 x))))))
112− (wing 43:8 x)
156+ (value 38:1 known-left
113− (arm 44:7 (lit 44:7 ~) (lit 44:9 %add))
157+ (gate 38:15
114− (arm 45:7
158+ (face 38:18 x (ref 38:20 msg))
115− (cell 45:7 (lit 45:8 ~) (bind 45:10 text))
159+ (cast 38:24
116− (tuple 45:16 (lit 45:17 %note) (wing 45:23 text)))))))))
160+ (cell 38:27
117− (value 46:1 shadow
161+ (face 38:28 a (ref 38:30 msg)))
162+ (tuple 38:35
163+ (face 38:36 a (wing 38:38 x))))))
164+ (value 39:1 mismatch-left
118− (gate 46:11
165+ (gate 39:18
119− (face 46:14 x (ref 46:16 maybe))
166+ (face 39:21 x (ref 39:23 msg))
120− (body 47:3
167+ (cast 39:27
121− (cast 47:3
168+ (cell 39:30
122− (ref 47:6 msg)
169+ (face 39:31 a (ref 39:33 alt)))
123− (body 48:5
170+ (tuple 39:38
124− (branch 48:5
171+ (face 39:39 a (wing 39:41 x))))))
125− (wing 48:8 x)
172+ (value 40:1 contextual
126− (arm 49:7 (lit 49:7 ~) (lit 49:9 %add))
127− (arm 50:7
128− (cell 50:7 (lit 50:8 ~) (bind 50:10 x))
129− (tuple 50:13 (lit 50:14 %note) (wing 50:20 x)))))))))
130− (value 51:1 pending
131− (gate 51:12
173+ (gate 40:15
132− (face 51:15 x (ref 51:17 maybe))
174+ (face 40:18 x (tvar 40:20 A))
133− (body 52:3
175+ (cast 40:22
134− (trace 52:3
176+ (cell 40:25
135− (lit 52:6 %unknown)
177+ (face 40:26 a (tvar 40:28 A))
136− (body 53:5
178+ (face 40:30 b
137− (cast 53:5
179+ (apply 40:32 unit (tvar 40:38 A))))
138− (ref 53:8 msg)
180+ (tuple 40:42
139− (body 54:7
181+ (face 40:43 a (wing 40:45 x))
140− (branch 54:7
182+ (face 40:47 b
141− (wing 54:10 x)
183+ (unit 40:49 (wing 40:50 x)))))))
142− (arm 55:9 (lit 55:9 ~) (lit 55:11 %add))
184+ (value 41:1 contextual-bad
143− (arm 56:9
144− (cell 56:9 (lit 56:10 ~) (bind 56:12 text))
145− (tuple 56:18 (lit 56:19 %note) (wing 56:25 text)))))))))))
146− (value 57:1 nested-unit
147− (gate 57:16
185+ (gate 41:19
148− (face 57:19 x (ref 57:21 maybe))
186+ (face 41:22 x (tvar 41:24 A))
149− (body 58:3
187+ (cast 41:26
150− (cast 58:3
188+ (cell 41:29
151− (ref 58:6 msg)
189+ (face 41:30 a (tvar 41:32 A))
152− (body 59:5
190+ (face 41:34 b
153− (branch 59:5
191+ (apply 41:36 unit (tvar 41:42 A))))
154− (wing 59:8 x)
192+ (tuple 41:46
155− (arm 60:7
193+ (face 41:47 a (wing 41:49 x))
156− (lit 60:7 ~)
194+ (face 41:51 b
157− (body 61:9
195+ (unit 41:53 (str 41:54 "hi")))))))
158− (branch 61:9
196+ (value 42:1 nested-units
159− (wing 61:12 x)
197+ (cast 42:17
160− (arm 62:11 (lit 62:11 ~) (lit 62:13 %add))
198+ (apply 42:20 list
161− (arm 63:11
199+ (apply 42:26 unit (ref 42:32 msg)))
162− (cell 63:11 (lit 63:12 ~) (bind 63:14 inner))
200+ (list 42:38
163− (tuple 63:21 (lit 63:22 %note) (wing 63:28 inner))))))
201+ (unit 42:40 (lit 42:41 %go))
164− (arm 64:7
202+ (unit 42:45 (lit 42:46 %stay)))))
165− (cell 64:7 (lit 64:8 ~) (bind 64:10 text))
203+ (value 43:1 nested-units-bad
166− (tuple 64:16 (lit 64:17 %note) (wing 64:23 text)))))))))
204+ (cast 43:21
167− (value 65:1 pending-null
205+ (apply 43:24 list
168− (gate 65:17
206+ (apply 43:30 unit (ref 43:36 msg)))
169− (face 65:20 x (ref 65:22 maybe))
207+ (list 43:42
170− (body 66:3
208+ (unit 43:44 (lit 43:45 %go))
171− (trace 66:3
209+ (unit 43:49 (lit 43:50 %oops)))))
172− (lit 66:6 ~)
210+ (value 44:1 case-discarded
173− (body 67:5
174− (cast 67:5
175− (ref 67:8 msg)
176− (body 68:7
211+ (body 45:3
177− (branch 68:7
212+ (trace 45:3
178− (wing 68:10 x)
213+ (lit 45:6 %pending)
179− (arm 69:9 (lit 69:9 ~) (lit 69:11 %add))
214+ (body 46:5
180− (arm 70:9
215+ (cast 46:5
181− (cell 70:9 (lit 70:10 ~) (bind 70:12 text))
216+ (ref 46:8 record)
182− (tuple 70:18 (lit 70:19 %note) (wing 70:25 text))))))))))))
217+ (tuple 46:15
218+ (unit 46:16 (lit 46:17 %go))
219+ (list 46:21
220+ (unit 46:23 (str 46:24 "hi"))))))))))
tests/golden/types-unit-context/types.txt+90−22
@@ -1,27 +1,95 @@
1partial inference; module not checked
1partial inference; module not checked
2−+$ maybe: cases proven disjoint; mold not checked
3+$ msg: cases proven disjoint; mold not checked
2+$ msg: cases proven disjoint; mold not checked
4−++ cast: $-(maybe msg)
3++$ mimic: cases proven disjoint; mold not checked
5−++ reversed: $-(maybe msg)
4++$ record: not checked
6−++ consume: $-(msg @t)
5+++ valid: (unit msg)
7−++ call: $-(maybe @t)
6+++ invalid: unit payload does not fit its expected type
8−++ nested: $-(maybe msg)
7+/tests/golden/types-unit-context/source.jibb:9:15: expected unit payload
8+++ invalid ^- (unit msg) `%bad
9+ ^
10+/tests/golden/types-unit-context/source.jibb:9:27: payload
11+++ invalid ^- (unit msg) `%bad
12+ ^
13+++ str: (unit @t)
9−++ bad-empty: branch arm does not fit its expected union
14+++ wrong: unit payload does not fit its expected type
10−/tests/golden/types-unit-context/source.jibb:32:6: expected union
15+/tests/golden/types-unit-context/source.jibb:11:13: expected unit payload has type @t
11− ^- msg
16+++ wrong ^- (unit @t) `~zod
12− ^
17+ ^
13−/tests/golden/types-unit-context/source.jibb:34:9: branch arm
18+/tests/golden/types-unit-context/source.jibb:11:24: payload has type @p
14− ~ %missing
19+++ wrong ^- (unit @t) `~zod
15− ^
20+ ^
21+++ nest: (unit (unit @t))
16−++ bad-present: branch arm does not fit its expected union
22+++ nested-bad: unit payload does not fit its expected type
23+/tests/golden/types-unit-context/source.jibb:13:18: expected unit payload has type @t
24+++ nested-bad ^- (unit (unit @t)) ``~zod
25+ ^
17−/tests/golden/types-unit-context/source.jibb:37:6: expected union
26+/tests/golden/types-unit-context/source.jibb:13:37: payload has type @p
18− ^- msg
27+++ nested-bad ^- (unit (unit @t)) ``~zod
19− ^
28+ ^
29+++ lis: (unit (list @t))
30+++ list-bad: list item does not fit its expected type
20−/tests/golden/types-unit-context/source.jibb:40:16: branch arm
31+/tests/golden/types-unit-context/source.jibb:15:16: expected item has type @t
21− [~ text] %missing
32+++ list-bad ^- (unit (list @t)) `~[~zod]
22 ^
33 ^
34+/tests/golden/types-unit-context/source.jibb:15:36: list item has type @p
35+++ list-bad ^- (unit (list @t)) `~[~zod]
36+ ^
37+++ accept: $-((unit msg) (unit msg))
38+++ call: (unit msg)
39+++ bad-call: unit payload does not fit its expected type
40+/tests/golden/types-unit-context/source.jibb:18:14: expected unit payload
41+++ bad-call (accept `%bad)
42+ ^
43+/tests/golden/types-unit-context/source.jibb:18:22: payload
44+++ bad-call (accept `%bad)
45+ ^
46+++ field: [u=(unit msg) xs=(list (unit @t))]
47+++ field-bad: unit payload does not fit its expected type
48+/tests/golden/types-unit-context/source.jibb:20:17: expected unit payload
49+++ field-bad ^- record [`%bad ~[`"hi"]]
50+ ^
51+/tests/golden/types-unit-context/source.jibb:20:26: payload
52+++ field-bad ^- record [`%bad ~[`"hi"]]
53+ ^
23−++ unknown: unit branch subject is not supported by partial inference
54+++ mimic-mismatch: cast constraint is not supported by partial inference
24−++ shadow: pattern binder shadows a name
55+++ without-context: tag needs context in partial inference
25++ pending: tag needs context in partial inference
56++ pending: tag needs context in partial inference
26−++ nested-unit: $-(maybe msg)
27++ pending-null: `~` needs context in partial inference
57++ pending-null: `~` needs context in partial inference
58+++ preserve: $-(A (unit A))
59+++ force: explicit capital constraints are not supported by partial inference
60++$ alt: cases proven disjoint; mold not checked
61+++ field-wrong-payload: unit payload does not fit its expected type
62+/tests/golden/types-unit-context/source.jibb:34:27: expected unit payload has type @t
63+++ field-wrong-payload ^- record [`%go ~[`~zod]]
64+ ^
65+/tests/golden/types-unit-context/source.jibb:34:43: payload has type @p
66+++ field-wrong-payload ^- record [`%go ~[`~zod]]
67+ ^
68+++ wrong-name: cast mold and expression type do not unify
69+/tests/golden/types-unit-context/source.jibb:35:18: cast mold
70+++ wrong-name ^- record [wrong=`%go xs=~[`"hi"]]
71+ ^
72+/tests/golden/types-unit-context/source.jibb:35:25: expression
73+++ wrong-name ^- record [wrong=`%go xs=~[`"hi"]]
74+ ^
75+++ wrong-union: unit payload constraint is not supported by partial inference
76+++ no-field-context: cast mold and expression type do not unify
77+/tests/golden/types-unit-context/source.jibb:37:31: cast mold has type [a=A]
78+++ no-field-context |= x=A ^- [a=A] [wrong=x]
79+ ^
80+/tests/golden/types-unit-context/source.jibb:37:37: expression has type [wrong=A]
81+++ no-field-context |= x=A ^- [a=A] [wrong=x]
82+ ^
83+++ known-left: $-(msg [a=msg])
84+++ mismatch-left: cast constraint is not supported by partial inference
85+++ contextual: $-(A [a=A b=(unit A)])
86+++ contextual-bad: explicit capital constraints are not supported by partial inference
87+++ nested-units: (list (unit msg))
88+++ nested-units-bad: unit payload does not fit its expected type
89+/tests/golden/types-unit-context/source.jibb:43:24: expected unit payload
90+++ nested-units-bad ^- (list (unit msg)) ~[`%go `%oops]
91+ ^
92+/tests/golden/types-unit-context/source.jibb:43:50: payload
93+++ nested-units-bad ^- (list (unit msg)) ~[`%go `%oops]
94+ ^
95+++ case-discarded: tag needs context in partial inference
tests/lib/jibb.hoon+1−1
@@ -2984,7 +2984,7 @@
2984++ test-types-unit-construction
2984++ test-types-unit-construction
2985 (weld (check ~.types-unit-construction src-533 `tok-533 `tre-533) (check-module-types ~.types-unit-construction ~[%tests %golden ~.types-unit-construction %source %jibb] src-533 `typ-533 ~ ~ ~))
2985 (weld (check ~.types-unit-construction src-533 `tok-533 `tre-533) (check-module-types ~.types-unit-construction ~[%tests %golden ~.types-unit-construction %source %jibb] src-533 `typ-533 ~ ~ ~))
2986++ test-types-unit-context
2986++ test-types-unit-context
2987− (weld (check ~.types-unit-context src-534 `tok-534 `tre-534) (check-types ~.types-unit-context ~[%tests %golden ~.types-unit-context %source %jibb] src-534 `typ-534))
2987+ (weld (check ~.types-unit-context src-534 `tok-534 `tre-534) (check-module-types ~.types-unit-context ~[%tests %golden ~.types-unit-context %source %jibb] src-534 `typ-534 ~ ~ ~))
2988++ test-types-unit-patterns
2988++ test-types-unit-patterns
2989 (weld (check ~.types-unit-patterns src-535 `tok-535 `tre-535) (check-types ~.types-unit-patterns ~[%tests %golden ~.types-unit-patterns %source %jibb] src-535 `typ-535))
2989 (weld (check ~.types-unit-patterns src-535 `tok-535 `tre-535) (check-types ~.types-unit-patterns ~[%tests %golden ~.types-unit-patterns %source %jibb] src-535 `typ-535))
2990::
2990::