Skip to content

Refuse phantom classification without evidence - #9983

Merged
briansrls merged 1 commit into
mainfrom
session/neat-otter-332-marker-evidence-v2
Sep 2, 2026
Merged

briansrls merged 1 commit into
mainfrom
session/neat-otter-332-marker-evidence-v2

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 2, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

This v1-freeze maintenance cut serves the v2 self-host program. It fixes an evidence defect at the Rust applied-type renderer seam: the renderer previously received an empty TypeEnv, and an unobserved unit-variant census silently answered “absent.” The advertised lookup never had identity evidence; NS-0B removed the fallback coincidence rather than breaking rendering.

This does not fix or claim the separate 48-alias NS-0B marker regression. Main's emitted marker bytes remain correct by coincidence until the occurrence-to-renderer identity modeling question is resolved separately.

Change

  • Thread the module-own TypeEnv through the shared applied-type renderer path.
  • Represent census observation explicitly and return typed EvidenceUnavailable rather than widening “no evidence” into “not a marker.”
  • Preserve that modeled uncertainty at last-resort resolver selection with the located UnitVariantPhantomIdentityEvidenceUnavailable { name, span } diagnostic; do not fabricate UnresolvedType when the missing census prevents that conclusion.
  • Add a real-renderer discriminator: an empty census refuses, while a genuinely populated Time contribution renders through the positive arm.
  • Regenerate the nine affected Rust projections from the edited authorities.

The refusal is established AT THIS RENDERER SEAM, by a fixture that reaches the real applied-type renderer. It does not establish that every consumer of the marker classification refuses on empty evidence, and it does not fire #9915's ceiling trigger.

Authority and regenerated projections are one atomic commit; an authority-only head would be an invalid intermediate.

Constructor census

The raw brace-form census found 25 matches under stage0. One is the TypeEnv struct definition, leaving 24 constructors = 17 generated + 7 hand-maintained. No alternate TypeEnv::new, TypeEnv::default, or braceless construction path exists. The seven hand sites all truthfully set unit_variant_index_observed: false, for distinct local reasons:

  • infer_semantics_witness.rs:336: empty_type_env is unobserved by definition.
  • :1078, :1109, :1140: Optional fixtures carry Optional through cardinality and do not build this census.
  • :1279: ordinary User TypeBinding; it never runs build_unit_variant_index.
  • :2004: ordinary generic Box TypeBinding; it never runs that census.
  • cli_run.rs:34880: a SymbolIndex/bindings probe; it does not scan a unit-variant census.

No hand-maintained site is observed=true. Production establishes that state only through build_unit_variant_index; the populated renderer fixture exercises that true path with a real Time contribution.

The seed-growth rosters govern DeclarationRef/public-item additions. These edits change existing bodies and add zero declarations or public items, so no roster member is added. The PURPOSE admission is explicit: this frozen-v1 maintenance enables the v2 self-host program.

Evidence

  • Unfixed main RED: the real renderer fixture reports empty census silently answered absence; rendered=Box<Time>.
  • Corrected GREEN: render_rust_applied_type_routes_qualified_base_through_leaf_name passes with both empty-evidence refusal and populated-index positive control.
  • Clean producer lineage from base 99ace7a15668f0d2d364a1aeef53076215524459: the original lineage changed eight projections; the resolver-diagnostic correction then changed exactly v1_std_core.rs and v1_compiler_infer_resolve.rs; the final exact-tree regeneration reached first_generation_equal=true, planned/executed/adjudicated 149/149/149.
  • The final projection population is nine paths. v1_std_core.rs moved because it is the generated projection of the diagnostic type, span, and message authority; v1_compiler_infer_resolve.rs moved because it projects the resolver emission arm.
  • Install bridge: admitted set equals installed set in both directions for the terminal candidates; every destination is byte-equal to its candidate. Cargo.toml was neither offered nor applied.
  • cargo test --release -p v1-compiler --all-targets --no-run succeeds, covering test-only and binary constructors.
  • git diff --check and pre-commit/pre-push formatting checks succeed.

Resolver-refusal instrument correction

The speculative-peel witness already said it counted typed resolver refusals, but its filter counted only UnresolvedType. The refusal population legitimately grew when missing marker evidence became the distinct, truthful UnitVariantPhantomIdentityEvidenceUnavailable; the instrument now counts the enumerated union and separately asserts that both observed refusals are the evidence-unavailable variant. The union is deliberately enumerated: a broad “any diagnostic” predicate would accept unrelated diagnostics, while adding another typed refusal variant to this path now obliges updating this roster.

With the correction present, the exact witness observes total typed resolver refusals 2, evidence-unavailable refusals 2, retired diagnostics 0, and quiet diagnostics 0. A dropped-arm mutation that emitted no diagnostic went RED at cli_run.rs:34965: a resolver refusal during speculative peel must remain typed and countable, with left: 0, right: 2. A second mutation replaced the truthful evidence-unavailable diagnostic with fabricated UnresolvedType: the union-total assertion passed at 2, then the composition assertion went RED at cli_run.rs:34969: an unobserved marker census must remain a distinct typed refusal, with left: 0, right: 2. Each mutation was restored by SHA-256 and byte comparison before its green rerun.

Named emitted consequence: Nat field realization

WalkPopulationBudgetRefusal.population_index changes from the authored alias spelling Nat to its grounded Rust realization i64. This is the evidence fix exposing an existing native-numeric decision, not a unit-variant decision: v1.compiler.coercion.numeric_realization_declaring_modules enrolls dag/std/nat.dag, and rust_seed_host_numeric_alias therefore realizes that declaration as i64. The generated std_nat.rs independently declares pub type Nat = i64.

At this exact head there is no Measure<..., Nat> occurrence in std_realization_schedule.rs. The remaining Nat spelling is the import plus cost_account_time_count's return. That return takes the function-signature path, where rust_fn_sig_preserves_authored_alias_leaf explicitly preserves Nat; it does not consult the applied-type unit-variant census. The record field takes render_rust_field_type_with_applied_binding and the native-numeric realization authority. The spellings differ by a declared renderer policy but denote the same Rust type through pub type Nat = i64; this PR newly changes only the field because the formerly empty renderer environment prevented that path from seeing the grounded declaration.

The complete terminal emitted candidate crate was checked directly with cargo check --release and succeeds. This is separate from the seed all-target build.

@briansrls briansrls left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REQUEST_CHANGES at exact head f0ed0fd2a8e2a9e96a42cd084a4e34d857aeaf5d.

The technical repair is accepted: the module-own TypeEnv reaches the applied-type renderer, observation is no longer conflated with absence, UnitVariantPhantomEvidenceUnavailable becomes a distinct located refusal rather than fabricated UnresolvedType, and the two mutations discriminate both refusal presence and refusal identity. The bounded claim is also honest: this proves the renderer seam, not every marker-classification consumer or the separate NS-0B alias population.

The present head cannot be authorized for landing because its exact-tree evidence is stale against current main. f0ed0fd2... is one commit on parent 99ace7a...; live main is now 3ac78310..., nine commits ahead. Both histories changed src/v1/compiler_tests_rust.dag, and both changed its generated projections src/v1/stage0/src/compiler_tests.rs and src/v1/stage0/src/v1_compiler_compiler_tests_rust.rs. The branch's 149/149/149 fixed point and exact-head CI therefore certify only the pre-composition tree. --match-head-commit would pin the source head but would not prove the automatically composed landing tree or its generated fixed point.

The cached GitHub merge subject is also unusable: it still names a merge into 87ecf818..., while the live pull endpoint currently reports mergeability unknown against a stale base snapshot.

Required re-review bar: merge current main forward into this branch (do not rebase away the reviewed history); preserve both authority edits; regenerate the generated projections from the composed authority rather than accepting a textual merge; reach a fresh exact-head fixed point and install bridge; run exact-head CI; return the new SHA.

Metadata correction on return: the PR body sentence saying these edits add 'zero declarations or public items' is literally too broad because UnitVariantPhantomLookup is a new modeled declaration and generated public enum. The seed-growth conclusion can remain, but should say zero hand-authored Rust seed declarations/public items.

@briansrls
briansrls merged commit 877a3d8 into main Sep 2, 2026
6 checks passed
@briansrls
briansrls deleted the session/neat-otter-332-marker-evidence-v2 branch September 2, 2026 03:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant