Skip to content

Rust emitter: String ordering via the host text carrier, present-binding arms, bytes_octets/utf8_encode_bytes as realized seams (native App Attest) - #12261

Merged
gunbai-bot[bot] merged 12 commits into
mainfrom
session/wise-hawk-615
Sep 25, 2026
Merged

gunbai-bot[bot] merged 12 commits into
mainfrom
session/wise-hawk-615

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Rust emitter gaps blocking native App Attest (#12251, stern-raven-24). Each defect was traced back to the earliest link that could not be justified (DESIGN §6b), not patched per call site.

C: String ordering (Timestamp <). Timestamp comparison did not need a new typed ordering. The interpreter already orders Strings byte-lexicographically (its (Str, Str) arm), and gunbc.auth.approval_capability utc_instant_before is itself a < b. The fault was in the emitter's operand classifier, v1.compiler.emit_rust rust_operand_realization_of_type. It filed the corpus String as OperandIdentityUnavailable, even though the type renderer realizes String as the host text carrier (is_host_text_carrier_type). So < refused by operator class while == on the same operand passed.

  • std.operator_realization HostRealizationReason gains HostTextCarrier, and the classifier now reads the renderer's own predicate.
  • is_string_comparison admits Lt/Gt/Le/Ge through the same host-string seam that equality uses.
  • An ordering over an optional String refuses at emission with a typed compile_error!. The interpreter has no Null-vs-Str ordering, and Rust's None-first Option order would be a fabricated answer.

A: present binding (null => 0; o => o). emit_typed_match_arm_strs reads the checker's own optional_scrutinee_binding_is_present over match_unguarded_absent_arm_index. It emits Some(o) in exactly that arm and does not re-derive the narrowing.

D: octets. std.bytes bytes_octets and utf8_encode_bytes were builtins the interpreter intercepts, but their .dag bodies were placeholders:

  • bytes_octets emitted [pure_dag_seam_unreachable()], i.e. vec![1 / 0].
  • utf8_encode_bytes emitted s as Bytes, a cast no Rust row realizes, which became a runtime panic.

Both are now declared HostRealizedSeams: a self-call body, a std.primitive_projection row, a std.primitive_identity declaration with a SourcePreservingOrder traversal fact, an rt_function_registry row, and a v1.runtime_rust body. bytes_octets returns List<Int>, per the bounded_natural_arithmetic_evaluated_as_unbounded_int ruling (the same retype #12250 makes). UInt8 has no emitted realization that can hold an octet, and bytes_qualified_octets is the one boundary that checks the range.

More links, found by execution and review:

  • TCO turned a realized seam into an infinite loop. Once rostered and bridged, call sites routed to v1_rt::bytes_octets, but the name-keyed tail-call rewrite lowered the declaration to loop { … continue; }. That's the invalid state of host_seam_self_call_diverges_when_its_arm_is_absent, reached with the arm present. rust_host_seam_is_realized (same registry as the unrealized arm) now exempts a realized seam from the TCO and stacker lowerings.
  • unconditional_panic refused every crate reaching std.bytes. rustc's deny-by-default lint fires on pure_dag_seam_unreachable's constant 1 / 0. The first cut relaxed the lint for generated code. Review 71098 correctly refused that: it widens a real check to get one placeholder through, and the placeholder is the earlier link. pure_dag_seam_unreachable is now a realized seam too, and the lint stays on. It has a self-call body, a roster row, an identity declaration with an OrderFreeResult traversal fact, and a registry row. In v1_rt it panics by name. The interpreter gets a new free_call.pure_dag_seam_unreachable arm that refuses with a typed error naming the seam, where before it relied on DivisionByZero.
  • Present binding in the String-literal re-emission (side chat). emit_typed_match's needs_string_from path re-emitted arms without the decision. It now reads the same predicate, and a string-literal arm over an optional scrutinee emits Some(ref __s), since a literal matches only a present value.
  • Present binding in the tail-call lowering. The native-app-attest run left one error, in extdeps.standards.rfc_5280 read_extensions_list: a tail-recursive function, whose matches are rendered by emit_typed_tco_match_arm. That emitter now reads the same checker predicate. The fixtures gained a tail-recursive case, and the expected line gained 989.

Evidence (local; BuildBuddy can't run gunbc, see HostBudgetUnreadable):

  • Fixture test.fixture.emitted_interpreted_parity.string_order_octets_present_binding:
    • Interpreted, it exits 0; a RED control (wrong expected line) exits 1 and prints the observed line.
    • Emitted, the crate builds and prints the identical line T F T F T 6 2962370309 97 0 989 ex none q (exit 0).
  • Enrolled claim module test.claim.emitter_string_order_present_binding_witness_test (5 test fns, all PASS locally): host-string ordering over an alias; the named refusal for ordering over a String?, which inference admits today, so the refusal arm is reachable; and the present binding in all three match renderings (ordinary, tail-call, String-literal re-emission). An earlier Rust integration target was deleted per review 71155, since CI never executes those.
  • Before the fix (on main): < emitted compile_error!("operator realization: host operator < on an operand whose declaration could not be read …"), bytes_octets emitted vec![1/0] (rustc: attempt to divide 1_i64 by zero), and utf8_encode_bytes panicked with unsupported cast from String to Vec<u8>.
  • --required-regen: first_generation_equal=true.
  • Receipts were added to accepted_source_emits_uncompilable_target and host_seam_self_call_diverges_when_its_arm_is_absent. The class rung is unchanged (mitigatable); its trigger is still a required phase that emits and compiles a fixture closure.

Integration: gunbc test //gunbc/instruments:native-app-attest on #12251 merged with this branch. At 3754b5c, the emitted App Attest crate went from 45 rustc errors to 1, which was the tail-call arm fixed above. The re-run at the current head will be posted as a comment.

v1 seed growth: purpose receipt (gunbc.v1_maintenance_standing v1_seed_standing). This PR adds hand-written seed Rust:

  • one interpreter arm, free_call.pure_dag_seam_unreachable;
  • three v1_rt bodies, bytes_octets, utf8_encode_bytes and pure_dag_seam_unreachable, mirrored in v1.runtime_rust.

Each one replaces a .dag placeholder whose emitted form was fabricated or refused: vec![1/0], a String→Vec cast panic, and a constant 1 / 0 that rustc rejects crate-wide. Each is the realization of a seam the interpreter already intercepted, except the new arm, which replaces DivisionByZero with a refusal that names the seam. Purpose: v2 self-host emission plus native App Attest. The checkable receipt is the native-app-attest run on #12251 posted in the comments (exit 0, 14/14 held), which fails on main without this change.

Found and NOT fixed here (interpreter/inference, not the emitter): a function returning String? via Present { value: s } gives the interpreter a variant value. A later literal arm then never matches it, and v => v binds the whole variant even though inference types v as String. When the optional comes from a builtin like first, the interpreter holds a bare value, so the fixture uses first. Reported to the parent lane.

Not in scope: octets_bytes (o as Bytes) still emits the unsupported-cast panic. It is loud rather than silent, and App Attest doesn't reach it.

🤖 Generated with Claude Code

gunbc-ci-auto-heal and others added 6 commits September 24, 2026 19:23
…ing arms, bytes_octets/utf8_encode_bytes as realized seams

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	dag/gunbc/recurring_failure_mode/accepted_source_emits_uncompilable_target.dag
#	src/v1/stage0/src/extdeps_languages_rust_emit.rs
#	src/v1/stage0/src/v1_compiler_emit_rust.rs
#	src/v1/stage0/src/v1_compiler_runtime_rust.rs
#	src/v1/stage0/src/v1_rt.rs
…1098); present binding in the tail-call match lowering too

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Review 71098 (the unconditional_panic finding): agreed, and fixed in a7b98b3. The earliest unjustified link was the 1 / 0 placeholder, not the lint, so the relaxation is reverted. std.bytes pure_dag_seam_unreachable is now a rostered HostRealizedSeam. In v1_rt it panics by name. In the interpreter a new free_call.pure_dag_seam_unreachable arm refuses with a typed error naming the seam; I checked that control locally. Emitted std_bytes.rs now reads pub fn pure_dag_seam_unreachable() -> i64 { v1_rt::pure_dag_seam_unreachable() }, and the fixture crate builds with the lint on. The _float/_string projections keep their .dag bodies, which call the Int seam, so they diverge through it.

— sent from wise-hawk-615

@gunbai-bot

gunbai-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Integration receipt at a7b98b3: I merged it into #12251's branch (809a5db) in a scratch worktree, reached the regen fixed point, then ran gunbc test //gunbc/instruments:native-app-attest. It exits 0.

— sent from wise-hawk-615

@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.

SOURCE HOLD at exact live head 18afcb15720d66f86f76d54b773f8235c6727cbe (the requested a7b98b3da14c1dbfcf725c3e5b877aacd15beb9f was superseded by a main merge whose only textual conflict was dag/std/bytes.dag).

The implementation direction is accepted. The ordinary and TCO match renderers now read the checker's own match_unguarded_absent_arm_index / optional_scrutinee_binding_is_present authority, so a binding after an unguarded Absent arm emits Some(binding) rather than re-deriving narrowing. String ordering is correctly admitted through the same host-text-carrier predicate used by type rendering, and the UTF-8/order fixture discriminates the interpreter's ordering. bytes_octets, utf8_encode_bytes, and pure_dag_seam_unreachable are modeled as realized seams at the primitive/runtime authorities; the realized-seam test prevents the self-call declaration from being rewritten as TCO recursion; and the unconditional-panic lint remains enabled. The a7b head had all five checks green, and the scratch composition with #12251 executed native-app-attest 14/14 with exit 0.

Two narrow blockers remain.

  1. The Optional refusal branch has no committed discriminator. This PR deliberately adds is_optional_string_ordering so an Optional String ordering cannot fall through to Rust's Option ordering (which would fabricate a None-first answer where the interpreter refuses Null-vs-Str). But the fixture and integration test exercise only non-optional Timestamp/String ordering. Add an emitted-path control whose source orders optional Strings and establish the typed compile_error!/refusal, alongside the existing non-optional green control. Without that, the safety branch may be unreachable or misclassified while all current evidence remains green.

  2. The durable occurrence receipt omits the final tail-call repair and cites stale output. accepted_source_emits_uncompilable_target still says the parity fixture prints T F T F T 6 2962370309 97 0. The fixture now requires T F T F T 6 2962370309 97 0 989; 989 is the discriminator for the separate emit_typed_tco_match_arm present-binding path found in rfc_5280.read_extensions_list. Update the receipt to name both renderers and the ten-field result. The PR body is already accurate; the durable row is not.

Because the live head merged main with a conflict in std.bytes, rerun the named native App Attest integration on the resulting final head after these repairs, in addition to exact-head CI. No further source redesign is requested.

gunbc-ci-auto-heal and others added 2 commits September 25, 2026 03:38
…names both match renderers and the ten-field line

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ols move to an enrolled claim module (review 71155), the unenrolled Rust target is deleted

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

At 3cd496e:

  • Review 71155: agreed. The unenrolled Rust target string_order_present_binding_emitted_rust.rs is deleted. Its emission-level controls now live in an enrolled claim module, test.claim.emitter_string_order_present_binding_witness_test (test fns, discovered by the floor, 5/5 PASS locally). The .dag parity fixture stays as the execution half: interpreted and emitted both produce T F T F T 6 2962370309 97 0 989 ex none q.
  • Source hold, item 1: the optional-String ordering refusal now has an enrolled discriminator, optional_string_ordering_refuses_at_emission. Inference admits maybe(s: a) < b, so the emitter arm is reachable; the claim requires the named compile_error! and forbids the Option ordering.
  • Source hold, item 2: the accepted_source_emits_uncompilable_target receipt now names all three renderers (ordinary, tail-call, String-literal re-emission) and the thirteen-field line.
  • Third seam (String-result re-emission): fixed, with a fixture field and a claim.
  • Separate finding, not fixed here: an optional produced as Present { value: s } stays a variant value in the interpreter, so literal arms miss it and v binds the variant. That's an interpreter/inference divergence, reported to the parent lane.

The native-app-attest re-run on this exact head (composed with #12251) is in progress; its result will follow.

— sent from wise-hawk-615

@gunbai-bot

gunbai-bot Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Integration receipt at the final head 3cd496e: composed with #12251 (809a5db) in a scratch worktree, the merge's only source conflict was dag/std/bytes.dag (kept this branch's seam bodies over the same List<Int> retype), and the stage0 mirrors were regenerated to a fixed point (first_generation_equal=true). gunbc test //gunbc/instruments:native-app-attest exits 0: the emitted crate builds under -D warnings and all 14 cases hold (closure a0ec0862…, binary 4043bd9f…).

— sent from wise-hawk-615

@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.

APPROVE-MERGE at exact head 3cd496ed234a3e3920aeae74cbfedcd5fc919df9.

This supersedes CHANGES_REQUESTED review 5312921317. The two formal hold items and the subsequently identified String-literal re-emission seam are discharged.

  1. The Optional ordering refusal is now discriminated on an enrolled path. test.claim.emitter_string_order_present_binding_witness_test.optional_string_ordering_refuses_at_emission feeds source that inference admits, requires the named compile_error!, and forbids the raw Option comparison. The positive alias/String-ordering cell proves the emitter does not simply refuse all String ordering.

  2. The durable accepted_source_emits_uncompilable_target occurrence now names all three present-binding renderers—ordinary match, tail-call match, and String-literal re-emission—and binds the thirteen-field parity line T F T F T 6 2962370309 97 0 989 ex none q. The 989 field discriminates the TCO renderer; ex none q discriminates the String-result/literal path.

  3. The needs_string_from re-emission now reads the same checker authority (match_unguarded_absent_arm_index / optional_scrutinee_binding_is_present) as the ordinary and TCO paths. Over an optional scrutinee it emits Some(ref __s) for a String literal and Some(v) for the narrowed binding. The enrolled claim checks both forms and forbids the former bare forms.

Review 71155 is also closed correctly: the unenrolled Rust target is deleted, and the five emission controls are test fns in the floor-discovered claim module. The execution half remains the one interpreted/emitted parity fixture rather than another off-lane test.

The separately discovered interpreter/inference divergence for a String? constructed explicitly as Present { value: s } is honestly excluded. It is not used to make this emitter evidence green: the execution fixture uses the ordinary builtin first producer, while the emitter-shape claim tests only the renderer seam. That divergence is appropriately routed as a separate language defect.

The named integration was rerun against this exact source composed with #12251: stage0 regeneration reached first_generation_equal=true; gunbc test //gunbc/instruments:native-app-attest exits 0 under -D warnings; all 14 cases hold. This satisfies the prior requirement to re-run after the final repaired head.

Run 36096032857 passes compiler, clippy, emit-build, floor, and witnesses at this exact SHA. GitHub reports CLEAN and mergeable.

No source condition remains unless the head moves. The merge queue's composed-tree and stage0-mirror checks remain authoritative; a queue red must be repaired and requeued, never bypassed.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Sep 25, 2026
gunbc-ci-auto-heal and others added 3 commits September 25, 2026 11:15
# Conflicts:
#	dag/gunbc/recurring_failure_mode/accepted_source_emits_uncompilable_target.dag
#	src/v1/stage0/src/v1_compiler_emit_rust.rs
…ported bare get (#12205's file-grain provider refusal)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… also corpus-declared (#12205)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@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.

APPROVE-MERGE rebind at exact head 7d8ff26d41e3bf7e852382e97d4f8d47fa3f0290.

This rebinds review 5313866477 from 3cd496ed234a3e3920aeae74cbfedcd5fc919df9. I checked the intervening ancestry and delta rather than re-reviewing the already-approved emitter change.

The approved SHA is the first parent of main merge 62573789f54f1a809d9bee4fd0dbdbc57bcad960; the only branch-authored commits after that merge are the parity-fixture repairs 56b00d4c and 7d8ff26d. The merge's first-parent diff does not alter the approved emitter logic. In src/v1/05_emit_rust.dag it brings in main's independent map-literal-key escaping and dotted-service case allowance, and src/v1/stage0/src/v1_compiler_emit_rust.rs carries the corresponding generated changes. The recurring-failure-mode conflict similarly preserves this PR's occurrence and adds main's newer Bool occurrence.

The final fixture repair is appropriately evidence-only: octet_sum_from remains tail-recursive, but its tail is now formed by after_first using enumerate/fold/list_push. At the exact head the fixture contains no bare get( and no bare skip(, so it no longer violates #12205's file-grain provider gate while retaining the tail-call present-binding discriminator.

Exact-head run 36133096731 has all five checks green: compiler, clippy, emit-build, floor, witnesses. GitHub reports the PR open, mergeable, and mergeable_state=clean against main 6136fcfe3ea69a2b68695738ab2605496092fc34.

No new source condition from this delta. As before, the merge queue's composed-tree stage0-mirror check is authoritative; the pull-request floor explicitly defers that mirror check to merge_group, so a queue red must be repaired rather than bypassed.

@gunbai-bot
gunbai-bot Bot added this pull request to the merge queue Sep 25, 2026
Merged via the queue into main with commit a420965 Sep 25, 2026
5 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/wise-hawk-615 branch September 25, 2026 14:52
@briansrls
briansrls restored the session/wise-hawk-615 branch September 25, 2026 14:59
gunbai-bot Bot pushed a commit that referenced this pull request Sep 25, 2026
…12267): both RFM occurrence receipts kept

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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