Module: Rigor::Inference::MultiTargetBinder
- Defined in:
- lib/rigor/inference/multi_target_binder.rb,
sig/rigor/inference.rbs
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_writefor the statement-levela, b = rhsform (Prism::MultiWriteNode).Rigor::Inference::BlockParameterBinderfor nested destructuring inside block parameter lists (Prism::MultiTargetNodeunderBlockParametersNode#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[Array], Dynamic[Top], Top, Bot, ...)
collapse to Dynamic[Top] 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-levela, b = rhsform. Bindstarget.nameto 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-sideMultiTargetNodeas parameter nodes rather than target nodes; the binder treats them uniformly with theirLocalVariableTargetNodecousins because they carry the samename: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 forrest) — itsexpressionMUST be aPrism::LocalVariableTargetNodeor aPrism::RequiredParameterNodeto 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
Instance Method Summary collapse
Class Method Details
.bind(target_node, rhs_type) ⇒ Hash{Symbol => Rigor::Type}
56 57 58 59 60 |
# File 'lib/rigor/inference/multi_target_binder.rb', line 56 def bind(target_node, rhs_type) bindings = {} visit(target_node, rhs_type, bindings) bindings end |
Instance Method Details
#self?.bind ⇒ Hash[Symbol, Type::t]
98 |
# File 'sig/rigor/inference.rbs', line 98
def self?.bind: (untyped target_node, Type::t rhs_type) -> Hash[Symbol, Type::t]
|