Skip to content

compiler modeling roadmap updates - #211

Merged
briansrls merged 11 commits into
mainfrom
quick-fox-607
Mar 26, 2026
Merged

briansrls merged 11 commits into
mainfrom
quick-fox-607

Conversation

@briansrls

@briansrls briansrls commented Mar 26, 2026 •

Copy link
Copy Markdown
Contributor

Note

Medium Risk
Touches compiler type resolution/inference and Rust emit by changing how aliases/variants are resolved and removing emit-time re-resolution; mistakes could surface as incorrect type-driven codegen or missed option/alias handling. Changes are localized and backed by new alias-chain regression coverage, but still affect core compilation behavior.

Overview
Strengthens the compiler’s fact composition so downstream stages rely on structurally resolved nodes instead of re-resolving by name.

Moves core Node structural helpers (e.g. leaf_node, cardinality wrappers, product/coproduct predicates) into 00_core.dag and updates imports accordingly. In inference, variant constructor locals now carry the parent enum’s structural node (and removes special-casing for Optional’s Some/None), and resolve_node_bounded now follows one level of alias .inferred to return the structural target.

Simplifies emit by removing Rust emitter usage of resolve_scrutinee_type_node/emit-time record-lit inference, pushing recursive-type metadata into EmitGraphInfo (so emit scopes can use an empty TypeEnv), and updates type_needs_rc to operate without TypeEnv. Adds a regression test for chained type-alias field access and expands the roadmap documentation around compositional basis/pipeline.

Written by Cursor Bugbot for commit 1aae3cb. This will update automatically on new commits. Configure here.

Comment thread src/v2/stage0/src/compile.rs Outdated
briansrls and others added 7 commits March 26, 2026 11:03
Add three new architectural sections to ROADMAP.md:

- Compositional Basis: what is primitive (Node, Conj/Disj, cardinality,
  slots, recursion, collections), what the kernel honestly knows today
  (Int/String/Bool as leaves), structural constructors table, derived
  concepts table.

- Composition Stack (Layers 0-7): full chain from Classical=True|False
  through Bit/Byte/Int/String/List up to Tree/DAG/Annotated (Layer 4,
  missing from std) to compiler domain types. Identifies Node as
  Tree<NodeFacts>, ModuleGraph as DAG<Module>, TypedModule as
  Annotated<Module, TypeFacts>. Type Layer Downgrade metric for
  architectural debt. P3.8 note: Tree<A> expressible today.

- Rewrite "Phase 5 Parallel: Compositional Pipeline" around fact
  composition contracts. Tightened per review: "no compensating
  re-derivation" (not "no passes"), structurally authoritative (not
  fully-resolved), Optional binding/coproduct distinction preserved,
  SCC condensation for C4, C1 narrowed to truly timeless vocabulary,
  EmitGraphInfo carries rendering metadata not type authority.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move 7 timeless structural functions from 04_types.dag to 00_core.dag:
- Constructors: leaf_node, with_optional_cardinality, with_required_cardinality, no_span
- Predicates: node_is_product, node_is_coproduct, node_has_structure

Update imports across 14 .dag files to source these from v2.std.core.
Bridge-era policy helpers (rt_type, error_type_node, child_inferred_or_name)
stay in 04_types.dag — they encode stage-boundary semantics.

Tighten Composition Stack per review:
- Layer 1 uses Vector<n, Bit> not List<Bit> (machine/container distinction)
- DAG<Id,A> defined as nodes + edges + acyclicity law, not "tree with sharing"
- Node split: NodePayload (declared shape) vs NodeFacts (computed metadata)
- ASTNode = Annotated<LabeledTree<NodePayload>, NodeFacts>
- Pair/Either are ergonomic aliases over Conj/Disj, not new primitives
- Span<I> is generic; SourceSpan = Span<Nat>
- Token is parser-domain, not universal std
- LabeledTree moved to Layer 4 (structural, not text/source)
- Phase placement: declare Tree<A>, Annotated<A,F> in Phase 3 when generics stable

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
C2.1: Variant constructor locals now carry the structural parent enum
node (binding.resolved / item) instead of leaf_node(name: binding.name).
This means .inferred on variant expressions will be structurally
authoritative. Two sites fixed: imported_variant_locals in 04_infer.dag
and variant_locals_from_items in 04_items.dag.

C4.1: Service expansion now exits early when converged (total service
count unchanged between passes) instead of always running 5 passes.
Most codebases converge in 1-2 passes.

All 119 non-ignored tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When resolve_node_bounded encounters an alias node (leaf with .inferred
but no structure), follow ONE level of .inferred to return the structural
target. This is O(1), not recursive — topo ordering guarantees the
target is already resolved.

Without this, downstream consumers see an alias_node wrapper (e.g.
{ name: "UserId", inferred: Resolved { node: leaf("String") } }) and
must re-resolve through TypeEnv — a layer downgrade from structural
to name-based authority.

All 112 non-ignored tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
C2.2: Remove explicit leaf_node(name: "Optional") overrides for Some/None
variant locals. The general variant constructor mechanism (C2.1) already
handles Optional — kernel_optional is a Disj node in env.bindings, so
imported_variant_locals registers Some and None with the structural parent.
The explicit overrides were undoing C2.1's fix.

C2.3: In resolve_node_bounded, when encountering an alias node (leaf with
.inferred but no structure), follow ONE level of .inferred to return the
structural target. O(1), safe with topo ordering. This eliminates the
alias_node wrapper that forced emit to re-resolve through TypeEnv.

C2.4 (ResolvedFuncSig) is likely fixed by C2.3 — the return type flows
through resolve_item_types → resolve_optional_node → resolve_node_bounded
(now with alias following) before reaching DeclaredFuncSig.

All 112 non-ignored tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add total timing output before each of the 4 early-return sites
(frontend error, resolve error, normalize error, typecheck error).
Previously t_total was initialized but only printed on the happy path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… notes

Record implementation findings from this session:
- C2.3 was the key fix (in resolve_node_bounded, not build_type_env)
- C2.4 was already fixed by C2.3 (resolution chain flows through)
- C2.2 was redundant with C2.1 (general mechanism handles Optional)
- C4.1 implemented as early convergence (full topo-order deferred)

Add detailed C2.5 implementation notes for next worker: 12 call sites
in 05_emit_rust.dag, per-site migration pattern, risk assessment,
is_already_optional simplification guidance.

Mark all completed items: C1.1-C1.3, C2.1-C2.4, C4.1, C5.1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread src/v2/04_items.dag
Comment thread src/v2/05_emit_rust.dag
briansrls and others added 2 commits March 26, 2026 13:23
C1 moved node constructors from 04_types.dag to 00_core.dag. After stage0
regeneration, these functions live in v2_core instead of infer_types.
Update test imports to match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@briansrls
briansrls merged commit e5f9fa9 into main Mar 26, 2026
2 checks passed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread src/v2/05_emit_rust.dag

fn rust_map_value_type(receiver_type: Node, scope: InferScope) -> Node? {
let resolved = resolve_scrutinee_type_node(env: scope.type_env, n: normalize_access_type_node(n: receiver_type))
let resolved = normalize_access_type_node(n: receiver_type)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant double normalization in map value extraction

Low Severity

rust_map_value_type now calls normalize_access_type_node twice on the same input. Previously, the first line called resolve_scrutinee_type_node (which could produce a different node needing normalization). After replacing it with just normalize_access_type_node, the second call on resolved is redundant since normalize_access_type_node is idempotent — map_type will always equal resolved.

Additional Locations (1)
Fix in Cursor Fix in Web

gunbai-bot Bot pushed a commit that referenced this pull request Oct 7, 2026
…bservation

Repair 1 (msg_6a505028): megarac_recorder_trigger_power_on_field, megarac_trigger_power_on_field_wire, megarac_recorder_reset_survival and their rows and witness derive from the AMI bundle read; moved to gunbc-private #211, no public consumer remained.
Repair 2: CdErrorDeviceEjected promoted a coexistence to a cause. The code is now CdErrorNonzero { wire, firmware }; stopped_with_reason, stop_reason_text and MegaRacPresentationStopped are deleted, and admitting the attach for 16 on 0.32 is an explicit policy (cd_error_attach_policy_admits).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant