Repository navigation
XL-2: a return lowers only as a function body's tail; everywhere else it refuses located - #12607
Conversation
… it refuses located
No reader named `return`, so a first-match search lowered `return e` to `e` as
the value of whatever block held it: `let x = if c { return j } else { k }`
was ACCEPTED as x = Branch(c, j, k). The return is now recognised; it lowers
as the tail statement of a fn declaration's or fn value's own body, and every
other return refuses as body_lowering_reason_return_not_in_tail_position.
The else-less guard keeps refusing. RFM return_lowered_as_its_operand_outside_the_function_tail.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Census, from completed waves only (4 waves). Population: the 316-path Paired: 450 of 451. The unpaired path is this PR's new RFM row, which has no main side. Changed verdicts: 5 modules, each with a disposition.
Newly refusing modules: 2, one silent-wrong and one correct-by-luck. — sent from sharp-carp-336 |
|
Correction to the census comment above: its last line put the conserved and dropped totals down to the two newly refusing modules and the doc_reachability recovery. That is incomplete. I re-derived the per-module deltas (head minus main) from the same completed waves.
The seven modules accepted on both sides all move toward conserved. Their tail — sent from sharp-carp-336 |
briansrls
left a comment
There was a problem hiding this comment.
APPROVE-MERGE at exact head 6326413, through the merge queue only.
This closes a real below-floor path rather than merely renaming a refusal. return is now recognized before the first-match walkers can search past its keyword. A function declaration or block-bodied function value admits only its own direct tail statement; data initializers admit none; nested function values are pruned from the outer scan and own their returns. The admitted tail is lowered explicitly through the value reader, while every other site refuses with the located return_not_in_tail_position cause. The witnesses distinguish the original silent-wrong let/if case, a non-tail sequence, an arm return, a nested function-value return, the retained else-less-if refusal, lawful direct-tail cases, and an unbound tail operand that proves the operand is read.
The narrower current floor is stated honestly: a return in a tail-position if or match arm remains loud until tail position is carried through the value readers. The RFM and cause roster name that trigger instead of claiming structured early exit is already delivered.
I also checked the corrected census disposition. The two newly refusing modules are the silent-wrong specimen and one correct-by-luck structured-return case; every module accepted on both sides either improves conservation or is unchanged, and the recovered tail-return modules are accounted for. That supports the wall rather than hiding an unexplained accepted-program regression.
Current exact-head witnesses run 36542641708 completed successfully, and there are no unresolved review threads. No local tests or census were run by me. Require the actual merge_group candidate to pass against then-current main; no direct merge or check bypass.
…eturn-guard # Conflicts: # src/v2/workflow/floor_pure_producer_share.dag
briansrls
left a comment
There was a problem hiding this comment.
APPROVE-MERGE / REBIND at exact head b4307d7, through the merge queue only.
This renews my approval from 6326413. The only branch commit since that reviewed head is the merge of main (second parent 6571276). Its sole conflict was src/v2/workflow/floor_pure_producer_share.dag. The resolved PR diff retains the return-tail-position warm producer and its nine-specimen rationale while taking main's other roster additions; the PR's behavior files are unchanged from the approved head.
The original verdict therefore carries: return is recognized before first-match search can discard its keyword; only a function body's direct tail return lowers explicitly through the value reader; every other return refuses at its own site; nested function values own their returns; and the structured-tail-return limitation remains honestly open. The nine exact claims remain the discriminating floor evidence.
Exact-head witnesses run 36604560732 completed successfully, and GitHub reports the PR mergeable. No local tests or census were run by me. Require the actual merge_group candidate to pass against then-current main; no direct merge or check bypass.
…ipt; caret cause row stays retired; let-in comment matches the lowering)
The site lists built by list_append(left: acc, ..) and the per-site scan of the admitted list were quadratic. body_lower_exit_outside_tail_optional now walks the raw parse once, carrying the tail flag, and answers the first unadmitted exit in pre-order: no lists, no membership tests. #12607's return-site walker is deleted with them. An unadmitted guard is now refused at the guard (else_less_if_unlowered), its first exit in pre-order, which is the base's cause too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…view 5362016887 P2) The main merge reinstated #12607's row beside the replacement; replace, not duplicate. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
XL-2, the return floor fix (option A as ruled by quiet-seal-543):
returnis recognised, lowers only as a function body's tail, and refuses located everywhere else.The defect: silent wrongness on main
No reader in
v2.compiler.body_lowering_foldnameddag_token_kw_return. A deep first-match search answered the statementseq(return, e)withe, so the keyword was silently dropped. Measured on main 88436e5 throughmodule_roots_from_source_root_ingest:This was accepted as
x = Branch(c, j, k): the function continues where it should have exited. A return in an arm of a tail-positionif, and a return before another statement in a fn value, were accepted the same way.The change
body_lower_return_statement_expr_optionalrecognises a return statement.body_lower_return_outside_tail_optionalis the wall. It collects every return under a fn declaration, a fn value's block body or a data initializer, stopping at nested fn values, which own their own returns. It refuses the first one that is not the body's tail statement asbody_lowering_reason_return_not_in_tail_position, located at it, before any reader can search past it. It sits beside the existing else-less wall inbody_lower_fn_decl_to_arrow.body_lower_tail_statement_read: a return lowers to its operand, explicitly.body_lower_try_statement_spineroutes a sole return head into the spine rather than the expression walkers.else_less_if_unlowered.A consequence, stated plainly:
fn f(..) { if c { return a } else { b } }was accepted on main (correct only by luck) and now refuses asreturn_not_in_tail_position. Admitting it needs the tail position carried through the value readers. That is the next-rung trigger, sequenced after first-match PR-2. The census counts these cases.Evidence (local
gunbc run, same binary; the only variable is main'sbody_lowering_fold.dagversus head's)Witness
v2.test.claim.namespace_xl0.return_tail_position: one front end over 9 inline modules, enrolled warm.Census
Population: the 316-path pinned
reference_conservation_stratified_sample_paths, plus every file containingreturn(451 paths). Base 88436e5, head 6326413. Results follow in a comment when the completed waves pair: modules that newly refuse, each with a disposition.Carriers
return_lowered_as_its_operand_outside_the_function_tail. Rung: below the floor → mitigated. Its ceiling is structured early exit, and its trigger is the tail position through the value readers. Theelse_less_if_statement_has_no_lowered_formrow points to it.body_lowering_reason_return_not_in_tail_positionincompile_door_cause_ownership.🤖 Generated with Claude Code