Module: Rigor::Inference::Destructure
- Defined in:
- lib/rigor/inference/method_parameter_binder.rb
Overview
Builds the entry scope of a method body by translating the method's parameter list into a
name -> Rigor::Type map.
Parameter types come from the surrounding class's RBS signature when one is available;
otherwise every parameter defaults to Dynamic[Top]. The default is the Slice 1 fail-soft
answer for unknown values, so a method whose RBS signature is missing or whose parameters
cannot be matched still binds every name into the scope (a method body whose Local x
reads return Dynamic[Top] instead of falling through to the unbound-local
Dynamic[Top] event is the same observable type, but the binding presence is what later
slices need to attach narrowing facts to).
The class context (class_path:) and singleton: flag are supplied by the caller (the
StatementEvaluator) which threads them as the lexical class scope. The binder makes no
assumption about how that context was computed; it only uses it to build the
(class_name, method_name) lookup key for Rigor::Environment::RbsLoader#instance_method
/ #singleton_method.
See docs/internal-spec/inference-engine.md for the binding contract.
Leaf-name extraction for a destructured positional parameter (Prism::MultiTargetNode).
Stateless; lifted out of MethodParameterBinder so the binder's class length stays in
budget.
Class Method Summary collapse
- .names_for_entry(entry) ⇒ Object
-
.target_names(multi_target) ⇒ Object
Collect every leaf local name a
MultiTargetNodebinds, recursing through nested destructures (((a, b), c)) and the splat slot ((a, *rest)).
Class Method Details
.names_for_entry(entry) ⇒ Object
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/rigor/inference/method_parameter_binder.rb', line 45 def names_for_entry(entry) # A splat sub-target (`*rest` inside the destructure) wraps its real target in a # `SplatNode#expression`; unwrap it. entry = entry.expression if entry.is_a?(Prism::SplatNode) && entry.expression return [] if entry.nil? return target_names(entry) if entry.is_a?(Prism::MultiTargetNode) return [entry.name] if entry.respond_to?(:name) && entry.name [] end |
.target_names(multi_target) ⇒ Object
Collect every leaf local name a MultiTargetNode binds, recursing through nested
destructures (((a, b), c)) and the splat slot ((a, *rest)). Targets without a
#name (an index/call write target, vanishingly rare in a parameter position) are
skipped — there is no local to bind.
40 41 42 43 |
# File 'lib/rigor/inference/method_parameter_binder.rb', line 40 def target_names(multi_target) entries = multi_target.lefts + [multi_target.rest, *multi_target.rights].compact entries.flat_map { |entry| names_for_entry(entry) } end |