Repository navigation
Step 2: a generic fixed only by a lambda's return is solved from it (p8/p8b/p9 refuse; #9416 narrowing lifted) - #13418
Conversation
…ke_callable_type) against its formal in round 1; empty-literal placeholder solved by a later actual; #9416 note rewritten (mirrors pending regen round) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…verges: first_generation_equal=true, rebuild_packages=0, in a fresh tree at 864c9ce) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n pending Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ember closes with this PR; p7b stays open Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…cords the specimens, not a commit (review 76610) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… 3 first_generation_equal=true, convergence_stages=0, rebuild_packages=0) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Addressed review 76610 in a361b1e. The branch is now at 2ece97e after merging main and regenerating the infer mirror in a fresh checkout (round 3:
The PR body now also explains, at identity grain, the two census rises the program owner asked about. — sent from jolly-pike-330 |
…l the lambda-return witness: three reds and an accepted control (review 76646). Mirror pending regen Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
briansrls
left a comment
There was a problem hiding this comment.
NO-LAND at this exact head for one correctness blocker, plus one authority/control blocker.
empty_list_element_variable_idis not an identity; it is a spellableTypeVariable.id.unify_binding_is_placeholderclaims that only the compiler-minted empty-list placeholder yields, but it returns true for everyTypeVariable { id: "empty_list_element" }(and recursively for a one-child carrier containing one). Authored generic parameters use the same carrier with the authored parameter name as the id. Therefore a legal authored parameter namedempty_list_elementis treated as the compiler placeholder, and eitherunify_genericsorunify_lambda_solvesmay overwrite that informative binding with a later concrete actual. That directly violates this PR's stated rule that an informative binding is never overridden, and can turn an outer generic into a concrete result by spelling collision.
Please give the minted placeholder an unauthorable identity/spelling, or use a declaration/origin-backed distinction, and add a collision control with an authored generic named empty_list_element proving it never yields. The control should exercise both the ordinary later-actual replacement path and the lambda merge path if both retain the predicate.
- The repaired behavior has no committed executable witness: p8, p8b, p9, p7a/p7b/p7c exist only as scratch receipts/prose. This is a load-bearing infer rule and the current floor can remain green if the lambda contribution is later removed. Please enroll a small compile fixture that pins the concrete-return refusals, the round-2 mismatch control, and the stated p7b two-round boundary. While doing so, correct the canonical row's stale NEXT TRIGGER text: the preceding PARTIAL CLOSURE says p8/p8b now refuse with a concrete Int-vs-String mismatch, but the trigger still says p8, p8b and p7b must refuse with the future
cannot infercause. The future unresolved wall's discriminating member is now p7b; p8/p8b are closure controls, not members awaiting that cause.
The Arrow construction through make_callable_type, positional parameter/return unification, first-round-only merge, whole-closure census explanation, and the stated p7b boundary otherwise look coherent; exact-head CI is green.
… the class row's trigger names p7b as the wall's discriminating member and p8/p8b/p9 as closure controls; regenerate the infer mirror (fresh checkout: round 2 first_generation_equal=true, rebuild_packages=0) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Addressed review 76646, and the two blockers raised in the side-chat review of 2ece97e, at c431ac6 (with f84c29d).
The mirror was regenerated in a fresh checkout ( — sent from jolly-pike-330 |
Derived-node identity step 2. A generic fixed only by a lambda's return is now solved from that return, so a wrong value there becomes a located refusal instead of a silent acceptance.
Derivation (DESIGN §6b)
v1.compiler.inferinfer_call_arguments_generic_passskipped every lambda argument for unification. The note aboveexpr_contains_lambda(A lambda parameter whose declared type is a type variable now binds it: two independent defects, one of them a fabricated empty type #9416) stated the consequence: "a lambda return feeding a later formal — is still out of reach". This PR lifts that narrowing and rewrites the note beside the change.inferred(infer_exprExprLambda), not a callable type. A first build that unifiedresolved_type(lambda)against the formal Arrow had zero effect, measured. The repair builds the lambda's callable type at the call site with the existing authoritymake_callable_type(lambda_callable_type).unify_genericsgains an Arrow arm,unify_callable_generics. It unifies parameters positionally and then the return, each read throughchild_type_node.unify_lambda_solves). It never overrides an existing binding. A lambda return that is itself an unresolved variable (callable_param) is dropped. Round 2 is unchanged, so the bound stays at two rounds.Removed after review: an empty-literal placeholder rule. It let a later actual replace a binding to the
empty_list_elementplaceholder. It was spellable (anyTypeVariablewith that id matched, including an authored generic), and no case I could construct showed any effect:[]in argument position takes the formal as its expected type, and a let-bound[]gave identical results on main and here. Rule, id constant and lambda-path override are all deleted.Enrolled witness:
test.claim.lambda_return_solves_generic_witness_testThe witness runs each source through the real compile census (
gunbc.compile_census_probe); each helper returns -1 when the census cannot run.a_generic_fixed_by_a_lambda_return_refuses_a_wrong_argument_position(p8:lrs_take(b: lrs_idf(f: fn() { 5 })))a_generic_fixed_by_a_lambda_return_refuses_a_wrong_declared_return(p9)a_lambda_after_the_argument_that_fixes_its_parameter_solves_the_result(p8b)the_same_calls_at_the_type_the_lambda_returns_are_accepted(control)a_lambda_return_that_disagrees_with_a_fixed_parameter_refuses(round-2 mismatch control)a_lambda_before_the_argument_that_fixes_its_parameter_stays_unsolved_at_the_two_round_bound(p7b boundary pin)Removing the arm reds the first three. The p7b pin is expected to go red when the
unbound_generic_reaches_conformance_unjudgedwall lands, and is then rewritten to assert the refusal.Predictions (sent to the program owner before the run) and outcomes
fold_list(xs, empty: [], cons: snoc(acc, m))then a field read, becomes Acceptedno field 'module' on type 'Unit', as on main. The cause is not located. A self-contained copy with local generics reproduces the miss. It is a pre-existing refusal on main, not a regression, and it is owned by the shape-2 PR #13330.first_generation_equal=true,rebuild_packages=0P5: census before/after
gunbc test //gunbc/instruments:generic-identity-censusover the v2 compile closure, run in place against mainaae7da34ca(the main merged into this branch) and against this PR. STANDING held and all 7 controls held on both.The two rises were diffed at identity grain. That row diff ran at base
864c9ce0c9, with the since-removed placeholder rule in; the matched deltas above are +2790 and +22, against +2780 and +22 there. I have not re-diffed the rows on this base.body_expression_typerows in which a body expression whose type was an unbound generic is now a concrete product, and the census counts that product's field children. The largest groups:TargetText'sempty/partsinv2.compiler.target_serializeserialize_relation_row_nested_bounded;Cons'shead/tailinv2.compiler.body_lowering_foldbody_lower_collect_param_edges.v2.std.compilers.semantic_decl_emissionsemantic_decl_binding_spelling_rows_from_catalog,bind_outcome::<U>(main:foreign_in_a_value_argument) is now solved from the lambda's return. That return isoutcome_rejected(...), whose own T no value argument carries.optional_absent::<T>inv2.compiler.body_lowering_foldbody_lower_declared_domain_from_param_listhas the same shape.P6: self-host emitted-artifact diff
gunbc compile --entry src/v2/compiler/00_compile.dag --target rust, mainaae7da34caagainst this PR.v2_compiler_infer.rs:pair: _becomespair: Rc<InferTypePair>;v2_std_demand_engine.rs: the sort closure's parameters become&Rc<DemandIdentity>;v2_std_type_binder.rs:pa: _becomespa: Rc<TypeParamArgument>.04_infer.dag:3432(×2),fn_index.dag:268,qualified_name.dag:429andtype_binder.dag:314.00_compile.dag:5924.Whole-corpus refusals: none. CI's floor run (the whole-corpus check) is green on
c431ac6ec0, as are emit-build, generated and witnesses.Row:
unbound_generic_reaches_conformance_unjudgedrecords this PR closing its lambda-return member. Its NEXT TRIGGER now names p7b as the wall's discriminating member and p8/p8b/p9 as closure controls.🤖 Generated with Claude Code