Repository navigation
XL-2 resolve: a wildcard '_' match arm binds nothing and names nothing - #12297
Conversation
resolve_pattern_node_walk recognized `_` only as a constructor field's target; a bare `_` arm pattern fell to resolve_node_walk and was looked up as a symbol. It now recognizes the wildcard at every pattern depth. Witness v2.test.claim.namespace_xl0.wildcard_arm_resolve (warm-shared). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
APPROVE on exact head 5d563b9 for MERGE-QUEUE landing only.
The fix is appropriately narrow at the resolver boundary: resolve_pattern_node_walk recognizes the exact _ pattern as binding no name, without changing named-binder handling or suppressing references in the arm body. The three controls discriminate those boundaries: the top-level wildcard is red on main and green here; a named arm binder still binds; and an undeclared name used inside the wildcard arm body still refuses at that atom.
The census consequence is material for XL-2: before this repair, the spurious wildcard failure was emitted as a real residual chain while observation remained complete. This head removes that false row rather than hiding it through incompleteness.
Keeping a_wildcard_match_arm_resolves_as_an_unbound_name OPEN is correct. This PR delivers only the resolve-grain property that _ does not become an unbound reference; it does not deliver the row's terminal requirement of a distinct lowered wildcard form.
Carrier follow-up boundary: mark Wildcard delivered at resolve grain with that qualification, and admit QualifiedFieldTypeVisibility as OUTSTANDING in the same carrier update so the prerequisite universe does not falsely appear closed.
All five exact-head checks are green and GitHub reports CLEAN. Enqueue this exact head; do not direct-merge it, and require the merge_group candidate to revalidate against then-current main.
What
v2.compiler.resolveresolve_pattern_node_walkrecognized_only as a constructor field target (resolve_pattern_field_target_walk). A bare_arm pattern hit theconstruct_tag_optional = Absentarm and went toresolve_node_walk, which looked it up as a reference to a symbol spelled_. That was the earliest wrong link: lowering hands resolve the same_atom in both positions, and resolve already treated it as a wildcard in one of them. The fix is one recognizer (resolve_pattern_is_wildcard) at the top of the pattern walk, so every depth goes through it. The field-only helper is removed.body_lowering_fold.dagis not touched.Witness:
v2.test.claim.namespace_xl0.wildcard_arm_resolveNative census route (
native_test_context_from_ingest→native_census_module_resolution), four inline modules. The claims were run locally withgunbc runagainst main69e0bb7566eand against this head:a_match_exhaustive_through_a_wildcard_arm_resolves(specimen)an_undeclared_name_in_a_wildcard_arm_body_is_the_sole_refusal_at_its_atoma_wildcard_in_a_constructor_field_resolves(control)a_named_binder_arm_still_binds(control: exhaustive through named arms,WcB { r: r } => r)wc_outcomesis enrolled WARM inv2.workflow.floor_pure_producer_share, the same as its sibling*_outcomesrows.Measurement (2): census-resolve behavior before and after
I used a scratch probe that printed each module's census outcome, meaning its chain atoms and
ObservationCompleteness. The probe was deleted afterwards.wc_arm: REFUSED first=_ obs=complete·wc_body: REFUSED first=_ +wc_undeclared_body obs=completewc_arm: RESOLVED·wc_body: REFUSED first=wc_undeclared_body obs=completeSo on main the wildcard refusal never marked the match or the module incomplete. Observation stayed
ObservationComplete. What it did was refuse the whole module as an extra, spurious chain that came first, ahead of the real body refusal. The real refusal was still reported, as a second chain. On head that spurious chain is gone and the body refusal is the only one.RFM
a_wildcard_match_arm_resolves_as_an_unbound_nameis not retired. Its trigger names a capability: the lowered pattern carries the wildcard as its own form. That capability is not delivered here. The wildcard is still an atom spelled_that resolve recognizes throughpattern_wildcard_name, and the construction lives inbody_lowering_fold(another worker's). I appended a receipt that records the repair, the measurement and why the row stays open.Carrier wording (for
compiler_frontend_program_status, not edited here)Carrier arm Wildcard: the spurious unbound rows are removed on the native census route. A
_arm pattern at any depth resolves, and a refusal in a_arm's body is reported at its own atom as the only chain. Proposed status: resolve-side DONE (witnessv2.test.claim.namespace_xl0.wildcard_arm_resolve). The lowered-form climb stays tracked by the RFM.🤖 Generated with Claude Code