Skip to content

emit_rust: a hand-written impl header carries its item header's bounds (native broker 2A, rule 1) - #13144

Merged
briansrls merged 3 commits into
mainfrom
session/snappy-owl-646
Oct 3, 2026
Merged

briansrls merged 3 commits into
mainfrom
session/snappy-owl-646

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Native broker 2A, rule 1: a hand-written impl header carries its item header's bounds

Part of the native-broker program (owner gentle-dove-36): class A of the approval broker's native emission errors (X: Clone / X: Ord / ==).

The defect

When a generic parameter reaches a Set (or a FreeMonoid), the Rust emitter takes Debug and PartialEq off the derive list and writes those impls by hand, bounding each parameter with the trait's own requirement. A derive would also have copied the declaration's bounds onto the impl; the hand-written header did not. So an item whose header earns C: Clone from a bare field emitted

pub struct PublicationContext<C: Clone, P> { .. }
impl<C: std::fmt::Debug, P: Ord + std::fmt::Debug> std::fmt::Debug for PublicationContext<C, P> { .. }

which rustc refuses at the for type (E0277, C: Clone not satisfied), whatever the body does. v1.compiler.emit_rust already stated the law ("the item header and its supplemental impl headers are one fact") and applied it to one consumer only, the GroupCompletion impls, as a Bool.

The fix

The header decision is taken once (emit_item_header_clone_param_names) and is now passed as a list into every hand-written impl header: v1_set_impl_type_params and v1_freemonoid_impl_type_params union it under the trait's own requirement (deduplicated), for structs and enums alike. The GroupCompletion Bool is derived from the same list.

Two readers of the same record are deleted because they could disagree with the header: v1_carrier_param_needs_clone_bound (it re-read the record without the callable-field subtraction the header applies) and emit_item_type_params_with_clone_bounds (the enum branch now uses the same header function as the struct branch). An unused second call to v1_emit_struct_from_capability_table in emit_type_def_from_connective is removed.

Evidence (one remote dispatch, amd64 runner, branch head 561db6b plus the regenerated mirrors)

Native emission control: new gunbc test //gunbc/instruments:native-emission-controls, a NativeClaimDriver program (gunbc.instruments.native_emission_controls) that is emitted, built with -D warnings, and run. Its carriers have the PublicationContext / DisclosureRequest shape; six cases decide == over them, each positive paired with reds.

seed emitter before the rule after
emitted control crate does not compile: E0277 C: Clone, P: Clone, F: Clone at the four hand-written impls builds, warning_count=0
run n/a exit 0, 6/6 held

Textual witness (test.claim.generic_item_clone_bound_witness, two new arms): the struct header and both impl headers asserted together, plus a converse control that a bare-header coproduct's impls stay P: Ord + .. and gain no Clone. These two arms were not executed locally; CI's floor is their first run.

Regen: claim_executor --required-regen drifted on exactly v1_compiler_emit_rust.rs and v1_compiler_trait_derive_emit.rs; after installing them, first_generation_equal=true and --required-regen-fixed-point reports fixed_point_equal=true. No other mirror changed, so no emitted seed module carries a bound it did not carry before.

Error delta

probe before after
std.authorization_profile closure (--entry dag/std/authorization_profile.dag, 13 files) 77 3
approval broker at this base (fd30a50, before lane 1A's closure cut) 884 882

The broker row is small because at this base rustc stops before reporting most of std_authorization_profile (the 14 E0119 lane 1A's census describes as masking 73 of them); only the two visible ones (F: Clone at DisclosureRequest's Debug, == on Rc<im::Vector<F>>) are in the count. On the 1A census base the same module contributes 77, and this rule removes 74 of them. That figure is derived from the small-closure run, not measured on the 1A base.

What class A still contains (not this PR)

The baseline shows class A is four rules, not one. The other three stay red:

  • fn-level P: Ord (3 errors, std_authorization_profile.rs:74/85): audience_subset<P: Clone> reaches v1_rt::rc_set_union<T: Ord + Clone>. Next PR from this lane.
  • bare-name collision in the type declaration index (10 errors, std_access.rs:25-31): the broker closure holds both std.access::AccessRequest<S,A,O,C,E> and gunbc.auth.access_request::AccessRequest<Subject>; type_decl_items and clone_bounded_type_params are keyed by leaf name, last write wins, so std.access's header is emitted bare. This is the site the lane brief described as "generic users don't repeat the bound"; the fixpoint does propagate it, and it does so correctly in a closure without the second AccessRequest.
  • Subject: Clone at a generic fn passed as a value (2 errors, std_key_relation.rs:106).

Shared instrument

native-emission-controls is one label for all emitter-rule controls: a new rule adds its carrier, its cases and its roster identities to the program rather than a new label. It is run by name and is not a merge gate. The host change is one registry row in target_invocation_host.rs, the hand mirror gunbc.native_claim_program_seed_growth already describes as one arm generic over its entry.

🤖 Generated with Claude Code

Brian Searls and others added 3 commits October 3, 2026 18:33
…er's bounds (WIP, mirrors not regenerated)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…er bounds (fixed point verified at 561db6b)

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.

LGTM. The declaration and every hand-written supplemental impl now read one bound decision: header_clone_param_names is computed once, threaded through the Set and FreeMonoid struct/enum paths, unioned with each trait's own requirements, and deduplicated. The converse fixture prevents this from becoming blanket Clone, and the shared native-emission control is the right executing evidence route.

@briansrls
briansrls merged commit 4998418 into main Oct 3, 2026
4 checks passed
@briansrls
briansrls deleted the session/snappy-owl-646 branch October 3, 2026 20:58
gunbai-bot Bot pushed a commit that referenced this pull request Oct 3, 2026
…p this PR's Set-element Ord bound, lambda-argument guard and class-B repairs (mirrors regenerated next)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Oct 3, 2026
…g main (regen fixed point equal); drop the impl-header witness row now owned by main's set_struct_hand_written_impls_carry_header_bounds (#13144)

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