Module: Rigor::Inference::MultiTargetBinder
- Defined in:
- lib/rigor/inference/multi_target_binder.rb
Overview
Slice 5 phase 2 sub-phase 2 destructuring binder.
‘Rigor::Inference::MultiTargetBinder` decomposes a tuple-shaped right-hand side type against a Prism multi-target tree and produces a `name -> Rigor::Type` binding map. The binder is shared between two surfaces:
-
‘Rigor::Inference::StatementEvaluator#eval_multi_write` for the statement-level `a, b = rhs` form (`Prism::MultiWriteNode`).
-
‘Rigor::Inference::BlockParameterBinder` for nested destructuring inside block parameter lists (`Prism::MultiTargetNode` under `BlockParametersNode#requireds`).
Both Prism nodes share the same ‘lefts` / `rest` (a `Prism::SplatNode`) / `rights` triple, so the binder treats them uniformly. The binder is pure: it MUST NOT mutate its inputs and MUST return a fresh `Hash` on every call.
The binder threads ‘Type::Tuple` decompositions when the right-hand side carrier is a known-arity tuple. Other carriers (`Nominal`, `Dynamic`, `Top`, `Bot`, …) collapse to `Dynamic` per slot — Slice 5 phase 2 sub-phase 2 stays conservative on dynamic-arity right-hand sides until the narrower receiver-shape lattice lands.
Targets the binder recognises:
-
‘Prism::LocalVariableTargetNode` — used by the statement-level `a, b = rhs` form. Binds `target.name` to its slice of the right-hand side.
-
‘Prism::RequiredParameterNode` — used by block-parameter destructuring (`|(a, b), c|`). Prism encodes the inner names of a block-side `MultiTargetNode` as parameter nodes rather than target nodes; the binder treats them uniformly with their `LocalVariableTargetNode` cousins because they carry the same `name:` field and the same observable semantics (binding a fresh local in the block-entry scope).
-
‘Prism::MultiTargetNode` — recurses with the slot’s type as the new right-hand side.
-
‘Prism::SplatNode` (used for `rest`) — its `expression` MUST be a `Prism::LocalVariableTargetNode` or a `Prism::RequiredParameterNode` to be observable; an anonymous `*` splat or a non-local target is skipped.
Other target kinds (‘InstanceVariableTargetNode`, `ConstantTargetNode`, `IndexTargetNode`, `CallTargetNode`, `ConstantPathTargetNode`, `ImplicitRestNode`, …) MUST be silently skipped: they have no observable contribution to the local-variable scope the StatementEvaluator threads.
See docs/internal-spec/inference-engine.md for the binding contract and docs/adr/4-type-inference-engine.md for the slice rationale.
Class Method Summary collapse
Class Method Details
.bind(target_node, rhs_type) ⇒ Hash{Symbol => Rigor::Type}
68 69 70 71 72 |
# File 'lib/rigor/inference/multi_target_binder.rb', line 68 def bind(target_node, rhs_type) bindings = {} visit(target_node, rhs_type, bindings) bindings end |