diff --git a/ROADMAP.md b/ROADMAP.md index aeb2e7c613f..e19d66499fb 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -651,6 +651,29 @@ Cleared (prior PR #521): `DerivedOpEffect { method, path_template, shape }` coll **Stage 1e.0 closeout — pattern-role authority structural** → ✅ Structurally resolved for the live single-role state (`VectorList` only): list-pattern lowering does not dispatch on a host `PatternStrategy` enum in emitters — each `spec/{rust,go,python}.dag` `*_list_pattern` declares `strategy: VectorList` plus the template bundle; Rust/Go/Python emitters validate that tag fail-closed when indexing realizations and render from the loaded templates only (`src/v3/std/emit_model.dag` documents the split). When a second distinct lowering path ships, restore strategy on the emitter binding and branch in render (still fail-closed from spec rows), and extend `PatternStrategy` + `spec/*.dag` data — YAGNI until then. +### Lane 1 Stage 1e tail — SG-7 emit cutover (active, SG-program owned) + +**Scope.** SG-7 is the SG-program lane that dissolves `src/v3/compiler/src/emit/rust_target.rs` (≈5.5K hand-authored lines) and `src/v3/compiler/src/emit/python_target.rs` (≈2K hand-authored lines) into spec-driven declarations in `src/v3/spec/{rust,python}.dag`, consumed by the shared `emit.rs` walker (already on main via Go's port). Per SG program rule, each migrated `.rs` file ends its diff either deleted, generated, or reduced to a narrow host shim — no dual-authority period. SG-7 IS the Rust/Python half of remaining Stage 1e walker-body dissolution; it is not a separate effort tracked in parallel. + +**Sub-lane labeling.** XL-XXL size makes single-PR landing unlikely; ship partial with explicit sub-lane labels: + +- **SG-7.1 — `emit/rust_target.rs` cutover.** Active sub-lane. +- **SG-7.2 — `emit/python_target.rs` cutover.** Sequenced after SG-7.1 settles (smaller surface, post-Python Stage 1e.0 bridge clear). + +Each sub-PR must reduce handwritten-Rust line count in `src/v3/compiler/src/emit/` net-down vs. its base. + +**Coordination (recorded per director clarification).** SG-program (`clever-swift` manager) owns Stage 1e Rust/Python walker-body dissolution via SG-7 — not the Features manager. `warm-wren` focuses on Stage 3b parse/apply tail and feature work, NOT `emit/*_target.rs`. Overlap on these files while SG-7 is in flight is a coordination failure to escalate to director, not resolve in-PR. + +**Dependencies.** + +- **SG-0 ratchet soundness (in flight, #559)** — affects trust in the handwritten-Rust census but does NOT block authoring or merging SG-7 sub-PRs. The census can back-fill verification once it lands. +- **Stage 1e Rust dissolution** — not a separate prerequisite; it IS SG-7's scope. +- **Pre-existing on main, not blockers:** `emit.rs` shared walker (#542 + #547) and `spec/rust.dag` / `spec/python.dag` carriers (active Stage 1e work). + +**Explicit non-goal.** **Do not** ship a PR whose only handwritten-Rust reduction is porting the 23-line target facades (`emit_rust.rs`, `emit_python.rs`, `emit_go.rs`). They carry zero target heuristic authority; deleting them alone moves the SG-0 census without moving the thesis acceptance ("all target behavior is spec-driven, no per-target heuristic authority remains in handwritten Rust"). SG-7's cutover is the walker, not the facade. + +**Cross-references:** `docs/emit-bridges.md` (bridge inventory), `docs/phase1-lane3-consolidation-build-plan.md` §"Wrapper exception receipt," `src/v3/SELF_HOSTING.md` §3 (Stage 1 emit.dag design note). + ### Cross-cutting — performance **Deferral: self-compile perf ratchet investigation (M, not on any critical path but compounding).** Self-compile time drifted from ~60s to ~70s in recent cycles (~16% growth). The ratchet keeps getting bumped without a root-cause investigation; each bump normalizes the regression. Scope: (1) profile a single `cargo test -p v3-compiler-tests` run, identify the top hot paths; (2) measure where the 10s came from across recent PRs (bisect across #479, #489, #490 if signal is unclear); (3) either fix the regression or document it as an accepted cost with a new ratchet ceiling. **Yellow-flag threshold: 90s.** If self-compile exceeds that before this deferral is scheduled, it preempts other work. No design doc needed; profiling is a data-gathering exercise. diff --git a/docs/emit-bridges.md b/docs/emit-bridges.md index bd70124fd98..81d5ffa69e7 100644 --- a/docs/emit-bridges.md +++ b/docs/emit-bridges.md @@ -125,11 +125,13 @@ The earlier **“≥ 86 sites”** lane estimate used a looser union/overlap men --- -### B15 — Hardcoded Rust attributes / derives +### B15 — Hardcoded Rust attributes / derives → ✅ Dissolved (SG-7.1) -| Where | What | Dissolution | +| Where | What | Resolution | |-------|------|-------------| -| `emit_rust.rs` `render_type_declaration` | Prepends `"#[derive(Clone, Debug)]\n"` before struct/enum templates | **P0:** `TypeDefinitionSyntax` gains **attribute template list** or `record_derive` carriers (see `spec-field-gaps.md` §2). | +| `emit/rust_target.rs` `render_type_declaration` (was `emit_rust.rs`) | Previously prepended `"#[derive(Clone, Debug)]\n"` before struct/enum templates | **Dissolved in SG-7.1**: `spec/rust.dag` now bakes the derive line into `rust_type_defs.struct_def` and `rust_type_defs.enum_def` templates directly; the Rust emitter is a pass-through `render_named_template` with no target-specific prelude. If future Rust types need different derives, the authority is the spec template, not hand-coded Rust. | + +**Why no new `record_derive` carrier.** The emit-model's `TypeDefinitionSyntax` templates already treat target-specific scaffolding (e.g., `@dataclass\n` in Python, `type {name} struct { ... }` in Go) as part of the template string. Baking `#[derive(Clone, Debug)]\n` into Rust's `struct_def` / `enum_def` is consistent with that established pattern — no new substrate field required. If a future need emerges for conditional/per-type derive sets (e.g., `Copy` iff the type is copy-safe), that motivates a structural carrier; YAGNI until then. --- @@ -177,13 +179,13 @@ These are **not** all separate “name bridges,” but they are **behavior bridg | `LanguageSpec` discrimination | **Yes** | Use `language` refs — B11 largely closed. | | List / optional **variant roles** | **Partial** | Need explicit metadata or spec fields (B13). | | Canonical algebra fallback | **Partial** | `OrderedRing` name is the gap (B14). | -| Rust derive attributes | **No** | Hardcoded (B15). | +| Rust derive attributes | **Yes** | Baked into `spec/rust.dag` `rust_type_defs.struct_def` / `enum_def` templates; B15 dissolved in SG-7.1. | --- ## Suggested dissolution priority (for P2) -1. **B14** + **B15** + **Loop** (B19) — unblock “spec-complete” Rust/Go/Python. +1. **B14** + **Loop** (B19) — unblock “spec-complete” Rust/Go/Python. (B15 dissolved in SG-7.1.) 2. **B13** — remove cross-target string variant compares. 3. **B12**, **B16**, **B17**, **B18** — polish and de-string remaining bootstrap. diff --git a/src/v3/compiler/src/emit/rust_target.rs b/src/v3/compiler/src/emit/rust_target.rs index 8e05d8d2027..06fdf70690b 100644 --- a/src/v3/compiler/src/emit/rust_target.rs +++ b/src/v3/compiler/src/emit/rust_target.rs @@ -4502,12 +4502,9 @@ impl<'a> Ctx<'a> { .map(|field| self.render_struct_field(field)) .collect::, _>>()?; let fields_joined = join_rendered(&fields, " "); - Ok(format!( - "#[derive(Clone, Debug)]\n{}", - render_named_template( - &self.indexes.syntax.type_definitions.struct_def, - &[("name", name), ("fields", &fields_joined)], - ) + Ok(render_named_template( + &self.indexes.syntax.type_definitions.struct_def, + &[("name", name), ("fields", &fields_joined)], )) } TypeConnective::Disj { variants } => { @@ -4516,12 +4513,9 @@ impl<'a> Ctx<'a> { .map(|variant| self.render_enum_variant(variant)) .collect::, _>>()?; let variants_joined = join_rendered(&rendered_variants, " "); - Ok(format!( - "#[derive(Clone, Debug)]\n{}", - render_named_template( - &self.indexes.syntax.type_definitions.enum_def, - &[("name", name), ("variants", &variants_joined)], - ) + Ok(render_named_template( + &self.indexes.syntax.type_definitions.enum_def, + &[("name", name), ("variants", &variants_joined)], )) } _ => Err(EmitError::UnsupportedBehavior(format!( diff --git a/src/v3/spec/rust.dag b/src/v3/spec/rust.dag index dc895b438ba..b096f350d97 100644 --- a/src/v3/spec/rust.dag +++ b/src/v3/spec/rust.dag @@ -939,9 +939,9 @@ data rust_type_applications: TypeApplicationSyntax = { } data rust_type_defs: TypeDefinitionSyntax = { - struct_def: "pub struct {name} { {fields} }" + struct_def: "#[derive(Clone, Debug)]\npub struct {name} { {fields} }" struct_field: "pub {name}: {type}," - enum_def: "pub enum {name} { {variants} }" + enum_def: "#[derive(Clone, Debug)]\npub enum {name} { {variants} }" enum_unit_variant: "{name}," enum_data_variant: "{name} { {fields} }," }