Repository navigation
lever: cross-module recursive_type_set local-restrict + import-authority union (+ floor witness) - #5624
lever: cross-module recursive_type_set local-restrict + import-authority union (+ floor witness)#5624gunbai-bot[bot] wants to merge 4 commits into
Conversation
…ner aliases A nullary alias to a generic coproduct container (e.g. Witness<C> = Holds|Violates) whose only recursion is an imported recursive type is correctly un-marked non-recursive once cross-module recursion-marking is fixed. Such an alias was then COLLAPSED during resolution, dropping its coproduct arms -> VariantNotFound at match sites (e.g. self_host.dag StageEmissionEquality = Witness<StructurallyEqual>). Fix: the children==0 lazy-return branch already preserves the peelable form for recursive types (they cannot be eagerly expanded). Extend that SAME "do not collapse a peelable form" behavior to a second structural inhabitant: a resolved alias whose target is a registered container type with a Disj (coproduct) declaration. Name-free (is_container_type = container-registry membership; resolve_generic_use_decl(...) .connective == Disj); does not touch is_witness_type_name. This is recursion-INDEPENDENCE: the non-recursive coproduct-container alias now resolves to the same peelable form the recursive case produced, so the existing downstream variant resolution fires regardless of recursion-marking. No-op on main (835/0 emit == pristine); enables the cross-module recursive-set fix (separate PR) which exposes the previously recursion-masked sites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ity union; floor witness Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b62bb70 to
1daaeeb
Compare
|
Closing as SUPERSEDED — the v3 lever shape (filter-to-local + import-authority union) was refuted by execution and abandoned per parent's signed reorientation. Why it's dead:
Replacement (parent-signed reshape): a minimal de-conflation at the dependency-extraction call site ( Validated (apples-to-apples on identical sources): Replacement PR will be opened from branch |
…lf-containment (#5686) node_type_deps reports a leaf nominal's own identity (Symbol -> [Symbol]; opaque `type Symbol`, alias `type Email = String`, branded `type Char = Int where brand`) as a structural self-dependency, so detect_type_cycles_kahn's self_ref check spuriously marks every leaf nominal recursive -> spurious Box<> in emitted Rust (the cargo-green E0308 class). The kahn algorithm and import handling are correct; only the dependency-extraction input conflated identity with structural self-containment. Fix at the all_deps_map call site (both build_type_env copies, + seed mirror): a binding whose resolved form is a bare leaf (NoConnective, 0 children) and whose deps are exactly [own_name] contributes no self-dependency. Genuine structural recursion (GrammarExpr, whose self-name comes from variant children) flows the unchanged structural path and stays marked. node_type_deps and kahn unchanged; no filter, no import-union, no resolve-stage change. Validated apples-to-apples on identical sources: Box< 445->308, Box::new 258->123, 0 diagnostics before and after (no net-new); target_model 4/4; anthropic non-regression green; full v1-compiler-tests net-new=0 vs plain-main baseline. Supersedes #5624 (v3 filter+union lever, refuted by execution). Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
What
The cross-module recursive-set fix (the lever), plus a permanent floor witness. Stacked on #5623 (the
04_resolve(Y') prerequisite) — base will retarget tomainwhen #5623 merges.04_infer(bothbuild_type_env_resolved+build_type_env_unresolved): compute the type-cycle set over local bindings only, then union the imported modules' recursive-type authority:Why
Imported type bindings arrive as self-ref stubs (
node_type_depsreturns[own_name]), sodetect_type_cycles_kahnover the merged bindings re-marked every imported type recursive — spuriously boxing ~non-recursive concrete types in the emitted Rust (the E0308 value-wrapping long pole) and, where it failed open, masking real resolution defects.Single-authority fix: recursion is decided once, in the defining module. Local cycle detection stays local; imported types carry their defining-module recursive status via
import_recursive_set(previously computed-then-discarded — now used). Sound + complete because cross-module value cycles are forbidden (§4 acyclic import DAG toward std) → every genuine cycle is intra-module → caught locally + carried by the import authority.The prerequisite (#5623)
Correctly un-marking imported-recursive-arg coproduct aliases (e.g.
Witness<StructurallyEqual>) as non-recursive exposed a latent collapse defect: those aliases lost theirHolds/Violatesarms during resolution →VariantNotFound. #5623 fixes that at the resolution layer (preserve the peelable form). This PR depends on it.Floor witness (permanent, this PR)
src/v2/test/claim/algebra/witness_alias_recursion_independent_test.dag—NodePairEquality = Witness<NodePair>(a nullary Witness alias over a struct whose only recursion is the imported recursiveNode, structurally identical to the productionStageEmissionEquality = Witness<StructurallyEqual>). Thetest fnasserts both coproduct arms resolve (construction-stage;VariantNotFound= RED, fail-closed). Auto-enrolled by the*_test.dag+test fnnaming.It rides this PR (not #5623) because on
main+ (Y')-alone the alias is still recursive (non-discriminating); only with the lever does it exercise the (Y') resolved-alias path.Proof (by execution)
WitnessVariantNotFoundgone; zero net-new.gunbc run --claim-run --entry … --function witness_alias_resolves_holds_violates_independent_of_recursion→true.variant 'Holds'/'Violates' not found in type 'NodePairEquality'; restored →true. Discriminates precisely.v1-compiler-testsgreen incl.generic_alias_field_access_resolves_through_expansion,list_and_freemonoid_*alias-compat,*coproduct*;generic_alias_coproduct_resolves()→true.StageEmissionEqualityresolution is permanently floor-gated byself_host/fixed_point_test.dagtest fns (predates this work) + the corpus compile-clean gate.Seed mirror (
v1_compiler_infer.rs) hand-edited (no regen); gunbc builds clean.Note: a follow-up (the lever's full E0308 carrier delta + 3-way termination-delta witness) lands after this; the de-nickname of
is_witness_type_name(the witness-synthesis path) is filed as a separate grounded lever.🤖 Generated with Claude Code