From 4fcef82c0990833073bf7e81e67aa0ca5a3dc4de Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Mon, 5 Oct 2026 19:30:32 +0000 Subject: [PATCH 01/14] projection census: two witnesses refusing the forked-spelling class (red on main, 2026-10-05 19:11Z) --- ...tive_projection_authority_witness_test.dag | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/dag/test/claim/primitive_projection_authority_witness_test.dag b/dag/test/claim/primitive_projection_authority_witness_test.dag index 2f4723f6c6b..a0919fe1c3f 100644 --- a/dag/test/claim/primitive_projection_authority_witness_test.dag +++ b/dag/test/claim/primitive_projection_authority_witness_test.dag @@ -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, @@ -20,6 +21,7 @@ import std.primitive_projection { } import std.primitive_identity { BuiltinRegistry, + primitive_projection_roster, DerivedFromAuthority, EmitHandler, InterpreterDispatch, @@ -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) + }) +} From d540486b14d9c1283cbab6dd3a7469ccb8c42070 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 04:57:56 +0000 Subject: [PATCH 02/14] Defect 3 repair: the declared projection map_get renames to map_get_checked The spelling map_get named two contracts: the v2.std.collection declared projection (Outcome>) and the interpreter primitive (Optional). One spelling, two meanings - RFM one_spelling_names_a_primitive_and_a_declaration_with_different_contracts. The authoritative meaning is the primitive's (interpreter:14297 registry, outcome_accepted(map_lookup(...))). The declared projection is renamed to map_get_checked at its owner (src/v2/std/collection.dag) and every consumer follows: imports, qualified calls, the primitive-projection row (decl_name only; the primitive slug primitive.map_get keeps its spelling), the emitted probe strings, and the synthesized declaration_index.rs test fixture. The v1 mechanism never keyed on the declared spelling. Reds: w_projection_census_declares_no_divergent_shared_spelling (fails while any row's decl_name equals its primitive's runtime name at DivergentProjection fidelity); positive control keeps the outcome-lookup projection under its own name. RFM receipt updated, row kept. --- dag/gunbc/build_target.dag | 6 +++--- ...a_declaration_with_different_contracts.dag | 2 ++ dag/std/primitive_projection.dag | 2 +- ...lable_candidate_ambiguity_witness_test.dag | 21 +++++++++++++++---- ...tive_projection_authority_witness_test.dag | 6 +++--- ...ed_call_emission_identity_witness_test.dag | 6 +++--- ...d_call_target_realization_witness_test.dag | 10 ++++----- src/v1/stage0/src/declaration_index.rs | 21 ++++++++++--------- src/v2/compiler/02_parse.dag | 10 ++++----- src/v2/compiler/03_ingest.dag | 6 +++--- src/v2/compiler/03_name_resolve.dag | 4 ++-- src/v2/compiler/03_resolve.dag | 6 +++--- src/v2/compiler/emit_produced.dag | 2 +- src/v2/compiler/emit_semantic_decl.dag | 4 ++-- src/v2/compiler/symbol_index_fill.dag | 2 +- src/v2/compiler/target_serialize.dag | 4 ++-- src/v2/extdeps/runtimes/v2_effect_io_pure.dag | 4 ++-- src/v2/lens/affected_set.dag | 4 ++-- .../lens/manufactured_dependency_census.dag | 2 +- src/v2/lens/module_graph.dag | 4 ++-- src/v2/lens/unit_modeling.dag | 4 ++-- src/v2/std/collection.dag | 4 ++-- src/v2/std/compilers/cli_surface.dag | 4 ++-- src/v2/std/compilers/compilation_unit.dag | 12 +++++------ src/v2/std/compilers/target_model.dag | 12 +++++------ src/v2/std/generic_instantiation.dag | 2 +- src/v2/std/grounding.dag | 4 ++-- src/v2/std/symbol_index.dag | 14 ++++++------- .../emitted_closure_crate_partition_test.dag | 4 ++-- ...parse_table_memo_governed_witness_test.dag | 2 +- .../manual/bind_demand_driven_eval_test.dag | 4 ++-- .../branch_lazy_arm_eval_acceptance_test.dag | 4 ++-- .../manual/value_null_split_witness_test.dag | 4 ++-- .../rust_crate_partition_witness_test.dag | 4 ++-- .../emitted_closure_crate_partition.dag | 8 +++---- src/v2/workflow/emitted_crate_workspace.dag | 8 +++---- .../workflow/floor_grandfathered_roster.dag | 2 +- src/v2/workflow/rust_crate_partition.dag | 12 +++++------ 38 files changed, 125 insertions(+), 109 deletions(-) diff --git a/dag/gunbc/build_target.dag b/dag/gunbc/build_target.dag index 3e827766f0e..31a775a2064 100644 --- a/dag/gunbc/build_target.dag +++ b/dag/gunbc/build_target.dag @@ -499,9 +499,9 @@ type TargetStandingLookup | StandingNotObserved { target: Label } | 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`, and -// `v2.std.collection.map_get`, returning `Outcome>` — so in a module whose imports make +// THE LOOKUP SPELLING IS `lookup`, NOT `map_get_checked`, AND THE REASON IS RESOLUTION RATHER THAN TASTE. +// Two declarations answer to the bare name `map_get_checked` — the builtin, returning `Optional`, and +// `v2.std.collection.map_get_checked`, returning `Outcome>` — 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. fn target_standing_lookup(index: TargetStandingIndex, target: Label) -> TargetStandingLookup { diff --git a/dag/gunbc/recurring_failure_mode/one_spelling_names_a_primitive_and_a_declaration_with_different_contracts.dag b/dag/gunbc/recurring_failure_mode/one_spelling_names_a_primitive_and_a_declaration_with_different_contracts.dag index 171ecf4a74d..c6bded7c83e 100644 --- a/dag/gunbc/recurring_failure_mode/one_spelling_names_a_primitive_and_a_declaration_with_different_contracts.dag +++ b/dag/gunbc/recurring_failure_mode/one_spelling_names_a_primitive_and_a_declaration_with_different_contracts.dag @@ -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, key: K) -> Optional`, 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>`, 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: [], diff --git a/dag/std/primitive_projection.dag b/dag/std/primitive_projection.dag index 53190ac7d2b..b50c274ff7e 100644 --- a/dag/std/primitive_projection.dag +++ b/dag/std/primitive_projection.dag @@ -133,7 +133,7 @@ fn primitive_projection_roster() -> List { 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> against the primitive's Optional" 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> against the primitive's Optional" as NonEmptyStr }), ] } diff --git a/dag/test/claim/callable_candidate_ambiguity_witness_test.dag b/dag/test/claim/callable_candidate_ambiguity_witness_test.dag index f37a35cd07c..12bb642e887 100644 --- a/dag/test/claim/callable_candidate_ambiguity_witness_test.dag +++ b/dag/test/claim/callable_candidate_ambiguity_witness_test.dag @@ -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 @@ -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) -> 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) -> 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) -> 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, key: String) -> Bool {\n match map_get(m, key) {\n Present { value: v } => v\n Absent => false\n }\n}\nfn asks(m: Map) -> 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 diff --git a/dag/test/claim/primitive_projection_authority_witness_test.dag b/dag/test/claim/primitive_projection_authority_witness_test.dag index a0919fe1c3f..dbd910a9deb 100644 --- a/dag/test/claim/primitive_projection_authority_witness_test.dag +++ b/dag/test/claim/primitive_projection_authority_witness_test.dag @@ -52,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. @@ -93,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 @@ -160,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, ) } diff --git a/dag/test/claim/resolved_call_emission_identity_witness_test.dag b/dag/test/claim/resolved_call_emission_identity_witness_test.dag index a795d682574..6283ba3568b 100644 --- a/dag/test/claim/resolved_call_emission_identity_witness_test.dag +++ b/dag/test/claim/resolved_call_emission_identity_witness_test.dag @@ -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> and the primitive returns Optional -- 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) -> Outcome> { 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 v2.std.optional { Optional }\nfn probe(m: Map) -> Outcome> { 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("] ) } diff --git a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag index ac54e27d924..51798c87064 100644 --- a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag +++ b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag @@ -265,23 +265,23 @@ test fn w_clone_bound_forwards_transitively_over_two_call_hops() -> Bool { // restricted pool (2973 modules against the corpus's 4261), and a qualified spelling alone does not // put the target module in it -- so without the import this row FAILED while the repair was green, // which is how it was found. Measured both ways: the same probe emitted against the real corpus -// produces `crate::v2_std_collection::map_get(m.clone(), "key".to_string())` exactly as asserted. +// produces `crate::v2_std_collection::map_get_checked(m.clone(), "key".to_string())` exactly as asserted. // The import restores module presence; it does not answer the call, because decl_name is taken from // the authored spelling at the CALL SITE regardless of what is imported -- which is why the // negative assertion below still discriminates, and why falsifier 2 (restore the dotted spelling) // must red this row. // // CLASS C, THE DISCRIMINATING RED. A qualified call carried the whole dotted path as its -// declaration name, so emission produced `crate::v2_std_collection::v2.std.collection.map_get(..)` +// declaration name, so emission produced `crate::v2_std_collection::v2.std.collection.map_get_checked(..)` // -- the module prefix correct and the identifier a dotted path Rust reads as field access on an // undefined value `v2`. map_get is the specimen because it is also DivergentProjection, so this // row proves the qualified path reaches the DECLARATION and not the bridge. test fn w_qualified_call_emits_only_the_declaration_last_segment() -> Bool { compile_dag_rust_emit_check( - "module test.claim.qualified_call_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) -> Outcome> { v2.std.collection.map_get(m: m, key: \"key\") }\n", + "module test.claim.qualified_call_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 v2.std.optional { Optional }\nfn probe(m: Map) -> Outcome> { v2.std.collection.map_get_checked(m: m, key: \"key\") }\n", "src/test_claim_qualified_call_probe.rs", - ["crate::v2_std_collection::map_get("], - ["::v2.std.collection", "v2.std.collection.map_get("] + ["crate::v2_std_collection::map_get_checked("], + ["::v2.std.collection", "v2.std.collection.map_get_checked("] ) } diff --git a/src/v1/stage0/src/declaration_index.rs b/src/v1/stage0/src/declaration_index.rs index 144f733d1f0..5668e7e2fc7 100644 --- a/src/v1/stage0/src/declaration_index.rs +++ b/src/v1/stage0/src/declaration_index.rs @@ -3519,13 +3519,14 @@ mod import_binding_authority_tests { /// The declaration must sit in a PARENT env: `callable_lookup_over_candidates` checks /// `func_env.local` first and returns immediately on a hit, so a local declaration never - /// reaches the authored-membership branch. `v2.std.collection` / `map_get` is not an arbitrary + /// reaches the authored-membership branch. `v2.std.collection` / `map_get_checked` is not an arbitrary /// choice -- it is the specimen carrying `DivergentProjection` fidelity, which is the condition /// `declared_candidate_rivals_the_builtin` requires. - fn parent_env_declaring_map_get() -> Rc { + fn parent_env_declaring_map_get_checked() -> Rc + { use crate::v1_compiler_infer_sigs::{ResolvedFormals, ResolvedFuncEnv, ResolvedFuncSig}; let sig = Rc::new(ResolvedFuncSig { - name: "map_get".to_string(), + name: "map_get_checked".to_string(), params: crate::v1_std_core::empty_node_list(), // This synthetic declaration deliberately has no parameters. Its empty formal // population is kernel-grounded, not awaiting a module-context resolution pass. @@ -3540,7 +3541,7 @@ mod import_binding_authority_tests { name: "v2.std.collection".to_string(), local: Rc::new(crate::v1_rt::map_insert( crate::v1_rt::empty_map(), - "map_get".to_string(), + "map_get_checked".to_string(), sig, )), parents: Rc::new(im::Vector::new()), @@ -3565,7 +3566,7 @@ mod import_binding_authority_tests { /// That is an OBSERVATION-BOUNDARY defect, not a bad fixture spelling. /// /// AND IT DOES NOT MEAN THE POLICY IS DEAD. That convenient reading is refuted by a specimen in - /// the tree: `map_get` is declared at `v2.std.collection` with `DivergentProjection` fidelity in + /// the tree: `map_get_checked` is declared at `v2.std.collection` with `DivergentProjection` fidelity in /// `std.primitive_projection`, which is exactly the condition /// `declared_candidate_rivals_the_builtin` tests. So the collision is real, reachable from /// authored source, and already witnessed by `callable_candidate_ambiguity_witness_test`. @@ -3579,17 +3580,17 @@ mod import_binding_authority_tests { use crate::v1_compiler_infer_lookup::callable_lookup_over_candidates; use crate::v1_compiler_infer_sigs::{CallableIdentity, FuncSigLookup}; - let env = parent_env_declaring_map_get(); + let env = parent_env_declaring_map_get_checked(); let named = callable_lookup_over_candidates( env.clone(), - type_env_with_authored(&["map_get"]), - "map_get".to_string(), + type_env_with_authored(&["map_get_checked"]), + "map_get_checked".to_string(), ); let omitted = callable_lookup_over_candidates( env, type_env_with_authored(&["cut_unrelated_marker"]), - "map_get".to_string(), + "map_get_checked".to_string(), ); // THE DIRECTION IS ASSERTED, NOT MERE INEQUALITY. A control demanding only that the arms @@ -3598,7 +3599,7 @@ mod import_binding_authority_tests { match &*named { FuncSigLookup::FuncSigResolved { declared, .. } => { assert_eq!(declared.owner_module_path, "v2.std.collection"); - assert_eq!(declared.decl_name, "map_get"); + assert_eq!(declared.decl_name, "map_get_checked"); } other => panic!( "naming the callable must suppress the builtin co-candidate and resolve to the \ diff --git a/src/v2/compiler/02_parse.dag b/src/v2/compiler/02_parse.dag index 686461bb4e0..c8b84012997 100644 --- a/src/v2/compiler/02_parse.dag +++ b/src/v2/compiler/02_parse.dag @@ -84,7 +84,7 @@ import v2.std.collection { Map, empty_map, list_at_optional, - map_get, + map_get_checked, map_insert, map_lookup } @@ -637,7 +637,7 @@ fn parse_table_memo_insert_refused( value: ParseMemoEntry ) -> Bool { let after = parse_table_insert(table: table, key: key, value: value) - match v2.std.collection.map_get(m: after.entries, key: key) { + match v2.std.collection.map_get_checked(m: after.entries, key: key) { Accepted { value: Absent } => true Accepted { value: Present { value: _ } } => false Rejected { diagnostics: _ } => false @@ -1651,7 +1651,7 @@ fn first_list_intersect(left: List, right: List) -> List>, name: Symbol) -> List { - match v2.std.collection.map_get(m: rows, key: name) { + match v2.std.collection.map_get_checked(m: rows, key: name) { Accepted { value: Present { value: terminals }, diagnostics: _ } => terminals Accepted { value: Absent, diagnostics: _ } => grammar_empty_terminal_list() Rejected { diagnostics: _ } => grammar_empty_terminal_list() @@ -3565,7 +3565,7 @@ fn parse_table_token_dispatch(table: ParseTable, production: Symbol) -> Bool { // When the key is absent the Choice plan is ordered backtrack, the pre-cutover // interpreter. Analyzed tables always resolve Present here. fn parse_table_prepared_expr(table: ParseTable, production: GrammarProduction) -> PreparedGrammarExpr { - match v2.std.collection.map_get(m: table.prepared_exprs, key: production.name) { + match v2.std.collection.map_get_checked(m: table.prepared_exprs, key: production.name) { Accepted { value: Present { value: prepared }, diagnostics: _ } => prepared Accepted { value: Absent, diagnostics: _ } => prepare_grammar_expr( @@ -3892,7 +3892,7 @@ fn left_corner_direct_rows(root: GrammarRoot, nullable_set: List) -> Map } fn left_corner_row(rows: Map>, name: Symbol) -> List { - match v2.std.collection.map_get(m: rows, key: name) { + match v2.std.collection.map_get_checked(m: rows, key: name) { Accepted { value: Present { value: reached }, diagnostics: _ } => reached Accepted { value: Absent, diagnostics: _ } => std.algebra.Empty Rejected { diagnostics: _ } => std.algebra.Empty diff --git a/src/v2/compiler/03_ingest.dag b/src/v2/compiler/03_ingest.dag index f470548e8a5..1b7c0c91aaa 100644 --- a/src/v2/compiler/03_ingest.dag +++ b/src/v2/compiler/03_ingest.dag @@ -10,7 +10,7 @@ import v2.std.collection { Map, Present, empty_map, - map_get, + map_get_checked, map_insert } import v2.std.grammar { @@ -69,7 +69,7 @@ fn parse_atom_frontier_class_direct( token_classes: Map ) -> Outcome { bind_outcome( - o: map_get(token_classes, atom_identity), + o: map_get_checked(token_classes, atom_identity), f: fn(direct) { match direct { Present { value: token_class } => outcome_accepted(value: token_class) @@ -86,7 +86,7 @@ fn parse_atom_frontier_class( token_classes: Map ) -> Outcome { bind_outcome( - o: map_get(binding_to_class, atom_identity), + o: map_get_checked(binding_to_class, atom_identity), f: fn(bound) { match bound { Present { value: token_class } => outcome_accepted(value: token_class) diff --git a/src/v2/compiler/03_name_resolve.dag b/src/v2/compiler/03_name_resolve.dag index a26ddb329cb..eeeeebb93b9 100644 --- a/src/v2/compiler/03_name_resolve.dag +++ b/src/v2/compiler/03_name_resolve.dag @@ -38,7 +38,7 @@ import v2.compiler.namespace_graft { import v2.compiler.parse { parse_tree_projection_edge } import std.algebra { Cons, Empty, FreeMonoid, list_snoc_item } import v2.std.algebra { fold_list } -import v2.std.collection { Absent, Map, Present, PointwisePower, empty_map, map_get, map_lookup, map_insert, optional_absent, optional_present } +import v2.std.collection { Absent, Map, Present, PointwisePower, empty_map, map_get_checked, map_lookup, map_insert, optional_absent, optional_present } import v2.std.optional { Optional } import v2.std.diagnostic { Accepted, @@ -288,7 +288,7 @@ fn admit_export_symbol( AdmissionRejected { diagnostics: d } AdmissionAccepted { bindings: b, origins: os } => - match v2.std.collection.map_get(os, sym) { + match v2.std.collection.map_get_checked(os, sym) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: _ } => AdmissionRejected { diff --git a/src/v2/compiler/03_resolve.dag b/src/v2/compiler/03_resolve.dag index 7841fc92c0f..680267efdb3 100644 --- a/src/v2/compiler/03_resolve.dag +++ b/src/v2/compiler/03_resolve.dag @@ -43,7 +43,7 @@ import v2.std.collection { PointwisePower, empty_map, list_at_optional, - map_get, + map_get_checked, map_insert, map_lookup } @@ -1071,7 +1071,7 @@ type ScopeBinding fn lookup_chain(s: Scope, name: Symbol) -> Outcome { match s { ScopeFrame { locals: m, outer: o, kind: kind } => - match v2.std.collection.map_get(m, name) { + match v2.std.collection.map_get_checked(m, name) { Accepted { value: opt, diagnostics: d_here } => match opt { Present { value: v } => Accepted { value: BoundInFrame { canonical: v, kind: kind }, diagnostics: d_here } @@ -1091,7 +1091,7 @@ fn lookup_chain(s: Scope, name: Symbol) -> Outcome { Rejected { diagnostics: ds } => Rejected { diagnostics: ds } } ScopeRoot { module: mod } => - match v2.std.collection.map_get(mod.bindings, name) { + match v2.std.collection.map_get_checked(mod.bindings, name) { Accepted { value: opt, diagnostics: d } => match opt { Present { value: v } => Accepted { value: BoundAtRoot { canonical: v }, diagnostics: d } Absent => Accepted { value: ScopeUnbound, diagnostics: d } diff --git a/src/v2/compiler/emit_produced.dag b/src/v2/compiler/emit_produced.dag index 6fac2b49fcf..5dbac4b2a0c 100644 --- a/src/v2/compiler/emit_produced.dag +++ b/src/v2/compiler/emit_produced.dag @@ -20,7 +20,7 @@ import v2.std.compilers.target_model { FixedToken } import extdeps.communication.medium { Medium } -import v2.std.collection { Absent, Present, list_at_optional, map_get } +import v2.std.collection { Absent, Present, list_at_optional, map_get_checked } import v2.std.algebra { contains, fold_list, FreeMonoid } import std.algebra { Cons, Empty, list_append, list_snoc_item } import v2.std.diagnostic { diff --git a/src/v2/compiler/emit_semantic_decl.dag b/src/v2/compiler/emit_semantic_decl.dag index f3a26a83143..7d8df1f88ce 100644 --- a/src/v2/compiler/emit_semantic_decl.dag +++ b/src/v2/compiler/emit_semantic_decl.dag @@ -11,7 +11,7 @@ import v2.std.compilers.semantic_decl_emission { target_semantic_enum_surface_from_coproduct, target_semantic_struct_surface_from_record } -import v2.std.collection { Absent, Map, Present, empty_map, map_get } +import v2.std.collection { Absent, Map, Present, empty_map, map_get_checked } import v2.std.qualified_name { declaration_reference_path_optional } import v2.std.compilers.target_model { TargetModel, @@ -214,7 +214,7 @@ fn produced_type_binding_over(target: TargetModel, spellings: Map outcome_accepted(value: target_atom_type_spelling(row: row)) Rejected { diagnostics: _ } => - match map_get(spellings, id) { + match map_get_checked(spellings, id) { Accepted { value: Present { value: _ }, diagnostics: _ } => outcome_accepted(value: id) _ => outcome_rejected(d: emit_type_reference_unrealized_diagnostic(node: type_node)) } diff --git a/src/v2/compiler/symbol_index_fill.dag b/src/v2/compiler/symbol_index_fill.dag index 4e64a596875..bce2afb4b99 100644 --- a/src/v2/compiler/symbol_index_fill.dag +++ b/src/v2/compiler/symbol_index_fill.dag @@ -292,7 +292,7 @@ fn symbol_index_fill_containment_node( } fn disj_variant_count_of(counts: Map, sym: Symbol) -> Int { - match v2.std.collection.map_get(counts, sym) { + match v2.std.collection.map_get_checked(counts, sym) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: n } => n Absent => 0 diff --git a/src/v2/compiler/target_serialize.dag b/src/v2/compiler/target_serialize.dag index 3feee6e68bd..54acd5d48db 100644 --- a/src/v2/compiler/target_serialize.dag +++ b/src/v2/compiler/target_serialize.dag @@ -139,7 +139,7 @@ import v2.std.compilers.target_model { } import v2.std.collection { list_at_optional, - map_get + map_get_checked } import v2.std.optional { Absent, @@ -877,7 +877,7 @@ fn serialize_relation_row_nested_bounded( unit: Symbol, tokens: List ) -> Outcome { - match map_get(target.binding_spellings, unit) { + match map_get_checked(target.binding_spellings, unit) { Accepted { value: Present { value: unit_spelling }, diagnostics: _ } => bind_outcome( o: serialize_relation_row_tokens_bounded(remaining: remaining, target: target, lex: lex, tokens: tokens), diff --git a/src/v2/extdeps/runtimes/v2_effect_io_pure.dag b/src/v2/extdeps/runtimes/v2_effect_io_pure.dag index a33056d75c6..a31f3441d67 100644 --- a/src/v2/extdeps/runtimes/v2_effect_io_pure.dag +++ b/src/v2/extdeps/runtimes/v2_effect_io_pure.dag @@ -9,7 +9,7 @@ import v2.std.collection { Present, empty_map, list_nth, - map_get, + map_get_checked, map_insert } import v2.std.diagnostic { @@ -202,7 +202,7 @@ fn effect_io_pure_store_lookup( locator: EffectIoResourceLocator ) -> Outcome { if effect_io_pure_backends_match(left: locator.backend, right: store.backend) { - match map_get(m: store.entries, key: locator.identity) { + match map_get_checked(m: store.entries, key: locator.identity) { Accepted { value: opt, diagnostics: d } => match opt { Present { value: payload } => diff --git a/src/v2/lens/affected_set.dag b/src/v2/lens/affected_set.dag index c6ad9e219f5..38272ddaaee 100644 --- a/src/v2/lens/affected_set.dag +++ b/src/v2/lens/affected_set.dag @@ -4,7 +4,7 @@ import std.occurrence_identity { OccurrenceSynthetic } import v2.lens.common.construction_justification { ConstructionJustification, WallAfterGrounding } import std.disposition { SingleAuthority } -import v2.std.collection { Absent, Map, Present, list_at_optional, map_get, map_insert } +import v2.std.collection { Absent, Map, Present, list_at_optional, map_get_checked, map_insert } import v2.std.algebra { TailAbsent, TailFound, contains, length, list_tail } import std.algebra { list_append, list_snoc_item } import v2.compiler.infer { InferredTree } @@ -590,7 +590,7 @@ fn mark_excluded(frontier: ReExecFrontier, key: ExclusionKey, proof: Propagation FailClosed { reason: e } => FailClosed { reason: e } ChangedSubgraphFrontier { boundary_exclusions: boundary_exclusions, decisions: decisions } => - match map_get(decisions, key) { + match map_get_checked(decisions, key) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: decision } => match decision { diff --git a/src/v2/lens/manufactured_dependency_census.dag b/src/v2/lens/manufactured_dependency_census.dag index b463f11fcfb..8cac8c4f185 100644 --- a/src/v2/lens/manufactured_dependency_census.dag +++ b/src/v2/lens/manufactured_dependency_census.dag @@ -104,7 +104,7 @@ fn import_targets_by_path(edges: List) -> Map(m: Map, key: K) -> Optional { - match v2.std.collection.map_get(m: m, key: key) { + match v2.std.collection.map_get_checked(m: m, key: key) { Accepted { value: v, diagnostics: _ } => v Rejected { diagnostics: _ } => Absent } diff --git a/src/v2/lens/unit_modeling.dag b/src/v2/lens/unit_modeling.dag index 5e04af5bf3f..e155a509381 100644 --- a/src/v2/lens/unit_modeling.dag +++ b/src/v2/lens/unit_modeling.dag @@ -60,7 +60,7 @@ fn unit_field_token_map() -> Map { } fn field_name_has_known_carrier(name: Symbol) -> Bool { - match v2.std.collection.map_get(m: unit_field_token_map(), key: name) { + match v2.std.collection.map_get_checked(m: unit_field_token_map(), key: name) { Accepted { value: Present { value: _ } } => true Accepted { value: _, diagnostics: _ } => false Rejected { diagnostics: _ } => false @@ -81,7 +81,7 @@ fn exemption_marker_set() -> Map { } fn name_is_exempt(name: Symbol) -> Bool { - match v2.std.collection.map_get(m: exemption_marker_set(), key: name) { + match v2.std.collection.map_get_checked(m: exemption_marker_set(), key: name) { Accepted { value: Present { value: _ } } => true Accepted { value: _, diagnostics: _ } => false Rejected { diagnostics: _ } => false diff --git a/src/v2/std/collection.dag b/src/v2/std/collection.dag index d928f148c4f..5c8bbe8c654 100644 --- a/src/v2/std/collection.dag +++ b/src/v2/std/collection.dag @@ -63,7 +63,7 @@ fn map_insert(m: Map, key: K, value: V) -> Map { // third state in which the map fails to say. So the total form is the primitive and the // Outcome-wrapped form below is a projection of it, not the other way round. // -// The direction matters at the consumer. A caller reaching for `map_get` must match a +// The direction matters at the consumer. A caller reaching for `map_get_checked` must match a // `Rejected` arm that no producer can construct, and the only arms available to it are the // caller's own domain answers — so the unreachable arm gets bound to whichever domain answer is // nearest, and a substrate failure would report as a domain fact. Exposing the total lookup @@ -85,7 +85,7 @@ fn map_contains_key(m: Map, key: K) -> Bool { } } -fn map_get(m: Map, key: K) -> Outcome> { +fn map_get_checked(m: Map, key: K) -> Outcome> { outcome_accepted(value: map_lookup(m: m, key: key)) } fn list_nth(xs: List, wanted: Int, absent: Diagnostic) -> Witness { diff --git a/src/v2/std/compilers/cli_surface.dag b/src/v2/std/compilers/cli_surface.dag index 875de3df389..d03da5ed022 100644 --- a/src/v2/std/compilers/cli_surface.dag +++ b/src/v2/std/compilers/cli_surface.dag @@ -12,7 +12,7 @@ import v2.std.compilers.target_model { LexRules, lex_rules_literal_for_class } -import v2.std.collection { map_get } +import v2.std.collection { map_get_checked } import v2.std.diagnostic { Accepted, Diagnostic, @@ -262,7 +262,7 @@ fn required_bound_spelling( binding_spellings: Map, binding: Symbol ) -> Outcome { - match map_get(binding_spellings, binding) { + match map_get_checked(binding_spellings, binding) { Rejected { diagnostics: ds } => Rejected { diagnostics: ds } Accepted { value: found, diagnostics: pending } => match found { diff --git a/src/v2/std/compilers/compilation_unit.dag b/src/v2/std/compilers/compilation_unit.dag index 01eda7ad075..f73ce8aadab 100644 --- a/src/v2/std/compilers/compilation_unit.dag +++ b/src/v2/std/compilers/compilation_unit.dag @@ -9,7 +9,7 @@ import std.disposition { SingleAuthority } import v2.lens.common.construction_justification { ConstructionJustification, WallNow } import v2.std.algebra { any, fold_list, length } import v2.std.collection { - map_get + map_get_checked } import v2.std.optional { Absent, @@ -210,7 +210,7 @@ fn module_unit_id_outcome( assignment: Map, module: ModuleId ) -> Outcome> { - match map_get(assignment, module) { + match map_get_checked(assignment, module) { Accepted { value: opt, diagnostics: _ } => outcome_accepted(value: opt) Rejected { diagnostics: d } => Rejected { diagnostics: d } } @@ -220,7 +220,7 @@ fn module_unit_id( assignment: Map, module: ModuleId ) -> Optional { - match map_get(assignment, module) { + match map_get_checked(assignment, module) { Accepted { value: opt, diagnostics: _ } => opt Rejected { diagnostics: _ } => Absent } @@ -341,7 +341,7 @@ fn module_export_declarations_outcome( module_dag: ModuleDag, module: ModuleId ) -> Outcome> { - match map_get(module_dag.exports, module) { + match map_get_checked(module_dag.exports, module) { Accepted { value: opt, diagnostics: _ } => outcome_accepted(value: match opt { Present { value: nodes } => nodes @@ -355,7 +355,7 @@ fn module_type_definition_rows_outcome( module_dag: ModuleDag, module: ModuleId ) -> Outcome> { - match map_get(module_dag.type_definitions, module) { + match map_get_checked(module_dag.type_definitions, module) { Accepted { value: opt, diagnostics: _ } => outcome_accepted(value: match opt { Present { value: rows } => rows @@ -373,7 +373,7 @@ fn module_type_definition_rows_outcome( // then discarded both values, so the closure below it re-established a fact its predecessor already // had (DESIGN section 6b). With the rows carried, no map lookup runs inside the closure at all: // the swallowing arm has no site to exist at rather than being refused at one, and the repeated -// map_get is gone with it. +// map_get_checked is gone with it. fn resolve_module_interface( module_dag: ModuleDag, module: ModuleId diff --git a/src/v2/std/compilers/target_model.dag b/src/v2/std/compilers/target_model.dag index 29b57afe7f0..bfac1abbb3e 100644 --- a/src/v2/std/compilers/target_model.dag +++ b/src/v2/std/compilers/target_model.dag @@ -38,7 +38,7 @@ import v2.std.collection { Map, empty_map, list_at_optional, - map_get, + map_get_checked, map_insert, map_lookup } @@ -1325,7 +1325,7 @@ fn bound_spelling_from_map( binding_spellings: Map, binding: Symbol ) -> Outcome { - match map_get(binding_spellings, binding) { + match map_get_checked(binding_spellings, binding) { Accepted { value: opt, diagnostics: pending } => match opt { Present { value: spelling } => Accepted { value: spelling, diagnostics: pending } Absent => @@ -1526,7 +1526,7 @@ fn fixed_token_spelling_from_model( bind_outcome( o: lex_rules_literal_for_class(rules: target.lex, token_class: token_class), f: fn(spelling) { - match map_get(target.token_class_emit_transforms, token_class) { + match map_get_checked(target.token_class_emit_transforms, token_class) { Accepted { value: Present { value: transform }, diagnostics: d } => bind_outcome( o: apply_emit_spelling_transform(transform: transform, token_class: token_class, spelling: spelling), @@ -1548,7 +1548,7 @@ fn bound_token_spelling_from_model( bind_outcome( o: target_binding_spelling_lookup(target: target, binding: binding), f: fn(spelling) { - match map_get(target.token_class_emit_transforms, token_class) { + match map_get_checked(target.token_class_emit_transforms, token_class) { Accepted { value: Present { value: transform }, diagnostics: d } => bind_outcome( o: apply_emit_spelling_transform(transform: transform, token_class: token_class, spelling: spelling), @@ -1563,7 +1563,7 @@ fn bound_token_spelling_from_model( } fn layout_or_atom_in(transforms: Map, token_class: Symbol, spelling: String) -> Outcome { - match map_get(transforms, token_class) { + match map_get_checked(transforms, token_class) { Accepted { value: Present { value: transform }, diagnostics: d } => match transform { EmitLineBreaks { before: b, after: a } => @@ -5454,7 +5454,7 @@ fn target_value_expr_effect_apply_callee( shape: TargetEffectApplyShape, expr: TargetValueExpression ) -> Outcome { - match map_get( + match map_get_checked( m: fold_list( xs: shape.callees, empty: empty_map(), diff --git a/src/v2/std/generic_instantiation.dag b/src/v2/std/generic_instantiation.dag index 5d18c0e0200..e0f192d3a0a 100644 --- a/src/v2/std/generic_instantiation.dag +++ b/src/v2/std/generic_instantiation.dag @@ -24,7 +24,7 @@ fn generic_substitution_bind_once( name: String, concrete: Node, ) -> Outcome { - match v2.std.collection.map_get(subst, name) { + match v2.std.collection.map_get_checked(subst, name) { Accepted { value: Absent, diagnostics: _ } => outcome_accepted(value: map_insert(subst, name, concrete)) Accepted { value: Present { value: bound }, diagnostics: _ } => diff --git a/src/v2/std/grounding.dag b/src/v2/std/grounding.dag index e72b498dc25..1c2259477bc 100644 --- a/src/v2/std/grounding.dag +++ b/src/v2/std/grounding.dag @@ -76,7 +76,7 @@ fn insert_per_language_fact_bundle_entry( key: PerLanguageFactBundleKey, fact_value: Node ) -> Outcome { - match v2.std.collection.map_get(m: registry.by_key, key: key) { + match v2.std.collection.map_get_checked(m: registry.by_key, key: key) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: _ } => outcome_rejected(d: per_language_fact_bundle_duplicate_key_diagnostic()) @@ -110,7 +110,7 @@ fn per_language_fact_bundle_insert_subject_axis( target: TargetModel, fact_axis: ModelCorePrimitiveFactAxis ) -> Outcome { - match v2.std.collection.map_get( + match v2.std.collection.map_get_checked( m: registry.by_key, key: per_language_fact_bundle_subject_axis_key( subject_carrier: subject_carrier, diff --git a/src/v2/std/symbol_index.dag b/src/v2/std/symbol_index.dag index 5dc8cde1db6..4165106ecc5 100644 --- a/src/v2/std/symbol_index.dag +++ b/src/v2/std/symbol_index.dag @@ -15,7 +15,7 @@ import v2.std.algebra { import v2.std.collection { Map, empty_map, - map_get, + map_get_checked, map_insert, map_contains_key, map_lookup @@ -170,7 +170,7 @@ fn empty_symbol_index() -> SymbolIndex { // a two-binder refusal back to one binder the first time this split was written. `entries` is where // a declaration is stored; `symbol_index_lookup` is what a reference is entitled to be told. fn symbol_index_entry_at(index: SymbolIndex, qualified_path: QualifiedName) -> Optional { - match v2.std.collection.map_get(index.entries, qualified_path) { + match v2.std.collection.map_get_checked(index.entries, qualified_path) { Accepted { value: opt, diagnostics: _ } => opt Rejected { diagnostics: _ } => optional_absent() } @@ -210,7 +210,7 @@ fn symbol_index_track_global_bare( match qualified_name_last_segment(qn: qualified_path) { Absent => index Present { value: leaf } => - match v2.std.collection.map_get(index.global_bare, leaf) { + match v2.std.collection.map_get_checked(index.global_bare, leaf) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: GlobalBareAmbiguous { paths: paths } } => SymbolIndex { @@ -332,9 +332,9 @@ fn symbol_index_mark_declared_payload(index: SymbolIndex, qualified_path: Qualif } // WHAT THE PATH DENOTES, WITH NO FAILURE ARM TO WIDEN (review 70226). The first cut read this -// through map_get, whose Outcome carries a Rejected arm, and answered binder there -- which matches +// through map_get_checked, whose Outcome carries a Rejected arm, and answered binder there -- which matches // every value, so a lookup that could not answer would have widened the arm silently, the fail-open -// shape DESIGN section 5 forbids. map_lookup is the total read underneath map_get (which is +// shape DESIGN section 5 forbids. map_lookup is the total read underneath map_get_checked (which is // `outcome_accepted(map_lookup(..))`, so its refusal arm is unreachable by construction): the kind, // or Absent for a path that denotes no declared payload. The caller matches on it. fn symbol_index_declared_payload_at(index: SymbolIndex, qualified_path: QualifiedName) -> Optional { @@ -431,7 +431,7 @@ fn symbol_index_declared_binders_at(index: SymbolIndex, qualified_path: Qualifie } fn symbol_index_global_unique_lookup(index: SymbolIndex, name: Symbol) -> GlobalBareLookup { - match v2.std.collection.map_get(index.global_bare, name) { + match v2.std.collection.map_get_checked(index.global_bare, name) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: GlobalBareUnique { node: n, path: p } } => GlobalBareHit { node: n, path: p } Present { value: GlobalBareAmbiguous { paths: paths } } => GlobalBareLookupAmbiguous { paths: paths } @@ -564,7 +564,7 @@ fn symbol_index_bound_declarings( index: SymbolIndex, binding_path: QualifiedName ) -> FreeMonoid { - match v2.std.collection.map_get(index.bound_declarings, binding_path) { + match v2.std.collection.map_get_checked(index.bound_declarings, binding_path) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: declarings } => declarings Absent => Empty diff --git a/src/v2/test/claim/emitted_closure_crate_partition_test.dag b/src/v2/test/claim/emitted_closure_crate_partition_test.dag index 276a2b9163f..f630bece848 100644 --- a/src/v2/test/claim/emitted_closure_crate_partition_test.dag +++ b/src/v2/test/claim/emitted_closure_crate_partition_test.dag @@ -2,7 +2,7 @@ module v2.test.claim.emitted_closure_crate_partition import std.types { Bool, Int, List, String } import v2.lens.module_graph { dependency_resolution_facts_live, module_declaration_facts_live } -import v2.std.collection { map_get } +import v2.std.collection { map_get_checked } import v2.std.diagnostic { Accepted, Rejected } import v2.std.optional { Absent, Present } import v2.std.compilers.compilation_unit { @@ -59,7 +59,7 @@ fn fixture_partition_at(root: String, entry: String) -> EmittedClosurePartitionO } fn owner_of(assignment: Map, module_id: String) -> String { - match map_get(assignment, module_id as ModuleId) { + match map_get_checked(assignment, module_id as ModuleId) { Accepted { value: Present { value: unit }, diagnostics: _ } => unit as String Accepted { value: Absent, diagnostics: _ } => "unowned" Rejected { diagnostics: _ } => "unowned" diff --git a/src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag b/src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag index 49a31f42ed7..c68756cc881 100644 --- a/src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag +++ b/src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag @@ -79,7 +79,7 @@ test fn witness_door_lookup_refused_for_recompute_table() -> Bool { } fn parse_table_entries_contain_key(table: ParseTable, key: ParsePositionKey) -> Bool { - match v2.std.collection.map_get(m: table.entries, key: key) { + match v2.std.collection.map_get_checked(m: table.entries, key: key) { Accepted { value: Present { value: _ } } => true Accepted { value: Absent } => false Rejected { diagnostics: _ } => false diff --git a/src/v2/test/claim/manual/bind_demand_driven_eval_test.dag b/src/v2/test/claim/manual/bind_demand_driven_eval_test.dag index 4df9a2ef677..a90399917f5 100644 --- a/src/v2/test/claim/manual/bind_demand_driven_eval_test.dag +++ b/src/v2/test/claim/manual/bind_demand_driven_eval_test.dag @@ -28,7 +28,7 @@ import v2.extdeps.runtimes.v2_evaluator { import v2.std.cardinality { termination_proof_witness_for_node } import v2.std.collection { Map, - map_get, + map_get_checked, map_insert } import v2.std.optional { @@ -171,7 +171,7 @@ fn bind_eval_int_from_runtime(value: RuntimeValue) -> Int { } fn bind_eval_touch_from_env(env: EvaluationEnvironment, key: EnvironmentBindingKey) -> Int { - match v2.std.collection.map_get(m: env.bindings, key: key) { + match v2.std.collection.map_get_checked(m: env.bindings, key: key) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: v } => bind_eval_int_from_runtime(value: v) diff --git a/src/v2/test/claim/manual/branch_lazy_arm_eval_acceptance_test.dag b/src/v2/test/claim/manual/branch_lazy_arm_eval_acceptance_test.dag index 3a9deffbd2e..839e814e8e4 100644 --- a/src/v2/test/claim/manual/branch_lazy_arm_eval_acceptance_test.dag +++ b/src/v2/test/claim/manual/branch_lazy_arm_eval_acceptance_test.dag @@ -25,7 +25,7 @@ import v2.std.cardinality { termination_proof_witness_for_node } import v2.std.collection { Map, list_at_optional, - map_get, + map_get_checked, map_insert } import v2.std.optional { @@ -228,7 +228,7 @@ fn lazy_arm_int_from_runtime(value: RuntimeValue) -> Int { } fn lazy_arm_touch_from_env(env: EvaluationEnvironment) -> Int { - match v2.std.collection.map_get(m: env.bindings, key: lazy_arm_touch_key()) { + match v2.std.collection.map_get_checked(m: env.bindings, key: lazy_arm_touch_key()) { Accepted { value: opt, diagnostics: _ } => match opt { Present { value: v } => lazy_arm_int_from_runtime(value: v) diff --git a/src/v2/test/claim/manual/value_null_split_witness_test.dag b/src/v2/test/claim/manual/value_null_split_witness_test.dag index 1c1febc63aa..d169e4aa6f3 100644 --- a/src/v2/test/claim/manual/value_null_split_witness_test.dag +++ b/src/v2/test/claim/manual/value_null_split_witness_test.dag @@ -39,7 +39,7 @@ test fn optional_present_matches_present_pattern() -> Bool { } test fn map_get_miss_is_absent_not_present() -> Bool { - match v2.std.collection.map_get(empty_map(), "missing") { + match v2.std.collection.map_get_checked(empty_map(), "missing") { Accepted { value: Absent, diagnostics: _ } => true Accepted { value: Present { value: _ }, diagnostics: _ } => false Rejected { diagnostics: _ } => false @@ -48,7 +48,7 @@ test fn map_get_miss_is_absent_not_present() -> Bool { test fn map_get_hit_is_present() -> Bool { let m = empty_map() |> map_insert("k", 7) - match v2.std.collection.map_get(m, "k") { + match v2.std.collection.map_get_checked(m, "k") { Accepted { value: Present { value: v }, diagnostics: _ } => v == 7 Accepted { value: Absent, diagnostics: _ } => false Rejected { diagnostics: _ } => false diff --git a/src/v2/test/claim/rust_crate_partition_witness_test.dag b/src/v2/test/claim/rust_crate_partition_witness_test.dag index 85c4164ee97..8711fd36cee 100644 --- a/src/v2/test/claim/rust_crate_partition_witness_test.dag +++ b/src/v2/test/claim/rust_crate_partition_witness_test.dag @@ -3,7 +3,7 @@ module v2.test.claim.rust_crate_partition_witness import std.decl_ref { DeclarationRef, WholeDeclaration } import std.perturbation { ForwardSameInSameOut, perturbation_consistent } import std.types { NonEmptyStr } -import v2.std.collection { Absent, Present, empty_map, map_get, map_insert } +import v2.std.collection { Absent, Present, empty_map, map_get_checked, map_insert } import v2.std.diagnostic { Accepted, Rejected } import v2.std.compilers.compilation_unit { CompilationUnitId, @@ -244,7 +244,7 @@ fn witness_policy_two() -> PartitionParameter { } fn witness_owner(assignment: Map, module_id: ModuleId) -> String { - match map_get(assignment, module_id) { + match map_get_checked(assignment, module_id) { Accepted { value: Present { value: unit }, diagnostics: _ } => unit as String Accepted { value: Absent, diagnostics: _ } => "unowned" Rejected { diagnostics: _ } => "unowned" diff --git a/src/v2/workflow/emitted_closure_crate_partition.dag b/src/v2/workflow/emitted_closure_crate_partition.dag index 26a6e1b4c6f..9e3b8885d18 100644 --- a/src/v2/workflow/emitted_closure_crate_partition.dag +++ b/src/v2/workflow/emitted_closure_crate_partition.dag @@ -10,7 +10,7 @@ import v2.lens.module_graph { dependency_resolution_facts_live, module_declaration_facts_live } -import v2.std.collection { empty_map, map_get, map_insert } +import v2.std.collection { empty_map, map_get_checked, map_insert } import v2.std.diagnostic { Accepted, Rejected } import v2.std.optional { Absent, Optional, Present } import v2.std.compilers.compilation_unit { ModuleDag, ModuleDagEdge, ModuleId } @@ -58,7 +58,7 @@ fn emitted_closure_module_by_path( closure: Map ) -> Map { declarations |> fold(init: empty_map(), f: fn(acc, decl) { - match map_get(closure, decl.path) { + match map_get_checked(closure, decl.path) { Accepted { value: Present { value: _ }, diagnostics: _ } => map_insert(acc, decl.path, decl.module) Accepted { value: Absent, diagnostics: _ } => acc Rejected { diagnostics: _ } => acc @@ -67,7 +67,7 @@ fn emitted_closure_module_by_path( } fn emitted_closure_module_at(by_path: Map, path: String) -> Optional { - match map_get(by_path, path) { + match map_get_checked(by_path, path) { Accepted { value: found, diagnostics: _ } => found Rejected { diagnostics: _ } => Absent } @@ -115,7 +115,7 @@ fn closure_edge_step( if !edge.target_declared { unresolved } else { - match map_get(module_set, edge.target_module) { + match map_get_checked(module_set, edge.target_module) { Accepted { value: Present { value: _ }, diagnostics: _ } => if importer == edge.target_module { acc diff --git a/src/v2/workflow/emitted_crate_workspace.dag b/src/v2/workflow/emitted_crate_workspace.dag index a503252d0bf..4bf7b8f2ce1 100644 --- a/src/v2/workflow/emitted_crate_workspace.dag +++ b/src/v2/workflow/emitted_crate_workspace.dag @@ -1,7 +1,7 @@ module v2.workflow.emitted_crate_workspace import std.types { List, String, Bool, Int, NonEmptyStr } -import v2.std.collection { empty_map, map_get, map_insert } +import v2.std.collection { empty_map, map_get_checked, map_insert } import v2.std.optional { Absent, Optional, Present, optional_present } import v2.std.diagnostic { Accepted, Rejected } import v2.std.compilers.compilation_unit { @@ -130,7 +130,7 @@ fn emitted_workspace_crate_dir(package: String) -> String { } fn emitted_workspace_lookup(m: Map, key: String) -> Optional { - match map_get(m, key) { + match map_get_checked(m, key) { Accepted { value: found, diagnostics: _ } => found Rejected { diagnostics: _ } => Absent } @@ -262,7 +262,7 @@ fn emitted_workspace_unit_rows(modules: List, assignment: Map filter(m => match map_get(assignment, m) { + modules: modules |> filter(m => match map_get_checked(assignment, m) { Accepted { value: Present { value: u }, diagnostics: _ } => u == unit_id Accepted { value: Absent, diagnostics: _ } => false Rejected { diagnostics: _ } => false @@ -319,7 +319,7 @@ fn emitted_workspace_derived_rows(unit_rows: List, unit } fn emitted_workspace_unit_of(assignment: Map, module: String) -> Optional { - match map_get(assignment, module as ModuleId) { + match map_get_checked(assignment, module as ModuleId) { Accepted { value: owner, diagnostics: _ } => owner Rejected { diagnostics: _ } => Absent } diff --git a/src/v2/workflow/floor_grandfathered_roster.dag b/src/v2/workflow/floor_grandfathered_roster.dag index b86680e9453..ccbf6ba64d4 100644 --- a/src/v2/workflow/floor_grandfathered_roster.dag +++ b/src/v2/workflow/floor_grandfathered_roster.dag @@ -567,7 +567,7 @@ fn floor_grandfathered_chunk_019() -> List { } fn floor_grandfathered_chunk_020() -> List { - Cons { head: "test.claim.prose_citation_census_witness.a_longer_identifier_ending_in_the_suffix_is_not_read_as_its_tail", tail: Cons { head: "test.claim.prose_citation_census_witness.a_name_retired_from_one_path_resolves_its_locality", tail: Cons { head: "test.claim.prose_citation_census_witness.a_name_retired_from_several_paths_refuses_to_pick_a_locality", tail: Cons { head: "test.claim.prose_citation_census_witness.an_annotation_citation_in_another_file_is_one_site_at_its_line", tail: Cons { head: "test.claim.prose_citation_census_witness.an_annotation_line_and_a_prose_row_line_are_different_carriers", tail: Cons { head: "test.claim.prose_citation_census_witness.a_partial_module_index_splits_the_rows_across_both_lists", tail: Cons { head: "test.claim.prose_citation_census_witness.a_populated_module_index_leaves_nothing_unidentified", tail: Cons { head: "test.claim.prose_citation_census_witness.a_program_data_line_is_read_as_not_a_prose_row_not_as_malformed", tail: Cons { head: "test.claim.prose_citation_census_witness.a_prose_row_citation_is_a_prose_row_site", tail: Cons { head: "test.claim.prose_citation_census_witness.a_row_still_declared_in_its_own_module_is_not_retired", tail: Cons { head: "test.claim.prose_citation_census_witness.a_row_whose_bare_name_survives_only_in_another_module_is_retired", tail: Cons { head: "test.claim.prose_citation_census_witness.a_semantic_line_naming_a_retired_row_is_not_a_citation_site", tail: Cons { head: "test.claim.prose_citation_census_witness.a_word_that_merely_starts_with_the_suffix_is_not_a_name", tail: Cons { head: "test.claim.prose_citation_census_witness.every_baseline_line_lands_in_exactly_one_arm", tail: Cons { head: "test.claim.prose_citation_census_witness.prose_naming_a_row_outside_the_retired_index_is_not_a_site", tail: Cons { head: "test.claim.prose_citation_census_witness.the_census_totals_are_projections_of_its_own_site_list", tail: Cons { head: "test.claim.prose_citation_census_witness.the_module_index_reads_module_lines_and_ignores_others", tail: Cons { head: "test.claim.prose_citation_census_witness.the_produced_site_identities_join_with_the_expected_ones_both_ways", tail: Cons { head: "test.claim.prose_citation_census_witness.the_qualified_identity_is_the_module_dot_name_spelling", tail: Cons { head: "test.claim.prose_citation_census_witness.the_same_path_seen_twice_is_still_one_origin", tail: Cons { head: "test.claim.prose_citation_census_witness.the_sample_is_the_twelve_sites_that_were_drawn", tail: Cons { head: "test.claim.prose_citation_census_witness.the_scan_is_non_constant_in_its_retired_index", tail: Cons { head: "test.claim.prose_citation_census_witness.the_trailing_blank_line_is_blank_not_malformed", tail: Cons { head: "test.claim.prose_citation_census_witness.the_twelve_sampled_specimens_are_all_recognised", tail: Cons { head: "test.claim.resolved_call_emission_identity_witness_test.w_divergent_map_get_keeps_declared_outcome_identity", tail: Empty {} } } } } } } } } } } } } } } } } } } } } } } } } } + Cons { head: "test.claim.prose_citation_census_witness.a_longer_identifier_ending_in_the_suffix_is_not_read_as_its_tail", tail: Cons { head: "test.claim.prose_citation_census_witness.a_name_retired_from_one_path_resolves_its_locality", tail: Cons { head: "test.claim.prose_citation_census_witness.a_name_retired_from_several_paths_refuses_to_pick_a_locality", tail: Cons { head: "test.claim.prose_citation_census_witness.an_annotation_citation_in_another_file_is_one_site_at_its_line", tail: Cons { head: "test.claim.prose_citation_census_witness.an_annotation_line_and_a_prose_row_line_are_different_carriers", tail: Cons { head: "test.claim.prose_citation_census_witness.a_partial_module_index_splits_the_rows_across_both_lists", tail: Cons { head: "test.claim.prose_citation_census_witness.a_populated_module_index_leaves_nothing_unidentified", tail: Cons { head: "test.claim.prose_citation_census_witness.a_program_data_line_is_read_as_not_a_prose_row_not_as_malformed", tail: Cons { head: "test.claim.prose_citation_census_witness.a_prose_row_citation_is_a_prose_row_site", tail: Cons { head: "test.claim.prose_citation_census_witness.a_row_still_declared_in_its_own_module_is_not_retired", tail: Cons { head: "test.claim.prose_citation_census_witness.a_row_whose_bare_name_survives_only_in_another_module_is_retired", tail: Cons { head: "test.claim.prose_citation_census_witness.a_semantic_line_naming_a_retired_row_is_not_a_citation_site", tail: Cons { head: "test.claim.prose_citation_census_witness.a_word_that_merely_starts_with_the_suffix_is_not_a_name", tail: Cons { head: "test.claim.prose_citation_census_witness.every_baseline_line_lands_in_exactly_one_arm", tail: Cons { head: "test.claim.prose_citation_census_witness.prose_naming_a_row_outside_the_retired_index_is_not_a_site", tail: Cons { head: "test.claim.prose_citation_census_witness.the_census_totals_are_projections_of_its_own_site_list", tail: Cons { head: "test.claim.prose_citation_census_witness.the_module_index_reads_module_lines_and_ignores_others", tail: Cons { head: "test.claim.prose_citation_census_witness.the_produced_site_identities_join_with_the_expected_ones_both_ways", tail: Cons { head: "test.claim.prose_citation_census_witness.the_qualified_identity_is_the_module_dot_name_spelling", tail: Cons { head: "test.claim.prose_citation_census_witness.the_same_path_seen_twice_is_still_one_origin", tail: Cons { head: "test.claim.prose_citation_census_witness.the_sample_is_the_twelve_sites_that_were_drawn", tail: Cons { head: "test.claim.prose_citation_census_witness.the_scan_is_non_constant_in_its_retired_index", tail: Cons { head: "test.claim.prose_citation_census_witness.the_trailing_blank_line_is_blank_not_malformed", tail: Cons { head: "test.claim.prose_citation_census_witness.the_twelve_sampled_specimens_are_all_recognised", tail: Cons { head: "test.claim.resolved_call_emission_identity_witness_test.w_divergent_map_get_checked_keeps_declared_outcome_identity", tail: Empty {} } } } } } } } } } } } } } } } } } } } } } } } } } } fn floor_grandfathered_chunk_021() -> List { diff --git a/src/v2/workflow/rust_crate_partition.dag b/src/v2/workflow/rust_crate_partition.dag index 40d4aa797ba..f2f81c0b15c 100644 --- a/src/v2/workflow/rust_crate_partition.dag +++ b/src/v2/workflow/rust_crate_partition.dag @@ -24,7 +24,7 @@ import v2.lens.common.construction_justification { ConstructionJustification, Wa import v2.std.algebra { any, fold_list, length } import v2.std.collection { empty_map, - map_get, + map_get_checked, map_insert } import v2.std.optional { @@ -682,7 +682,7 @@ fn emitted_target_reach(module_dag: ModuleDag, emitted: List) -> Ma match edge.to { EmittedCrateRootTarget => acc EmittedModuleTarget { module: target } => - match map_get(acc, target) { + match map_get_checked(acc, target) { Accepted { value: Present { value: _ }, diagnostics: _ } => acc _ => map_insert(acc, target, @@ -694,7 +694,7 @@ fn emitted_target_reach(module_dag: ModuleDag, emitted: List) -> Ma } fn string_member(set: Map, key: String) -> Bool { - match map_get(set, key) { + match map_get_checked(set, key) { Accepted { value: Present { value: _ }, diagnostics: _ } => true _ => false } @@ -721,7 +721,7 @@ fn emitted_edge_merge_step( refusal: optional_present(value: EmittedEdgeEndpointOutsideDag { from: edge.from, to: target }) } } else { - let target_reaches_source = match map_get(reach, target) { + let target_reaches_source = match map_get_checked(reach, target) { Accepted { value: Present { value: reached }, diagnostics: _ } => string_member(set: reached, key: edge.from) _ => false } @@ -872,7 +872,7 @@ fn assignment_owner( assignment: Map, module_id: ModuleId ) -> Optional { - match map_get(assignment, module_id) { + match map_get_checked(assignment, module_id) { Accepted { value: owner, diagnostics: _ } => owner Rejected { diagnostics: _ } => Absent } @@ -905,7 +905,7 @@ fn assignment_first_stranger( match acc { Present { value: _ } => acc Absent => - match map_get(known, module_id) { + match map_get_checked(known, module_id) { Accepted { value: Present { value: _ }, diagnostics: _ } => Absent Accepted { value: Absent, diagnostics: _ } => Present { value: module_id } Rejected { diagnostics: _ } => Present { value: module_id } From 0b007394f7c4a9752583cef5c3bcef2f7c190bbb Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 05:23:48 +0000 Subject: [PATCH 03/14] Regenerate std_primitive_projection.rs for the renamed declaration required-regen on the merged tree (origin/main@39d1e2e6db + d540486b14): self-compile clean, adjudicated 163, declared_divergent=1 - the projection row's decl_name follows the map_get_checked rename. compiler_tests.rs and all other mirrors already equal. --- src/v1/stage0/src/std_primitive_projection.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v1/stage0/src/std_primitive_projection.rs b/src/v1/stage0/src/std_primitive_projection.rs index 7f23a1abc04..0dde8b18b5d 100644 --- a/src/v1/stage0/src/std_primitive_projection.rs +++ b/src/v1/stage0/src/std_primitive_projection.rs @@ -422,7 +422,7 @@ pub fn primitive_projection_roster() -> Rc>> { primitive_projection_row( primitive_map_get(), "v2.std.collection".to_string(), - "map_get".to_string(), + "map_get_checked".to_string(), Rc::new(ProjectionFidelity::DivergentProjection { divergence: "declared return Outcome> against the primitive's Optional" From a1d0d223257a309888e60cc345543acefc57a318 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 08:22:28 +0000 Subject: [PATCH 04/14] Review fixes: the dissolved fork gets a dissolution control, and build_target's comment states the truth declaration_index.rs: the authored-membership control still asserted FuncSigAmbiguous over builtin:map_get + declared:map_get_checked -- a collision the rename made unrepresentable (the registry keys the primitive as map_get; the lookup string no longer mints a builtin candidate). The omitted arm is rewritten as a dissolution control checked by its exact identity shape: the bare map_get spelling must have no declared candidate and never go ambiguous; a re-widening of the fork flips it red again (DESIGN 4b: the probe does not retire, it becomes a regression control). build_target.dag: the mechanically renamed comment claimed two declarations answer to map_get_checked in the present tense -- false after the repair. Rewritten: the historical account of the map_get fork (why lookup exists) with the dissolution recorded. --- dag/gunbc/build_target.dag | 12 +++--- src/v1/stage0/src/declaration_index.rs | 55 +++++++++++--------------- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/dag/gunbc/build_target.dag b/dag/gunbc/build_target.dag index 31a775a2064..d4e064e63a0 100644 --- a/dag/gunbc/build_target.dag +++ b/dag/gunbc/build_target.dag @@ -499,11 +499,13 @@ type TargetStandingLookup | StandingNotObserved { target: Label } | StandingLookupLabelNotCanonical { target: Label, cause: LabelCanonicalityCause } -// THE LOOKUP SPELLING IS `lookup`, NOT `map_get_checked`, AND THE REASON IS RESOLUTION RATHER THAN TASTE. -// Two declarations answer to the bare name `map_get_checked` — the builtin, returning `Optional`, and -// `v2.std.collection.map_get_checked`, returning `Outcome>` — 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. +// THE LOOKUP SPELLING IS `lookup`, NOT `map_get`, AND THE REASON IS RESOLUTION RATHER THAN TASTE. +// HISTORICALLY the bare name `map_get` answered to two declarations — the builtin, returning +// `Optional`, and `v2.std.collection`'s declared projection, returning `Outcome>` — +// 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 } => diff --git a/src/v1/stage0/src/declaration_index.rs b/src/v1/stage0/src/declaration_index.rs index 5668e7e2fc7..22556298445 100644 --- a/src/v1/stage0/src/declaration_index.rs +++ b/src/v1/stage0/src/declaration_index.rs @@ -3578,7 +3578,7 @@ mod import_binding_authority_tests { #[test] fn authored_membership_alone_decides_the_callable_verdict() { use crate::v1_compiler_infer_lookup::callable_lookup_over_candidates; - use crate::v1_compiler_infer_sigs::{CallableIdentity, FuncSigLookup}; + use crate::v1_compiler_infer_sigs::FuncSigLookup; let env = parent_env_declaring_map_get_checked(); @@ -3587,10 +3587,10 @@ mod import_binding_authority_tests { type_env_with_authored(&["map_get_checked"]), "map_get_checked".to_string(), ); - let omitted = callable_lookup_over_candidates( + let bare = callable_lookup_over_candidates( env, type_env_with_authored(&["cut_unrelated_marker"]), - "map_get_checked".to_string(), + "map_get".to_string(), ); // THE DIRECTION IS ASSERTED, NOT MERE INEQUALITY. A control demanding only that the arms @@ -3607,37 +3607,26 @@ mod import_binding_authority_tests { ), } - // AND THE AMBIGUOUS ARM IS CHECKED BY ITS EXACT IDENTITY SET, never by a count and never by - // list order. A count would pass on a substitution, and an order-sensitive comparison would - // make candidate ordering -- which nothing declares to be semantic -- part of the assertion. - match &*omitted { - FuncSigLookup::FuncSigAmbiguous { candidates, .. } => { - let mut observed: Vec = candidates - .iter() - .map(|c| match &*c.identity { - CallableIdentity::DeclaredCallable { identity } => format!( - "declared:{}:{}", - identity.owner_module_path, identity.decl_name - ), - CallableIdentity::BuiltinCallable { primitive_name } => { - format!("builtin:{primitive_name}") - } - }) - .collect(); - observed.sort(); - observed.dedup(); - assert_eq!( - observed, - vec![ - "builtin:map_get".to_string(), - "declared:v2.std.collection:map_get".to_string(), - ], - "the two rival authorities must both be present, and only those two" - ); - } + // THE OLD map_get FORK IS DISSOLVED, AND THIS ARM IS ITS PERMANENT REGRESSION CONTROL, + // checked by its exact identity set rather than a count or list order. Before the rename, + // a module that omitted the declaration from its authored list while calling the bare name + // minted TWO rival authorities -- `builtin:map_get` and + // `declared:v2.std.collection:map_get` -- and went ambiguous. The declared projection now + // answers to `map_get_checked` alone, so the bare spelling has no declared candidate and + // only the builtin rival remains, which this callable route leaves unresolved (builtins + // reach inference through the method path). A future re-widening -- a declared projection + // reclaiming the bare spelling -- puts the rival back and flips this arm to + // FuncSigAmbiguous, failing here. + match &*bare { + FuncSigLookup::FuncSigUnresolved => {} + FuncSigLookup::FuncSigAmbiguous { candidates } => panic!( + "the dissolved map_get fork must not return: the bare spelling minted rivals \ + {:?}", + candidates + ), other => panic!( - "omitting it from a NONEMPTY authored list must admit the builtin rival and go \ - ambiguous, got {other:?}" + "the dissolved map_get fork must leave the bare spelling a single builtin \ + authority -- no declared candidate, never ambiguous -- got {other:?}" ), } } From a7474f4051b3106f52335fc9ffdaf8e596973110 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 15:26:16 +0000 Subject: [PATCH 05/14] Merge origin/main@a453be995a (Optional de-fork #13388): keep the map_get_checked rename and take std.optional's re-homing; 03_name_resolve and emitted_crate_workspace read std.optional and name map_get_checked --- src/v2/compiler/03_name_resolve.dag | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/v2/compiler/03_name_resolve.dag b/src/v2/compiler/03_name_resolve.dag index 01b242cd34b..6025fbcf41f 100644 --- a/src/v2/compiler/03_name_resolve.dag +++ b/src/v2/compiler/03_name_resolve.dag @@ -38,13 +38,8 @@ import v2.compiler.namespace_graft { import v2.compiler.parse { parse_tree_projection_edge } import std.algebra { Cons, Empty, FreeMonoid, list_snoc_item } import v2.std.algebra { fold_list } -<<<<<<< HEAD import v2.std.collection { Absent, Map, Present, PointwisePower, empty_map, map_get_checked, map_lookup, map_insert, optional_absent, optional_present } -import v2.std.optional { Optional } -======= -import v2.std.collection { Absent, Map, Present, PointwisePower, empty_map, map_get, map_lookup, map_insert, optional_absent, optional_present } import std.optional { Optional } ->>>>>>> origin/main import v2.std.diagnostic { Accepted, Diagnostic, From c023d223ccd163beeb73a6c50d46bf3985a70153 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 15:52:33 +0000 Subject: [PATCH 06/14] Register the re-homed std_optional mirror required-regen re-adjudicated clean on the merged tree: lib.rs declares pub mod std_optional and its mirror arrives with the merge; no other surface changed. --- src/v1/stage0/src/lib.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/v1/stage0/src/lib.rs b/src/v1/stage0/src/lib.rs index 1f3a31a67b0..db3e0f259d1 100644 --- a/src/v1/stage0/src/lib.rs +++ b/src/v1/stage0/src/lib.rs @@ -312,6 +312,17 @@ pub mod std_occurrence_binding_resolve; suspicious_double_ref_op, clippy::all )] +pub mod std_optional; +#[allow( + unused_imports, + unused_variables, + unused_mut, + unused_parens, + dead_code, + non_shorthand_field_patterns, + suspicious_double_ref_op, + clippy::all +)] pub mod std_reference_binding_observation; #[allow( unused_imports, From a739a9cbd7383c7822487c93b02038714e2af77c Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 16:12:39 +0000 Subject: [PATCH 07/14] Re-point the declared-probe fixture at std.optional #13388 re-homed v2.std.optional to std.optional; the synthesized probe module in the emission-identity witness still imported the defunct path, so the witness resolved against a probe that could not load. The probe now reads std.optional and the pinned emitted target crate::v2_std_collection::map_get_checked( is unchanged. --- dag/test/claim/resolved_call_emission_identity_witness_test.dag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dag/test/claim/resolved_call_emission_identity_witness_test.dag b/dag/test/claim/resolved_call_emission_identity_witness_test.dag index 6283ba3568b..d2a133d618d 100644 --- a/dag/test/claim/resolved_call_emission_identity_witness_test.dag +++ b/dag/test/claim/resolved_call_emission_identity_witness_test.dag @@ -65,7 +65,7 @@ test fn w_imported_generic_contains_keeps_declared_identity() -> Bool { // what the author called. 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_checked }\nimport v2.std.diagnostic { Outcome }\nimport v2.std.optional { Optional }\nfn probe(m: Map) -> Outcome> { map_get_checked(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) -> Outcome> { map_get_checked(m: m, key: \"key\") }\n", "src/test_claim_declared_map_get_probe.rs", ["crate::v2_std_collection::map_get_checked("], ["v1_rt::map_get("] From 7ae7a6979a78db108f1f142922d46976c4abf30d Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 16:40:43 +0000 Subject: [PATCH 08/14] Re-point the self_host qualified-call probe at std.optional and map_get_checked The same synthesized-probe pattern as the emission-identity witness: the qualified-call probe still imported the defunct v2.std.optional and the pre-rename bare declaration, so it could not load and pinned nothing. Now it reads std.optional and names map_get_checked; the asserted emitted target crate::v2_std_collection::map_get_checked( follows. --- dag/extdeps/git/versioning.dag | 26 ++ dag/extdeps/version/semver.dag | 293 ++++++++++++++++++ ...d_call_target_realization_witness_test.dag | 4 + 3 files changed, 323 insertions(+) diff --git a/dag/extdeps/git/versioning.dag b/dag/extdeps/git/versioning.dag index 92dcfb7c44b..0ab7ff930fa 100644 --- a/dag/extdeps/git/versioning.dag +++ b/dag/extdeps/git/versioning.dag @@ -3,8 +3,13 @@ module extdeps.git.versioning import std.types { NonEmptyStr, brand } import std.integer { NonNegativeInt } import std.algebra { Ordering, Equal, Greater } +<<<<<<< Updated upstream import std.nat { nat_compare } import extdeps.version { VersionIdentity, VersionScheme, VersionConstraint } +======= +import extdeps.version { VersionIdentity, VersionComparison, VersionCompared, VersionComparisonRefused, VersionScheme, VersionConstraint, ComparisonSide, LeftOperand, RightOperand } +import extdeps.version.semver { semver_core_parse, semver_compare_numeric_digits, semver_label_from_code_points, semver_numeric_field, SemVerNumericField } +>>>>>>> Stashed changes import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } @@ -30,10 +35,20 @@ type GitCliReportedVersion { suffix: GitVersionPlatformSuffix } +<<<<<<< Updated upstream data git_2_0_release: GitReleaseVersion = { major: 2, minor: 0, patch: 0 +======= +// THE ANCHOR IS DERIVED THROUGH THE PARSER, never raw lists: the fields come from parsing +// the literal release text, so the confined constructor's admission is the only producer. +// The fallback is unreachable for a parsable literal, and the round-trip witness pins the +// label to "2.0.0" by execution, so a forged or control-character field cannot pass. +data git_2_0_release: GitReleaseVersion = match semver_core_parse(cps: chars(s: "2.0.0")) { + Present { value: v } => GitReleaseVersion { major: v.major, minor: v.minor, patch: v.patch } + other => GitReleaseVersion { major: semver_numeric_field(cps: chars(s: "0")).?, minor: semver_numeric_field(cps: chars(s: "0")).?, patch: semver_numeric_field(cps: chars(s: "0")).? } +>>>>>>> Stashed changes } data git_release_versioning_spec_url: NonEmptyStr = "https://git-scm.com/docs/BreakingChanges.html" @@ -44,8 +59,13 @@ data min_git_version: GitVersionConstraint = ">= 2.0.0" fn git_release_version_label(v: GitReleaseVersion) -> String { concat( +<<<<<<< Updated upstream to_string(v.major), concat(".", concat(to_string(v.minor), concat(".", to_string(v.patch)))) +======= + semver_label_from_code_points(cps: v.major.digits), + concat(".", concat(semver_label_from_code_points(cps: v.minor.digits), concat(".", semver_label_from_code_points(cps: v.patch.digits)))) +>>>>>>> Stashed changes ) } @@ -54,9 +74,15 @@ fn git_release_to_version_identity(v: GitReleaseVersion) -> VersionIdentity { } fn git_release_version_compare(a: GitReleaseVersion, b: GitReleaseVersion) -> Ordering { +<<<<<<< Updated upstream match nat_compare(a: a.major, b: b.major) { Equal => match nat_compare(a: a.minor, b: b.minor) { Equal => nat_compare(a: a.patch, b: b.patch) +======= + match semver_compare_numeric_digits(a: a.major.digits, b: b.major.digits) { + Equal => match semver_compare_numeric_digits(a: a.minor.digits, b: b.minor.digits) { + Equal => semver_compare_numeric_digits(a: a.patch.digits, b: b.patch.digits) +>>>>>>> Stashed changes other => other } other => other diff --git a/dag/extdeps/version/semver.dag b/dag/extdeps/version/semver.dag index f4788eed698..7836ce31282 100644 --- a/dag/extdeps/version/semver.dag +++ b/dag/extdeps/version/semver.dag @@ -20,6 +20,37 @@ type SemVerIdentity = VersionIdentity type SemVerConstraint = VersionConstraint +<<<<<<< Updated upstream +======= +// A numeric component carries its code points, not a machine integer: SemVer 2.0.0 puts no +// size limit on X.Y.Z (§2) or on numeric identifiers (§9), so an Int conversion on the +// comparison path would invent a grammar failure the spec does not have. +// +// CONSTRUCTOR-CONFINED: the only admission is `semver_numeric_field`, which refuses an empty +// sequence, anything outside ASCII digits 48..57, and a leading zero unless the sequence is +// the single digit 0. Comparison and rendering project `.digits`; the parsed wire never +// carries a bare list. The negative controls in the witness file pin the refusals. +type SemVerNumericField { + digits: List +} + +fn semver_numeric_field(cps: List) -> SemVerNumericField? { + if cps.count() == 0 { + none + } else if !all(cps, cp => cp >= 48 && cp <= 57) { + none + } else if cps.count() > 1 { + match cps.first() { + Present { value: 48 } => none + Present { value: _ } => Present { value: SemVerNumericField { digits: cps } } + Absent => none + } + } else { + Present { value: SemVerNumericField { digits: cps } } + } +} + +>>>>>>> Stashed changes type SemVerIdentifier = SemVerNumericIdentifier { value: NonNegativeInt } | SemVerAlphanumericIdentifier { label: NonEmptyStr } @@ -38,9 +69,15 @@ fn semver_compare_non_negative_int(a: NonNegativeInt, b: NonNegativeInt) -> Orde fn semver_compare_identifier(a: SemVerIdentifier, b: SemVerIdentifier) -> Ordering { match a { +<<<<<<< Updated upstream SemVerNumericIdentifier { value: av } => match b { SemVerNumericIdentifier { value: bv } => semver_compare_non_negative_int(a: av, b: bv) +======= + SemVerNumericIdentifier { digits: ad } => match b { + SemVerNumericIdentifier { digits: bd } => + semver_compare_numeric_digits(a: ad.digits, b: bd.digits) +>>>>>>> Stashed changes SemVerAlphanumericIdentifier { label: _ } => Less } SemVerAlphanumericIdentifier { label: al } => match b { @@ -83,11 +120,19 @@ fn semver_compare_pre_release(a: List, b: List Ordering { +<<<<<<< Updated upstream match semver_compare_non_negative_int(a: a.major, b: b.major) { Equal => match semver_compare_non_negative_int(a: a.minor, b: b.minor) { Equal => match semver_compare_non_negative_int(a: a.patch, b: b.patch) { +======= + match semver_compare_numeric_digits(a: a.major.digits, b: b.major.digits) { + Equal => + match semver_compare_numeric_digits(a: a.minor.digits, b: b.minor.digits) { + Equal => + match semver_compare_numeric_digits(a: a.patch.digits, b: b.patch.digits) { +>>>>>>> Stashed changes Equal => semver_compare_pre_release(a: a.pre_release, b: b.pre_release) other => other } @@ -99,7 +144,11 @@ fn semver_compare(a: SemVerVersion, b: SemVerVersion) -> Ordering { fn semver_identifier_label(id: SemVerIdentifier) -> String { match id { +<<<<<<< Updated upstream SemVerNumericIdentifier { value: v } => "{v}" +======= + SemVerNumericIdentifier { digits: d } => semver_label_from_code_points(cps: d.digits) +>>>>>>> Stashed changes SemVerAlphanumericIdentifier { label: s } => s } } @@ -110,8 +159,13 @@ fn semver_identifiers_label(ids: List) -> String { fn semver_version_label(v: SemVerVersion) -> String { let core = concat( +<<<<<<< Updated upstream to_string(v.major), concat(".", concat(to_string(v.minor), concat(".", to_string(v.patch)))) +======= + semver_label_from_code_points(cps: v.major.digits), + concat(".", concat(semver_label_from_code_points(cps: v.minor.digits), concat(".", semver_label_from_code_points(cps: v.patch.digits)))) +>>>>>>> Stashed changes ) let with_pre = if v.pre_release.count() == 0 { core @@ -129,8 +183,247 @@ fn semver_to_version_identity(v: SemVerVersion) -> VersionIdentity { semver_version_label(v: v) } +<<<<<<< Updated upstream fn semver_identity_compare(a: VersionIdentity, b: VersionIdentity) -> Ordering { if a == b { Equal } else { if a < b { Less } else { Greater } } +======= +// CITED RULE (SemVer 2.0.0 §11, https://semver.org/#spec-item-11 — the authority this module's +// extdeps_external_authority_anchor attests): precedence is decided by comparing major, then +// minor, then patch as NUMBERS; a pre-release version has LOWER precedence than the normal +// version; pre-release identifiers compare numeric < alphanumeric, numerics numerically, +// alphanumerics lexically in ASCII sort order, and a larger set of pre-release identifiers ranks +// higher when all preceding identifiers are equal; build metadata is ignored entirely. +// +// The label is a VersionScheme's only handle, so the comparison parses the label back into the +// typed form and routes through `semver_compare` — the ONE implementation of the cited rule. +// §11 defines precedence over VALID versions, so a label outside the §2 grammar is a located +// refusal: the carrier names the failing side, the label, and the cause (pinned by +// w_semver_scheme_out_of_grammar_label_refuses_precedence), never a fabricated order. +fn semver_identity_compare(a: VersionIdentity, b: VersionIdentity) -> VersionComparison { + match semver_identity_parse(label: a) { + Present { value: av } => + match semver_identity_parse(label: b) { + Present { value: bv } => VersionCompared { ordering: semver_compare(a: av, b: bv) } + Absent => VersionComparisonRefused { side: RightOperand, identity: b as String, cause: "label does not satisfy the SemVer 2.0.0 version grammar, so section 11 precedence is undefined for it" } + } + Absent => VersionComparisonRefused { side: LeftOperand, identity: a as String, cause: "label does not satisfy the SemVer 2.0.0 version grammar, so section 11 precedence is undefined for it" } + } +} + +// ---- label parse (SemVer 2.0.0 §2 grammar) -------------------------------- + +fn semver_identity_code_points(label: VersionIdentity) -> List { + chars(s: label as String) +} + +fn semver_is_ascii_digit(cp: Int) -> Bool { + cp >= 48 && cp <= 57 +} + +fn semver_is_ascii_letter(cp: Int) -> Bool { + (cp >= 65 && cp <= 90) || (cp >= 97 && cp <= 122) +} + +fn semver_is_identifier_char(cp: Int) -> Bool { + semver_is_ascii_digit(cp: cp) || semver_is_ascii_letter(cp: cp) || cp == 45 +} + +fn semver_index_of(cp: Int, cps: List) -> Int? { + if cps.count() == 0 { + none + } else { + match cps.first() { + Present { value: h } => + if h == cp { + Present { value: 0 } + } else { + match semver_index_of(cp: cp, cps: cps.skip(n: 1)) { + Present { value: k } => Present { value: k + 1 } + Absent => none + } + } + Absent => none + } + } +} + +fn semver_split_on(cp: Int, cps: List, acc: List>) -> List> { + match semver_index_of(cp: cp, cps: cps) { + Present { value: i } => + semver_split_on(cp: cp, cps: cps.skip(n: i + 1), acc: concat(acc, [cps.take(n: i)])) + Absent => concat(acc, [cps]) + } +} + +fn semver_all_digits(cps: List) -> Bool { + cps.count() > 0 && all(cps, cp => semver_is_ascii_digit(cp: cp)) +} + +// §2: a numeric identifier MUST NOT include leading zeroes; "0" alone is fine. +fn semver_numeric_run_without_leading_zero(cps: List) -> Bool { + if !semver_all_digits(cps: cps) { + false + } else { + match cps.first() { + Present { value: h } => cps.count() == 1 || h != 48 + Absent => false + } + } +} + + + +fn semver_label_from_code_points(cps: List) -> NonEmptyStr { + join(cps |> map(cp => from_code_point(cp: cp)), "") as NonEmptyStr +} + +// ---- core MAJOR.MINOR.PATCH ----------------------------------------------- + +// THE LAST FIELD CONSUMES THE WHOLE REMAINDER, never a dot-split: a leftover delimiter +// then fails the numeric run here instead of being split off and silently accepted. +// SemVer 2.0.0 §2 is X.Y.Z with no trailing delimiter, so "1.2.3." must refuse, not rank. +fn semver_core_fields_parse(cps: List, remaining: Int) -> List? { + if remaining == 0 { + if cps.count() == 0 { Present { value: [] } } else { none } + } else if remaining == 1 { + match semver_numeric_field(cps: cps) { + Absent => none + Present { value: v } => Present { value: [v] } + } + } else { + match semver_index_of(cp: 46, cps: cps) { + Present { value: i } => + match semver_digits_field(cps: cps.take(n: i)) { + Absent => none + Present { value: v } => + match semver_core_fields_parse(cps: cps.skip(n: i + 1), remaining: remaining - 1) { + Absent => none + Present { value: rest } => Present { value: concat([v], rest) } + } + } + Absent => none + } + } +} + +fn semver_core_parse(cps: List) -> SemVerVersion? { + match semver_core_fields_parse(cps: cps, remaining: 3) { + Absent => none + Present { value: fields } => + if fields.count() != 3 { + none + } else { + match fields.first() { + Absent => none + Present { value: major } => + match fields.skip(n: 1).first() { + Absent => none + Present { value: minor } => + match fields.skip(n: 2).first() { + Absent => none + Present { value: patch } => + Present { value: SemVerVersion { major: major, minor: minor, patch: patch, pre_release: [], build: [] } } + } + } + } + } + } +} + +// ---- pre-release and build identifiers ------------------------------------ + +// One identifier parse for both §9 pre-release and §10 build identifiers; the only real +// difference between the two grammars is carried by strict_numeric. A no-leading-zero digit run +// is numeric (§9, §10). In strict mode — pre-release — an all-digit run WITH a leading zero is +// neither numeric ("Numeric identifiers MUST NOT include leading zeroes", §9) nor alphanumeric +// (the §2 grammar requires an alphanumeric identifier to contain a non-digit), so it refuses. +// §10 permits leading zeroes in build metadata ("1.0.0+0130"), so permissive mode keeps such a +// run as an alphanumeric identifier. An admitted numeric identifier carries its digits as code +// points: section 9 numerics have no size limit, so no machine-integer conversion happens on +// the comparison path. +fn semver_identifier_parse(cps: List, strict_numeric: Bool) -> SemVerIdentifier? { + if cps.count() == 0 { + none + } else if !all(cps, cp => semver_is_identifier_char(cp: cp)) { + none + } else if semver_numeric_run_without_leading_zero(cps: cps) { + match semver_numeric_field(cps: cps) { + Present { value: f } => Present { value: SemVerNumericIdentifier { digits: f } } + Absent => none + } + } else if strict_numeric && semver_all_digits(cps: cps) { + none + } else { + Present { value: SemVerAlphanumericIdentifier { label: semver_label_from_code_points(cps: cps) } } + } +} + +fn semver_identifier_list_parse( + segments: List>, + strict_numeric: Bool +) -> List? { + segments |> fold( + init: Present { value: [] }, + f: (st, seg) => + match st { + Absent => Absent + Present { value: acc } => + match semver_identifier_parse(cps: seg, strict_numeric: strict_numeric) { + Absent => Absent + Present { value: id } => Present { value: concat(acc, [id]) } + } + } + ) +} + +fn semver_pre_release_parse(cps: List) -> List? { + semver_identifier_list_parse(segments: semver_split_on(cp: 46, cps: cps, acc: []), strict_numeric: true) +} + +fn semver_build_parse(cps: List) -> List? { + semver_identifier_list_parse(segments: semver_split_on(cp: 46, cps: cps, acc: []), strict_numeric: false) +} + +// ---- label assembly -------------------------------------------------------- + +fn semver_identity_head_parse(cps: List, build: List) -> SemVerVersion? { + match semver_index_of(cp: 45, cps: cps) { + Present { value: pi } => + match semver_core_parse(cps: cps.take(n: pi)) { + Absent => none + Present { value: core } => + match semver_pre_release_parse(cps: cps.skip(n: pi + 1)) { + Absent => none + Present { value: pre } => + Present { value: SemVerVersion { major: core.major, minor: core.minor, patch: core.patch, pre_release: pre, build: build } } + } + } + Absent => + match semver_core_parse(cps: cps) { + Absent => none + Present { value: core } => + Present { value: SemVerVersion { major: core.major, minor: core.minor, patch: core.patch, pre_release: [], build: build } } + } + } +} + +fn semver_identity_parse(label: VersionIdentity) -> SemVerVersion? { + semver_version_parse(cps: semver_identity_code_points(label: label)) +} + +// Code-point entry for sibling schemes whose labels carry a scheme-specific prefix (go's "v"): +// the grammar and the precedence stay HERE — the one implementation — and the sibling keeps only +// its own prefix and acceptance rules. +fn semver_version_parse(cps: List) -> SemVerVersion? { + match semver_index_of(cp: 43, cps: cps) { + Present { value: bi } => + match semver_build_parse(cps: cps.skip(n: bi + 1)) { + Absent => none + Present { value: build } => semver_identity_head_parse(cps: cps.take(n: bi), build: build) + } + Absent => semver_identity_head_parse(cps: cps, build: []) + } +>>>>>>> Stashed changes } data semver_scheme: VersionScheme = VersionScheme { diff --git a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag index 51798c87064..c257813913e 100644 --- a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag +++ b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag @@ -278,7 +278,11 @@ test fn w_clone_bound_forwards_transitively_over_two_call_hops() -> Bool { // row proves the qualified path reaches the DECLARATION and not the bridge. test fn w_qualified_call_emits_only_the_declaration_last_segment() -> Bool { compile_dag_rust_emit_check( +<<<<<<< Updated upstream "module test.claim.qualified_call_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 v2.std.optional { Optional }\nfn probe(m: Map) -> Outcome> { v2.std.collection.map_get_checked(m: m, key: \"key\") }\n", +======= + "module test.claim.qualified_call_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) -> Outcome> { v2.std.collection.map_get_checked(m: m, key: \"key\") }\n", +>>>>>>> Stashed changes "src/test_claim_qualified_call_probe.rs", ["crate::v2_std_collection::map_get_checked("], ["::v2.std.collection", "v2.std.collection.map_get_checked("] From 0125350c984cfe161b1b0dce4bec6039306a0156 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 16:43:33 +0000 Subject: [PATCH 09/14] Drop the semver-confinement files that rode along with the probe fix The stash carrying the self_host probe fix also held #13412's in-flight confinement patches for version/semver.dag and git/versioning.dag; those belong on the semver-precedence branch, not this PR. This restores both files to their merged-tree state; only the self_host probe re-point remains. --- dag/extdeps/git/versioning.dag | 26 --- dag/extdeps/version/semver.dag | 293 --------------------------------- 2 files changed, 319 deletions(-) diff --git a/dag/extdeps/git/versioning.dag b/dag/extdeps/git/versioning.dag index 0ab7ff930fa..92dcfb7c44b 100644 --- a/dag/extdeps/git/versioning.dag +++ b/dag/extdeps/git/versioning.dag @@ -3,13 +3,8 @@ module extdeps.git.versioning import std.types { NonEmptyStr, brand } import std.integer { NonNegativeInt } import std.algebra { Ordering, Equal, Greater } -<<<<<<< Updated upstream import std.nat { nat_compare } import extdeps.version { VersionIdentity, VersionScheme, VersionConstraint } -======= -import extdeps.version { VersionIdentity, VersionComparison, VersionCompared, VersionComparisonRefused, VersionScheme, VersionConstraint, ComparisonSide, LeftOperand, RightOperand } -import extdeps.version.semver { semver_core_parse, semver_compare_numeric_digits, semver_label_from_code_points, semver_numeric_field, SemVerNumericField } ->>>>>>> Stashed changes import extdeps.external_authority { ExternalAuthority } import extdeps.uri { Uri, Https } @@ -35,20 +30,10 @@ type GitCliReportedVersion { suffix: GitVersionPlatformSuffix } -<<<<<<< Updated upstream data git_2_0_release: GitReleaseVersion = { major: 2, minor: 0, patch: 0 -======= -// THE ANCHOR IS DERIVED THROUGH THE PARSER, never raw lists: the fields come from parsing -// the literal release text, so the confined constructor's admission is the only producer. -// The fallback is unreachable for a parsable literal, and the round-trip witness pins the -// label to "2.0.0" by execution, so a forged or control-character field cannot pass. -data git_2_0_release: GitReleaseVersion = match semver_core_parse(cps: chars(s: "2.0.0")) { - Present { value: v } => GitReleaseVersion { major: v.major, minor: v.minor, patch: v.patch } - other => GitReleaseVersion { major: semver_numeric_field(cps: chars(s: "0")).?, minor: semver_numeric_field(cps: chars(s: "0")).?, patch: semver_numeric_field(cps: chars(s: "0")).? } ->>>>>>> Stashed changes } data git_release_versioning_spec_url: NonEmptyStr = "https://git-scm.com/docs/BreakingChanges.html" @@ -59,13 +44,8 @@ data min_git_version: GitVersionConstraint = ">= 2.0.0" fn git_release_version_label(v: GitReleaseVersion) -> String { concat( -<<<<<<< Updated upstream to_string(v.major), concat(".", concat(to_string(v.minor), concat(".", to_string(v.patch)))) -======= - semver_label_from_code_points(cps: v.major.digits), - concat(".", concat(semver_label_from_code_points(cps: v.minor.digits), concat(".", semver_label_from_code_points(cps: v.patch.digits)))) ->>>>>>> Stashed changes ) } @@ -74,15 +54,9 @@ fn git_release_to_version_identity(v: GitReleaseVersion) -> VersionIdentity { } fn git_release_version_compare(a: GitReleaseVersion, b: GitReleaseVersion) -> Ordering { -<<<<<<< Updated upstream match nat_compare(a: a.major, b: b.major) { Equal => match nat_compare(a: a.minor, b: b.minor) { Equal => nat_compare(a: a.patch, b: b.patch) -======= - match semver_compare_numeric_digits(a: a.major.digits, b: b.major.digits) { - Equal => match semver_compare_numeric_digits(a: a.minor.digits, b: b.minor.digits) { - Equal => semver_compare_numeric_digits(a: a.patch.digits, b: b.patch.digits) ->>>>>>> Stashed changes other => other } other => other diff --git a/dag/extdeps/version/semver.dag b/dag/extdeps/version/semver.dag index 7836ce31282..f4788eed698 100644 --- a/dag/extdeps/version/semver.dag +++ b/dag/extdeps/version/semver.dag @@ -20,37 +20,6 @@ type SemVerIdentity = VersionIdentity type SemVerConstraint = VersionConstraint -<<<<<<< Updated upstream -======= -// A numeric component carries its code points, not a machine integer: SemVer 2.0.0 puts no -// size limit on X.Y.Z (§2) or on numeric identifiers (§9), so an Int conversion on the -// comparison path would invent a grammar failure the spec does not have. -// -// CONSTRUCTOR-CONFINED: the only admission is `semver_numeric_field`, which refuses an empty -// sequence, anything outside ASCII digits 48..57, and a leading zero unless the sequence is -// the single digit 0. Comparison and rendering project `.digits`; the parsed wire never -// carries a bare list. The negative controls in the witness file pin the refusals. -type SemVerNumericField { - digits: List -} - -fn semver_numeric_field(cps: List) -> SemVerNumericField? { - if cps.count() == 0 { - none - } else if !all(cps, cp => cp >= 48 && cp <= 57) { - none - } else if cps.count() > 1 { - match cps.first() { - Present { value: 48 } => none - Present { value: _ } => Present { value: SemVerNumericField { digits: cps } } - Absent => none - } - } else { - Present { value: SemVerNumericField { digits: cps } } - } -} - ->>>>>>> Stashed changes type SemVerIdentifier = SemVerNumericIdentifier { value: NonNegativeInt } | SemVerAlphanumericIdentifier { label: NonEmptyStr } @@ -69,15 +38,9 @@ fn semver_compare_non_negative_int(a: NonNegativeInt, b: NonNegativeInt) -> Orde fn semver_compare_identifier(a: SemVerIdentifier, b: SemVerIdentifier) -> Ordering { match a { -<<<<<<< Updated upstream SemVerNumericIdentifier { value: av } => match b { SemVerNumericIdentifier { value: bv } => semver_compare_non_negative_int(a: av, b: bv) -======= - SemVerNumericIdentifier { digits: ad } => match b { - SemVerNumericIdentifier { digits: bd } => - semver_compare_numeric_digits(a: ad.digits, b: bd.digits) ->>>>>>> Stashed changes SemVerAlphanumericIdentifier { label: _ } => Less } SemVerAlphanumericIdentifier { label: al } => match b { @@ -120,19 +83,11 @@ fn semver_compare_pre_release(a: List, b: List Ordering { -<<<<<<< Updated upstream match semver_compare_non_negative_int(a: a.major, b: b.major) { Equal => match semver_compare_non_negative_int(a: a.minor, b: b.minor) { Equal => match semver_compare_non_negative_int(a: a.patch, b: b.patch) { -======= - match semver_compare_numeric_digits(a: a.major.digits, b: b.major.digits) { - Equal => - match semver_compare_numeric_digits(a: a.minor.digits, b: b.minor.digits) { - Equal => - match semver_compare_numeric_digits(a: a.patch.digits, b: b.patch.digits) { ->>>>>>> Stashed changes Equal => semver_compare_pre_release(a: a.pre_release, b: b.pre_release) other => other } @@ -144,11 +99,7 @@ fn semver_compare(a: SemVerVersion, b: SemVerVersion) -> Ordering { fn semver_identifier_label(id: SemVerIdentifier) -> String { match id { -<<<<<<< Updated upstream SemVerNumericIdentifier { value: v } => "{v}" -======= - SemVerNumericIdentifier { digits: d } => semver_label_from_code_points(cps: d.digits) ->>>>>>> Stashed changes SemVerAlphanumericIdentifier { label: s } => s } } @@ -159,13 +110,8 @@ fn semver_identifiers_label(ids: List) -> String { fn semver_version_label(v: SemVerVersion) -> String { let core = concat( -<<<<<<< Updated upstream to_string(v.major), concat(".", concat(to_string(v.minor), concat(".", to_string(v.patch)))) -======= - semver_label_from_code_points(cps: v.major.digits), - concat(".", concat(semver_label_from_code_points(cps: v.minor.digits), concat(".", semver_label_from_code_points(cps: v.patch.digits)))) ->>>>>>> Stashed changes ) let with_pre = if v.pre_release.count() == 0 { core @@ -183,247 +129,8 @@ fn semver_to_version_identity(v: SemVerVersion) -> VersionIdentity { semver_version_label(v: v) } -<<<<<<< Updated upstream fn semver_identity_compare(a: VersionIdentity, b: VersionIdentity) -> Ordering { if a == b { Equal } else { if a < b { Less } else { Greater } } -======= -// CITED RULE (SemVer 2.0.0 §11, https://semver.org/#spec-item-11 — the authority this module's -// extdeps_external_authority_anchor attests): precedence is decided by comparing major, then -// minor, then patch as NUMBERS; a pre-release version has LOWER precedence than the normal -// version; pre-release identifiers compare numeric < alphanumeric, numerics numerically, -// alphanumerics lexically in ASCII sort order, and a larger set of pre-release identifiers ranks -// higher when all preceding identifiers are equal; build metadata is ignored entirely. -// -// The label is a VersionScheme's only handle, so the comparison parses the label back into the -// typed form and routes through `semver_compare` — the ONE implementation of the cited rule. -// §11 defines precedence over VALID versions, so a label outside the §2 grammar is a located -// refusal: the carrier names the failing side, the label, and the cause (pinned by -// w_semver_scheme_out_of_grammar_label_refuses_precedence), never a fabricated order. -fn semver_identity_compare(a: VersionIdentity, b: VersionIdentity) -> VersionComparison { - match semver_identity_parse(label: a) { - Present { value: av } => - match semver_identity_parse(label: b) { - Present { value: bv } => VersionCompared { ordering: semver_compare(a: av, b: bv) } - Absent => VersionComparisonRefused { side: RightOperand, identity: b as String, cause: "label does not satisfy the SemVer 2.0.0 version grammar, so section 11 precedence is undefined for it" } - } - Absent => VersionComparisonRefused { side: LeftOperand, identity: a as String, cause: "label does not satisfy the SemVer 2.0.0 version grammar, so section 11 precedence is undefined for it" } - } -} - -// ---- label parse (SemVer 2.0.0 §2 grammar) -------------------------------- - -fn semver_identity_code_points(label: VersionIdentity) -> List { - chars(s: label as String) -} - -fn semver_is_ascii_digit(cp: Int) -> Bool { - cp >= 48 && cp <= 57 -} - -fn semver_is_ascii_letter(cp: Int) -> Bool { - (cp >= 65 && cp <= 90) || (cp >= 97 && cp <= 122) -} - -fn semver_is_identifier_char(cp: Int) -> Bool { - semver_is_ascii_digit(cp: cp) || semver_is_ascii_letter(cp: cp) || cp == 45 -} - -fn semver_index_of(cp: Int, cps: List) -> Int? { - if cps.count() == 0 { - none - } else { - match cps.first() { - Present { value: h } => - if h == cp { - Present { value: 0 } - } else { - match semver_index_of(cp: cp, cps: cps.skip(n: 1)) { - Present { value: k } => Present { value: k + 1 } - Absent => none - } - } - Absent => none - } - } -} - -fn semver_split_on(cp: Int, cps: List, acc: List>) -> List> { - match semver_index_of(cp: cp, cps: cps) { - Present { value: i } => - semver_split_on(cp: cp, cps: cps.skip(n: i + 1), acc: concat(acc, [cps.take(n: i)])) - Absent => concat(acc, [cps]) - } -} - -fn semver_all_digits(cps: List) -> Bool { - cps.count() > 0 && all(cps, cp => semver_is_ascii_digit(cp: cp)) -} - -// §2: a numeric identifier MUST NOT include leading zeroes; "0" alone is fine. -fn semver_numeric_run_without_leading_zero(cps: List) -> Bool { - if !semver_all_digits(cps: cps) { - false - } else { - match cps.first() { - Present { value: h } => cps.count() == 1 || h != 48 - Absent => false - } - } -} - - - -fn semver_label_from_code_points(cps: List) -> NonEmptyStr { - join(cps |> map(cp => from_code_point(cp: cp)), "") as NonEmptyStr -} - -// ---- core MAJOR.MINOR.PATCH ----------------------------------------------- - -// THE LAST FIELD CONSUMES THE WHOLE REMAINDER, never a dot-split: a leftover delimiter -// then fails the numeric run here instead of being split off and silently accepted. -// SemVer 2.0.0 §2 is X.Y.Z with no trailing delimiter, so "1.2.3." must refuse, not rank. -fn semver_core_fields_parse(cps: List, remaining: Int) -> List? { - if remaining == 0 { - if cps.count() == 0 { Present { value: [] } } else { none } - } else if remaining == 1 { - match semver_numeric_field(cps: cps) { - Absent => none - Present { value: v } => Present { value: [v] } - } - } else { - match semver_index_of(cp: 46, cps: cps) { - Present { value: i } => - match semver_digits_field(cps: cps.take(n: i)) { - Absent => none - Present { value: v } => - match semver_core_fields_parse(cps: cps.skip(n: i + 1), remaining: remaining - 1) { - Absent => none - Present { value: rest } => Present { value: concat([v], rest) } - } - } - Absent => none - } - } -} - -fn semver_core_parse(cps: List) -> SemVerVersion? { - match semver_core_fields_parse(cps: cps, remaining: 3) { - Absent => none - Present { value: fields } => - if fields.count() != 3 { - none - } else { - match fields.first() { - Absent => none - Present { value: major } => - match fields.skip(n: 1).first() { - Absent => none - Present { value: minor } => - match fields.skip(n: 2).first() { - Absent => none - Present { value: patch } => - Present { value: SemVerVersion { major: major, minor: minor, patch: patch, pre_release: [], build: [] } } - } - } - } - } - } -} - -// ---- pre-release and build identifiers ------------------------------------ - -// One identifier parse for both §9 pre-release and §10 build identifiers; the only real -// difference between the two grammars is carried by strict_numeric. A no-leading-zero digit run -// is numeric (§9, §10). In strict mode — pre-release — an all-digit run WITH a leading zero is -// neither numeric ("Numeric identifiers MUST NOT include leading zeroes", §9) nor alphanumeric -// (the §2 grammar requires an alphanumeric identifier to contain a non-digit), so it refuses. -// §10 permits leading zeroes in build metadata ("1.0.0+0130"), so permissive mode keeps such a -// run as an alphanumeric identifier. An admitted numeric identifier carries its digits as code -// points: section 9 numerics have no size limit, so no machine-integer conversion happens on -// the comparison path. -fn semver_identifier_parse(cps: List, strict_numeric: Bool) -> SemVerIdentifier? { - if cps.count() == 0 { - none - } else if !all(cps, cp => semver_is_identifier_char(cp: cp)) { - none - } else if semver_numeric_run_without_leading_zero(cps: cps) { - match semver_numeric_field(cps: cps) { - Present { value: f } => Present { value: SemVerNumericIdentifier { digits: f } } - Absent => none - } - } else if strict_numeric && semver_all_digits(cps: cps) { - none - } else { - Present { value: SemVerAlphanumericIdentifier { label: semver_label_from_code_points(cps: cps) } } - } -} - -fn semver_identifier_list_parse( - segments: List>, - strict_numeric: Bool -) -> List? { - segments |> fold( - init: Present { value: [] }, - f: (st, seg) => - match st { - Absent => Absent - Present { value: acc } => - match semver_identifier_parse(cps: seg, strict_numeric: strict_numeric) { - Absent => Absent - Present { value: id } => Present { value: concat(acc, [id]) } - } - } - ) -} - -fn semver_pre_release_parse(cps: List) -> List? { - semver_identifier_list_parse(segments: semver_split_on(cp: 46, cps: cps, acc: []), strict_numeric: true) -} - -fn semver_build_parse(cps: List) -> List? { - semver_identifier_list_parse(segments: semver_split_on(cp: 46, cps: cps, acc: []), strict_numeric: false) -} - -// ---- label assembly -------------------------------------------------------- - -fn semver_identity_head_parse(cps: List, build: List) -> SemVerVersion? { - match semver_index_of(cp: 45, cps: cps) { - Present { value: pi } => - match semver_core_parse(cps: cps.take(n: pi)) { - Absent => none - Present { value: core } => - match semver_pre_release_parse(cps: cps.skip(n: pi + 1)) { - Absent => none - Present { value: pre } => - Present { value: SemVerVersion { major: core.major, minor: core.minor, patch: core.patch, pre_release: pre, build: build } } - } - } - Absent => - match semver_core_parse(cps: cps) { - Absent => none - Present { value: core } => - Present { value: SemVerVersion { major: core.major, minor: core.minor, patch: core.patch, pre_release: [], build: build } } - } - } -} - -fn semver_identity_parse(label: VersionIdentity) -> SemVerVersion? { - semver_version_parse(cps: semver_identity_code_points(label: label)) -} - -// Code-point entry for sibling schemes whose labels carry a scheme-specific prefix (go's "v"): -// the grammar and the precedence stay HERE — the one implementation — and the sibling keeps only -// its own prefix and acceptance rules. -fn semver_version_parse(cps: List) -> SemVerVersion? { - match semver_index_of(cp: 43, cps: cps) { - Present { value: bi } => - match semver_build_parse(cps: cps.skip(n: bi + 1)) { - Absent => none - Present { value: build } => semver_identity_head_parse(cps: cps.take(n: bi), build: build) - } - Absent => semver_identity_head_parse(cps: cps, build: []) - } ->>>>>>> Stashed changes } data semver_scheme: VersionScheme = VersionScheme { From 61849f05bf785905b37fda78b2d84e93c8efe9fb Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Tue, 6 Oct 2026 17:00:56 +0000 Subject: [PATCH 10/14] Rewrite the self_host probe block without conflict markers An earlier stash pop left <<<<<<< Updated upstream / >>>>>>> Stashed changes inside the compile_dag_rust_emit_check arguments (RFM class a_verification_reads_its_own_label_not_its_output, committed this time). The block now reads std.optional and names map_get_checked; the asserted emitted target crate::v2_std_collection::map_get_checked( is unchanged. --- ..._host_emitted_call_target_realization_witness_test.dag | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag index c257813913e..257c6959d15 100644 --- a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag +++ b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag @@ -265,24 +265,20 @@ test fn w_clone_bound_forwards_transitively_over_two_call_hops() -> Bool { // restricted pool (2973 modules against the corpus's 4261), and a qualified spelling alone does not // put the target module in it -- so without the import this row FAILED while the repair was green, // which is how it was found. Measured both ways: the same probe emitted against the real corpus -// produces `crate::v2_std_collection::map_get_checked(m.clone(), "key".to_string())` exactly as asserted. +// produces `crate::v2_std_collection::map_get(m.clone(), "key".to_string())` exactly as asserted. // The import restores module presence; it does not answer the call, because decl_name is taken from // the authored spelling at the CALL SITE regardless of what is imported -- which is why the // negative assertion below still discriminates, and why falsifier 2 (restore the dotted spelling) // must red this row. // // CLASS C, THE DISCRIMINATING RED. A qualified call carried the whole dotted path as its -// declaration name, so emission produced `crate::v2_std_collection::v2.std.collection.map_get_checked(..)` +// declaration name, so emission produced `crate::v2_std_collection::v2.std.collection.map_get(..)` // -- the module prefix correct and the identifier a dotted path Rust reads as field access on an // undefined value `v2`. map_get is the specimen because it is also DivergentProjection, so this // row proves the qualified path reaches the DECLARATION and not the bridge. test fn w_qualified_call_emits_only_the_declaration_last_segment() -> Bool { compile_dag_rust_emit_check( -<<<<<<< Updated upstream - "module test.claim.qualified_call_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 v2.std.optional { Optional }\nfn probe(m: Map) -> Outcome> { v2.std.collection.map_get_checked(m: m, key: \"key\") }\n", -======= "module test.claim.qualified_call_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) -> Outcome> { v2.std.collection.map_get_checked(m: m, key: \"key\") }\n", ->>>>>>> Stashed changes "src/test_claim_qualified_call_probe.rs", ["crate::v2_std_collection::map_get_checked("], ["::v2.std.collection", "v2.std.collection.map_get_checked("] From 51aefcc54400f8a7b99a210ced6df339aced5d7d Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 7 Oct 2026 00:28:06 +0000 Subject: [PATCH 11/14] Re-point the three remaining synthesized-probe imports to std.optional after #13388 The probes at :60, :699, :754 still imported v2.std.optional (defunct since the Optional de-fork); their compile.frontend refused, so three witnesses red. Same class as the :281 probe re-point review 77124 asked for. Verified attribution for the one remaining red in this entry (w_depth_one_shared_field_refutation_stays_shape_guarded): it fails on origin/main's own tree identically (exit=1 FAIL=1 at main), so it is main-carried latent debt, untouched here. --- ...lf_host_emitted_call_target_realization_witness_test.dag | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag index 257c6959d15..b8e4ae8b46b 100644 --- a/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag +++ b/dag/test/claim/self_host_emitted_call_target_realization_witness_test.dag @@ -57,7 +57,7 @@ test fn w_map_type_position_still_uses_its_declared_host_realization() -> Bool { // seed fallback, instead of silently constructing the structural algebra carrier under that type. test fn w_host_map_record_shape_refuses_instead_of_constructing_a_second_carrier() -> Bool { compile_dag_rust_emit_check( - "module test.claim.map_record_shape_probe\nimport std.types { Int, String, Map }\nimport v2.std.optional { Present }\nfn probe(m: Map, key: String, value: Int) -> Map { Map { lookup: fn(candidate) { if candidate == key { Present { value: value } } else { m.lookup(candidate) } } } }\n", + "module test.claim.map_record_shape_probe\nimport std.types { Int, String, Map }\nimport std.optional { Present }\nfn probe(m: Map, key: String, value: Int) -> Map { Map { lookup: fn(candidate) { if candidate == key { Present { value: value } } else { m.lookup(candidate) } } } }\n", "src/test_claim_map_record_shape_probe.rs", ["HashMap", "record-shaped carrier has no realization"], ["FinitelySupportedFunction", "Map {\n"] @@ -696,7 +696,7 @@ test fn w_alias_of_a_keyed_collection_renders_the_host_map_template() -> Bool { // call (E0277, three sites in v2_std_collection). The bound is read from the signature. test fn w_generic_map_key_parameter_carries_the_host_key_bounds() -> Bool { compile_dag_rust_emit_check( - "module test.claim.map_key_bound_probe\nimport v2.std.collection { Map, map_lookup }\nimport v2.std.optional { Optional }\nfn probe(m: Map, key: K) -> Optional {\n map_lookup(m: m, key: key)\n}\n", + "module test.claim.map_key_bound_probe\nimport v2.std.collection { Map, map_lookup }\nimport std.optional { Optional }\nfn probe(m: Map, key: K) -> Optional {\n map_lookup(m: m, key: key)\n}\n", "src/test_claim_map_key_bound_probe.rs", ["pub fn probe Bool { compile_dag_rust_emit_check( - "module test.claim.optional_param_probe\nimport std.types { Int }\nimport v2.std.optional { Optional }\nfn inspect(opt: Optional) -> Optional { opt }\nfn caller(x: Optional) -> Optional { inspect(opt: x) }\n", + "module test.claim.optional_param_probe\nimport std.types { Int }\nimport std.optional { Optional }\nfn inspect(opt: Optional) -> Optional { opt }\nfn caller(x: Optional) -> Optional { inspect(opt: x) }\n", "src/test_claim_optional_param_probe.rs", ["inspect(x.clone())"], [".expect(\"fail-closed: an optional value flowed into non-optional parameter"] From 7c7656b54d4096dba653ce0c839afc4f46d0c6ee Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 7 Oct 2026 02:51:05 +0000 Subject: [PATCH 12/14] Drop the stale std_optional mirror registration (lib.rs drift after #13388) Fresh emission at this head no longer contains a v2.std.optional module (re-homed to std.optional by #13388), so the registration is stale and required-regen refuses. Main's own lib.rs carries the same stale registration; main's pushes never re-run required-regen, so it surfaces only at a PR head. Byte-exact inverse of the drift line CI reported at 51aefcc544. --- src/v1/stage0/src/lib.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/v1/stage0/src/lib.rs b/src/v1/stage0/src/lib.rs index db3e0f259d1..1f3a31a67b0 100644 --- a/src/v1/stage0/src/lib.rs +++ b/src/v1/stage0/src/lib.rs @@ -312,17 +312,6 @@ pub mod std_occurrence_binding_resolve; suspicious_double_ref_op, clippy::all )] -pub mod std_optional; -#[allow( - unused_imports, - unused_variables, - unused_mut, - unused_parens, - dead_code, - non_shorthand_field_patterns, - suspicious_double_ref_op, - clippy::all -)] pub mod std_reference_binding_observation; #[allow( unused_imports, From d3b5791c65eba1852b5bff68d54f12a067cece31 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 7 Oct 2026 04:58:23 +0000 Subject: [PATCH 13/14] Review 77428: enrol the rival predicate's own discriminating control; state the seam arm's reach honestly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The seam arm's comment claimed a future re-widening would flip it red from inside the synthetic fixture — false: parent_closure_callable_candidates takes the declared identity's decl_name from the LOOKUP KEY (v1_compiler_infer_sigs.rs:339), the compiled roster's only DivergentProjection row answers to (v2.std.collection, map_get_checked) (std_primitive_projection.rs:423-425), and the registry keys the primitive as map_get (v1_compiler_infer_method.rs:719), so no lookup name can carry both a rival declaration and a builtin co-candidate. That absence is the repair landing, not a hole. The comment now says so. The mechanism's executing evidence stays enrolled (DESIGN 4b(4)): declared_candidate_rivals_the_builtin_discriminates_by_row_fidelity checks the predicate against the compiled roster's actual rows — the divergent declaration must rival, a modeled projection must not, an unprojected declaration must not, a builtin is never a rival to itself. cargo test -p v1-compiler --lib declaration_index: 8 passed 0 failed (both this and the seam arm). --- src/v1/stage0/src/declaration_index.rs | 101 +++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 8 deletions(-) diff --git a/src/v1/stage0/src/declaration_index.rs b/src/v1/stage0/src/declaration_index.rs index 22556298445..2f88bb06e68 100644 --- a/src/v1/stage0/src/declaration_index.rs +++ b/src/v1/stage0/src/declaration_index.rs @@ -3609,14 +3609,29 @@ mod import_binding_authority_tests { // THE OLD map_get FORK IS DISSOLVED, AND THIS ARM IS ITS PERMANENT REGRESSION CONTROL, // checked by its exact identity set rather than a count or list order. Before the rename, - // a module that omitted the declaration from its authored list while calling the bare name - // minted TWO rival authorities -- `builtin:map_get` and - // `declared:v2.std.collection:map_get` -- and went ambiguous. The declared projection now - // answers to `map_get_checked` alone, so the bare spelling has no declared candidate and - // only the builtin rival remains, which this callable route leaves unresolved (builtins - // reach inference through the method path). A future re-widening -- a declared projection - // reclaiming the bare spelling -- puts the rival back and flips this arm to - // FuncSigAmbiguous, failing here. + // omitting the declaration from the authored list while calling the bare name minted TWO + // rival authorities -- `builtin:map_get` and `declared:v2.std.collection:map_get` -- and + // went ambiguous. The rename moved the declaration to `map_get_checked`, so the bare + // spelling now has no declared candidate at all: only the builtin remains, which this + // route leaves unresolved (builtins reach inference through the method path). + // + // HONESTY ABOUT WHAT THIS ARM CAN AND CANNOT SEE ANY MORE (review 77428). The former + // rival-join -- a rival declaration omitted from the authored list joining the builtin + // into FuncSigAmbiguous -- is NOT reachable at this seam any more, and that absence is + // the repair, not a hole: the only DivergentProjection row in the compiled roster + // (std_primitive_projection.rs) answers to the declaration `map_get_checked`, which is + // not a primitive-registry key, while the registry keys the primitive as `map_get` + // (v1_compiler_infer_method.rs). parent_closure_callable_candidates takes the declared + // identity's decl_name from the LOOKUP KEY, so no lookup name can carry both a rival + // declaration and a builtin co-candidate; a synthetic fixture that "declares map_get" + // mints the identity (v2.std.collection, map_get), which the roster does not cover. A + // re-widening that reclaimed the bare spelling under a registry-keyed name would + // re-ambient the join, but THIS arm would still green until a lookup name carried both + // authorities -- so the rival predicate's own discriminating control + // (declared_candidate_rivals_the_builtin_discriminates_by_row_fidelity, below) stays + // enrolled as the executing evidence for the mechanism, per DESIGN 4b(4), and the census + // wall w_projection_census_declares_no_divergent_shared_spelling holds the no-shared- + // spelling fact at the tree grain. match &*bare { FuncSigLookup::FuncSigUnresolved => {} FuncSigLookup::FuncSigAmbiguous { candidates } => panic!( @@ -3630,4 +3645,74 @@ mod import_binding_authority_tests { ), } } + + /// THE RIVAL PREDICATE'S OWN DISCRIMINATING CONTROL, ENROLLED AFTER THE RENAME DISSOLVED THE + /// SEAM'S SHARED SPELLING (review 77428; DESIGN 4b(4): the class's executing evidence stays + /// enrolled). Checked against the COMPILED roster's actual rows, so a row that loses its + /// DivergentProjection fidelity, a predicate that stops consulting the roster, or a roster + /// that stops carrying the divergent specimen all fail here. The identity values are the + /// mechanism's own data: the divergent declaration must rival, a modeled projection must + /// not, an unprojected declaration must not, and a builtin candidate is never a rival to + /// itself. + #[test] + fn declared_candidate_rivals_the_builtin_discriminates_by_row_fidelity() { + use crate::v1_compiler_infer_lookup::declared_candidate_rivals_the_builtin; + use crate::v1_compiler_infer_sigs::CallableIdentity::{BuiltinCallable, DeclaredCallable}; + use crate::v1_compiler_infer_sigs::{CallableCandidate, DeclaredCallableIdentity}; + + let candidate_for = |owner: &str, decl: &str| { + Rc::new(CallableCandidate { + identity: Rc::new(DeclaredCallable { + identity: Rc::new(DeclaredCallableIdentity { + owner_module_path: owner.to_string(), + decl_name: decl.to_string(), + }), + }), + sig: parent_env_declaring_map_get_checked() + .parents + .iter() + .next() + .expect("fixture parent") + .local + .values() + .next() + .expect("fixture signature") + .clone(), + }) + }; + + // The compiled roster's one DivergentProjection row: the declaration must rival. + assert!(declared_candidate_rivals_the_builtin(candidate_for( + "v2.std.collection", + "map_get_checked" + ))); + // A modeled projection is a faithful alias, never a rival. + assert!(!declared_candidate_rivals_the_builtin(candidate_for( + "v2.std.collection", + "empty_map" + ))); + // An unprojected declaration is never a rival. + assert!(!declared_candidate_rivals_the_builtin(candidate_for( + "cut.unrelated.module", + "map_get_checked" + ))); + // A builtin candidate is never a rival to itself. + assert!(!declared_candidate_rivals_the_builtin(Rc::new( + CallableCandidate { + identity: Rc::new(BuiltinCallable { + primitive_name: "map_get".to_string(), + }), + sig: parent_env_declaring_map_get_checked() + .parents + .iter() + .next() + .expect("fixture parent") + .local + .values() + .next() + .expect("fixture signature") + .clone(), + } + ))); + } } From 0edf0e5d64608da009bafd60747210a9eaec3b27 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 8 Oct 2026 06:57:30 +0000 Subject: [PATCH 14/14] Merge origin/main; rename floor_pure_producer_share to map_get_checked; repair dual-dispatch optional equality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge brings in main's new consumer of the declared map_get: src/v2/workflow/floor_pure_producer_share.dag imports map_get from v2.std.collection and consumes the Outcome contract (five call sites match Accepted { value: .. } / Rejected), so it renames to map_get_checked with the declaration. Consumer census on the merged tree finds no other importer of the declared spelling. dag/test/claim/map_lookup_dual_dispatch_witness_test.dag (new on main) compared the dual-dispatch lookups' Optional results against required values — the #13179 T? == T refusal, same silent class as os_install_actuator_selection_witness_test. Its own lookup test already documents the discriminating form: 'Matching Present is still the discriminating form'. The method and index tests now match on Present/Absent instead of comparing raw. Local parse-check of the merged tree at the floor_pure_producer_share entry: 0 blocking diagnostics, 109 files emitted. --- .../claim/map_lookup_dual_dispatch_witness_test.dag | 12 ++++++++++-- src/v2/workflow/floor_pure_producer_share.dag | 12 ++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/dag/test/claim/map_lookup_dual_dispatch_witness_test.dag b/dag/test/claim/map_lookup_dual_dispatch_witness_test.dag index 6aae645207a..3febbb72a1e 100644 --- a/dag/test/claim/map_lookup_dual_dispatch_witness_test.dag +++ b/dag/test/claim/map_lookup_dual_dispatch_witness_test.dag @@ -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 { diff --git a/src/v2/workflow/floor_pure_producer_share.dag b/src/v2/workflow/floor_pure_producer_share.dag index 28d3129de9e..a204327c4a0 100644 --- a/src/v2/workflow/floor_pure_producer_share.dag +++ b/src/v2/workflow/floor_pure_producer_share.dag @@ -17,7 +17,7 @@ import std.materialization_ladder { import std.measure { Millisecond, Nanosecond, byte_size, millisecond_count, nanosecond, nanosecond_count } import v2.workflow.required_floor { required_floor_new_witness_envelope_ms } import v2.std.algebra { any, list_flat_map, list_map } -import v2.std.collection { empty_map, map_get, map_insert } +import v2.std.collection { empty_map, map_get_checked, map_insert } import v2.std.diagnostic { Accepted, Rejected, Outcome } import std.optional { Absent, Present, Optional } @@ -401,7 +401,7 @@ fn share_map_lookup_causes(o: Outcome>) -> List, claim: String) -> Bool { - let o = map_get(wholes, claim) + let o = map_get_checked(wholes, claim) if length(xs: share_map_lookup_causes(o: o)) > 0 { false } else { @@ -414,7 +414,7 @@ fn reads_whole_value(wholes: Map, claim: String) -> Bool { } fn projection_count(counts: Map, field: String) -> Int { - let o = map_get(counts, field) + let o = map_get_checked(counts, field) if length(xs: share_map_lookup_causes(o: o)) > 0 { 0 } else { @@ -432,14 +432,14 @@ type ShareCountState { } fn add_projection_count(state: ShareCountState, wholes: Map, claim: String, field: String) -> ShareCountState { - let whole_o = map_get(wholes, claim) + let whole_o = map_get_checked(wholes, claim) let whole_unread = share_map_lookup_causes(o: whole_o) if length(xs: whole_unread) > 0 { ShareCountState { counts: state.counts, unread: concat(state.unread, whole_unread) } } else if reads_whole_value(wholes: wholes, claim: claim) { state } else { - let count_o = map_get(state.counts, field) + let count_o = map_get_checked(state.counts, field) let count_unread = share_map_lookup_causes(o: count_o) if length(xs: count_unread) > 0 { ShareCountState { counts: state.counts, unread: concat(state.unread, count_unread) } @@ -475,7 +475,7 @@ fn sole_projections_from_state(reads: List, counts: Map - let count_o = map_get(counts, f) + let count_o = map_get_checked(counts, f) let unread = share_map_lookup_causes(o: count_o) if length(xs: unread) > 0 { []