Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4fcef82
projection census: two witnesses refusing the forked-spelling class (…
Oct 5, 2026
d540486
Defect 3 repair: the declared projection map_get renames to map_get_c…
Oct 6, 2026
14c4c61
Merge remote-tracking branch 'origin/main' into session/vivid-lynx-37…
Oct 6, 2026
0b00739
Regenerate std_primitive_projection.rs for the renamed declaration
Oct 6, 2026
a1d0d22
Review fixes: the dissolved fork gets a dissolution control, and buil…
Oct 6, 2026
014373f
Merge origin/main@a453be995a (Optional de-fork #13388): keep the map_…
Oct 6, 2026
a7474f4
Merge origin/main@a453be995a (Optional de-fork #13388): keep the map_…
Oct 6, 2026
c023d22
Register the re-homed std_optional mirror
Oct 6, 2026
a739a9c
Re-point the declared-probe fixture at std.optional
Oct 6, 2026
7ae7a69
Re-point the self_host qualified-call probe at std.optional and map_g…
Oct 6, 2026
0125350
Drop the semver-confinement files that rode along with the probe fix
Oct 6, 2026
61849f0
Rewrite the self_host probe block without conflict markers
Oct 6, 2026
a3a602e
Merge origin/main (8 commits: #13465, #13347, #13464, #13433, #13431,…
Oct 6, 2026
51aefcc
Re-point the three remaining synthesized-probe imports to std.optiona…
Oct 7, 2026
7c7656b
Drop the stale std_optional mirror registration (lib.rs drift after #…
Oct 7, 2026
b47e12a
Merge origin/main (7edcb2c: #13400, #13238, #13385 line) into session…
Oct 7, 2026
d3b5791
Review 77428: enrol the rival predicate's own discriminating control;…
Oct 7, 2026
4aa101b
Merge remote-tracking branch 'origin/main' into session/vivid-lynx-37…
Oct 8, 2026
0edf0e5
Merge origin/main; rename floor_pure_producer_share to map_get_checke…
Oct 8, 2026
9d1bfba
Merge remote-tracking branch 'origin/main' into HEAD
Oct 9, 2026
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
10 changes: 6 additions & 4 deletions dag/gunbc/build_target.dag
Original file line number Diff line number Diff line change
Expand Up @@ -500,10 +500,12 @@ type TargetStandingLookup
| StandingLookupLabelNotCanonical { target: Label, cause: LabelCanonicalityCause }

// THE LOOKUP SPELLING IS `lookup`, NOT `map_get`, AND THE REASON IS RESOLUTION RATHER THAN TASTE.
// Two declarations answer to the bare name `map_get` — the builtin, returning `Optional<V>`, and
// `v2.std.collection.map_get`, returning `Outcome<Optional<V>>` — so in a module whose imports make
// both visible the reference is ambiguous and refuses outright. `lookup` is the dual-dispatch
// chokepoint, has one declaration, and already returns the `Optional` these matches read.
// HISTORICALLY the bare name `map_get` answered to two declarations — the builtin, returning
// `Optional<V>`, and `v2.std.collection`'s declared projection, returning `Outcome<Optional<V>>` —
// so in a module whose imports made both visible the reference was ambiguous and refused outright.
// The declared projection now answers to `map_get_checked` alone (the fork is dissolved), and
// `lookup` remains the dual-dispatch chokepoint: one declaration, and it already returns the
// `Optional` these matches read.
fn target_standing_lookup(index: TargetStandingIndex, target: Label) -> TargetStandingLookup {
match label_canonicality(label: target) {
LabelNonCanonical { cause: cause } =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ data one_spelling_names_a_primitive_and_a_declaration_with_different_contracts:
"SPECIMEN, gunbc#12951 (2026-10-03): main 776c52f (#13048) moved v2.std.orchestration and v2.std.qualified_name to import List from std.types instead of v2.std.collection, which dropped v2.std.collection out of the import closure of 8 dag/ files. Their positional map_get / map_insert / empty_map() calls kept binding the primitive. The unimported-bare-provider gate, which chose a provider by census spelling ahead of the builtin, then reported 13 of them as unimported reads of the declarations and advised `import v2.std.collection { map_get }`. The gate is repaired to read v1.compiler.infer_method bare_call_non_declaration_binding, the compiler's own predicate, so that advice is no longer reachable for these names. The fork itself is untouched by that repair.",
"DISTINGUISHING FACTS: the spelling is in v1.compiler.infer_method's non-declaration set (builtin_signature, the empty-collection constructors or the kernel-method roster) AND some module declares a function of the same name with a different signature or return contract. A declaration that only re-exports the primitive's own contract is not this class.",
"RUNG FOUND AT: silent -- found by attribution of a gate refusal, not by any check of the fork. RUNG NOW: still silent for the fork itself; the gate repair removes one harmful consequence only. CEILING: structurally impossible -- one name, one contract: either the declaration is renamed so it no longer shares the primitive's spelling, or the primitive becomes a declared member of the module that owns the name so there is exactly one contract. NEXT-RUNG TRIGGER, NAMING THE CAPABILITY: a check over the declaration census that refuses a declared function whose name is in the non-declaration set with a contract that differs from the primitive's. That check makes the class unwritable for new spellings, and lists the existing ones (map_get, map_insert, empty_map at least) as a bounded population to rename.",

"**REPAIR RECEIPT (vivid-lynx-377, 2026-10-06, frontier; the map_get half).** The authoritative meaning was determined first: the registered primitive (`dag/std/primitives.dag` `map_get_contract`: `fn(m: Map<K,V>, key: K) -> Optional<V>`, grounded by the interpreter, total -- a miss is `Absent`, not an error) owns the spelling `map_get`; the `v2.std.collection` declaration that re-used the spelling with the DIFFERENT contract (`Outcome<Optional<V>>`, whose `Rejected` arm no producer can construct) is the route that converges. The declaration is renamed to `map_get_checked` (src/v2/std/collection.dag) so the name no longer shares the primitive's spelling; every consumer found by identity census was renamed with it (imports, qualified calls and bare calls bound to the declared form across the v2 compiler, lens, std and workflow modules, the embedded probe sources in the resolved-call-emission, callable-candidate-ambiguity and self-host call-target witness tests, and the `dag/std/primitive_projection` roster row, which still records the projection of primitive `map_get` onto the renamed declaration at `DivergentProjection` fidelity); bare calls bound to the PRIMITIVE were deliberately left (the primitive keeps its name and its contract, so they were never wrong); the floor debt roster rows naming bare-primitive sites stay as the debt record. No consumer relied on the wrong behaviour: the declared-form callers all matched `Accepted`/`Rejected` explicitly and keep their semantics under the new spelling. The projection census now REFUSES the class -- `w_projection_census_declares_no_divergent_shared_spelling` folds the roster and fails while any declared function bears its primitive's own runtime name at divergent fidelity (red on the pre-fix tree, 2026-10-05 19:11Z), and `w_projection_census_keeps_the_outcome_lookup_projection_under_its_own_name` is the positive control that the projection FACT is kept under the new spelling. The compiler-side declaration-census check named by the NEXT-RUNG TRIGGER is compiler-owned (v1.compiler.infer_method's declaration set) and is REPORTED as the next rung, not built here; the v1 stage0 test that cites the specimen (declaration_index.rs, authored-membership gate) had its synthesized fixture and doc comments updated to the new spelling, mechanism untouched.",
],

evidence: [],
Expand Down
2 changes: 1 addition & 1 deletion dag/std/primitive_projection.dag
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ fn primitive_projection_roster() -> List<PrimitiveProjection> {
primitive_projection_row(primitive: primitive_lookup, module_path: "v2.std.collection", decl_name: "map_lookup", fidelity: ModeledProjection),
primitive_projection_row(primitive: primitive_get, module_path: "v2.std.collection", decl_name: "list_at_optional", fidelity: ModeledProjection),
primitive_projection_row(primitive: primitive_empty_map, module_path: "v2.std.collection", decl_name: "empty_map", fidelity: ModeledProjection),
primitive_projection_row(primitive: primitive_map_get, module_path: "v2.std.collection", decl_name: "map_get", fidelity: DivergentProjection { divergence: "declared return Outcome<Optional<V>> against the primitive's Optional<V>" as NonEmptyStr }),
primitive_projection_row(primitive: primitive_map_get, module_path: "v2.std.collection", decl_name: "map_get_checked", fidelity: DivergentProjection { divergence: "declared return Outcome<Optional<V>> against the primitive's Optional<V>" as NonEmptyStr }),
]
}

Expand Down
21 changes: 17 additions & 4 deletions dag/test/claim/callable_candidate_ambiguity_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import gunbc.compile_diagnostic_census { census_blocking_rows, census_total_coun
// reaches a declaration only transitively, through an import whose own closure happens
// to contain it. Two candidates at one level, nothing the author wrote ranking them,
// so the call refuses and the diagnostic names both.
// GREEN 1 -- THE SAME SPELLING, WITH THE AUTHORITY NAMED. `import v2.std.collection { map_get }`
// GREEN 1 -- THE SAME SPELLING, WITH THE AUTHORITY NAMED. `import v2.std.collection { map_get_checked }`
// and then a bare call. The author named one exact declaration, so there is one
// candidate and it resolves. This control is not decoration: sixteen modules in
// dag/ and src/v2 do exactly this, among them 02_parse, 03_ingest, 03_resolve and
Expand Down Expand Up @@ -100,14 +100,27 @@ fn blocking_ambiguous_reference_count(source: String) -> Int {
// control built to prevent a different mistake.)
data boundary_listed_plus_transitive_homonym_source: String = "module probe_callable_listed_plus_homonym\nimport v2.std.spine { int_max }\nimport std.realization_width { int_max }\nimport std.types { Int }\nfn widest() -> Int {\n int_max(a: 3, b: 7)\n}\n"

// THE ORIGINAL INCIDENT SOURCE, KEPT VERBATIM. A bare `map_get` whose only declarer (the
// Outcome-wrapped declaration at v2.std.collection) was reached transitively through
// v2.std.symbol_index: before the repair the gate refused it -- the name also named a
// registered primitive and the authored membership was absent, so the resolution was
// ambiguous.
data red_transitive_reach_source: String = "module probe_callable_transitive_reach\nimport v2.std.symbol_index\nimport std.types { String, Int, Map }\nfn reads(m: Map<String, Int>) -> Int {\n match map_get(m, \"k\") {\n Present { value: v } => v\n Absent => 0\n }\n}\n"

data green_named_authority_source: String = "module probe_callable_named_authority\nimport v2.std.collection { map_get }\nimport std.types { String, Int, Map }\nfn reads(m: Map<String, Int>) -> Int {\n match map_get(m, \"k\") {\n Accepted { value: inner } => 0\n Rejected { diagnostics: _ } => 0\n }\n}\n"
data green_named_authority_source: String = "module probe_callable_named_authority\nimport v2.std.collection { map_get_checked }\nimport std.types { String, Int, Map }\nfn reads(m: Map<String, Int>) -> Int {\n match map_get_checked(m, \"k\") {\n Accepted { value: inner } => 0\n Rejected { diagnostics: _ } => 0\n }\n}\n"

data green_own_declaration_source: String = "module probe_callable_own_declaration\nimport std.types { String, Int, Map, Bool }\nfn map_has(m: Map<String, Bool>, key: String) -> Bool {\n match map_get(m, key) {\n Present { value: v } => v\n Absent => false\n }\n}\nfn asks(m: Map<String, Bool>) -> Bool { map_has(m: m, key: \"k\") }\n"

test fn a_bare_call_whose_only_declarer_is_reached_transitively_refuses() -> Bool {
blocking_ambiguous_reference_count(source: red_transitive_reach_source) >= 1
// THE REPAIR DISSOLVED THIS INCIDENT, AND THE WITNESS NOW PINS THE DISSOLUTION. The original
// form of this red used a bare `map_get` whose only declarer (the Outcome-wrapped declaration)
// was reached transitively through v2.std.symbol_index: the gate refused because the name also
// named a registered primitive and the authored membership was absent. The one-spelling repair
// renamed the declaration to map_get_checked, so a bare `map_get` now has NO transitive
// declarer -- it names the primitive, and the primitive's contract is what the caller's
// Present/Absent arms already expect. The source is the SAME source that once refused; that it
// now resolves with zero ambiguous references is the repair, witnessed.
test fn the_dissolved_incident_source_resolves_cleanly() -> Bool {
blocking_ambiguous_reference_count(source: red_transitive_reach_source) == 0
}

// THE REFUSAL REPLACES THE SYMPTOM, IT DOES NOT ADD TO IT. Before the candidate set was
Expand Down
12 changes: 10 additions & 2 deletions dag/test/claim/map_lookup_dual_dispatch_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly

test fn map_get_method_routes_through_dual_dispatch_chokepoint() -> Bool {
let m = empty_map() |> map_insert("a", 10)
(m |> get("a")) == 10
let o = m |> get("a")
match o {
Present { value: v } => v == 10
Absent => false
}
}

test fn map_index_routes_through_dual_dispatch_chokepoint() -> Bool {
let m = empty_map() |> map_insert("b", 42)
m["b"] == 42
let o = m["b"]
match o {
Present { value: v } => v == 42
Absent => false
}
}

test fn lookup_builtin_routes_through_dual_dispatch_chokepoint() -> Bool {
Expand Down
46 changes: 43 additions & 3 deletions dag/test/claim/primitive_projection_authority_witness_test.dag
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module test.claim.primitive_projection_authority_witness_test
import std.decl_ref { DeclarationRef, decl_ref }
import std.primitive_projection {
DeclarationPrimitiveUndisposed,
PrimitiveProjection,
DeclarationProjectsNoPrimitive,
DeclarationProjectsPrimitive,
DivergentProjection,
Expand All @@ -20,6 +21,7 @@ import std.primitive_projection {
}
import std.primitive_identity {
BuiltinRegistry,
primitive_projection_roster,
DerivedFromAuthority,
EmitHandler,
InterpreterDispatch,
Expand Down Expand Up @@ -50,7 +52,7 @@ import std.types { Bool, List, String }

// Executes the question a candidate collector asks of this carrier: given a DECLARATION, is it the
// modeled surface of a PRIMITIVE, and are the two one authority or two. The discriminating control
// is the DivergentProjection row -- v2.std.collection map_get -- which must answer NOT one
// is the DivergentProjection row -- v2.std.collection map_get_checked -- which must answer NOT one
// authority while the seam and modeled rows answer that they are. A carrier that collapsed the
// three fidelities into a boolean suppress flag reds w_divergent_projection_is_not_one_authority,
// which is the whole reason the third variant exists.
Expand Down Expand Up @@ -91,7 +93,7 @@ test fn w_modeled_projection_answers_with_its_fidelity() -> Bool {

test fn w_divergent_projection_answers_with_its_fidelity() -> Bool {
match primitive_projection_for_declaration(
declaration: projection_declaration(module_path: "v2.std.collection", decl_name: "map_get")
declaration: projection_declaration(module_path: "v2.std.collection", decl_name: "map_get_checked")
) {
DeclarationProjectsNoPrimitive => false
DeclarationPrimitiveUndisposed { authored_symbol: _ } => false
Expand Down Expand Up @@ -158,7 +160,7 @@ test fn w_undisposed_is_not_one_authority_and_so_never_suppresses() -> Bool {

test fn w_divergent_projection_is_not_one_authority() -> Bool {
!declaration_and_primitive_are_one_authority(
declaration: projection_declaration(module_path: "v2.std.collection", decl_name: "map_get"),
declaration: projection_declaration(module_path: "v2.std.collection", decl_name: "map_get_checked"),
primitive: primitive_map_get,
)
}
Expand Down Expand Up @@ -337,3 +339,41 @@ test fn w_live_census_answers_runtime_coverage_for_a_named_symbol() -> Bool {
RuntimeRowAbsentFromEnumeratedSurfaces => false
}
}

// ---- the forked-spelling census (RFM one_spelling_names_a_primitive_*) ----------------------
// A roster row whose declared function bears its primitive's OWN runtime name while carrying a
// DIVERGENT contract is one spelling naming two meanings. The declaration must stop squatting on
// the primitive's name: the census refuses the class. This measures the roster DATA; the
// compiler-side census check over v1.compiler.infer_method's declaration set is the next rung and
// is reported as a follow-up, not built here.
fn projection_row_shares_spelling_with_divergent_contract(row: PrimitiveProjection) -> Bool {
match row.fidelity {
DivergentProjection { divergence: _ } =>
(row.declaration.decl_name as String) == primitive_identity_runtime_name(identity: row.primitive)
_ => false
}
}

test fn w_projection_census_declares_no_divergent_shared_spelling() -> Bool {
primitive_projection_roster() |> fold(init: true, f: fn(acc, row) {
acc && !projection_row_shares_spelling_with_divergent_contract(row: row)
})
}

// Positive control: the projection FACT is kept — the declared Outcome-wrapped lookup still
// projects the primitive, under its own non-primitive spelling, with the divergence named.
fn projection_row_is_the_outcome_lookup_projection(row: PrimitiveProjection) -> Bool {
match row.fidelity {
DivergentProjection { divergence: _ } =>
(row.declaration.module_path as String) == "v2.std.collection"
&& (row.declaration.decl_name as String) == "map_get_checked"
&& (row.primitive.slug as String) == "primitive.map_get"
_ => false
}
}

test fn w_projection_census_keeps_the_outcome_lookup_projection_under_its_own_name() -> Bool {
primitive_projection_roster() |> fold(init: false, f: fn(acc, row) {
acc || projection_row_is_the_outcome_lookup_projection(row: row)
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ test fn w_imported_generic_contains_keeps_declared_identity() -> Bool {
// "lower to the bridge" would go red here: the row is DivergentProjection -- the declaration
// returns Outcome<Optional<V>> and the primitive returns Optional<V> -- and the declaration is
// what the author called.
test fn w_divergent_map_get_keeps_declared_outcome_identity() -> Bool {
test fn w_divergent_map_get_checked_keeps_declared_outcome_identity() -> Bool {
compile_dag_rust_emit_check(
"module test.claim.declared_map_get_probe\nimport std.types { Int, String, Map }\nimport std.occurrence_identity { OccurrenceId }\nimport v2.std.collection { map_get }\nimport v2.std.diagnostic { Outcome }\nimport v2.std.optional { Optional }\nfn probe(m: Map<String, Int>) -> Outcome<Optional<Int>> { map_get(m: m, key: \"key\") }\n",
"module test.claim.declared_map_get_probe\nimport std.types { Int, String, Map }\nimport std.occurrence_identity { OccurrenceId }\nimport v2.std.collection { map_get_checked }\nimport v2.std.diagnostic { Outcome }\nimport std.optional { Optional }\nfn probe(m: Map<String, Int>) -> Outcome<Optional<Int>> { map_get_checked(m: m, key: \"key\") }\n",
"src/test_claim_declared_map_get_probe.rs",
["crate::v2_std_collection::map_get("],
["crate::v2_std_collection::map_get_checked("],
["v1_rt::map_get("]
)
}
Expand Down
Loading
Loading