Skip to content

Emitter seal: see through aliases; don't parse a sealed-reaching data row from JSON - #13013

Merged
briansrls merged 2 commits into
mainfrom
emit-empty-list-and-alias-seal
Oct 3, 2026
Merged

briansrls merged 2 commits into
mainfrom
emit-empty-list-and-alias-seal

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Follow-up to #12999. The full rustc list of #12942's self-host build (srv1, neat-boar-16; 9 × E0277) showed two more paths by which a type that reaches a sole_constructor carrier still kept or used Deserialize. Both break the existing rule in dag/extdeps/languages/rust/capabilities.dag (the sealed-construction derive contract): a derived Deserialize is a second, unsealed mint.

(B) Aliases (3 errors). decl_member_type_nodes read an alias, a leaf type item with connective NoConnective, as a coproduct and visited no member. So v2.compiler.source_authority DagSourceAst { tree: ParseTree } kept its derive, where v2.std.grammar ParseTree = Node. An alias's one member is now its resolved target. The contrast case NormalizedDagSourceAst { tree: NormalizedTree } was already correct.

(A) Data rows (6 errors). emit_data_def_body realizes a nested-record data row by parsing a JSON document through serde_json::from_str. That needs Deserialize on the row type, and it is the forbidden mint. The six sites were empty List rows whose element types (Frame, CacheProvider, Diagnostic, FnArrowDecl) transitively hold Node. A row whose type reaches a sealed carrier now takes the typed-expression arm, which builds the value with the constructors the source wrote. This is the rule, not an empty-list special case: a non-empty row of such a type would have minted through serde too.

Controls (test.claim.emitter_sole_constructor_seal_witness_test), each paired with a positive control so its negative pattern is known to match:

  • alias_of_a_seal_drops_deserialize: a field typed by type Hold = Sealed drops the derive. A type PlainHold = Int field keeps it.
  • sealed_data_row_is_not_parsed_from_json: data carriers: List<Carrier> = [] over a sealed-reaching Carrier reaches no serde_json. plain_data_row_is_parsed_from_json shows the same shape over a plain record still does.

Mirror: v1_compiler_emit_rust.rs needs regeneration on srv1, as #12999 did. CI's first run should show the reds and the generated drift.

Unblocks #12942's self-host build (emit-build).

🤖 Generated with Claude Code

gunbc-ci-auto-heal and others added 2 commits October 2, 2026 21:12
…w is not parsed from JSON

Two more paths by which a type reaching a sole_constructor carrier kept or used
Deserialize, found by the full rustc list of #12942's self-host build (srv1,
neat-boar-16):
- decl_member_type_nodes read an alias (a leaf type item) as a coproduct and
  visited nothing, so DagSourceAst { tree: ParseTree } (ParseTree = Node) kept
  its derive. An alias's one member is now its resolved target.
- emit_data_def_body realized a nested-record data row by parsing JSON through
  serde, which needs Deserialize and is the very mint the seal forbids; six empty
  List rows of sealed-reaching element types refused E0277. A row whose type
  reaches a sealed carrier now takes the typed-expression arm.

Controls in emitter_sole_constructor_seal_witness_test: an alias-typed field
drops Deserialize while a plain alias keeps it; a sealed-reaching data row
reaches no serde_json while a plain row of the same shape still does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@briansrls
briansrls added this pull request to the merge queue Oct 3, 2026
Merged via the queue into main with commit 5251e7f Oct 3, 2026
4 checks passed
@briansrls
briansrls deleted the emit-empty-list-and-alias-seal branch October 3, 2026 14:09
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