Repository navigation
recursion-cycle: de-conflate leaf-nominal identity from structural self-containment (un-spurious-Box leaf types; supersedes #5624) - #5686
Merged
Conversation
…lf-containment 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: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
De-conflate a leaf nominal's own identity from structural self-containment in the recursion-cycle dependency extraction, so opaque/alias/branded leaf types (
Symbol,Char,Email,Url,Path-class, type parameters …) are no longer spuriously marked recursive and spuriouslyBox-wrapped in emitted Rust.Root cause (by execution)
detect_type_cycles_kahnmarks a type recursive if its deps contain its own name (self_ref).node_type_depsreturns a leaf nominal's own name as a "dependency" (Symbol deps=[Symbol]) — becausetype Symbol(opaque),type Email = String(alias),type Char = Int where brand(...)(branded) all resolve to their own nominal identity. That self-name is the type's identity, not a structural dependency, so kahn over-marks every such leaf as recursive → spuriousBox<…>in emit (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 dependency-extraction call site (
all_deps_map, bothbuild_type_envcopies): 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_depsand the kahn algorithm are unchanged; no filter, no import-union, no resolve-stage change.src/v1/04_infer.dag: helperdeps_excluding_leaf_self+ both fold sites (authority)src/v1/stage0/src/v1_compiler_infer.rs: hand-mirror (both sites, inline)Validation (by execution)
Apples-to-apples on identical sources (dsl-first compile-clean closure,
--dependency-pool-index primary-precedence):Box<445 → 308 (−137);Box::new258 → 123 (−135).GrammarExpr/GrammarProduction/GrammarRoot/Node/FreeMonoid/CoreNode) preserved.Supersedes #5624 (the v3 filter+union lever, refuted by execution).
🤖 Generated with Claude Code