Repository navigation
XL-2: a binder is read as a name; an unread parameter slot refuses instead of leaving the domain - #12780
Conversation
…stead of leaving the domain body_lower_param_binding_atom_optional fell back to the OPERAND reader and mapped its refusal to Absent; a binder is an identifier, so it now reads a name through shells whose value is that atom. body_lower_collect_typed_params filtered unread slots out of the Arrow domain; each slot is now read or refused (parameter_unlowered) and the refusal is carried to the fn declaration. The comma-sequence reader reads its parameter by position. Retires the trigger of RFM lowering_accessor_collapses_a_sequence_operand. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
CI red at 396755a: the only blocker is a wet-lane witness that really executes on the runner host, |
…d one The slot walk answered a capture that is neither a parameter nor a pair with a refusing slot, so fn f() -> .. refused parameter_unlowered; an empty capture now has no slots, and any other unread capture still refuses. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Correction to my earlier comment: the wet-lane witness was not the whole story. On the rerun, 9 real claims failed on 396755a:
The first run's wet-lane refusal had stopped the floor before it reported them. Cause, mine: the slot walk answered a capture that is neither a parameter nor a pair with a refusing slot, so an empty parameter list ( Fixed in 6d6b66f: an empty capture has no slots; any other unread capture still refuses. Locally all 9 claims pass, and — sent from sharp-carp-336 |
|
Census on the fixed head, from completed waves only. Setup:
Why the zero is readable: every parameter, field, named-argument label, let key, type parameter and projection member in the sample now goes through the name reader rather than the operand fallback. Main shows the same conservation, so the name reader reads every real binder exactly as before. The slot refusal fires only on supplied input, which Local run on the merge: parameter_slot_refusal 2/2, statement_let_bind plus parse_test_fn_decl_return_clause 9/9 (the claims the empty-list regression broke), reify_operand_refusal 4/4 (after #12779), else_arm_nested_if 5/5, wildcard 9/9. — sent from sharp-carp-336 |
briansrls
left a comment
There was a problem hiding this comment.
APPROVE-MERGE at exact head 5069baf.
No findings. The binder route is repaired at the earliest wrong link: binder positions are read as names through value-preserving shells and no longer consult OperandRefRead. The parameter walk is now slot-preserving and fail-closed: every non-empty slot is read or refuses with body_lowering_reason_parameter_unlowered, and that Outcome propagates through the shared domain/binder view to both fn-declaration lowering routes. The empty-parameter-list regression from the intermediate head is fixed by treating the empty capture as zero slots; exact-head floor and the disclosed sibling controls pass. The 316/316 paired census is neutral, as expected for real grammar-produced binders.
Merge queue only. All applicable exact-head checks and the actual merge_group candidate must pass against then-current main; no direct merge and no check bypass.
XL-2: the last route of RFM
lowering_accessor_collapses_a_sequence_operand, the binder chain. The plan was approved by quiet-seal-543, including the name-reader refinement. Depends on #12779 (reify witness specimen): this PR touchesbody_lowering_fold, so the floor plansreify_operand_refusal, whose specimen #12420 made stale. It merges main once #12779 lands.Why the binder reader reads a name, not an operand
body_lower_param_binding_atom_optionalfell back to the operand reader and mappedOperandRefRefusedto Absent. Every binder position the grammar writes is an identifier, possibly under shells whose value is that one atom:The operand reader refuses only on an operator expression. So
OperandRefRefusedat a binder position requires ungrammatical input, and the earliest wrong link was calling the operand reader at all.The reader now reads a name (
body_lower_binder_name_behind_shell_optional). It peels only shells whose value is the one atom (a production's captured child, an optional element, a sequence with an empty right projection) and answers Absent otherwise. Every caller already refuses located on Absent. The reader never calls the operand reader, so it has no refusal arm to collapse.That meets the retirement condition by construction: no caller of
OperandRefReadmaps Refused to Absent. EveryOperandRefRefusedsite in the compiler propagates. The one non-propagating arm left, stated plainly, is thecomplexity_accumulator_copylens: it reads a refused operand as its raw capture, whole, which #12615 wrote deliberately. It is never a part and never Absent.The real silent drop: parameter slots filtered out of the domain
body_lower_collect_typed_params, lowering's view, filtered out a slot it could not read, so a declaration was Accepted with that parameter missing from its Arrow domain. Now:body_lower_typed_param_slot→body_lowering_reason_parameter_unlowered, located at the slot);body_lower_param_list,body_lower_declared_domain_from_param_listandbody_lower_fn_signature_optional, nowOutcome<Optional<..>>, where Absent is still the declared retained-shell frontier, to the fn declaration;body_lower_typed_param_from_comma_seqreads its parameter by position (the right element ofseq(,, param)). It no longer tries the right element and then the left one, the,token.Evidence (local
gunbc run, same binary; the only variable is main'sbody_lowering_fold.dagagainst head's)Witness
v2.test.claim.body_lowering.parameter_slot_refusal, atbody_lower_fn_decl_to_arrowwith a supplied declaration.fn psr_f(psr_a: Int, psr_b: Int)is parsed, and its first slot is replaced by an atom that is not a typed parameter. A few probes found no parameter shape that parses and then fails to read, so the input is supplied. The unmodified declaration is the control. The claims are enrolled warm.psr_adropped from the domain)The other witnesses on this head pass: wildcard_pattern_form and wildcard_arm_resolve 9/9, else_arm_nested_if 5/5, parameter_slot_refusal 2/2.
Census: pinned sample, running; results will follow in a comment.
Carriers
lowering_accessor_collapses_a_sequence_operand: trigger met, receipt added, rung structurally guaranteed on the lowering routes, and the lens arm stated.body_lowering_reason_parameter_unlowered: a wall with no measured population.🤖 Generated with Claude Code