Documentation
¶
Overview ¶
Package join provides type joining operations for phi node merging.
When control flow merges at phi nodes, the join package computes the resulting type from multiple incoming branches. The join operation produces a type that is a supertype of all incoming types.
Coalescing Rules ¶
The join package applies several coalescing rules before creating unions:
- Empty records are removed when maps are present
- Open and closed records are unified to open records
- Records with identical field signatures merge their map components
- Multiple maps merge into a single map with joined key/value types
- Unknown types are filtered out (they don't contribute information)
These rules ensure that join results are as precise as possible while remaining sound supertypes of all inputs.
Usage ¶
Call Types with the types from each incoming branch:
result := join.Types(branchA, branchB, branchC)
For single-type or identical inputs, Types returns the input directly without creating unnecessary unions.
Index ¶
- func CoalesceCompatibleRecords(types []typ.Type) []typ.Type
- func CoalesceEmptyRecordWithArray(types []typ.Type) []typ.Type
- func CoalesceEmptyRecordWithMap(types []typ.Type) []typ.Type
- func CoalesceMaps(types []typ.Type) []typ.Type
- func CoalesceRecordMapComponents(types []typ.Type) []typ.Type
- func CoalesceRecordOpenness(types []typ.Type) []typ.Type
- func Types(types ...typ.Type) typ.Type
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CoalesceCompatibleRecords ¶ added in v1.5.8
CoalesceCompatibleRecords merges structurally compatible record variants into one optional-field record. This keeps flow joins precise for mutation-style code paths while preserving discriminated unions.
func CoalesceEmptyRecordWithArray ¶ added in v1.5.8
CoalesceEmptyRecordWithArray removes empty records when arrays are present.
Lua uses the same table runtime value for map-like and list-like tables. During flow joins, a common pattern is {} on one path and array growth on another (table.insert). Keeping {} in the union loses sequence intent and creates downstream nil-index noise. When an array shape is present, prefer it.
func CoalesceEmptyRecordWithMap ¶
CoalesceEmptyRecordWithMap removes empty records when maps are present.
In Lua, {} (empty table) is a common initial value that gets populated later. When joining {} with a map type, the empty record is redundant since the map already represents "table with dynamic keys." Keeping the empty record would create an imprecise union.
Example: Joining {} and {[string]: number} produces {[string]: number}, not {} | {[string]: number}.
func CoalesceMaps ¶
CoalesceMaps merges multiple map types into a single map with unioned key/value types.
When joining branches that each produce a map type, rather than creating a union of maps, we create a single map with the union of key types and union of value types. This is more precise and matches Lua semantics.
Example: Joining {[string]: number} and {[string]: boolean} produces {[string]: number|boolean}, not {[string]: number} | {[string]: boolean}.
Non-map types in the input are preserved unchanged in the result.
func CoalesceRecordMapComponents ¶
CoalesceRecordMapComponents merges map components across records with identical fields.
Lua tables can have both named fields (record component) and dynamic keys (map component). When joining records with the same field signature but different map components, this function merges the map components.
Example: Joining {foo: string, [string]: number} and {foo: string, [string]: boolean} produces {foo: string, [string]: number|boolean}.
Records are grouped by field signature (name, type, optional/readonly flags). Only groups where at least one record has a map component are merged. Records with different field signatures are not affected.
func CoalesceRecordOpenness ¶
CoalesceRecordOpenness converts closed records to open when joining with open records.
In Lua, a closed record {x: number, y: string} can flow to code expecting an open record {x: number, ...}. When branches produce different record variants, we open all closed records to allow the join to represent "at least these fields."
This prevents spurious errors when one branch produces a known-complete record and another produces a record that might have additional fields.
If all records are closed or all are open, no transformation is needed.
Types ¶
This section is empty.