Repository navigation
The compiler admits DUPLICATE FUNCTION DEFINITIONS in one module and silently resolves the call to the last one: a below-floor name-resolution defect with LIVE exposure, verified by execution, needing a fixture-boundary RED and a 4b row - #9481
briansrls wants to merge 2 commits into
Conversation
…use them, with a fixture-boundary RED and two live specimens repaired A module declaring one name twice was ACCEPTED with zero diagnostics, and every reference bound whichever declaration was written last. `v1.compiler.env` `symbol_index_insert` is a `map_insert` keyed on the qualified name, so the second declaration REPLACED the first in the symbol index -- two authorities for one fact (DESIGN section 3) with no refusal anywhere. Names resolving is the ordinary compiler floor, so this sat BELOW it (DESIGN section 4b): silent wrongness, outside the ladder rather than a weak rung on it. MEASURED BY EXECUTION, instrument named. Binary built from source at ddb7f53 (main tip), sha256 1b2eb218e6725f76..., mtime 2026-08-27T13:31:07Z -- not the installed /usr/local/bin/gunbc, which is two days stale and proves nothing about current main: fn probe_dup() -> Int { 1 } fn probe_dup() -> Int { 1 } fn probe_dup() -> Int { 2 } fn probe_dup_caller() -> Int { probe_dup() } fn probe_dup_caller() ... => 2 (the LAST definition) => 1 (control) The collision is NOT fn/fn only, which the original finding did not cover: a `data` and a `fn` of one name share the same key, and a bare reference to the data evaluated to `<fn thing>`. LIVE EXPOSURE, denominator stated: 4163 tracked .dag files scanned, 2 modules carried it, both repaired here. * dag/gunbc/systemctl_list_units.dag -- `data systemctl_list_units_all_states: String` shadowed by `fn systemctl_list_units_all_states(..)`, so the ListUnits `state:` argument bound the FUNCTION rather than "active,inactive,failed". A production module with two importers. The data row is renamed `systemctl_all_unit_states_selector`; the function keeps its name, which is what both importers call. * dag/test/claim/spark_managed_grant_reconcile_witness_test.dag -- one `data` row declared twice with an identical value; the second is deleted. The deletion IS the census: with the dotted-name form of the scan (`service shell.Find` is one name, not `shell` repeated) zero duplicates remain. THE WALL. `v1.compiler.resolve` `check_duplicate_declarations` folds each module's OWN item list and emits a blocking `DuplicateDeclaration` on the second declaration of one name. It reads nothing outside the module it judges -- no corpus walk, no import resolution, no type information -- so the class is decidable from one module's source, which is what makes it a wall rather than a ratchet (DESIGN section 5). Rung: R2, mechanically preventable. The R4 climb is a keyed declaration roster at ingestion that cannot HOLD two entries for one name, and that is the row's next-rung trigger. THE EVIDENCE, and where it does NOT live. The first cut of this change put the RED in `v1.compiler.compiler_tests_rust`. That carrier is DEAD: its output is `#[cfg(test)] mod compiler_tests;` inside the v1-compiler crate, while the only test package that runs is the separate v1-compiler-tests, so cfg(test) is never set for it and the block is not compiled -- a mechanism `src/v1/05_emit_rust.dag` `checkpoint_table_bypasses_identity_note` already records a prior lane discovering the same way. It was reverted, and the evidence is authored where an equivalent witness demonstrably executes: dag/test/claim/duplicate_declaration_wall_witness_test.dag, `SubstrateInputsOnly`, driving the real v1 compile over inline fixtures through `compile_dag_rust_emit_check`, following `checkpoint_identity_keying_witness_test.dag`. Two REDs (fn/fn and data/fn) each paired with a control that differs from it by exactly the duplicated declaration and nothing else -- `compile_dag_rust_emit_check` answers false for ANY hard diagnostic, so the discrimination is carried by the PAIR, not by either row alone. All four measured `true` on the post-wall binary (sha256 1659e35605...), and per DESIGN 4b(4) the controls stay enrolled: they are the executing evidence that the rung is real. THE BOUND THAT MATTERS MOST IS NOT THE COMPILER'S, and it is written into both the witness and the gap-analysis row: where two definitions of one name are semantically EQUIVALENT, no behavioural witness can discriminate them whichever wins. Green-by-execution proves BEHAVIOUR and is structurally blind to duplicate AUTHORSHIP -- which this repository leans on everywhere, and which is why the live specimens above passed every witness over them. Also here: the DESIGN 4b row in docs/plans/compiler-guarantee-recovery-gap-analysis.md (invalid state, harm, distinguishing facts vs the cross-module last-import-wins row, rung, ceiling with reason, next trigger); a prose correction on dag/test/claim/duplicate_definition_binding_probe.dag, which asserted this refusal before it existed and is still `DeclinedLiveTree`, so what flipped is its SUBJECT and not its reach; and the fourth-lane receipt in `v1.std.core` `compiler_diagnostic_seed_projection_note`, which its own text obliges whenever the diagnostic coproduct grows -- cli_run.rs fn census FLAT at 895 on both sides, 2 added / 0 removed, 0 added lines declaring a fn. v1 SEED PURPOSE, since the change touches the seed: the wall is a floor repair on the name-resolution path the v2 self-host program compiles through, and the two repaired specimens are corpus modules that self-host must emit correctly. Nothing here grows the seed's capability -- the two cli_run.rs lines are the mechanical consequence of the coproduct gaining a member. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…n/main moves under other merges, so the named command reported a diff nobody authored (review 56644)
The receipt in `v1.std.core` `compiler_diagnostic_seed_projection_note` names three
commands and requires that each figure be re-derivable from them. All three were keyed
to `origin/main`. THAT REF MOVES. Measured on this branch, hours apart, with no edit to
the change being certified:
git diff --numstat origin/main -- src/v1/stage0/src/cli_run.rs
when authored: 2 added / 0 removed
at review: 6 added / 64 removed
The 64 removals are MAIN's work, not this branch's. A diff has two sides and only one of
them is this branch, so a receipt keyed to the moving side reports a figure that changes
without anyone touching the diff it describes -- which is exactly the rot this row exists
to make visible, arriving through the REF rather than through the NUMBER. That is why it
survived three prior lanes: each author re-measured honestly and the command was already
wrong.
REPAIR: every figure is now measured against `$(git merge-base origin/main HEAD)`, this
branch's own fork point, which does not move; and the base commit is NAMED (ddb7f53)
so the reading stays reproducible after a later merge. Re-measured against it -- fn
census FLAT at 895 on both sides, 2 added / 0 removed, 0 added lines declaring a fn.
THE EARLIER LANES' FIGURES ARE NOT RE-BASED OR AMENDED. They were correct against the
main they named at the time, and rewriting them would destroy the evidence that a receipt
keyed to a moving ref decays -- which is the finding. What changes is the command the
NEXT lane runs.
v1_std_core.rs is the regenerated mirror of the edited note; required-regen reported it
as the only drifting surface and it is installed from the candidate tree.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Closing as contained by #9452, which merged at 12:56:46 as Verified per-file against
The containment test that actually answers it, per file:
Every line this PR adds — the No v1-seed admission argument is owed. The seed change already merged with whatever argument #9452 carried; writing one now would be a second admission for one landed fact. The wall is doing its job right now. |
Auto-opened by session-dashboard for session
sleek-gull-113.Pushing to
session/sleek-gull-113advances this PR.Worker attestation
Before flipping this PR to ready for review, confirm each item:
npm test,cargo test) and the result.Closes #Ndirective.Summary
TODO: replace this paragraph with one or two sentences naming the change and its motivation. Reviewers read this first.
Test plan