Skip to content
Merged

SG-0 #559

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 28 additions & 35 deletions dsl/gunbc/compiler.dag
Original file line number Diff line number Diff line change
Expand Up @@ -245,42 +245,35 @@ data test_package: NonEmptyStr = "v2-compiler-tests"
// shrinks one lane at a time. The SG program (SG-0..SG-7) sequences
// that dissolution. Each lane's PR ports a group of .rs files to
// .dag authority AND removes those .rs files as authority in the
// same PR — deleted, generated, or reduced to a narrow host shim
// that carries a generated header. No dual-authority period.
// same PR — deleted, generated, or reduced to a narrow host shim.
//
// This section is the STRUCTURAL authority for the census: the
// directories that count against the inventory, and the marker that
// separates generated files from hand-authored ones. The ENFORCED
// authority — the concrete list of hand-authored .rs paths that
// must only shrink over time — lives with the ratchet test at
// src/v3/compiler/tests/integration/sg0_census_test.rs. The two
// agree today by discipline; when the v3 pipeline is self-hosting
// enough, the test's constant can be derived from this file.

// Directories the census walks for .rs files. The walk is recursive
// within each root; nested build artifacts (target/) are skipped by
// the walker. One root today (`src/v3/compiler`) is enough to reach
// every v3-compiler .rs file on disk — the crate sources, bin
// targets, the emit subtree, the integration test tree, and the
// crate's `build.rs`. Additional census roots land here if v3
// ever grows Rust sources outside this crate.
type V3CensusRoot {
path: FilePath
}

data v3_census_roots: List<V3CensusRoot> = [
{ path: "src/v3/compiler" }
]

// First non-blank line prefix on every generated .rs file. Every
// regen driver (src/v3/compiler/src/bin/regen_*.rs and the crate's
// build.rs) prepends a header beginning with this string; the
// census classifies any file whose first non-blank line begins with
// it as generated-by-construction and drops it from the hand-
// authored count. Hand-editing a generated file is still forbidden
// by feedback_no_generated_code_on_disk — this marker is the
// discrimination protocol, not a permission.
data v3_generated_marker_prefix: NonEmptyStr = "// AUTO-GENERATED"
// **What "narrow host shim" means.** A retired-to-shim .rs file's
// ONLY hand-authored content is (a) `use` imports, (b) a `#[path]`
// or `include!` directive pulling in generated code, or (c) `pub
// use` re-exports that surface generated symbols under the original
// module path. Any function body, match arm, or control-flow
// statement keeps the file counted as hand-authored. The shim rule
// is structural — a lens will eventually check it — but today it
// is enforced by review.
//
// **No dual-authority in merged/main.** By the time an SG PR lands,
// the old .rs is gone as authority. In-PR intermediate commits may
// temporarily hold both old and new authorities while parity is
// being established; the rule bites at merge time, not at every
// commit.
//
// **Where the authority lives today.** SG-0 is a Rust-side ratchet:
// `src/v3/compiler/build.rs` declares the producer-owned manifest
// `REGEN_OUTPUTS` (the set of .rs files every codegen authority is
// allowed to write under src/v3/compiler); `src/v3/compiler/tests/
// integration/sg0_census_test.rs` reads that manifest to partition
// generated vs hand-authored, and ratchets the hand-authored set
// down. No structural data lives in this file yet — declaring the
// census roots or generated marker here would be parallel-
// representation debt (`feedback_parallel_representation_debt`)
// because the test would not consume it. When v3 self-hosts enough
// to compile this file (SG-6 cutover), the manifest migrates here
// as first-class `.dag` data and `build.rs` is retired as authority.

// ── Command derivation ──────────────────────────────────────────────
// Every builder takes a resolved cargo/grep/diff/cp/rm path instead of
Expand Down
43 changes: 43 additions & 0 deletions src/v3/compiler/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,47 @@ fn main() {
let compiler_out = out_dir.join("v3_compiler_files.rs");
fs::write(&compiler_out, compiler_generated)
.unwrap_or_else(|e| panic!("failed to write {}: {}", compiler_out.display(), e));

// SG-0 producer-owned generated manifest. The census at
// `tests/integration/sg0_census_test.rs` reads this list as the
// sole authority for "which .rs files under src/v3/compiler are
// generated." Every codegen driver (the `regen_*` binaries plus
// the ignored `emit_lens_provenance_snapshot` test) imports the
// same manifest and asserts its output path is in it before
// writing — so a typo in a regen output path fails loud rather
// than silently writing to an uncounted path.
//
// The manifest lives only in OUT_DIR — it is ephemeral,
// reconstructed every build from this list. A hand-edited
// manifest file is clobbered on the next `cargo build`; the
// spoof surface collapses to this `REGEN_OUTPUTS` literal,
// reviewed alongside any real producer change.
//
// Paths are workspace-relative and sorted for determinism. They
// match exactly what the regen drivers write to disk as
// committed Rust.
const REGEN_OUTPUTS: &[&str] = &[
"src/v3/compiler/src/infer_helpers_generated.rs",
"src/v3/compiler/src/lens_cost_generated.rs",
"src/v3/compiler/src/lens_cost_symbolic_generated.rs",
"src/v3/compiler/src/lens_provenance_generated.rs",
"src/v3/compiler/src/lens_structural_resolution_generated.rs",
"src/v3/compiler/src/lens_unused_parameters_generated.rs",
];
let mut manifest = String::from(
"// AUTO-GENERATED by build.rs. Do not edit.\n\
//\n\
// Paths (workspace-relative) of every .rs file under\n\
// src/v3/compiler that is produced by a codegen authority\n\
// (regen_* binaries today; build.rs-driven include_str!\n\
// projections if that surface ever grows into src/).\n\
pub static GENERATED_FILES: &[&str] = &[\n",
);
for path in REGEN_OUTPUTS {
manifest.push_str(&format!(" \"{path}\",\n"));
}
manifest.push_str("];\n");
let manifest_out = out_dir.join("v3_generated_files.rs");
fs::write(&manifest_out, manifest)
.unwrap_or_else(|e| panic!("failed to write {}: {}", manifest_out.display(), e));
}
6 changes: 6 additions & 0 deletions src/v3/compiler/src/bin/regen_infer_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ fn main() {
assert!(output.status.success(), "rustfmt failed");
let formatted = String::from_utf8(output.stdout).expect("utf8");

const OUT_REL: &str = "src/v3/compiler/src/infer_helpers_generated.rs";
assert!(
v3_compiler::generated_files::GENERATED_FILES.contains(&OUT_REL),
"SG-0 producer manifest mismatch: `{OUT_REL}` is not in GENERATED_FILES — \
add it to REGEN_OUTPUTS in src/v3/compiler/build.rs."
);
let out_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
.join("infer_helpers_generated.rs");
Expand Down
6 changes: 6 additions & 0 deletions src/v3/compiler/src/bin/regen_lens_cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ fn main() {
assert!(output.status.success(), "rustfmt failed");
let formatted = String::from_utf8(output.stdout).expect("utf8");

const OUT_REL: &str = "src/v3/compiler/src/lens_cost_generated.rs";
assert!(
v3_compiler::generated_files::GENERATED_FILES.contains(&OUT_REL),
"SG-0 producer manifest mismatch: `{OUT_REL}` is not in GENERATED_FILES — \
add it to REGEN_OUTPUTS in src/v3/compiler/build.rs."
);
let out_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
.join("lens_cost_generated.rs");
Expand Down
6 changes: 6 additions & 0 deletions src/v3/compiler/src/bin/regen_lens_cost_symbolic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ fn main() {
assert!(output.status.success(), "rustfmt failed");
let formatted = String::from_utf8(output.stdout).expect("utf8");

const OUT_REL: &str = "src/v3/compiler/src/lens_cost_symbolic_generated.rs";
assert!(
v3_compiler::generated_files::GENERATED_FILES.contains(&OUT_REL),
"SG-0 producer manifest mismatch: `{OUT_REL}` is not in GENERATED_FILES — \
add it to REGEN_OUTPUTS in src/v3/compiler/build.rs."
);
let out_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
.join("lens_cost_symbolic_generated.rs");
Expand Down
6 changes: 6 additions & 0 deletions src/v3/compiler/src/bin/regen_lens_structural_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ fn main() {
assert!(output.status.success(), "rustfmt failed");
let formatted = String::from_utf8(output.stdout).expect("utf8");

const OUT_REL: &str = "src/v3/compiler/src/lens_structural_resolution_generated.rs";
assert!(
v3_compiler::generated_files::GENERATED_FILES.contains(&OUT_REL),
"SG-0 producer manifest mismatch: `{OUT_REL}` is not in GENERATED_FILES — \
add it to REGEN_OUTPUTS in src/v3/compiler/build.rs."
);
let out_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
.join("lens_structural_resolution_generated.rs");
Expand Down
6 changes: 6 additions & 0 deletions src/v3/compiler/src/bin/regen_lens_unused_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ fn main() {
assert!(output.status.success(), "rustfmt failed");
let formatted = String::from_utf8(output.stdout).expect("utf8");

const OUT_REL: &str = "src/v3/compiler/src/lens_unused_parameters_generated.rs";
assert!(
v3_compiler::generated_files::GENERATED_FILES.contains(&OUT_REL),
"SG-0 producer manifest mismatch: `{OUT_REL}` is not in GENERATED_FILES — \
add it to REGEN_OUTPUTS in src/v3/compiler/build.rs."
);
let out_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
.join("lens_unused_parameters_generated.rs");
Expand Down
14 changes: 14 additions & 0 deletions src/v3/compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@

pub mod dag;
pub mod diagnostics;

/// SG-0 producer-owned generated-file manifest.
///
/// `GENERATED_FILES` is the workspace-relative path list of every
/// `.rs` file under `src/v3/compiler` that is produced by a codegen
/// authority. The list is emitted by `build.rs` at build time; the
/// literal is reviewed there. Two consumers today: the `regen_*`
/// binaries (they assert their output path is in the list before
/// writing) and the SG-0 census test (it uses the list as the sole
/// generated/hand-authored partition — no content-marker scanning).
pub mod generated_files {
include!(concat!(env!("OUT_DIR"), "/v3_generated_files.rs"));
}

pub mod emit;
pub mod emit_go;
pub mod emit_python;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ fn render_handwritten_oracle(program_source: &str, file_name: &str) -> String {
#[test]
#[ignore]
fn emit_lens_provenance_snapshot() {
const OUT_REL: &str = "src/v3/compiler/src/lens_provenance_generated.rs";
assert!(
v3_compiler::generated_files::GENERATED_FILES.contains(&OUT_REL),
"SG-0 producer manifest mismatch: `{OUT_REL}` is not in GENERATED_FILES — \
add it to REGEN_OUTPUTS in src/v3/compiler/build.rs."
);
let fresh = emit_lens_module();
let out_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src")
Expand Down
Loading
Loading